hackport 0.6.5 → 0.6.6
raw patch · 1030 files changed
+45975/−27073 lines, 1030 filesdep +QuickCheckdep +doctestdep +hspecdep ~arraydep ~basedep ~binary
Dependencies added: QuickCheck, doctest, hspec
Dependency ranges changed: array, base, binary, bytestring, containers, deepseq, directory, filepath, mtl, parsec, pretty, process, text, time, transformers, unix, xml
Files
- .github/workflows/haskell.yml +45/−0
- .gitignore +1/−0
- AnsiColor.hs +1/−1
- Cabal2Ebuild.hs +31/−24
- Error.hs +8/−1
- HACKING.rst +3/−5
- HackPort/GlobalFlags.hs +4/−1
- Main.hs +1/−1
- Merge.hs +85/−106
- Merge/Dependencies.hs +25/−22
- Merge/Utils.hs +142/−0
- Portage/Cabal.hs +47/−8
- Portage/Dependency/Types.hs +26/−12
- Portage/EBuild.hs +38/−14
- Portage/EBuild/CabalFeature.hs +3/−2
- Portage/EMeta.hs +22/−7
- Portage/GHCCore.hs +68/−6
- Portage/Metadata.hs +82/−19
- Portage/Overlay.hs +6/−5
- Portage/PackageId.hs +67/−27
- Portage/Tables.hs +12/−2
- Portage/Version.hs +43/−20
- README.rst +5/−0
- Status.hs +1/−1
- cabal/.docker/validate-7.10.3.dockerfile +78/−0
- cabal/.docker/validate-7.6.3.dockerfile +79/−0
- cabal/.docker/validate-7.8.4.dockerfile +80/−0
- cabal/.docker/validate-8.0.2.dockerfile +69/−0
- cabal/.docker/validate-8.10.1.dockerfile +76/−0
- cabal/.docker/validate-8.2.2.dockerfile +78/−0
- cabal/.docker/validate-8.4.4.dockerfile +76/−0
- cabal/.docker/validate-8.6.5.dockerfile +76/−0
- cabal/.docker/validate-8.8.3.dockerfile +76/−0
- cabal/.docker/validate-old.dockerfile +72/−0
- cabal/.docker/validate.dockerfile.zinza +89/−0
- cabal/.dockerignore +2/−0
- cabal/.gitattributes +3/−0
- cabal/.github/PULL_REQUEST_TEMPLATE.md +1/−2
- cabal/.github/workflows/artifacts.yml +136/−0
- cabal/.github/workflows/bootstrap.yml +64/−0
- cabal/.github/workflows/linux.yml +497/−0
- cabal/.github/workflows/macos.yml +129/−0
- cabal/.github/workflows/quick-jobs.yml +84/−0
- cabal/.github/workflows/windows.yml +76/−0
- cabal/.gitignore +4/−0
- cabal/.readthedocs.yml +9/−0
- cabal/.travis.yml +0/−177
- cabal/CONTRIBUTING.md +8/−8
- cabal/Cabal/Cabal-QuickCheck/Cabal-QuickCheck.cabal +24/−0
- cabal/Cabal/Cabal-QuickCheck/src/Test/QuickCheck/GenericArbitrary.hs +49/−0
- cabal/Cabal/Cabal-QuickCheck/src/Test/QuickCheck/Instances/Cabal.hs +513/−0
- cabal/Cabal/Cabal-described/Cabal-described.cabal +26/−0
- cabal/Cabal/Cabal-described/src/Distribution/Described.hs +577/−0
- cabal/Cabal/Cabal-described/src/Distribution/Utils/CharSet.hs +242/−0
- cabal/Cabal/Cabal-described/src/Distribution/Utils/GrammarRegex.hs +215/−0
- cabal/Cabal/Cabal-tree-diff/Cabal-tree-diff.cabal +21/−0
- cabal/Cabal/Cabal-tree-diff/src/Data/TreeDiff/Instances/Cabal.hs +135/−0
- cabal/Cabal/Cabal-tree-diff/src/Data/TreeDiff/Instances/CabalLanguage.hs +17/−0
- cabal/Cabal/Cabal-tree-diff/src/Data/TreeDiff/Instances/CabalSPDX.hs +28/−0
- cabal/Cabal/Cabal-tree-diff/src/Data/TreeDiff/Instances/CabalVersion.hs +14/−0
- cabal/Cabal/Cabal.cabal +110/−23
- cabal/Cabal/ChangeLog.md +41/−9
- cabal/Cabal/Distribution/Backpack.hs +4/−3
- cabal/Cabal/Distribution/Backpack/ComponentsGraph.hs +17/−18
- cabal/Cabal/Distribution/Backpack/Configure.hs +5/−4
- cabal/Cabal/Distribution/Backpack/ConfiguredComponent.hs +24/−38
- cabal/Cabal/Distribution/Backpack/Id.hs +4/−5
- cabal/Cabal/Distribution/Backpack/LinkedComponent.hs +10/−12
- cabal/Cabal/Distribution/Backpack/ModuleShape.hs +3/−1
- cabal/Cabal/Distribution/Backpack/ReadyComponent.hs +7/−10
- cabal/Cabal/Distribution/Backpack/UnifyM.hs +7/−8
- cabal/Cabal/Distribution/CabalSpecVersion.hs +68/−20
- cabal/Cabal/Distribution/Compat/Async.hs +2/−0
- cabal/Cabal/Distribution/Compat/Binary.hs +8/−8
- cabal/Cabal/Distribution/Compat/CharParsing.hs +9/−0
- cabal/Cabal/Distribution/Compat/CopyFile.hs +7/−11
- cabal/Cabal/Distribution/Compat/CreatePipe.hs +10/−6
- cabal/Cabal/Distribution/Compat/DList.hs +7/−2
- cabal/Cabal/Distribution/Compat/Environment.hs +1/−1
- cabal/Cabal/Distribution/Compat/Exception.hs +12/−2
- cabal/Cabal/Distribution/Compat/GetShortPathName.hs +2/−2
- cabal/Cabal/Distribution/Compat/Graph.hs +20/−16
- cabal/Cabal/Distribution/Compat/Internal/TempFile.hs +28/−14
- cabal/Cabal/Distribution/Compat/Lens.hs +0/−1
- cabal/Cabal/Distribution/Compat/MD5.hs +0/−50
- cabal/Cabal/Distribution/Compat/NonEmptySet.hs +155/−0
- cabal/Cabal/Distribution/Compat/Prelude.hs +94/−34
- cabal/Cabal/Distribution/Compat/Process.hs +82/−0
- cabal/Cabal/Distribution/Compat/ResponseFile.hs +67/−68
- cabal/Cabal/Distribution/Compat/Semigroup.hs +9/−2
- cabal/Cabal/Distribution/Compat/Time.hs +9/−5
- cabal/Cabal/Distribution/Compat/Typeable.hs +18/−0
- cabal/Cabal/Distribution/Compiler.hs +11/−5
- cabal/Cabal/Distribution/FieldGrammar.hs +5/−1
- cabal/Cabal/Distribution/FieldGrammar/Class.hs +52/−19
- cabal/Cabal/Distribution/FieldGrammar/FieldDescrs.hs +14/−6
- cabal/Cabal/Distribution/FieldGrammar/Newtypes.hs +339/−0
- cabal/Cabal/Distribution/FieldGrammar/Parsec.hs +29/−12
- cabal/Cabal/Distribution/FieldGrammar/Pretty.hs +5/−2
- cabal/Cabal/Distribution/Fields/ConfVar.hs +6/−6
- cabal/Cabal/Distribution/Fields/Field.hs +1/−1
- cabal/Cabal/Distribution/Fields/ParseResult.hs +12/−1
- cabal/Cabal/Distribution/Fields/Parser.hs +0/−1
- cabal/Cabal/Distribution/Fields/Pretty.hs +23/−9
- cabal/Cabal/Distribution/InstalledPackageInfo.hs +12/−7
- cabal/Cabal/Distribution/License.hs +1/−1
- cabal/Cabal/Distribution/Make.hs +0/−2
- cabal/Cabal/Distribution/ModuleName.hs +57/−72
- cabal/Cabal/Distribution/PackageDescription.hs +73/−117
- cabal/Cabal/Distribution/PackageDescription/Check.hs +90/−264
- cabal/Cabal/Distribution/PackageDescription/Configuration.hs +56/−54
- cabal/Cabal/Distribution/PackageDescription/FieldGrammar.hs +193/−46
- cabal/Cabal/Distribution/PackageDescription/Parsec.hs +141/−50
- cabal/Cabal/Distribution/PackageDescription/PrettyPrint.hs +74/−30
- cabal/Cabal/Distribution/PackageDescription/Quirks.hs +20/−3
- cabal/Cabal/Distribution/Parsec.hs +126/−12
- cabal/Cabal/Distribution/Parsec/Newtypes.hs +0/−230
- cabal/Cabal/Distribution/Parsec/Warning.hs +7/−0
- cabal/Cabal/Distribution/Pretty.hs +4/−0
- cabal/Cabal/Distribution/SPDX/License.hs +1/−0
- cabal/Cabal/Distribution/SPDX/LicenseExceptionId.hs +52/−9
- cabal/Cabal/Distribution/SPDX/LicenseExpression.hs +2/−1
- cabal/Cabal/Distribution/SPDX/LicenseId.hs +307/−292
- cabal/Cabal/Distribution/SPDX/LicenseListVersion.hs +2/−1
- cabal/Cabal/Distribution/SPDX/LicenseReference.hs +1/−0
- cabal/Cabal/Distribution/Simple.hs +40/−58
- cabal/Cabal/Distribution/Simple/Bench.hs +0/−1
- cabal/Cabal/Distribution/Simple/Build.hs +10/−5
- cabal/Cabal/Distribution/Simple/Build/Macros.hs +56/−102
- cabal/Cabal/Distribution/Simple/Build/Macros/Z.hs +140/−0
- cabal/Cabal/Distribution/Simple/BuildPaths.hs +0/−2
- cabal/Cabal/Distribution/Simple/BuildTarget.hs +7/−6
- cabal/Cabal/Distribution/Simple/BuildToolDepends.hs +0/−3
- cabal/Cabal/Distribution/Simple/Command.hs +6/−1
- cabal/Cabal/Distribution/Simple/Compiler.hs +30/−17
- cabal/Cabal/Distribution/Simple/Configure.hs +122/−148
- cabal/Cabal/Distribution/Simple/Doctest.hs +2/−2
- cabal/Cabal/Distribution/Simple/Flag.hs +9/−1
- cabal/Cabal/Distribution/Simple/GHC.hs +34/−31
- cabal/Cabal/Distribution/Simple/GHC/EnvironmentParser.hs +0/−2
- cabal/Cabal/Distribution/Simple/GHC/Internal.hs +33/−40
- cabal/Cabal/Distribution/Simple/GHCJS.hs +17/−20
- cabal/Cabal/Distribution/Simple/Glob.hs +7/−9
- cabal/Cabal/Distribution/Simple/Haddock.hs +26/−18
- cabal/Cabal/Distribution/Simple/HaskellSuite.hs +7/−12
- cabal/Cabal/Distribution/Simple/InstallDirs.hs +7/−4
- cabal/Cabal/Distribution/Simple/InstallDirs/Internal.hs +5/−2
- cabal/Cabal/Distribution/Simple/LocalBuildInfo.hs +1/−1
- cabal/Cabal/Distribution/Simple/PackageIndex.hs +11/−4
- cabal/Cabal/Distribution/Simple/PreProcess.hs +3/−12
- cabal/Cabal/Distribution/Simple/Program.hs +1/−0
- cabal/Cabal/Distribution/Simple/Program/Builtin.hs +1/−2
- cabal/Cabal/Distribution/Simple/Program/Db.hs +16/−9
- cabal/Cabal/Distribution/Simple/Program/Find.hs +8/−6
- cabal/Cabal/Distribution/Simple/Program/GHC.hs +26/−7
- cabal/Cabal/Distribution/Simple/Program/HcPkg.hs +59/−36
- cabal/Cabal/Distribution/Simple/Program/Hpc.hs +1/−2
- cabal/Cabal/Distribution/Simple/Program/Run.hs +47/−35
- cabal/Cabal/Distribution/Simple/Program/Script.hs +9/−3
- cabal/Cabal/Distribution/Simple/Program/Types.hs +4/−1
- cabal/Cabal/Distribution/Simple/Register.hs +3/−4
- cabal/Cabal/Distribution/Simple/Setup.hs +28/−38
- cabal/Cabal/Distribution/Simple/ShowBuildInfo.hs +4/−1
- cabal/Cabal/Distribution/Simple/SrcDist.hs +133/−130
- cabal/Cabal/Distribution/Simple/Test.hs +0/−1
- cabal/Cabal/Distribution/Simple/Test/ExeV10.hs +34/−26
- cabal/Cabal/Distribution/Simple/Test/LibV09.hs +17/−11
- cabal/Cabal/Distribution/Simple/Test/Log.hs +1/−1
- cabal/Cabal/Distribution/Simple/UHC.hs +10/−8
- cabal/Cabal/Distribution/Simple/Utils.hs +189/−78
- cabal/Cabal/Distribution/System.hs +8/−5
- cabal/Cabal/Distribution/Types/AbiDependency.hs +3/−1
- cabal/Cabal/Distribution/Types/AbiHash.hs +2/−2
- cabal/Cabal/Distribution/Types/Benchmark.hs +1/−1
- cabal/Cabal/Distribution/Types/BenchmarkInterface.hs +1/−1
- cabal/Cabal/Distribution/Types/BenchmarkType.hs +3/−2
- cabal/Cabal/Distribution/Types/BuildInfo.hs +3/−3
- cabal/Cabal/Distribution/Types/BuildType.hs +2/−1
- cabal/Cabal/Distribution/Types/ComponentId.hs +1/−0
- cabal/Cabal/Distribution/Types/ComponentLocalBuildInfo.hs +4/−2
- cabal/Cabal/Distribution/Types/ComponentName.hs +1/−0
- cabal/Cabal/Distribution/Types/ComponentRequestedSpec.hs +4/−1
- cabal/Cabal/Distribution/Types/CondTree.hs +7/−5
- cabal/Cabal/Distribution/Types/Condition.hs +1/−1
- cabal/Cabal/Distribution/Types/ConfVar.hs +2/−1
- cabal/Cabal/Distribution/Types/Dependency.hs +120/−60
- cabal/Cabal/Distribution/Types/DependencyMap.hs +16/−17
- cabal/Cabal/Distribution/Types/ExeDependency.hs +8/−4
- cabal/Cabal/Distribution/Types/Executable.hs +1/−1
- cabal/Cabal/Distribution/Types/ExecutableScope.hs +2/−1
- cabal/Cabal/Distribution/Types/ExposedModule.hs +3/−2
- cabal/Cabal/Distribution/Types/Flag.hs +110/−9
- cabal/Cabal/Distribution/Types/ForeignLib.hs +4/−4
- cabal/Cabal/Distribution/Types/ForeignLibOption.hs +2/−1
- cabal/Cabal/Distribution/Types/ForeignLibType.hs +2/−1
- cabal/Cabal/Distribution/Types/GenericPackageDescription.hs +40/−13
- cabal/Cabal/Distribution/Types/GenericPackageDescription/Lens.hs +21/−16
- cabal/Cabal/Distribution/Types/GivenComponent.hs +1/−1
- cabal/Cabal/Distribution/Types/IncludeRenaming.hs +3/−2
- cabal/Cabal/Distribution/Types/InstalledPackageInfo.hs +12/−9
- cabal/Cabal/Distribution/Types/InstalledPackageInfo/FieldGrammar.hs +72/−52
- cabal/Cabal/Distribution/Types/InstalledPackageInfo/Lens.hs +11/−9
- cabal/Cabal/Distribution/Types/LegacyExeDependency.hs +5/−4
- cabal/Cabal/Distribution/Types/Library.hs +1/−1
- cabal/Cabal/Distribution/Types/LibraryName.hs +1/−0
- cabal/Cabal/Distribution/Types/LibraryVisibility.hs +3/−0
- cabal/Cabal/Distribution/Types/LocalBuildInfo.hs +3/−1
- cabal/Cabal/Distribution/Types/Mixin.hs +62/−5
- cabal/Cabal/Distribution/Types/Module.hs +1/−0
- cabal/Cabal/Distribution/Types/ModuleReexport.hs +2/−3
- cabal/Cabal/Distribution/Types/ModuleRenaming.hs +2/−1
- cabal/Cabal/Distribution/Types/MungedPackageId.hs +1/−0
- cabal/Cabal/Distribution/Types/MungedPackageName.hs +1/−0
- cabal/Cabal/Distribution/Types/PackageDescription.hs +27/−49
- cabal/Cabal/Distribution/Types/PackageDescription/Lens.hs +48/−46
- cabal/Cabal/Distribution/Types/PackageId.hs +4/−3
- cabal/Cabal/Distribution/Types/PackageName.hs +17/−1
- cabal/Cabal/Distribution/Types/PackageVersionConstraint.hs +48/−13
- cabal/Cabal/Distribution/Types/PkgconfigDependency.hs +3/−3
- cabal/Cabal/Distribution/Types/PkgconfigName.hs +8/−1
- cabal/Cabal/Distribution/Types/PkgconfigVersion.hs +14/−0
- cabal/Cabal/Distribution/Types/PkgconfigVersionRange.hs +28/−9
- cabal/Cabal/Distribution/Types/SetupBuildInfo.hs +1/−1
- cabal/Cabal/Distribution/Types/SourceRepo.hs +45/−18
- cabal/Cabal/Distribution/Types/TestSuite.hs +1/−0
- cabal/Cabal/Distribution/Types/TestSuiteInterface.hs +1/−0
- cabal/Cabal/Distribution/Types/TestType.hs +3/−1
- cabal/Cabal/Distribution/Types/UnitId.hs +10/−1
- cabal/Cabal/Distribution/Types/UnqualComponentName.hs +8/−3
- cabal/Cabal/Distribution/Types/Version.hs +1/−0
- cabal/Cabal/Distribution/Types/VersionInterval.hs +13/−13
- cabal/Cabal/Distribution/Types/VersionRange.hs +32/−19
- cabal/Cabal/Distribution/Types/VersionRange/Internal.hs +151/−58
- cabal/Cabal/Distribution/Utils/Generic.hs +47/−17
- cabal/Cabal/Distribution/Utils/IOData.hs +58/−33
- cabal/Cabal/Distribution/Utils/LogProgress.hs +3/−3
- cabal/Cabal/Distribution/Utils/MD5.hs +79/−0
- cabal/Cabal/Distribution/Utils/NubList.hs +6/−3
- cabal/Cabal/Distribution/Utils/ShortText.hs +52/−4
- cabal/Cabal/Distribution/Utils/Structured.hs +472/−0
- cabal/Cabal/Distribution/Verbosity.hs +88/−41
- cabal/Cabal/Distribution/Verbosity/Internal.hs +6/−2
- cabal/Cabal/Distribution/Version.hs +0/−17
- cabal/Cabal/Distribution/ZinzaPrelude.hs +43/−0
- cabal/Cabal/LICENSE +4/−1
- cabal/Cabal/Language/Haskell/Extension.hs +25/−0
- cabal/Cabal/Makefile +5/−4
- cabal/Cabal/doc/README.md +2/−7
- cabal/Cabal/doc/buildinfo-fields-reference.rst +654/−0
- cabal/Cabal/doc/cabal-commands.rst +402/−0
- cabal/Cabal/doc/cabal-package.rst +3335/−0
- cabal/Cabal/doc/cabal-project.rst +1549/−0
- cabal/Cabal/doc/cabaldomain.py +16/−13
- cabal/Cabal/doc/conf.py +9/−6
- cabal/Cabal/doc/developing-packages.rst +485/−3749
- cabal/Cabal/doc/file-format-changelog.rst +21/−6
- cabal/Cabal/doc/getting-started.rst +169/−0
- cabal/Cabal/doc/hcar/Cabal-201604.tex +1/−1
- cabal/Cabal/doc/hcar/Cabal-201611.tex +1/−1
- cabal/Cabal/doc/index.rst +8/−2
- cabal/Cabal/doc/installing-packages.rst +204/−1735
- cabal/Cabal/doc/misc.rst +1/−1
- cabal/Cabal/doc/nix-integration.rst +5/−0
- cabal/Cabal/doc/nix-local-build-overview.rst +3/−1
- cabal/Cabal/doc/nix-local-build.rst +211/−2119
- cabal/Cabal/doc/references.inc +1/−1
- cabal/Cabal/doc/requirements.txt +2/−0
- cabal/Cabal/doc/setup-commands.rst +1422/−0
- cabal/LICENSE +1/−1
- cabal/Makefile +132/−18
- cabal/appveyor.yml +2/−2
- cabal/boot/SPDX.LicenseExceptionId.template.hs +14/−0
- cabal/boot/SPDX.LicenseId.template.hs +33/−1
- cabal/boot/cabal_macros.template.h +41/−0
- cabal/boot/ci-artifacts.template.yml +136/−0
- cabal/boot/ci-bootstrap.template.yml +64/−0
- cabal/boot/ci-linux.template.yml +72/−0
- cabal/boot/ci-macos.template.yml +68/−0
- cabal/boot/ci-quick-jobs.template.yml +84/−0
- cabal/boot/ci-windows.template.yml +84/−0
- cabal/buildinfo-reference-generator/buildinfo-reference-generator.cabal +16/−0
- cabal/buildinfo-reference-generator/src/Main.hs +274/−0
- cabal/buildinfo-reference-generator/template.zinza +233/−0
- cabal/cabal-benchmarks/LICENSE +34/−0
- cabal/cabal-benchmarks/README.md +3/−0
- cabal/cabal-benchmarks/bench/CabalBenchmarks.hs +14/−0
- cabal/cabal-benchmarks/cabal-benchmarks.cabal +34/−0
- cabal/cabal-dev-scripts/LICENSE +7/−3
- cabal/cabal-dev-scripts/cabal-dev-scripts.cabal +69/−10
- cabal/cabal-dev-scripts/src/AnalyseImports.hs +106/−0
- cabal/cabal-dev-scripts/src/Capture.hs +31/−0
- cabal/cabal-dev-scripts/src/GenCabalInstallCabal.hs +49/−0
- cabal/cabal-dev-scripts/src/GenCabalMacros.hs +119/−0
- cabal/cabal-dev-scripts/src/GenSPDX.hs +9/−3
- cabal/cabal-dev-scripts/src/GenSPDXExc.hs +6/−1
- cabal/cabal-dev-scripts/src/GenUtils.hs +11/−5
- cabal/cabal-dev-scripts/src/GenValidate.hs +157/−0
- cabal/cabal-dev-scripts/src/GenValidateDockerfile.hs +74/−0
- cabal/cabal-dev-scripts/src/Preprocessor.hs +0/−222
- cabal/cabal-install/Distribution/Client/BuildReports/Anonymous.hs +72/−232
- cabal/cabal-install/Distribution/Client/BuildReports/Lens.hs +46/−0
- cabal/cabal-install/Distribution/Client/BuildReports/Storage.hs +17/−14
- cabal/cabal-install/Distribution/Client/BuildReports/Types.hs +136/−20
- cabal/cabal-install/Distribution/Client/BuildReports/Upload.hs +8/−9
- cabal/cabal-install/Distribution/Client/Check.hs +0/−1
- cabal/cabal-install/Distribution/Client/CmdBench.hs +72/−66
- cabal/cabal-install/Distribution/Client/CmdBuild.hs +32/−77
- cabal/cabal-install/Distribution/Client/CmdClean.hs +2/−6
- cabal/cabal-install/Distribution/Client/CmdConfigure.hs +43/−24
- cabal/cabal-install/Distribution/Client/CmdErrorMessages.hs +75/−48
- cabal/cabal-install/Distribution/Client/CmdExec.hs +17/−32
- cabal/cabal-install/Distribution/Client/CmdFreeze.hs +30/−30
- cabal/cabal-install/Distribution/Client/CmdHaddock.hs +26/−61
- cabal/cabal-install/Distribution/Client/CmdInstall.hs +378/−400
- cabal/cabal-install/Distribution/Client/CmdInstall/ClientInstallFlags.hs +20/−36
- cabal/cabal-install/Distribution/Client/CmdInstall/ClientInstallTargetSelector.hs +68/−0
- cabal/cabal-install/Distribution/Client/CmdLegacy.hs +9/−15
- cabal/cabal-install/Distribution/Client/CmdListBin.hs +368/−0
- cabal/cabal-install/Distribution/Client/CmdRepl.hs +106/−146
- cabal/cabal-install/Distribution/Client/CmdRun.hs +126/−117
- cabal/cabal-install/Distribution/Client/CmdSdist.hs +119/−153
- cabal/cabal-install/Distribution/Client/CmdTest.hs +75/−67
- cabal/cabal-install/Distribution/Client/CmdUpdate.hs +76/−72
- cabal/cabal-install/Distribution/Client/Compat/Directory.hs +47/−2
- cabal/cabal-install/Distribution/Client/Compat/ExecutablePath.hs +2/−0
- cabal/cabal-install/Distribution/Client/Compat/FilePerms.hs +2/−0
- cabal/cabal-install/Distribution/Client/Compat/Orphans.hs +41/−0
- cabal/cabal-install/Distribution/Client/Compat/Prelude.hs +8/−3
- cabal/cabal-install/Distribution/Client/Compat/Process.hs +5/−0
- cabal/cabal-install/Distribution/Client/Compat/Semaphore.hs +6/−2
- cabal/cabal-install/Distribution/Client/Config.hs +142/−113
- cabal/cabal-install/Distribution/Client/Configure.hs +13/−20
- cabal/cabal-install/Distribution/Client/Dependency.hs +63/−98
- cabal/cabal-install/Distribution/Client/Dependency/Types.hs +16/−19
- cabal/cabal-install/Distribution/Client/DistDirLayout.hs +20/−21
- cabal/cabal-install/Distribution/Client/Exec.hs +8/−126
- cabal/cabal-install/Distribution/Client/Fetch.hs +10/−11
- cabal/cabal-install/Distribution/Client/FetchUtils.hs +25/−24
- cabal/cabal-install/Distribution/Client/FileMonitor.hs +42/−31
- cabal/cabal-install/Distribution/Client/Freeze.hs +12/−21
- cabal/cabal-install/Distribution/Client/GZipUtils.hs +7/−1
- cabal/cabal-install/Distribution/Client/GenBounds.hs +3/−12
- cabal/cabal-install/Distribution/Client/Get.hs +28/−34
- cabal/cabal-install/Distribution/Client/Glob.hs +58/−80
- cabal/cabal-install/Distribution/Client/GlobalFlags.hs +69/−57
- cabal/cabal-install/Distribution/Client/Haddock.hs +5/−4
- cabal/cabal-install/Distribution/Client/HashValue.hs +85/−0
- cabal/cabal-install/Distribution/Client/HttpUtils.hs +99/−47
- cabal/cabal-install/Distribution/Client/IndexUtils.hs +340/−148
- cabal/cabal-install/Distribution/Client/IndexUtils/ActiveRepos.hs +174/−0
- cabal/cabal-install/Distribution/Client/IndexUtils/IndexState.hs +138/−0
- cabal/cabal-install/Distribution/Client/IndexUtils/Timestamp.hs +40/−71
- cabal/cabal-install/Distribution/Client/Init.hs +2/−1288
- cabal/cabal-install/Distribution/Client/Init/Command.hs +730/−0
- cabal/cabal-install/Distribution/Client/Init/Defaults.hs +41/−0
- cabal/cabal-install/Distribution/Client/Init/FileCreators.hs +650/−0
- cabal/cabal-install/Distribution/Client/Init/Heuristics.hs +11/−14
- cabal/cabal-install/Distribution/Client/Init/Licenses.hs +12/−0
- cabal/cabal-install/Distribution/Client/Init/Prompt.hs +145/−0
- cabal/cabal-install/Distribution/Client/Init/Types.hs +26/−13
- cabal/cabal-install/Distribution/Client/Init/Utils.hs +38/−0
- cabal/cabal-install/Distribution/Client/Install.hs +72/−135
- cabal/cabal-install/Distribution/Client/InstallPlan.hs +40/−35
- cabal/cabal-install/Distribution/Client/InstallSymlink.hs +47/−66
- cabal/cabal-install/Distribution/Client/JobControl.hs +5/−2
- cabal/cabal-install/Distribution/Client/List.hs +115/−89
- cabal/cabal-install/Distribution/Client/Manpage.hs +44/−3
- cabal/cabal-install/Distribution/Client/ManpageFlags.hs +40/−0
- cabal/cabal-install/Distribution/Client/Nix.hs +3/−23
- cabal/cabal-install/Distribution/Client/NixStyleOptions.hs +85/−0
- cabal/cabal-install/Distribution/Client/Outdated.hs +27/−26
- cabal/cabal-install/Distribution/Client/PackageHash.hs +52/−122
- cabal/cabal-install/Distribution/Client/PackageUtils.hs +0/−38
- cabal/cabal-install/Distribution/Client/ParseUtils.hs +9/−9
- cabal/cabal-install/Distribution/Client/ProjectBuilding.hs +24/−39
- cabal/cabal-install/Distribution/Client/ProjectBuilding/Types.hs +3/−5
- cabal/cabal-install/Distribution/Client/ProjectConfig.hs +67/−54
- cabal/cabal-install/Distribution/Client/ProjectConfig/Legacy.hs +157/−124
- cabal/cabal-install/Distribution/Client/ProjectConfig/Types.hs +31/−20
- cabal/cabal-install/Distribution/Client/ProjectFlags.hs +60/−0
- cabal/cabal-install/Distribution/Client/ProjectOrchestration.hs +129/−84
- cabal/cabal-install/Distribution/Client/ProjectPlanOutput.hs +27/−25
- cabal/cabal-install/Distribution/Client/ProjectPlanning.hs +128/−102
- cabal/cabal-install/Distribution/Client/ProjectPlanning/Types.hs +15/−9
- cabal/cabal-install/Distribution/Client/RebuildMonad.hs +1/−2
- cabal/cabal-install/Distribution/Client/Reconfigure.hs +6/−60
- cabal/cabal-install/Distribution/Client/Run.hs +5/−7
- cabal/cabal-install/Distribution/Client/Sandbox.hs +21/−768
- cabal/cabal-install/Distribution/Client/Sandbox/Index.hs +0/−285
- cabal/cabal-install/Distribution/Client/Sandbox/PackageEnvironment.hs +32/−321
- cabal/cabal-install/Distribution/Client/Sandbox/Timestamp.hs +0/−273
- cabal/cabal-install/Distribution/Client/Sandbox/Types.hs +0/−65
- cabal/cabal-install/Distribution/Client/SavedFlags.hs +5/−7
- cabal/cabal-install/Distribution/Client/Security/DNS.hs +3/−7
- cabal/cabal-install/Distribution/Client/Security/HTTP.hs +40/−41
- cabal/cabal-install/Distribution/Client/Setup.hs +240/−560
- cabal/cabal-install/Distribution/Client/SetupWrapper.hs +29/−29
- cabal/cabal-install/Distribution/Client/SolverInstallPlan.hs +34/−39
- cabal/cabal-install/Distribution/Client/SourceFiles.hs +14/−15
- cabal/cabal-install/Distribution/Client/SourceRepo.hs +0/−96
- cabal/cabal-install/Distribution/Client/SrcDist.hs +79/−141
- cabal/cabal-install/Distribution/Client/Store.hs +6/−7
- cabal/cabal-install/Distribution/Client/Tar.hs +5/−1
- cabal/cabal-install/Distribution/Client/TargetProblem.hs +55/−0
- cabal/cabal-install/Distribution/Client/TargetSelector.hs +85/−55
- cabal/cabal-install/Distribution/Client/Targets.hs +80/−119
- cabal/cabal-install/Distribution/Client/Types.hs +25/−589
- cabal/cabal-install/Distribution/Client/Types/AllowNewer.hs +241/−0
- cabal/cabal-install/Distribution/Client/Types/BuildResults.hs +59/−0
- cabal/cabal-install/Distribution/Client/Types/ConfiguredId.hs +83/−0
- cabal/cabal-install/Distribution/Client/Types/ConfiguredPackage.hs +86/−0
- cabal/cabal-install/Distribution/Client/Types/Credentials.hs +9/−0
- cabal/cabal-install/Distribution/Client/Types/InstallMethod.hs +32/−0
- cabal/cabal-install/Distribution/Client/Types/OverwritePolicy.hs +28/−0
- cabal/cabal-install/Distribution/Client/Types/PackageLocation.hs +50/−0
- cabal/cabal-install/Distribution/Client/Types/PackageSpecifier.hs +55/−0
- cabal/cabal-install/Distribution/Client/Types/ReadyPackage.hs +31/−0
- cabal/cabal-install/Distribution/Client/Types/Repo.hs +184/−0
- cabal/cabal-install/Distribution/Client/Types/RepoName.hs +45/−0
- cabal/cabal-install/Distribution/Client/Types/SourcePackageDb.hs +23/−0
- cabal/cabal-install/Distribution/Client/Types/SourceRepo.hs +108/−0
- cabal/cabal-install/Distribution/Client/Types/WriteGhcEnvironmentFilesPolicy.hs +20/−0
- cabal/cabal-install/Distribution/Client/Update.hs +21/−14
- cabal/cabal-install/Distribution/Client/Upload.hs +19/−20
- cabal/cabal-install/Distribution/Client/Utils.hs +18/−7
- cabal/cabal-install/Distribution/Client/Utils/Assertion.hs +4/−0
- cabal/cabal-install/Distribution/Client/Utils/Json.hs +5/−8
- cabal/cabal-install/Distribution/Client/VCS.hs +154/−13
- cabal/cabal-install/Distribution/Client/Win32SelfUpgrade.hs +5/−4
- cabal/cabal-install/Distribution/Client/World.hs +21/−50
- cabal/cabal-install/Distribution/Deprecated/ParseUtils.hs +49/−210
- cabal/cabal-install/Distribution/Deprecated/Text.hs +0/−409
- cabal/cabal-install/Distribution/Deprecated/ViewAsFieldDescr.hs +0/−2
- cabal/cabal-install/Distribution/Solver/Modular.hs +0/−1
- cabal/cabal-install/Distribution/Solver/Modular/Assignment.hs +6/−5
- cabal/cabal-install/Distribution/Solver/Modular/Builder.hs +8/−6
- cabal/cabal-install/Distribution/Solver/Modular/ConfiguredConversion.hs +1/−1
- cabal/cabal-install/Distribution/Solver/Modular/ConflictSet.hs +71/−33
- cabal/cabal-install/Distribution/Solver/Modular/Dependency.hs +70/−11
- cabal/cabal-install/Distribution/Solver/Modular/Explore.hs +165/−37
- cabal/cabal-install/Distribution/Solver/Modular/Index.hs +21/−3
- cabal/cabal-install/Distribution/Solver/Modular/IndexConversion.hs +110/−123
- cabal/cabal-install/Distribution/Solver/Modular/LabeledGraph.hs +3/−2
- cabal/cabal-install/Distribution/Solver/Modular/Linking.hs +5/−3
- cabal/cabal-install/Distribution/Solver/Modular/Message.hs +121/−4
- cabal/cabal-install/Distribution/Solver/Modular/Package.hs +8/−9
- cabal/cabal-install/Distribution/Solver/Modular/Preference.hs +5/−5
- cabal/cabal-install/Distribution/Solver/Modular/RetryLog.hs +3/−0
- cabal/cabal-install/Distribution/Solver/Modular/Solver.hs +11/−5
- cabal/cabal-install/Distribution/Solver/Modular/Tree.hs +2/−0
- cabal/cabal-install/Distribution/Solver/Modular/Validate.hs +90/−37
- cabal/cabal-install/Distribution/Solver/Modular/Version.hs +6/−3
- cabal/cabal-install/Distribution/Solver/Types/ComponentDeps.hs +19/−0
- cabal/cabal-install/Distribution/Solver/Types/ConstraintSource.hs +3/−2
- cabal/cabal-install/Distribution/Solver/Types/DependencyResolver.hs +2/−1
- cabal/cabal-install/Distribution/Solver/Types/Flag.hs +2/−0
- cabal/cabal-install/Distribution/Solver/Types/InstSolverPackage.hs +6/−4
- cabal/cabal-install/Distribution/Solver/Types/InstalledPreference.hs +2/−0
- cabal/cabal-install/Distribution/Solver/Types/OptionalStanza.hs +3/−4
- cabal/cabal-install/Distribution/Solver/Types/PackageConstraint.hs +16/−19
- cabal/cabal-install/Distribution/Solver/Types/PackageIndex.hs +23/−5
- cabal/cabal-install/Distribution/Solver/Types/PackagePath.hs +10/−9
- cabal/cabal-install/Distribution/Solver/Types/PkgConfigDb.hs +2/−1
- cabal/cabal-install/Distribution/Solver/Types/Progress.hs +1/−1
- cabal/cabal-install/Distribution/Solver/Types/ResolverPackage.hs +4/−2
- cabal/cabal-install/Distribution/Solver/Types/Settings.hs +27/−9
- cabal/cabal-install/Distribution/Solver/Types/SolverId.hs +4/−2
- cabal/cabal-install/Distribution/Solver/Types/SolverPackage.hs +4/−2
- cabal/cabal-install/Distribution/Solver/Types/SourcePackage.hs +13/−10
- cabal/cabal-install/Distribution/Solver/Types/Variable.hs +2/−0
- cabal/cabal-install/LICENSE +4/−1
- cabal/cabal-install/Setup.hs +2/−62
- cabal/cabal-install/bootstrap.sh +21/−12
- cabal/cabal-install/cabal-install.cabal +52/−27
- cabal/cabal-install/cabal-install.cabal.dev +587/−0
- cabal/cabal-install/cabal-install.cabal.pp +0/−669
- cabal/cabal-install/cabal-install.cabal.prod +397/−0
- cabal/cabal-install/cabal-install.cabal.zinza +616/−0
- cabal/cabal-install/changelog +33/−3
- cabal/cabal-install/main/Main.hs +95/−332
- cabal/cabal-install/solver-dsl/UnitTests/Distribution/Solver/Modular/DSL.hs +183/−104
- cabal/cabal-install/tests/IntegrationTests2.hs +139/−138
- cabal/cabal-install/tests/IntegrationTests2/targets/complex/q/q.cabal +2/−1
- cabal/cabal-install/tests/IntegrationTests2/targets/simple/app/Main.hs +0/−0
- cabal/cabal-install/tests/IntegrationTests2/targets/simple/p.cabal +5/−0
- cabal/cabal-install/tests/IntegrationTests2/targets/simple/q/Q.hs +0/−0
- cabal/cabal-install/tests/IntegrationTests2/targets/simple/q/q.cabal +1/−0
- cabal/cabal-install/tests/UnitTests.hs +7/−7
- cabal/cabal-install/tests/UnitTests/Distribution/Client/ArbitraryInstances.hs +320/−125
- cabal/cabal-install/tests/UnitTests/Distribution/Client/BuildReport.hs +32/−0
- cabal/cabal-install/tests/UnitTests/Distribution/Client/Described.hs +37/−0
- cabal/cabal-install/tests/UnitTests/Distribution/Client/DescribedInstances.hs +316/−0
- cabal/cabal-install/tests/UnitTests/Distribution/Client/FileMonitor.hs +23/−12
- cabal/cabal-install/tests/UnitTests/Distribution/Client/GZipUtils.hs +5/−6
- cabal/cabal-install/tests/UnitTests/Distribution/Client/GenericInstances.hs +0/−10
- cabal/cabal-install/tests/UnitTests/Distribution/Client/Get.hs +9/−9
- cabal/cabal-install/tests/UnitTests/Distribution/Client/Glob.hs +24/−112
- cabal/cabal-install/tests/UnitTests/Distribution/Client/IndexUtils/Timestamp.hs +10/−9
- cabal/cabal-install/tests/UnitTests/Distribution/Client/Init/FileCreators.hs +184/−0
- cabal/cabal-install/tests/UnitTests/Distribution/Client/InstallPlan.hs +10/−8
- cabal/cabal-install/tests/UnitTests/Distribution/Client/JobControl.hs +15/−15
- cabal/cabal-install/tests/UnitTests/Distribution/Client/ProjectConfig.hs +103/−251
- cabal/cabal-install/tests/UnitTests/Distribution/Client/Sandbox.hs +0/−28
- cabal/cabal-install/tests/UnitTests/Distribution/Client/Sandbox/Timestamp.hs +0/−63
- cabal/cabal-install/tests/UnitTests/Distribution/Client/Tar.hs +9/−6
- cabal/cabal-install/tests/UnitTests/Distribution/Client/Targets.hs +10/−14
- cabal/cabal-install/tests/UnitTests/Distribution/Client/TreeDiffInstances.hs +23/−54
- cabal/cabal-install/tests/UnitTests/Distribution/Client/VCS.hs +80/−20
- cabal/cabal-install/tests/UnitTests/Distribution/Solver/Modular/DSL/TestCaseUtils.hs +9/−4
- cabal/cabal-install/tests/UnitTests/Distribution/Solver/Modular/MemoryUsage.hs +16/−11
- cabal/cabal-install/tests/UnitTests/Distribution/Solver/Modular/QuickCheck.hs +83/−50
- cabal/cabal-install/tests/UnitTests/Distribution/Solver/Modular/Solver.hs +396/−72
- cabal/cabal-testsuite/LICENSE +4/−1
- cabal/cabal-testsuite/PackageTests/Ambiguity/reexport/reexport.cabal +1/−1
- cabal/cabal-testsuite/PackageTests/Ambiguity/setup-package-import.cabal.out +0/−3
- cabal/cabal-testsuite/PackageTests/Ambiguity/setup-reexport.cabal.out +0/−4
- cabal/cabal-testsuite/PackageTests/AutoconfBadPaths/cabal.test.hs +1/−1
- cabal/cabal-testsuite/PackageTests/AutogenModules/Package/my.cabal +1/−1
- cabal/cabal-testsuite/PackageTests/AutogenModules/Package/setup.cabal.out +0/−2
- cabal/cabal-testsuite/PackageTests/AutogenModules/Package/setup.out +0/−1
- cabal/cabal-testsuite/PackageTests/AutogenModules/SrcDist/AutogenModules.cabal +5/−1
- cabal/cabal-testsuite/PackageTests/AutogenModules/SrcDist/setup.cabal.out +0/−4
- cabal/cabal-testsuite/PackageTests/AutogenModules/SrcDist/setup.out +0/−2
- cabal/cabal-testsuite/PackageTests/AutogenModules/SrcDist/setup.test.hs +4/−4
- cabal/cabal-testsuite/PackageTests/Backpack/Fail1/Fail1.cabal +1/−1
- cabal/cabal-testsuite/PackageTests/Backpack/Fail1/setup.cabal.out +0/−1
- cabal/cabal-testsuite/PackageTests/Backpack/Fail2/Fail2.cabal +1/−1
- cabal/cabal-testsuite/PackageTests/Backpack/Fail2/setup.cabal.out +1/−2
- cabal/cabal-testsuite/PackageTests/Backpack/Fail2/setup.out +1/−1
- cabal/cabal-testsuite/PackageTests/Backpack/Fail3/Fail3.cabal +1/−1
- cabal/cabal-testsuite/PackageTests/Backpack/Fail3/setup.cabal.out +0/−1
- cabal/cabal-testsuite/PackageTests/Backpack/Includes1/Includes1.cabal +1/−1
- cabal/cabal-testsuite/PackageTests/Backpack/Includes1/setup.cabal.out +0/−1
- cabal/cabal-testsuite/PackageTests/Backpack/Includes2/Includes2.cabal +1/−1
- cabal/cabal-testsuite/PackageTests/Backpack/Includes2/Includes2.cabal.fail +1/−1
- cabal/cabal-testsuite/PackageTests/Backpack/Includes2/cabal-internal.out +2/−2
- cabal/cabal-testsuite/PackageTests/Backpack/Includes2/exe/exe.cabal +1/−1
- cabal/cabal-testsuite/PackageTests/Backpack/Includes2/mylib/mylib.cabal +1/−1
- cabal/cabal-testsuite/PackageTests/Backpack/Includes2/mysql/mysql.cabal +1/−1
- cabal/cabal-testsuite/PackageTests/Backpack/Includes2/postgresql/postgresql.cabal +1/−1
- cabal/cabal-testsuite/PackageTests/Backpack/Includes2/setup-external.cabal.out +0/−15
- cabal/cabal-testsuite/PackageTests/Backpack/Includes2/setup-internal-fail.cabal.out +0/−1
- cabal/cabal-testsuite/PackageTests/Backpack/Includes2/setup-internal.cabal.out +0/−1
- cabal/cabal-testsuite/PackageTests/Backpack/Includes2/src/src.cabal +1/−1
- cabal/cabal-testsuite/PackageTests/Backpack/Includes3/Includes3.cabal +1/−1
- cabal/cabal-testsuite/PackageTests/Backpack/Includes3/repo/exe-0.1.0.0/exe.cabal +1/−1
- cabal/cabal-testsuite/PackageTests/Backpack/Includes3/repo/indef-0.1.0.0/indef.cabal +1/−1
- cabal/cabal-testsuite/PackageTests/Backpack/Includes3/repo/sigs-0.1.0.0/sigs.cabal +1/−1
- cabal/cabal-testsuite/PackageTests/Backpack/Includes3/setup-external-fail.cabal.out +0/−2
- cabal/cabal-testsuite/PackageTests/Backpack/Includes3/setup-external-ok.cabal.out +0/−5
- cabal/cabal-testsuite/PackageTests/Backpack/Includes3/setup-internal.cabal.out +0/−1
- cabal/cabal-testsuite/PackageTests/Backpack/Includes3/setup-internal.test.hs +1/−1
- cabal/cabal-testsuite/PackageTests/Backpack/Includes4/Includes4.cabal +1/−1
- cabal/cabal-testsuite/PackageTests/Backpack/Includes4/setup.cabal.out +0/−1
- cabal/cabal-testsuite/PackageTests/Backpack/Includes5/Includes5.cabal +1/−1
- cabal/cabal-testsuite/PackageTests/Backpack/Includes5/setup.cabal.out +0/−1
- cabal/cabal-testsuite/PackageTests/Backpack/Indef1/Indef1.cabal +1/−1
- cabal/cabal-testsuite/PackageTests/Backpack/Indef2/Indef2.cabal +1/−1
- cabal/cabal-testsuite/PackageTests/Backpack/Indef2/setup.cabal.out +0/−1
- cabal/cabal-testsuite/PackageTests/Backpack/Reexport1/p/p.cabal +1/−1
- cabal/cabal-testsuite/PackageTests/Backpack/Reexport1/setup.cabal.out +0/−2
- cabal/cabal-testsuite/PackageTests/Backpack/Reexport2/Reexport2.cabal +1/−1
- cabal/cabal-testsuite/PackageTests/Backpack/Reexport2/setup.cabal.out +0/−1
- cabal/cabal-testsuite/PackageTests/Backpack/T4447/T4447.cabal +1/−1
- cabal/cabal-testsuite/PackageTests/Backpack/T4447/setup.cabal.out +0/−1
- cabal/cabal-testsuite/PackageTests/Backpack/T4754/p.cabal +3/−1
- cabal/cabal-testsuite/PackageTests/Backpack/T4754/setup.cabal.out +0/−2
- cabal/cabal-testsuite/PackageTests/Backpack/T4754/setup.out +0/−1
- cabal/cabal-testsuite/PackageTests/Backpack/T5634/T5634.cabal +4/−1
- cabal/cabal-testsuite/PackageTests/Backpack/T5634/setup.cabal.out +0/−2
- cabal/cabal-testsuite/PackageTests/Backpack/T5634/setup.out +0/−1
- cabal/cabal-testsuite/PackageTests/Backpack/TemplateHaskell/bkpth.cabal +1/−1
- cabal/cabal-testsuite/PackageTests/Backpack/TemplateHaskell/setup.cabal.out +0/−1
- cabal/cabal-testsuite/PackageTests/BenchmarkExeV10/my.cabal +3/−1
- cabal/cabal-testsuite/PackageTests/BenchmarkExeV10/setup.cabal.out +0/−1
- cabal/cabal-testsuite/PackageTests/BenchmarkOptions/BenchmarkOptions.cabal +3/−1
- cabal/cabal-testsuite/PackageTests/BenchmarkOptions/setup.cabal.out +0/−5
- cabal/cabal-testsuite/PackageTests/BenchmarkStanza/my.cabal +2/−0
- cabal/cabal-testsuite/PackageTests/BenchmarkStanza/setup.cabal.out +0/−2
- cabal/cabal-testsuite/PackageTests/BenchmarkStanza/setup.out +0/−1
- cabal/cabal-testsuite/PackageTests/BuildDeps/DepCycle/setup.cabal.out +2/−3
- cabal/cabal-testsuite/PackageTests/BuildDeps/DepCycle/setup.out +2/−2
- cabal/cabal-testsuite/PackageTests/BuildDeps/InternalLibrary0/setup.cabal.out +0/−1
- cabal/cabal-testsuite/PackageTests/BuildDeps/InternalLibrary1/cabal.out +4/−1
- cabal/cabal-testsuite/PackageTests/BuildDeps/InternalLibrary1/my.cabal +1/−1
- cabal/cabal-testsuite/PackageTests/BuildDeps/InternalLibrary1/setup.cabal.out +0/−1
- cabal/cabal-testsuite/PackageTests/BuildDeps/InternalLibrary2/setup.cabal.out +0/−2
- cabal/cabal-testsuite/PackageTests/BuildDeps/InternalLibrary3/setup.cabal.out +0/−2
- cabal/cabal-testsuite/PackageTests/BuildDeps/SameDepsAllRound/setup.cabal.out +0/−1
- cabal/cabal-testsuite/PackageTests/BuildDeps/TargetSpecificDeps1/setup.cabal.out +0/−1
- cabal/cabal-testsuite/PackageTests/BuildDeps/TargetSpecificDeps2/setup.cabal.out +0/−1
- cabal/cabal-testsuite/PackageTests/BuildDeps/TargetSpecificDeps3/setup.cabal.out +0/−1
- cabal/cabal-testsuite/PackageTests/BuildTargetErrors/BuildTargetErrors.cabal +3/−1
- cabal/cabal-testsuite/PackageTests/BuildToolDependsInternalMissing/setup.cabal.out +0/−1
- cabal/cabal-testsuite/PackageTests/BuildTools/Foreign/setup.cabal.out +0/−1
- cabal/cabal-testsuite/PackageTests/BuildTools/Internal/cabal.out +1/−1
- cabal/cabal-testsuite/PackageTests/BuildTools/Internal/setup.cabal.out +0/−1
- cabal/cabal-testsuite/PackageTests/CMain/my.cabal +2/−1
- cabal/cabal-testsuite/PackageTests/CMain/setup.cabal.out +0/−1
- cabal/cabal-testsuite/PackageTests/COnlyMain/my.cabal +1/−1
- cabal/cabal-testsuite/PackageTests/COnlyMain/setup.cabal.out +0/−1
- cabal/cabal-testsuite/PackageTests/CabalMacros/Mdl.hs +5/−0
- cabal/cabal-testsuite/PackageTests/CabalMacros/my.cabal +16/−0
- cabal/cabal-testsuite/PackageTests/CabalMacros/setup.cabal.out +15/−0
- cabal/cabal-testsuite/PackageTests/CabalMacros/setup.out +15/−0
- cabal/cabal-testsuite/PackageTests/CabalMacros/setup.test.hs +18/−0
- cabal/cabal-testsuite/PackageTests/CaretOperator/my.cabal +1/−1
- cabal/cabal-testsuite/PackageTests/Check/DifferentGhcOptions/cabal.out +1/−1
- cabal/cabal-testsuite/PackageTests/CmmSources/cabal.out +13/−0
- cabal/cabal-testsuite/PackageTests/CmmSources/cabal.project +1/−0
- cabal/cabal-testsuite/PackageTests/CmmSources/cabal.test.hs +6/−0
- cabal/cabal-testsuite/PackageTests/CmmSources/cbits/HeapPrim.cmm +6/−0
- cabal/cabal-testsuite/PackageTests/CmmSources/cmmexperiment.cabal +27/−0
- cabal/cabal-testsuite/PackageTests/CmmSources/demo/Main.hs +2/−0
- cabal/cabal-testsuite/PackageTests/CmmSources/setup.out +7/−0
- cabal/cabal-testsuite/PackageTests/CmmSources/setup.test.hs +7/−0
- cabal/cabal-testsuite/PackageTests/CmmSources/src/Demo.hs +37/−0
- cabal/cabal-testsuite/PackageTests/Configure/cabal.out +8/−0
- cabal/cabal-testsuite/PackageTests/Configure/cabal.project +2/−0
- cabal/cabal-testsuite/PackageTests/Configure/cabal.test.hs +10/−0
- cabal/cabal-testsuite/PackageTests/Configure/setup.test.hs +1/−1
- cabal/cabal-testsuite/PackageTests/ConfigureComponent/Exe/setup.cabal.out +0/−8
- cabal/cabal-testsuite/PackageTests/ConfigureComponent/SubLib/setup-explicit-fail.out +1/−1
- cabal/cabal-testsuite/PackageTests/ConfigureComponent/SubLib/setup-explicit.test.hs +1/−1
- cabal/cabal-testsuite/PackageTests/CopyComponent/Exe/setup.cabal.out +0/−1
- cabal/cabal-testsuite/PackageTests/CopyComponent/Lib/setup.cabal.out +0/−1
- cabal/cabal-testsuite/PackageTests/CustomDep/sandbox.out +0/−5
- cabal/cabal-testsuite/PackageTests/CustomDep/sandbox.test.hs +0/−22
- cabal/cabal-testsuite/PackageTests/CustomPlain/setup.test.hs +1/−1
- cabal/cabal-testsuite/PackageTests/CustomPreProcess/Setup.hs +14/−0
- cabal/cabal-testsuite/PackageTests/CustomPreProcess/cabal.out +2/−0
- cabal/cabal-testsuite/PackageTests/CustomPreProcess/cabal.project +2/−0
- cabal/cabal-testsuite/PackageTests/CustomPreProcess/cabal.test.hs +13/−0
- cabal/cabal-testsuite/PackageTests/CustomPreProcess/internal-preprocessor-test.cabal +3/−0
- cabal/cabal-testsuite/PackageTests/CustomPreProcess/setup.test.hs +1/−1
- cabal/cabal-testsuite/PackageTests/DeterministicAr/my.cabal +2/−1
- cabal/cabal-testsuite/PackageTests/DeterministicAr/setup-default-ar.cabal.out +0/−1
- cabal/cabal-testsuite/PackageTests/DeterministicAr/setup-old-ar-without-at-args.cabal.out +0/−1
- cabal/cabal-testsuite/PackageTests/DuplicateModuleName/setup.cabal.out +0/−9
- cabal/cabal-testsuite/PackageTests/EmptyLib/setup.cabal.out +0/−1
- cabal/cabal-testsuite/PackageTests/Exec/T4049/UseLib.c +0/−9
- cabal/cabal-testsuite/PackageTests/Exec/T4049/csrc/MyForeignLibWrapper.c +0/−23
- cabal/cabal-testsuite/PackageTests/Exec/T4049/my-foreign-lib.cabal +0/−19
- cabal/cabal-testsuite/PackageTests/Exec/T4049/sandbox.out +0/−12
- cabal/cabal-testsuite/PackageTests/Exec/T4049/sandbox.test.hs +0/−20
- cabal/cabal-testsuite/PackageTests/Exec/T4049/src/MyForeignLib/Hello.hs +0/−10
- cabal/cabal-testsuite/PackageTests/Exec/T4049/src/MyForeignLib/SomeBindings.hsc +0/−10
- cabal/cabal-testsuite/PackageTests/Exec/sandbox-ghc-pkg.out +0/−16
- cabal/cabal-testsuite/PackageTests/Exec/sandbox-ghc-pkg.test.hs +0/−12
- cabal/cabal-testsuite/PackageTests/Exec/sandbox-hc-pkg.out +0/−16
- cabal/cabal-testsuite/PackageTests/Exec/sandbox-hc-pkg.test.hs +0/−26
- cabal/cabal-testsuite/PackageTests/Exec/sandbox-path.out +0/−16
- cabal/cabal-testsuite/PackageTests/Exec/sandbox-path.test.hs +0/−8
- cabal/cabal-testsuite/PackageTests/Exec/sandbox.out +0/−16
- cabal/cabal-testsuite/PackageTests/Exec/sandbox.test.hs +0/−7
- cabal/cabal-testsuite/PackageTests/ForeignLibs/setup.test.hs +3/−2
- cabal/cabal-testsuite/PackageTests/Freeze/freeze.test.hs +0/−2
- cabal/cabal-testsuite/PackageTests/Freeze/my.cabal +4/−1
- cabal/cabal-testsuite/PackageTests/GhcPkgGuess/SameDirectory/setup.cabal.out +1/−0
- cabal/cabal-testsuite/PackageTests/GhcPkgGuess/SameDirectoryGhcVersion/setup.cabal.out +1/−0
- cabal/cabal-testsuite/PackageTests/GhcPkgGuess/SameDirectoryVersion/setup.cabal.out +1/−0
- cabal/cabal-testsuite/PackageTests/GhcPkgGuess/Symlink/setup.cabal.out +1/−0
- cabal/cabal-testsuite/PackageTests/GhcPkgGuess/SymlinkGhcVersion/setup.cabal.out +1/−0
- cabal/cabal-testsuite/PackageTests/GhcPkgGuess/SymlinkVersion/setup.cabal.out +1/−0
- cabal/cabal-testsuite/PackageTests/Haddock/my.cabal +2/−1
- cabal/cabal-testsuite/PackageTests/Haddock/setup.cabal.out +0/−1
- cabal/cabal-testsuite/PackageTests/HaddockNewline/setup.cabal.out +0/−1
- cabal/cabal-testsuite/PackageTests/InternalLibraries/Executable/foo.cabal +1/−1
- cabal/cabal-testsuite/PackageTests/InternalLibraries/Executable/setup-static.cabal.out +0/−2
- cabal/cabal-testsuite/PackageTests/InternalLibraries/Library/foolib/foolib.cabal +2/−1
- cabal/cabal-testsuite/PackageTests/InternalLibraries/Library/setup.cabal.out +0/−3
- cabal/cabal-testsuite/PackageTests/InternalLibraries/Library/setup.out +0/−1
- cabal/cabal-testsuite/PackageTests/InternalLibraries/cabal.out +2/−0
- cabal/cabal-testsuite/PackageTests/InternalLibraries/p/p.cabal +1/−1
- cabal/cabal-testsuite/PackageTests/InternalLibraries/sandbox-shadow.out +0/−18
- cabal/cabal-testsuite/PackageTests/InternalLibraries/sandbox-shadow.test.hs +0/−6
- cabal/cabal-testsuite/PackageTests/InternalLibraries/sandbox.out +0/−17
- cabal/cabal-testsuite/PackageTests/InternalLibraries/sandbox.test.hs +0/−5
- cabal/cabal-testsuite/PackageTests/InternalLibraries/setup-gen-pkg-config.cabal.out +0/−2
- cabal/cabal-testsuite/PackageTests/InternalLibraries/setup-gen-script.cabal.out +0/−2
- cabal/cabal-testsuite/PackageTests/InternalLibraries/setup.cabal.out +0/−2
- cabal/cabal-testsuite/PackageTests/InternalVersions/BuildDependsBad/setup.cabal.out +0/−8
- cabal/cabal-testsuite/PackageTests/InternalVersions/BuildDependsExtra/setup.cabal.out +0/−3
- cabal/cabal-testsuite/PackageTests/InternalVersions/BuildDependsExtra/setup.out +0/−2
- cabal/cabal-testsuite/PackageTests/InternalVersions/BuildToolDependsBad/setup.cabal.out +0/−1
- cabal/cabal-testsuite/PackageTests/InternalVersions/BuildToolDependsExtra/setup.cabal.out +0/−3
- cabal/cabal-testsuite/PackageTests/InternalVersions/BuildToolDependsExtra/setup.out +0/−2
- cabal/cabal-testsuite/PackageTests/InternalVersions/BuildToolsBad/setup.cabal.out +0/−1
- cabal/cabal-testsuite/PackageTests/InternalVersions/BuildToolsExtra/setup.cabal.out +0/−3
- cabal/cabal-testsuite/PackageTests/InternalVersions/BuildToolsExtra/setup.out +0/−2
- cabal/cabal-testsuite/PackageTests/Macros/setup.cabal.out +0/−1
- cabal/cabal-testsuite/PackageTests/Manpage/cabal.out +1/−1
- cabal/cabal-testsuite/PackageTests/Manpage/cabal.test.hs +1/−1
- cabal/cabal-testsuite/PackageTests/MultipleLibraries/Failing/cabal.out +8/−0
- cabal/cabal-testsuite/PackageTests/MultipleLibraries/Failing/cabal.project +4/−0
- cabal/cabal-testsuite/PackageTests/MultipleLibraries/Failing/cabal.test.hs +4/−0
- cabal/cabal-testsuite/PackageTests/MultipleLibraries/Failing/d/d.cabal +12/−0
- cabal/cabal-testsuite/PackageTests/MultipleLibraries/Failing/p/p.cabal +8/−0
- cabal/cabal-testsuite/PackageTests/MultipleLibraries/Successful/cabal.out +14/−0
- cabal/cabal-testsuite/PackageTests/MultipleLibraries/Successful/cabal.project +4/−0
- cabal/cabal-testsuite/PackageTests/MultipleLibraries/Successful/cabal.test.hs +4/−0
- cabal/cabal-testsuite/PackageTests/MultipleLibraries/Successful/pkg-abc/Main.hs +5/−0
- cabal/cabal-testsuite/PackageTests/MultipleLibraries/Successful/pkg-abc/pkg-abc.cabal +10/−0
- cabal/cabal-testsuite/PackageTests/MultipleLibraries/Successful/pkg-def/pkg-def.cabal +14/−0
- cabal/cabal-testsuite/PackageTests/MultipleLibraries/Successful/pkg-def/publib/PkgDef.hs +4/−0
- cabal/cabal-testsuite/PackageTests/MultipleLibraries/Successful/pkg-def/src/PkgDef.hs +4/−0
- cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083Post/cabal.out +15/−0
- cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083Post/cabal.project +4/−0
- cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083Post/cabal.test.hs +6/−0
- cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083Post/pkg-abc/exe/Main.hs +5/−0
- cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083Post/pkg-abc/pkg-abc.cabal +19/−0
- cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083Post/pkg-abc/pkg-def/PkgDef.hs +4/−0
- cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083Post/pkg-def/pkg-def.cabal +17/−0
- cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083Post/pkg-def/publib/PkgDef.hs +4/−0
- cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083Post/pkg-def/src/PkgDef.hs +4/−0
- cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083PostMixin/cabal.out +16/−0
- cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083PostMixin/cabal.project +4/−0
- cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083PostMixin/cabal.test.hs +6/−0
- cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083PostMixin/pkg-abc/exe/Main.hs +5/−0
- cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083PostMixin/pkg-abc/pkg-abc.cabal +20/−0
- cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083PostMixin/pkg-abc/pkg-def/PkgDef.hs +4/−0
- cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083PostMixin/pkg-def/pkg-def.cabal +17/−0
- cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083PostMixin/pkg-def/publib/PkgDef.hs +4/−0
- cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083PostMixin/pkg-def/src/PkgDef.hs +4/−0
- cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083Pre/cabal.out +14/−0
- cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083Pre/cabal.project +4/−0
- cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083Pre/cabal.test.hs +6/−0
- cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083Pre/pkg-abc/exe/Main.hs +5/−0
- cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083Pre/pkg-abc/pkg-abc.cabal +19/−0
- cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083Pre/pkg-abc/pkg-def/PkgDef.hs +4/−0
- cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083Pre/pkg-def/pkg-def.cabal +17/−0
- cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083Pre/pkg-def/publib/PkgDef.hs +4/−0
- cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083Pre/pkg-def/src/PkgDef.hs +4/−0
- cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083PreMixin/cabal.out +14/−0
- cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083PreMixin/cabal.project +4/−0
- cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083PreMixin/cabal.test.hs +6/−0
- cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083PreMixin/pkg-abc/exe/Main.hs +5/−0
- cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083PreMixin/pkg-abc/pkg-abc.cabal +20/−0
- cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083PreMixin/pkg-abc/pkg-def/PkgDef.hs +4/−0
- cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083PreMixin/pkg-def/pkg-def.cabal +17/−0
- cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083PreMixin/pkg-def/publib/PkgDef.hs +4/−0
- cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083PreMixin/pkg-def/src/PkgDef.hs +4/−0
- cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6894/Bar.hs +1/−0
- cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6894/Foo.hs +1/−0
- cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6894/cabal.out +15/−0
- cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6894/cabal.project +1/−0
- cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6894/cabal.test.hs +3/−0
- cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6894/issue.cabal +13/−0
- cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6894/setup.cabal.out +8/−0
- cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6894/setup.out +8/−0
- cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6894/setup.test.hs +3/−0
- cabal/cabal-testsuite/PackageTests/MultipleLibraries/cabal.out +0/−12
- cabal/cabal-testsuite/PackageTests/MultipleLibraries/cabal.project +0/−4
- cabal/cabal-testsuite/PackageTests/MultipleLibraries/cabal.test.hs +0/−4
- cabal/cabal-testsuite/PackageTests/MultipleLibraries/d/d.cabal +0/−12
- cabal/cabal-testsuite/PackageTests/MultipleLibraries/p/p.cabal +0/−8
- cabal/cabal-testsuite/PackageTests/NewBuild/CmdRun/Script/script.hs +11/−11
- cabal/cabal-testsuite/PackageTests/NewConfigure/LocalConfigOverwrite/cabal.out +26/−1
- cabal/cabal-testsuite/PackageTests/NewConfigure/LocalConfigOverwrite/cabal.test.hs +17/−2
- cabal/cabal-testsuite/PackageTests/NewConfigure/LocalConfigOverwrite/foo.project +1/−0
- cabal/cabal-testsuite/PackageTests/NewConfigure/LocalConfigOverwrite/foo.project.local +0/−0
- cabal/cabal-testsuite/PackageTests/NewSdist/DeterministicTrivial/deterministic.test.hs +7/−1
- cabal/cabal-testsuite/PackageTests/OrderFlags/my.cabal +2/−1
- cabal/cabal-testsuite/PackageTests/OrderFlags/setup.cabal.out +0/−1
- cabal/cabal-testsuite/PackageTests/Outdated/my.cabal +3/−1
- cabal/cabal-testsuite/PackageTests/PathsModule/Executable/setup.cabal.out +0/−1
- cabal/cabal-testsuite/PackageTests/PathsModule/Library/my.cabal +1/−1
- cabal/cabal-testsuite/PackageTests/PathsModule/Library/setup.cabal.out +0/−1
- cabal/cabal-testsuite/PackageTests/PreProcess/setup.cabal.out +0/−1
- cabal/cabal-testsuite/PackageTests/PreProcessExtraSources/setup.cabal.out +0/−1
- cabal/cabal-testsuite/PackageTests/QuasiQuotes/dynamic/setup.cabal.out +0/−1
- cabal/cabal-testsuite/PackageTests/QuasiQuotes/profiling/setup.cabal.out +0/−1
- cabal/cabal-testsuite/PackageTests/QuasiQuotes/vanilla/setup.cabal.out +0/−1
- cabal/cabal-testsuite/PackageTests/ReexportedModules/p/p.cabal +1/−1
- cabal/cabal-testsuite/PackageTests/ReexportedModules/p/p.cabal.fail-ambiguous +1/−1
- cabal/cabal-testsuite/PackageTests/ReexportedModules/p/p.cabal.fail-missing +1/−1
- cabal/cabal-testsuite/PackageTests/ReexportedModules/p/p.cabal.fail-other +1/−1
- cabal/cabal-testsuite/PackageTests/ReexportedModules/setup-fail-ambiguous.cabal.out +0/−2
- cabal/cabal-testsuite/PackageTests/ReexportedModules/setup-fail-missing.cabal.out +0/−1
- cabal/cabal-testsuite/PackageTests/ReexportedModules/setup-fail-other.cabal.out +0/−1
- cabal/cabal-testsuite/PackageTests/ReexportedModules/setup.cabal.out +0/−2
- cabal/cabal-testsuite/PackageTests/Regression/T2755/setup.cabal.out +1/−2
- cabal/cabal-testsuite/PackageTests/Regression/T2971/setup.cabal.out +0/−2
- cabal/cabal-testsuite/PackageTests/Regression/T2971a/setup.cabal.out +0/−1
- cabal/cabal-testsuite/PackageTests/Regression/T3199/Cabal/Cabal.cabal +0/−8
- cabal/cabal-testsuite/PackageTests/Regression/T3199/Main.hs +0/−4
- cabal/cabal-testsuite/PackageTests/Regression/T3199/Setup.hs +0/−2
- cabal/cabal-testsuite/PackageTests/Regression/T3199/sandbox.out +0/−8
- cabal/cabal-testsuite/PackageTests/Regression/T3199/sandbox.test.hs +0/−11
- cabal/cabal-testsuite/PackageTests/Regression/T3199/test-3199.cabal +0/−27
- cabal/cabal-testsuite/PackageTests/Regression/T3294/setup.cabal.out +0/−1
- cabal/cabal-testsuite/PackageTests/Regression/T3436/Cabal-1.2/Cabal.cabal +0/−8
- cabal/cabal-testsuite/PackageTests/Regression/T3436/Cabal-1.2/CabalMessage.hs +0/−3
- cabal/cabal-testsuite/PackageTests/Regression/T3436/Cabal-2.0/Cabal.cabal +0/−8
- cabal/cabal-testsuite/PackageTests/Regression/T3436/Cabal-2.0/CabalMessage.hs +0/−3
- cabal/cabal-testsuite/PackageTests/Regression/T3436/cabal.out +0/−9
- cabal/cabal-testsuite/PackageTests/Regression/T3436/cabal.project +0/−1
- cabal/cabal-testsuite/PackageTests/Regression/T3436/custom-setup/Setup.hs +0/−5
- cabal/cabal-testsuite/PackageTests/Regression/T3436/custom-setup/custom-setup.cabal +0/−9
- cabal/cabal-testsuite/PackageTests/Regression/T3436/sandbox.out +0/−22
- cabal/cabal-testsuite/PackageTests/Regression/T3436/sandbox.test.hs +0/−21
- cabal/cabal-testsuite/PackageTests/Regression/T3847/T3847.cabal +3/−1
- cabal/cabal-testsuite/PackageTests/Regression/T3847/setup.cabal.out +0/−1
- cabal/cabal-testsuite/PackageTests/Regression/T4025/T4025.cabal +2/−0
- cabal/cabal-testsuite/PackageTests/Regression/T4025/setup.cabal.out +0/−2
- cabal/cabal-testsuite/PackageTests/Regression/T4025/setup.out +0/−1
- cabal/cabal-testsuite/PackageTests/Regression/T4270/T4270.cabal +3/−1
- cabal/cabal-testsuite/PackageTests/Regression/T4270/setup.cabal.out +0/−5
- cabal/cabal-testsuite/PackageTests/Regression/T4291/dependee/dependee.cabal +1/−1
- cabal/cabal-testsuite/PackageTests/Regression/T4291/depender/depender.cabal +1/−1
- cabal/cabal-testsuite/PackageTests/Regression/T4291/setup.cabal.out +0/−2
- cabal/cabal-testsuite/PackageTests/Regression/T4449/setup.out +0/−1
- cabal/cabal-testsuite/PackageTests/Regression/T5309/cabal.out +3/−3
- cabal/cabal-testsuite/PackageTests/Regression/T5309/memoized-tcm/costMatrix.h +1/−1
- cabal/cabal-testsuite/PackageTests/Regression/T5318/sdist-list-sources.out +2/−3
- cabal/cabal-testsuite/PackageTests/Regression/T5318/sdist-list-sources.test.hs +2/−2
- cabal/cabal-testsuite/PackageTests/Regression/T5677/cabal.out +1/−1
- cabal/cabal-testsuite/PackageTests/Regression/T5677/prog/prog.cabal +1/−1
- cabal/cabal-testsuite/PackageTests/Regression/T5677/prog/prog.hs +0/−5
- cabal/cabal-testsuite/PackageTests/Regression/T5677/prog/program.hs +5/−0
- cabal/cabal-testsuite/PackageTests/Regression/T6125/setup.cabal.out +0/−1
- cabal/cabal-testsuite/PackageTests/Regression/T6853/cabal.out +8/−0
- cabal/cabal-testsuite/PackageTests/Regression/T6853/cabal.project +1/−0
- cabal/cabal-testsuite/PackageTests/Regression/T6853/cabal.test.hs +3/−0
- cabal/cabal-testsuite/PackageTests/Regression/T6853/pkg-foo/Foo.hs +1/−0
- cabal/cabal-testsuite/PackageTests/Regression/T6853/pkg-foo/pkg-foo.cabal +17/−0
- cabal/cabal-testsuite/PackageTests/ReplCSources/Lib.hs +5/−0
- cabal/cabal-testsuite/PackageTests/ReplCSources/cabal-csrc-repl.cabal +8/−0
- cabal/cabal-testsuite/PackageTests/ReplCSources/cabal.out +2/−0
- cabal/cabal-testsuite/PackageTests/ReplCSources/cabal.project +1/−0
- cabal/cabal-testsuite/PackageTests/ReplCSources/cabal.test.hs +9/−0
- cabal/cabal-testsuite/PackageTests/ReplCSources/foo.c +1/−0
- cabal/cabal-testsuite/PackageTests/SDist/T5195/cabal.out +1/−1
- cabal/cabal-testsuite/PackageTests/SDist/T5195/cabal.test.hs +1/−2
- cabal/cabal-testsuite/PackageTests/SPDX/cabal-old-build.cabal.out +0/−1
- cabal/cabal-testsuite/PackageTests/SPDX/cabal-old-build.test.hs +0/−3
- cabal/cabal-testsuite/PackageTests/SPDX/my.cabal +1/−1
- cabal/cabal-testsuite/PackageTests/Sandbox/MultipleSources/cabal.out +0/−12
- cabal/cabal-testsuite/PackageTests/Sandbox/MultipleSources/cabal.test.hs +0/−6
- cabal/cabal-testsuite/PackageTests/Sandbox/MultipleSources/p/LICENSE +0/−0
- cabal/cabal-testsuite/PackageTests/Sandbox/MultipleSources/p/Setup.hs +0/−2
- cabal/cabal-testsuite/PackageTests/Sandbox/MultipleSources/p/p.cabal +0/−11
- cabal/cabal-testsuite/PackageTests/Sandbox/MultipleSources/q/LICENSE +0/−0
- cabal/cabal-testsuite/PackageTests/Sandbox/MultipleSources/q/Setup.hs +0/−2
- cabal/cabal-testsuite/PackageTests/Sandbox/MultipleSources/q/q.cabal +0/−11
- cabal/cabal-testsuite/PackageTests/Sandbox/Reinstall/p/Main.hs +0/−7
- cabal/cabal-testsuite/PackageTests/Sandbox/Reinstall/p/p.cabal +0/−8
- cabal/cabal-testsuite/PackageTests/Sandbox/Reinstall/q/Q.hs +0/−4
- cabal/cabal-testsuite/PackageTests/Sandbox/Reinstall/q/Q.hs.in2 +0/−4
- cabal/cabal-testsuite/PackageTests/Sandbox/Reinstall/q/q.cabal +0/−8
- cabal/cabal-testsuite/PackageTests/Sandbox/Reinstall/sandbox.out +0/−15
- cabal/cabal-testsuite/PackageTests/Sandbox/Reinstall/sandbox.test.hs +0/−9
- cabal/cabal-testsuite/PackageTests/Sandbox/Sources/p/LICENSE +0/−0
- cabal/cabal-testsuite/PackageTests/Sandbox/Sources/p/Setup.hs +0/−2
- cabal/cabal-testsuite/PackageTests/Sandbox/Sources/p/p.cabal +0/−11
- cabal/cabal-testsuite/PackageTests/Sandbox/Sources/q/LICENSE +0/−0
- cabal/cabal-testsuite/PackageTests/Sandbox/Sources/q/Setup.hs +0/−2
- cabal/cabal-testsuite/PackageTests/Sandbox/Sources/q/q.cabal +0/−11
- cabal/cabal-testsuite/PackageTests/Sandbox/Sources/sandbox.out +0/−15
- cabal/cabal-testsuite/PackageTests/Sandbox/Sources/sandbox.test.hs +0/−7
- cabal/cabal-testsuite/PackageTests/SimpleDefault/my.cabal +1/−1
- cabal/cabal-testsuite/PackageTests/TemplateHaskell/dynamic/setup.cabal.out +0/−1
- cabal/cabal-testsuite/PackageTests/TemplateHaskell/profiling/setup.cabal.out +0/−1
- cabal/cabal-testsuite/PackageTests/TemplateHaskell/vanilla/setup.cabal.out +0/−1
- cabal/cabal-testsuite/PackageTests/TestNameCollision/setup.cabal.out +0/−6
- cabal/cabal-testsuite/PackageTests/TestOptions/TestOptions.cabal +3/−1
- cabal/cabal-testsuite/PackageTests/TestOptions/setup.cabal.out +0/−5
- cabal/cabal-testsuite/PackageTests/TestStanza/setup.cabal.out +0/−1
- cabal/cabal-testsuite/PackageTests/TestSuiteTests/ExeV10/cabal.out +2/−2
- cabal/cabal-testsuite/PackageTests/TestSuiteTests/ExeV10/my.cabal +4/−1
- cabal/cabal-testsuite/PackageTests/TestSuiteTests/ExeV10/setup-no-markup.cabal.out +0/−5
- cabal/cabal-testsuite/PackageTests/TestSuiteTests/ExeV10/setup-no-tix.cabal.out +0/−5
- cabal/cabal-testsuite/PackageTests/TestSuiteTests/LibV09/LibV09.cabal +3/−1
- cabal/cabal-testsuite/PackageTests/TestSuiteTests/LibV09/setup-deadlock.cabal.out +0/−5
- cabal/cabal-testsuite/PackageTests/TestSuiteTests/LibV09/setup.cabal.out +0/−1
- cabal/cabal-testsuite/PackageTests/UniqueIPID/setup.cabal.out +0/−2
- cabal/cabal-testsuite/Test/Cabal/CheckArMetadata.hs +0/−87
- cabal/cabal-testsuite/Test/Cabal/Monad.hs +0/−677
- cabal/cabal-testsuite/Test/Cabal/Plan.hs +0/−88
- cabal/cabal-testsuite/Test/Cabal/Prelude.hs +0/−1028
- cabal/cabal-testsuite/Test/Cabal/Run.hs +0/−72
- cabal/cabal-testsuite/Test/Cabal/Script.hs +0/−97
- cabal/cabal-testsuite/Test/Cabal/Server.hs +0/−443
- cabal/cabal-testsuite/Test/Cabal/Workdir.hs +0/−30
- cabal/cabal-testsuite/cabal-testsuite.cabal +19/−13
- cabal/cabal-testsuite/main/cabal-tests.hs +1/−1
- cabal/cabal-testsuite/src/Test/Cabal/CheckArMetadata.hs +87/−0
- cabal/cabal-testsuite/src/Test/Cabal/Monad.hs +614/−0
- cabal/cabal-testsuite/src/Test/Cabal/OutputNormalizer.hs +79/−0
- cabal/cabal-testsuite/src/Test/Cabal/Plan.hs +88/−0
- cabal/cabal-testsuite/src/Test/Cabal/Prelude.hs +994/−0
- cabal/cabal-testsuite/src/Test/Cabal/Run.hs +83/−0
- cabal/cabal-testsuite/src/Test/Cabal/Script.hs +97/−0
- cabal/cabal-testsuite/src/Test/Cabal/Server.hs +443/−0
- cabal/cabal-testsuite/src/Test/Cabal/Workdir.hs +30/−0
- cabal/cabal.project +5/−0
- cabal/cabal.project.buildinfo +10/−0
- cabal/cabal.project.release +11/−0
- cabal/cabal.project.validate +10/−1
- cabal/cabal.project.validate.libonly +5/−0
- cabal/cabal.project.weeder +14/−0
- cabal/changelog.d/Cabal-QuickCheck +4/−0
- cabal/changelog.d/Cabal-tree-diff +3/−0
- cabal/changelog.d/PerCompilerFlavor-functor +3/−0
- cabal/changelog.d/active-repositories +14/−0
- cabal/changelog.d/added-tests +11/−0
- cabal/changelog.d/backported +43/−0
- cabal/changelog.d/build-reports +3/−0
- cabal/changelog.d/cabal-init +19/−0
- cabal/changelog.d/cabal-list +5/−0
- cabal/changelog.d/cabal-project-local-tilde +3/−0
- cabal/changelog.d/cabal-sdist +32/−0
- cabal/changelog.d/cabal-spec-3.4 +9/−0
- cabal/changelog.d/cabal-testsuite +8/−0
- cabal/changelog.d/cabalInstallVersion +3/−0
- cabal/changelog.d/changelog +3/−0
- cabal/changelog.d/ci +24/−0
- cabal/changelog.d/code-organization +16/−0
- cabal/changelog.d/config +2/−0
- cabal/changelog.d/copyright +2/−0
- cabal/changelog.d/dependency +16/−0
- cabal/changelog.d/described +8/−0
- cabal/changelog.d/documentation +4/−0
- cabal/changelog.d/expose-all-unfoldings +9/−0
- cabal/changelog.d/flag-assignment +3/−0
- cabal/changelog.d/ghc-8.12 +18/−0
- cabal/changelog.d/ghci-fix +8/−0
- cabal/changelog.d/help-remove-new-aliases +3/−0
- cabal/changelog.d/index-state +5/−0
- cabal/changelog.d/install-prints-destination +3/−0
- cabal/changelog.d/install-sha256 +3/−0
- cabal/changelog.d/issue-4746 +4/−0
- cabal/changelog.d/issue-5224 +4/−0
- cabal/changelog.d/issue-5555 +4/−0
- cabal/changelog.d/issue-5586 +12/−0
- cabal/changelog.d/issue-5973 +14/−0
- cabal/changelog.d/issue-6083 +23/−0
- cabal/changelog.d/issue-6210 +4/−0
- cabal/changelog.d/issue-6281 +3/−0
- cabal/changelog.d/issue-6288 +3/−0
- cabal/changelog.d/issue-6369 +4/−0
- cabal/changelog.d/issue-6393 +4/−0
- cabal/changelog.d/issue-6432 +4/−0
- cabal/changelog.d/issue-6485 +3/−0
- cabal/changelog.d/issue-6565 +13/−0
- cabal/changelog.d/issue-6575 +4/−0
- cabal/changelog.d/issue-6589 +6/−0
- cabal/changelog.d/issue-6610 +11/−0
- cabal/changelog.d/issue-6622 +4/−0
- cabal/changelog.d/issue-6691 +13/−0
- cabal/changelog.d/issue-6710 +16/−0
- cabal/changelog.d/issue-6729 +11/−0
- cabal/changelog.d/issue-6739 +3/−0
- cabal/changelog.d/issue-6804 +4/−0
- cabal/changelog.d/issue-6805 +3/−0
- cabal/changelog.d/issue-6807 +11/−0
- cabal/changelog.d/issue-6809 +4/−0
- cabal/changelog.d/issue-6856 +4/−0
- cabal/changelog.d/issue-6869 +4/−0
- cabal/changelog.d/linux-androideabi +9/−0
- cabal/changelog.d/man-command +3/−0
- cabal/changelog.d/others +10/−0
- cabal/changelog.d/parser-benchmark +2/−0
- cabal/changelog.d/pr-6878 +3/−0
- cabal/changelog.d/pr-6929 +2/−0
- cabal/changelog.d/public-libs +2/−0
- cabal/changelog.d/public-libs-solver +13/−0
- cabal/changelog.d/refactor-packagedescription-module +9/−0
- cabal/changelog.d/remove-sandbox +11/−0
- cabal/changelog.d/remove-text +11/−0
- cabal/changelog.d/rewriteFileLBS +3/−0
- cabal/changelog.d/spdx +3/−0
- cabal/changelog.d/specVersion-type +3/−0
- cabal/changelog.d/symlinking-windows +11/−0
- cabal/changelog.d/use-process-jobs +23/−0
- cabal/changelog.d/utf8 +3/−0
- cabal/changelog.d/version-range-parser +2/−0
- cabal/changelog.d/version-type +10/−0
- cabal/changelog.d/versions-exact +2/−0
- cabal/changelog.d/weeder +2/−0
- cabal/generics-sop-lens.hs +2/−2
- cabal/license-list-data/exceptions-3.9.json +466/−0
- cabal/license-list-data/licenses-3.9.json +5297/−0
- cabal/release-checklist.md +1/−0
- cabal/release-notes/Cabal-3.4.0.0.md +147/−0
- cabal/release-notes/cabal-install-3.4.0.0.md +235/−0
- cabal/solver-benchmarks/HackageBenchmark.hs +59/−18
- cabal/solver-benchmarks/LICENSE +4/−1
- cabal/solver-benchmarks/solver-benchmarks.cabal +4/−2
- cabal/tests/UnitTests/Distribution/Client/Init/goldens/generateCabalFile/exe-only.cabal +16/−0
- cabal/tests/UnitTests/Distribution/Client/Init/goldens/generateCabalFile/lib-exe-and-test.cabal +29/−0
- cabal/tests/fixtures/init/exe-only-golden.cabal +20/−0
- cabal/tests/fixtures/init/lib-and-exe-golden.cabal +31/−0
- cabal/tests/fixtures/init/lib-exe-and-test-golden.cabal +43/−0
- cabal/tests/fixtures/init/lib-exe-and-test-with-comments-golden.cabal +110/−0
- cabal/travis-common.sh +4/−4
- cabal/travis-deploy.sh +1/−1
- cabal/travis-install.sh +2/−2
- cabal/travis-meta.sh +4/−0
- cabal/travis-script.sh +4/−2
- cabal/travis/binaries/.travis.yml +2/−2
- cabal/validate.dockerfile +0/−48
- cabal/validate.sh +301/−133
- cabal/weeder.dhall +9/−0
- hackage-security/.travis.yml +60/−70
- hackage-security/example-client/example-client.cabal +2/−2
- hackage-security/hackage-repo-tool/ChangeLog.md +4/−0
- hackage-security/hackage-repo-tool/README.md +98/−0
- hackage-security/hackage-repo-tool/hackage-repo-tool.cabal +29/−23
- hackage-security/hackage-root-tool/hackage-root-tool.cabal +1/−1
- hackage-security/hackage-security-HTTP/hackage-security-HTTP.cabal +1/−1
- hackage-security/hackage-security-curl/hackage-security-curl.cabal +2/−2
- hackage-security/hackage-security-http-client/hackage-security-http-client.cabal +2/−2
- hackage-security/hackage-security/ChangeLog.md +6/−0
- hackage-security/hackage-security/hackage-security.cabal +8/−8
- hackage-security/hackage-security/src/Hackage/Security/TUF/Patterns.hs +8/−1
- hackage-security/hackage-security/src/Hackage/Security/Util/IO.hs +2/−2
- hackport.cabal +252/−15
- tests/Merge/UtilsSpec.hs +120/−0
- tests/Merge/UtilsSpec.hs~ +53/−0
- tests/Portage/CabalSpec.hs +69/−0
- tests/Portage/Dependency/PrintSpec.hs +327/−0
- tests/Portage/EBuildSpec.hs +29/−0
- tests/Portage/GHCCoreSpec.hs +23/−0
- tests/Portage/MetadataSpec.hs +80/−0
- tests/Portage/PackageIdSpec.hs +69/−0
- tests/Portage/VersionSpec.hs +27/−0
- tests/QuickCheck/Instances.hs +44/−0
- tests/Spec.hs +1/−0
- tests/doctests.hs +12/−0
+ .github/workflows/haskell.yml view
@@ -0,0 +1,45 @@+name: Haskell CI++on:+ push:+ branches: [ master ]+ pull_request:+ branches: [ master ]++jobs:+ build:++ runs-on: ubuntu-latest+ strategy:+ matrix:+ cabal: ["3.2"]+ ghc: ["8.0", "8.2", "8.4", "8.6", "8.8", "8.10"]+ steps:+ - uses: actions/checkout@v2+ with:+ submodules: 'recursive' + - uses: actions/setup-haskell@v1+ with:+ ghc-version: ${{ matrix.ghc }}+ cabal-version: ${{ matrix.cabal }}++ - name: Cache+ uses: actions/cache@v1+ env:+ cache-name: cache-cabal+ with:+ path: ~/.cabal+ key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/*.cabal') }}-${{ hashFiles('**/cabal.project') }}+ restore-keys: |+ ${{ runner.os }}-build-${{ env.cache-name }}-+ ${{ runner.os }}-build-+ ${{ runner.os }}-++ - name: Install dependencies+ run: |+ cabal update+ cabal build --only-dependencies --enable-tests --enable-benchmarks+ - name: Build+ run: cabal v2-build --enable-tests all+ - name: Run hspec tests+ run: cabal v2-test spec --test-option=--color --test-show-details=streaming
.gitignore view
@@ -3,3 +3,4 @@ cabal-dev/ .ghc.environment* cabal.project.local+report.html
AnsiColor.hs view
@@ -26,7 +26,7 @@ esc :: [String] -> String esc [] = ""-esc xs = "\ESC[" ++ (concat . intersperse ";" $ xs) ++ "m"+esc xs = "\ESC[" ++ (intercalate ";" xs) ++ "m" col :: Color -> Bool -> Color -> [String] col fg bf bg = show (fromEnum fg + 30) : bf' [show (fromEnum bg + 40)]
Cabal2Ebuild.hs view
@@ -1,16 +1,16 @@--- A program for generating a Gentoo ebuild from a .cabal file------ Author : Duncan Coutts <dcoutts@gentoo.org>------ Created: 21 July 2005------ Copyright (C) 2005 Duncan Coutts---+{-|+Module : Cabal2Ebuild+Copyright : (C) 2005, Duncan Coutts+License : GPL-2++Maintainer : haskell@gentoo.org++A program for generating a Gentoo ebuild from a .cabal file+-} -- This library is free software; you can redistribute it and/or -- modify it under the terms of the GNU General Public License -- as published by the Free Software Foundation; either version 2 -- of the License, or (at your option) any later version.---+ -- This library is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU@@ -22,14 +22,17 @@ ,convertDependency) where import qualified Distribution.PackageDescription as Cabal- (PackageDescription(..), license)-import qualified Distribution.Package as Cabal (PackageIdentifier(..)+ ( PackageDescription(..), license)+import qualified Distribution.Package as Cabal ( PackageIdentifier(..) , Dependency(..))-import qualified Distribution.Version as Cabal (VersionRange, cataVersionRange, normaliseVersionRange- , wildcardUpperBound, majorUpperBound)+import qualified Distribution.Version as Cabal ( VersionRange+ , cataVersionRange, normaliseVersionRange+ , majorUpperBound, mkVersion ) import Distribution.Version (VersionRangeF(..)) import Distribution.Pretty (prettyShow) +import qualified Distribution.Utils.ShortText as ST+ import Data.Char (isUpper) import Data.Maybe @@ -43,16 +46,19 @@ import qualified Portage.Overlay as O import Portage.Version +-- | Generate a 'Portage.EBuild' from a 'Portage.Category' and a 'Cabal.PackageDescription'. cabal2ebuild :: Portage.Category -> Cabal.PackageDescription -> Portage.EBuild cabal2ebuild cat pkg = Portage.ebuildTemplate { E.name = Portage.cabal_pn_to_PN cabal_pn, E.category = prettyShow cat, E.hackage_name= cabalPkgName, E.version = prettyShow (Cabal.pkgVersion (Cabal.package pkg)),- E.description = if null (Cabal.synopsis pkg) then Cabal.description pkg- else Cabal.synopsis pkg,- E.long_desc = if null (Cabal.description pkg) then Cabal.synopsis pkg- else Cabal.description pkg,+ E.description = ST.fromShortText $ if ST.null (Cabal.synopsis pkg)+ then Cabal.description pkg+ else Cabal.synopsis pkg,+ E.long_desc = ST.fromShortText $ if ST.null (Cabal.description pkg)+ then Cabal.synopsis pkg+ else Cabal.description pkg, E.homepage = thisHomepage, E.license = Portage.convertLicense $ Cabal.license pkg, E.slot = (E.slot E.ebuildTemplate) ++ (if hasLibs then "/${PV}" else ""),@@ -74,13 +80,15 @@ cabalPkgName = prettyShow cabal_pn hasLibs = isJust (Cabal.library pkg) hasTests = (not . null) (Cabal.testSuites pkg)- thisHomepage = if (null $ Cabal.homepage pkg)+ thisHomepage = if (ST.null $ Cabal.homepage pkg) then E.homepage E.ebuildTemplate- else Cabal.homepage pkg+ else ST.fromShortText $ Cabal.homepage pkg +-- | Map 'convertDependency' over ['Cabal.Dependency']. convertDependencies :: O.Overlay -> Portage.Category -> [Cabal.Dependency] -> [Dependency] convertDependencies overlay category = map (convertDependency overlay category) +-- | Convert 'Cabal.Dependency' into 'Dependency'. convertDependency :: O.Overlay -> Portage.Category -> Cabal.Dependency -> Dependency convertDependency overlay category (Cabal.Dependency pname versionRange _lib) = convert versionRange@@ -95,16 +103,15 @@ convert :: Cabal.VersionRange -> Dependency convert = Cabal.cataVersionRange alg . Cabal.normaliseVersionRange where- alg AnyVersionF = mk_p $ DRange ZeroB InfinityB alg (ThisVersionF v) = mk_p $ DExact $ p_v v alg (LaterVersionF v) = mk_p $ DRange (StrictLB $ p_v v) InfinityB alg (EarlierVersionF v) = mk_p $ DRange ZeroB $ StrictUB $ p_v v- alg (OrLaterVersionF v) = mk_p $ DRange (NonstrictLB $ p_v v) InfinityB+ alg (OrLaterVersionF v) = if v == Cabal.mkVersion [0] -- any version+ then mk_p $ DRange ZeroB InfinityB+ else mk_p $ DRange (NonstrictLB $ p_v v)+ InfinityB alg (OrEarlierVersionF v) = mk_p $ DRange ZeroB $ NonstrictUB $ p_v v- alg (WildcardVersionF v) = mk_p $ DRange (NonstrictLB $ p_v v)- $ StrictUB $ p_v $ Cabal.wildcardUpperBound v alg (MajorBoundVersionF v) = mk_p $ DRange (NonstrictLB $ p_v v) $ StrictUB $ p_v $ Cabal.majorUpperBound v alg (UnionVersionRangesF v1 v2) = DependAnyOf [v1, v2] alg (IntersectVersionRangesF v1 v2) = DependAllOf [v1, v2]- alg (VersionRangeParensF v) = v
Error.hs view
@@ -5,6 +5,7 @@ import Data.Typeable import Control.Exception.Extensible as EE +-- | Type holding all of the 'HackPortError' constructors. data HackPortError = ArgumentError String | ConnectionFailed String String@@ -26,16 +27,22 @@ -- | WrongCacheVersion -- | InvalidCache | InvalidServer String- deriving (Typeable, Show)+ deriving (Typeable+ , Show+ , Eq -- ^ needed for spec test-suite+ ) instance Exception HackPortError where +-- | Throw a 'HackPortError'. throwEx :: HackPortError -> IO a throwEx = EE.throw +-- | Catch a 'HackPortError'. catchEx :: IO a -> (HackPortError -> IO a) -> IO a catchEx = EE.catch +-- | Show the error string for a given 'HackPortError'. hackPortShowError :: HackPortError -> String hackPortShowError err = case err of ArgumentError str -> "Argument error: "++str
HACKING.rst view
@@ -140,8 +140,9 @@ The ``-s`` option signs the tag with your GnuPG key, if you wish to do this. -Next, run the ‘mk_release_tarball.bash’ script. ``cabal sdist`` does not-build the submodules, which is why we need to use this script instead.+Next, run the ‘mk_release_tarball.bash’ script. This is similar to ``cabal sdist``+except that it also strips out unnecessary files and creates a tarball+from the latest tag rather than ``HEAD``. Assuming everything builds correctly and you are a designated ``HackPort`` maintainer on Hackage, you can publish the ``HackPort``@@ -163,6 +164,3 @@ - Include section explaining how to determine and add the list of bundled libraries for a given GHC version to ``HackPort``.-- -
HackPort/GlobalFlags.hs view
@@ -17,6 +17,7 @@ import qualified Overlays +-- | Type containing global flags. data GlobalFlags = GlobalFlags { globalVersion :: DSS.Flag Bool , globalNumericVersion :: DSS.Flag Bool@@ -24,6 +25,7 @@ , globalPathToPortage :: DSS.Flag (Maybe FilePath) } +-- | Default 'GlobalFlags'. defaultGlobalFlags :: GlobalFlags defaultGlobalFlags = GlobalFlags { globalVersion = DSS.Flag False@@ -32,8 +34,9 @@ , globalPathToPortage = DSS.Flag Nothing } +-- | Default remote repository. Defaults to [hackage](hackage.haskell.org). defaultRemoteRepo :: DCT.RemoteRepo-defaultRemoteRepo = DCC.addInfoForKnownRepos $ (DCT.emptyRemoteRepo name) { DCT.remoteRepoURI = uri }+defaultRemoteRepo = DCC.addInfoForKnownRepos $ (DCT.emptyRemoteRepo (DCT.RepoName name)) { DCT.remoteRepoURI = uri } where Just uri = NU.parseURI "https://hackage.haskell.org/" name = "hackage.haskell.org"
Main.hs view
@@ -116,7 +116,7 @@ overlay <- Overlay.loadLazy overlayPath let pkgs | null extraArgs = CabalInstall.allPackages index | otherwise = concatMap (concatMap snd . CabalInstall.searchByNameSubstring index) extraArgs- normalized = map (normalizeCabalPackageId . CabalInstall.packageInfoId) pkgs+ normalized = map (normalizeCabalPackageId . CabalInstall.srcpkgPackageId) pkgs let decorated = map (\p -> (Overlay.inOverlay overlay p, p)) normalized mapM_ (putStrLn . pretty) decorated where
Merge.hs view
@@ -1,3 +1,10 @@+{-|+Module : Merge+License : GPL-3++Maintainer : haskell@gentoo.org++Core functionality of the @merge@ command of @HackPort@.+-} module Merge ( merge , mergeGenericPackageDescription@@ -5,9 +12,10 @@ import Control.Monad import Control.Exception-import qualified Data.ByteString.Lazy.Char8 as BL-import qualified Data.ByteString.Builder as BL (stringUtf8, toLazyByteString)+import qualified Data.Text as T+import qualified Data.Text.IO as T import Data.Function (on)+import qualified Data.Map.Strict as Map import Data.Maybe import qualified Data.List as L import qualified Data.Set as S@@ -29,7 +37,6 @@ import Distribution.Client.IndexUtils ( getSourcePackages ) import qualified Distribution.Client.GlobalFlags as CabalInstall import Distribution.Client.Types- -- others import qualified Data.List.Split as DLS import System.Directory ( getCurrentDirectory@@ -39,10 +46,10 @@ , listDirectory ) import System.Process (system)-import System.FilePath ((</>))-import qualified System.FilePath as SF+import System.FilePath ((</>),(<.>)) import System.Exit +import qualified AnsiColor as A import qualified Cabal2Ebuild as C2E import qualified Portage.EBuild as E import qualified Portage.EMeta as EM@@ -60,48 +67,43 @@ import qualified Portage.GHCCore as GHCCore import qualified Merge.Dependencies as Merge--(<.>) :: String -> String -> String-a <.> b = a ++ '.':b+import qualified Merge.Utils as Merge {- Requested features: * Add files to git? -} -readPackageString :: [String]- -> Either HackPortError ( Maybe Portage.Category- , Cabal.PackageName- , Maybe Portage.Version- )-readPackageString args = do- packageString <-- case args of- [] -> Left (ArgumentError "Need an argument, [category/]package[-version]")- [pkg] -> return pkg- _ -> Left (ArgumentError ("Too many arguments: " ++ unwords args))- case Portage.parseFriendlyPackage packageString of- Right v@(_,_,Nothing) -> return v- -- we only allow versions we can convert into cabal versions- Right v@(_,_,Just (Portage.Version _ Nothing [] 0)) -> return v- Left e -> Left $ ArgumentError $ "Could not parse [category/]package[-version]: "- ++ packageString ++ "\nParsec error: " ++ e- _ -> Left $ ArgumentError $ "Could not parse [category/]package[-version]: "- ++ packageString+-- | Call @diff@ between two ebuilds.+diffEbuilds :: FilePath -> Portage.PackageId -> Portage.PackageId -> IO ()+diffEbuilds fp a b = do _ <- system $ "diff -u --color=auto "+ ++ fp </> Portage.packageIdToFilePath a ++ " "+ ++ fp </> Portage.packageIdToFilePath b+ exitSuccess -- | Given a list of available packages, and maybe a preferred version, -- return the available package with that version. Latest version is chosen -- if no preference. resolveVersion :: [UnresolvedSourcePackage] -> Maybe Cabal.Version -> Maybe UnresolvedSourcePackage-resolveVersion avails Nothing = Just $ L.maximumBy (comparing (Cabal.pkgVersion . CabalInstall.packageInfoId)) avails+resolveVersion avails Nothing = Just $ L.maximumBy (comparing (Cabal.pkgVersion . CabalInstall.srcpkgPackageId)) avails resolveVersion avails (Just ver) = listToMaybe (filter match avails) where- match avail = ver == Cabal.pkgVersion (CabalInstall.packageInfoId avail)+ match avail = ver == Cabal.pkgVersion (CabalInstall.srcpkgPackageId avail) +-- | This function is executed by the @merge@ command of @HackPort@.+-- Its functionality is as follows:+--+-- 1. Feed user input to 'readPackageString'+-- 2. Look for a matching package on the @hackage@ database+-- 3. Run 'mergeGenericPackageDescription' with the supplied information+-- 4. Generate a coloured diff between the old and new ebuilds.+--+-- Various information is printed in between these steps depending on the+-- 'Verbosity'. merge :: Verbosity -> CabalInstall.RepoContext -> [String] -> FilePath -> Maybe String -> IO () merge verbosity repoContext args overlayPath users_cabal_flags = do (m_category, user_pName, m_version) <-- case readPackageString args of+ case Merge.readPackageString args of Left err -> throwEx err Right (c,p,m_v) -> case m_v of@@ -126,12 +128,12 @@ case map snd (CabalInstall.searchByName index user_pname_str) of [] -> throwEx (PackageNotFound user_pname_str) [pkg] -> return pkg- pkgs -> do let cabal_pkg_to_pn pkg = Cabal.unPackageName $ Cabal.pkgName (CabalInstall.packageInfoId pkg)+ pkgs -> do let cabal_pkg_to_pn pkg = Cabal.unPackageName $ Cabal.pkgName (CabalInstall.srcpkgPackageId pkg) names = map (cabal_pkg_to_pn . L.head) pkgs notice verbosity $ "Ambiguous names: " ++ L.intercalate ", " names forM_ pkgs $ \ps -> do let p_name = (cabal_pkg_to_pn . L.head) ps- notice verbosity $ p_name ++ ": " ++ (L.intercalate ", " $ map (prettyShow . Cabal.pkgVersion . CabalInstall.packageInfoId) ps)+ notice verbosity $ p_name ++ ": " ++ (L.intercalate ", " $ map (prettyShow . Cabal.pkgVersion . CabalInstall.srcpkgPackageId) ps) return $ concat pkgs -- select a single package taking into account the user specified version@@ -140,74 +142,35 @@ Nothing -> do putStrLn "No such version for that package, available versions:" forM_ availablePkgs $ \ avail ->- putStrLn (prettyShow . CabalInstall.packageInfoId $ avail)+ putStrLn (prettyShow . CabalInstall.srcpkgPackageId $ avail) throwEx (ArgumentError "no such version for that package") Just avail -> return avail -- print some info info verbosity "Selecting package:" forM_ availablePkgs $ \ avail -> do- let match_text | CabalInstall.packageInfoId avail == CabalInstall.packageInfoId selectedPkg = "* "+ let match_text | CabalInstall.srcpkgPackageId avail == CabalInstall.srcpkgPackageId selectedPkg = "* " | otherwise = "- "- info verbosity $ match_text ++ (prettyShow . CabalInstall.packageInfoId $ avail)+ info verbosity $ match_text ++ (prettyShow . CabalInstall.srcpkgPackageId $ avail) - let cabal_pkgId = CabalInstall.packageInfoId selectedPkg+ let cabal_pkgId = CabalInstall.srcpkgPackageId selectedPkg norm_pkgName = Cabal.packageName (Portage.normalizeCabalPackageId cabal_pkgId) cat <- maybe (Portage.resolveCategory verbosity overlay norm_pkgName) return m_category- mergeGenericPackageDescription verbosity overlayPath cat (CabalInstall.packageDescription selectedPkg) True users_cabal_flags+ mergeGenericPackageDescription verbosity overlayPath cat (CabalInstall.srcpkgDescription selectedPkg) True users_cabal_flags -- Maybe generate a diff let pkgPath = overlayPath </> (Portage.unCategory cat) </> (Cabal.unPackageName norm_pkgName) newPkgId = Portage.fromCabalPackageId cat cabal_pkgId pkgDir <- listDirectory pkgPath- case getPreviousPackageId pkgDir newPkgId of+ case Merge.getPreviousPackageId pkgDir newPkgId of Just validPkg -> do info verbosity "Generating a diff..." diffEbuilds overlayPath validPkg newPkgId _ -> info verbosity "Nothing to diff!"- --- | Call diff between two ebuilds.-diffEbuilds :: FilePath -> Portage.PackageId -> Portage.PackageId -> IO ()-diffEbuilds fp a b = do _ <- system $ "diff -u --color=auto "- ++ fp </> Portage.packageIdToFilePath a ++ " "- ++ fp </> Portage.packageIdToFilePath b- exitSuccess --- | Maybe return a PackageId of the next highest version for a given--- package, relative to the provided PackageId.-getPreviousPackageId :: [FilePath] -- ^ list of ebuilds for given package- -> Portage.PackageId -- ^ new PackageId- -> Maybe Portage.PackageId -- ^ maybe PackageId of previous version-getPreviousPackageId pkgDir newPkgId = do- let pkgIds = reverse - . L.sortOn (Portage.pkgVersion)- . filter (<newPkgId)- $ mapMaybe (Portage.filePathToPackageId (Portage.category . Portage.packageId $ newPkgId))- $ SF.dropExtension <$> filter (\fp -> SF.takeExtension fp == ".ebuild") pkgDir- case pkgIds of- x:_ -> Just x- _ -> Nothing--first_just_of :: [Maybe a] -> Maybe a-first_just_of = msum---- Gentoo allows underscore ('_') names in IUSE only for--- USE_EXPAND values. If it's not a user-specified rename mangle--- it into a hyphen ('-').-mangle_iuse :: String -> String-mangle_iuse = drop_prefix . map f- where f '_' = '-'- f c = c---- | Remove "with" or "use" prefixes from flag names.-drop_prefix :: String -> String-drop_prefix x- | take 5 x `elem` ["with_","with-"] = drop 5 x- | take 4 x `elem` ["use_","use-"] = drop 4 x- | otherwise = x- -- used to be FlagAssignment in Cabal but now it's an opaque type type CabalFlags = [(Cabal.FlagName, Bool)] +-- | Generate an ebuild from a 'Cabal.GenericPackageDescription'. mergeGenericPackageDescription :: Verbosity -> FilePath -> Portage.Category -> Cabal.GenericPackageDescription -> Bool -> Maybe String -> IO () mergeGenericPackageDescription verbosity overlayPath cat pkgGenericDesc fetch users_cabal_flags = do overlay <- Overlay.loadLazy overlayPath@@ -215,7 +178,7 @@ merged_PN = Portage.cabal_pn_to_PN merged_cabal_pkg_name pkgdir = overlayPath </> Portage.unCategory cat </> merged_PN existing_meta <- EM.findExistingMeta pkgdir- let requested_cabal_flags = first_just_of [users_cabal_flags, EM.cabal_flags existing_meta]+ let requested_cabal_flags = Merge.first_just_of [users_cabal_flags, EM.cabal_flags existing_meta] -- accepts things, like: "cabal_flag:iuse_name", "+cabal_flag", "-cabal_flag" read_fas :: Maybe String -> (CabalFlags, [(String, String)])@@ -264,7 +227,7 @@ pkgDesc = Merge.RetroPackageDescription pkgDesc0 accepted_deps cabal_flag_descs = Cabal.genPackageFlags pkgGenericDesc all_flags = map Cabal.flagName cabal_flag_descs- make_fas :: [Cabal.Flag] -> [CabalFlags]+ make_fas :: [Cabal.PackageFlag] -> [CabalFlags] make_fas [] = [[]] make_fas (f:rest) = [ (fn, is_enabled) : fas | fas <- make_fas rest@@ -286,7 +249,7 @@ cfn_to_iuse :: String -> String cfn_to_iuse cfn = case lookup cfn cf_to_iuse_rename of- Nothing -> mangle_iuse cfn+ Nothing -> Merge.mangle_iuse cfn Just ein -> ein -- key idea is to generate all possible list of flags deps1 :: [(CabalFlags, Merge.EDep)]@@ -439,6 +402,9 @@ norm_pkgName = Cabal.packageName (Portage.normalizeCabalPackageId cabal_pkgId) fetchDigestAndCheck verbosity (overlayPath </> prettyShow cat </> prettyShow norm_pkgName) +-- | Run various @repoman@ commands in the directory of the newly-generated ebuild.+-- This will ensure well-formed ebuilds and @metadata.xml@, and will update (if possible)+-- the @Manifest@ file. fetchDigestAndCheck :: Verbosity -> FilePath -- ^ directory of ebuild -> IO ()@@ -461,33 +427,44 @@ (\_ -> setCurrentDirectory oldDir) (\_ -> action) --- "amd64" -> "~amd64"-to_unstable :: String -> String-to_unstable kw =- case kw of- '~':_ -> kw- '-':_ -> kw- _ -> '~':kw---- | Generate a list of tuples containing Cabal flag names and descriptions-metaFlags :: [Cabal.Flag] -> [(String, String)]-metaFlags flags = zip (mangle_iuse . Cabal.unFlagName . Cabal.flagName <$> flags) (Cabal.flagDescription <$> flags)--mergeEbuild :: Verbosity -> EM.EMeta -> FilePath -> E.EBuild -> [Cabal.Flag] -> IO ()+-- | Write the ebuild (and sometimes a new @metadata.xml@) to its directory.+mergeEbuild :: Verbosity -> EM.EMeta -> FilePath -> E.EBuild -> [Cabal.PackageFlag] -> IO () mergeEbuild verbosity existing_meta pkgdir ebuild flags = do let edir = pkgdir elocal = E.name ebuild ++"-"++ E.version ebuild <.> "ebuild" epath = edir </> elocal emeta = "metadata.xml" mpath = edir </> emeta- default_meta = BL.toLazyByteString . BL.stringUtf8- $ Portage.makeDefaultMetadata (E.long_desc ebuild)- $ metaFlags flags+ yet_meta <- doesFileExist mpath+ -- If there is an existing @metadata.xml@, read it in as a 'T.Text'.+ -- Otherwise return 'T.empty'. We only use this once more to directly+ -- compare to @default_meta@ before writing it.+ current_meta <- if yet_meta+ then T.readFile mpath+ else return T.empty+ -- Either create an object of the 'Portage.Metadata' type from a valid @current_meta@,+ -- or supply a default minimal metadata object. Note the difference to @current_meta@:+ -- @current_meta@ is of type 'T.Text', @current_meta'@ is of type 'Portage.Metadata'.+ let current_meta' = fromMaybe Portage.makeMinimalMetadata+ (Portage.pureMetadataFromFile current_meta)+ -- Create the @metadata.xml@ string, adding new USE flags (if any) to those of+ -- the existing @metadata.xml@. If an existing flag has a new and old description,+ -- the new one takes precedence.+ default_meta = Portage.makeDefaultMetadata (E.long_desc ebuild)+ $ Merge.metaFlags flags `Map.union`+ Portage.metadataUseFlags current_meta'+ -- Create a 'Map.Map' of USE flags with updated descriptions.+ new_flags = Map.differenceWith (\new old -> if (new /= old)+ then Just $ old ++ A.bold (" -> " ++ new)+ else Nothing)+ (Merge.metaFlags flags)+ $ Portage.metadataUseFlags current_meta'+ createDirectoryIfMissing True edir now <- TC.getCurrentTime let (existing_keywords, existing_license, existing_description) = (EM.keywords existing_meta, EM.license existing_meta, EM.description existing_meta)- new_keywords = maybe (E.keywords ebuild) (map to_unstable) existing_keywords+ new_keywords = maybe (E.keywords ebuild) (map Merge.to_unstable) existing_keywords new_license = either (\err -> maybe (Left err) Right existing_license)@@ -504,12 +481,14 @@ notice verbosity $ "Current license: " ++ show existing_license ++ " -> " ++ show new_license notice verbosity $ "Writing " ++ elocal- length s_ebuild' `seq` BL.writeFile epath (BL.pack s_ebuild')+ length s_ebuild' `seq` T.writeFile epath (T.pack s_ebuild') - yet_meta <- doesFileExist mpath- if not yet_meta -- TODO: add --force-meta-rewrite to opts- then do notice verbosity $ "Writing " ++ emeta- BL.writeFile mpath default_meta- else do current_meta <- BL.readFile mpath- when (current_meta /= default_meta) $- notice verbosity $ "Default and current " ++ emeta ++ " differ."+ when (current_meta /= default_meta) $ do+ notice verbosity $ A.bold $ "Default and current " ++ emeta ++ " differ."+ if (new_flags /= Map.empty)+ then notice verbosity $ "New or updated USE flags:\n" +++ (unlines $ Portage.prettyPrintFlagsHuman new_flags)+ else notice verbosity "No new USE flags."++ notice verbosity $ "Writing " ++ emeta+ T.writeFile mpath default_meta
Merge/Dependencies.hs view
@@ -1,7 +1,11 @@-{-# LANGUAGE CPP #-}+{-|+Module : Merge.Dependencies+License : GPL-3++Maintainer : haskell@gentoo.org -{- | Merge a package from hackage to an ebuild.- -}+Merge a package from @hackage@ to an ebuild.+-}+{-# LANGUAGE CPP #-} module Merge.Dependencies ( EDep(..) , RetroPackageDescription(..)@@ -13,15 +17,14 @@ import Data.Maybe ( isJust, isNothing ) import Data.Monoid ( Monoid, mempty ) import qualified Data.List as L-import qualified Data.Set as S+import qualified Data.Set as S +import qualified Distribution.CabalSpecVersion as Cabal+import qualified Distribution.Compat.NonEmptySet as NES import qualified Distribution.Package as Cabal import qualified Distribution.PackageDescription as Cabal import qualified Distribution.Version as Cabal import qualified Distribution.Pretty as Cabal-import qualified Distribution.Types.ExeDependency as Cabal-import qualified Distribution.Types.LegacyExeDependency as Cabal-import qualified Distribution.Types.PkgconfigDependency as Cabal import qualified Distribution.Compiler as Cabal @@ -42,7 +45,7 @@ import Data.Semigroup (Semigroup(..)) #endif --- | Dependencies of an ebuild+-- | Dependencies of an ebuild. data EDep = EDep { rdep :: Portage.Dependency,@@ -52,25 +55,23 @@ } deriving (Show, Eq, Ord) --- | Cabal-1 style PackageDescription, with a top-level buildDepends function+-- | Cabal-1 style 'Cabal.PackageDescription', with a top-level 'buildDepends' function. data RetroPackageDescription = RetroPackageDescription { packageDescription :: Cabal.PackageDescription, buildDepends :: [Cabal.Dependency] } deriving (Show) --- | Construct a RetroPackageDescription using exeAndLibDeps for the buildDepends.+-- | Construct a 'RetroPackageDescription' using 'exeAndLibDeps' for the 'buildDepends'. mkRetroPD :: Cabal.PackageDescription -> RetroPackageDescription mkRetroPD pd = RetroPackageDescription { packageDescription = pd, buildDepends = exeAndLibDeps pd } --- | extract only the build dependencies for libraries and executables for a given package.+-- | Extract only the build dependencies for libraries and executables for a given package. exeAndLibDeps :: Cabal.PackageDescription -> [Cabal.Dependency]-exeAndLibDeps pkg = L.union- (concat- $ map Cabal.targetBuildDepends- $ map Cabal.buildInfo (Cabal.executables pkg))- (concat- $ map Cabal.targetBuildDepends- $ map Cabal.libBuildInfo (Cabal.allLibraries pkg))+exeAndLibDeps pkg = concatMap (Cabal.targetBuildDepends . Cabal.buildInfo)+ (Cabal.executables pkg)+ `L.union`+ concatMap (Cabal.targetBuildDepends . Cabal.libBuildInfo)+ (Cabal.allLibraries pkg) #if MIN_VERSION_base(4,9,0) instance Semigroup EDep where@@ -99,6 +100,7 @@ } #endif +-- | Resolve package dependencies from a 'RetroPackageDescription' into an 'EDep'. resolveDependencies :: Portage.Overlay -> RetroPackageDescription -> Cabal.CompilerInfo -> [Cabal.PackageName] -> Cabal.PackageName -> EDep@@ -193,7 +195,7 @@ testDependencies :: Portage.Overlay -> Cabal.PackageDescription -> [Cabal.PackageName] -> Cabal.PackageName -> [Portage.Dependency] testDependencies overlay pkg ghc_package_names merged_cabal_pkg_name = deps- where cabalDeps = concat $ map Cabal.targetBuildDepends $ map Cabal.testBuildInfo (Cabal.testSuites pkg)+ where cabalDeps = concatMap (Cabal.targetBuildDepends . Cabal.testBuildInfo) (Cabal.testSuites pkg) cabalDeps' = fst $ Portage.partition_depends ghc_package_names merged_cabal_pkg_name cabalDeps deps = C2E.convertDependencies overlay (Portage.Category "dev-haskell") cabalDeps' @@ -219,10 +221,11 @@ C2E.convertDependency overlay (Portage.Category "dev-haskell") (Cabal.Dependency (Cabal.mkPackageName "Cabal")- finalCabalDep (S.singleton Cabal.defaultLibName))+ finalCabalDep (NES.singleton Cabal.defaultLibName)) where versionNumbers = Cabal.versionNumbers cabal_version- userCabalVersion = Cabal.orLaterVersion (Cabal.specVersion pkg)+ userCabalVersion = Cabal.orLaterVersion $ Cabal.mkVersion+ $ Cabal.cabalSpecToVersionDigits $ Cabal.specVersion pkg shippedCabalVersion = GHCCore.cabalFromGHC versionNumbers shippedCabalDep = maybe Cabal.anyVersion Cabal.orLaterVersion shippedCabalVersion finalCabalDep = Cabal.simplifyVersionRange@@ -429,7 +432,7 @@ hackageBuildToolsDependencies :: Portage.Overlay -> Cabal.PackageDescription -> [Portage.Dependency] hackageBuildToolsDependencies overlay (Cabal.PackageDescription { Cabal.library = lib, Cabal.executables = exes }) = haskellDependencies overlay $ L.nub $- [ Cabal.Dependency pn versionRange $ S.singleton Cabal.defaultLibName+ [ Cabal.Dependency pn versionRange $ NES.singleton Cabal.defaultLibName | Cabal.ExeDependency pn _component versionRange <- cabalDeps ] where
+ Merge/Utils.hs view
@@ -0,0 +1,142 @@+{-|+Module : Merge.Utils+License : GPL-3++Maintainer : haskell@gentoo.org++Internal helper functions for "Merge".+-}+module Merge.Utils+ ( readPackageString+ , getPreviousPackageId+ , first_just_of+ , drop_prefix+ , mangle_iuse+ , to_unstable+ , metaFlags+ ) where++import qualified Control.Monad as M+import Data.Maybe (mapMaybe)+import qualified Data.List as L+import qualified Data.Map.Strict as Map+import qualified System.FilePath as SF++import Error+import qualified Portage.PackageId as Portage++import qualified Distribution.Package as Cabal+import qualified Distribution.PackageDescription as Cabal++-- | Parse a ['String'] as a valid package string. E.g. @category\/name-1.0.0@.+-- Return 'HackPortError' if the string to parse is invalid.+--+-- When the ['String'] is valid:+--+-- >>> readPackageString ["dev-haskell/packagename1-1.0.0"]+-- Right (Just (Category {unCategory = "dev-haskell"}),PackageName "packagename1",Just (Version {versionNumber = [1,0,0], versionChar = Nothing, versionSuffix = [], versionRevision = 0}))+--+-- When the ['String'] is empty:+--+-- >>> readPackageString []+-- Left ...+readPackageString :: [String]+ -> Either HackPortError ( Maybe Portage.Category+ , Cabal.PackageName+ , Maybe Portage.Version+ )+readPackageString args = do+ packageString <-+ case args of+ [] -> Left (ArgumentError "Need an argument, [category/]package[-version]")+ [pkg] -> return pkg+ _ -> Left (ArgumentError ("Too many arguments: " ++ unwords args))+ case Portage.parseFriendlyPackage packageString of+ Right v@(_,_,Nothing) -> return v+ -- we only allow versions we can convert into cabal versions+ Right v@(_,_,Just (Portage.Version _ Nothing [] 0)) -> return v+ Left e -> Left $ ArgumentError $ "Could not parse [category/]package[-version]: "+ ++ packageString ++ "\nParsec error: " ++ e+ _ -> Left $ ArgumentError $ "Could not parse [category/]package[-version]: "+ ++ packageString++-- | Maybe return a 'Portage.PackageId' of the next highest version for a given+-- package, relative to the provided 'Portage.PackageId'.+--+-- For example:+-- +-- >>> let ebuildDir = ["foo-bar2-3.0.1.ebuild","metadata.xml"]+-- >>> let newPkgId = Portage.PackageId (Portage.PackageName (Portage.Category "dev-haskell") (Cabal.mkPackageName "foo-bar2")) (Portage.Version [3,0,2] Nothing [] 0 )+--+-- >>> getPreviousPackageId ebuildDir newPkgId+-- Just (PackageId {packageId = PackageName {category = Category {unCategory = "dev-haskell"}, cabalPkgName = PackageName "foo-bar2"}, pkgVersion = Version {versionNumber = [3,0,1], versionChar = Nothing, versionSuffix = [], versionRevision = 0}})+getPreviousPackageId :: [FilePath] -- ^ list of ebuilds for given package+ -> Portage.PackageId -- ^ new PackageId+ -> Maybe Portage.PackageId -- ^ maybe PackageId of previous version+getPreviousPackageId pkgDir newPkgId = do+ let pkgIds = reverse + . L.sortOn (Portage.pkgVersion)+ . filter (<newPkgId)+ $ mapMaybe (Portage.filePathToPackageId (Portage.category . Portage.packageId $ newPkgId))+ $ SF.dropExtension <$> filter (\fp -> SF.takeExtension fp == ".ebuild") pkgDir+ case pkgIds of+ x:_ -> Just x+ _ -> Nothing++-- | Alias for 'msum'.+-- +-- prop> \a -> first_just_of a == M.msum a+first_just_of :: [Maybe a] -> Maybe a+first_just_of = M.msum++-- | Remove @with@ or @use@ prefixes from flag names.+--+-- >>> drop_prefix "with_conduit"+-- "conduit"+-- >>> drop_prefix "use-https"+-- "https"+-- >>> drop_prefix "no_examples"+-- "no_examples"+drop_prefix :: String -> String+drop_prefix x+ | take 5 x `elem` ["with_","with-"] = drop 5 x+ | take 4 x `elem` ["use_","use-"] = drop 4 x+ | otherwise = x++-- | Gentoo allows underscore ('_') names in @IUSE@ only for+-- @USE_EXPAND@ values. If it's not a user-specified rename mangle+-- it into a hyphen ('-').+-- +-- >>> mangle_iuse "use_remove_my_underscores"+-- "remove-my-underscores"+mangle_iuse :: String -> String+mangle_iuse = drop_prefix . map f+ where f '_' = '-'+ f c = c++-- | Convert all stable keywords to testing (unstable) keywords.+-- Preserve arch masks (-).+--+-- >>> to_unstable "amd64"+-- "~amd64"+-- >>> to_unstable "~amd64"+-- "~amd64"+-- >>> to_unstable "-amd64"+-- "-amd64"+to_unstable :: String -> String+to_unstable kw =+ case kw of+ '~':_ -> kw+ '-':_ -> kw+ _ -> '~':kw++-- | Generate a 'Map.Map' of 'Cabal.PackageFlag' names and their descriptions.+--+-- For example, if we construct a singleton list holding a 'Cabal.PackageFlag' with+-- 'Cabal.FlagName' @foo@ and 'Cabal.FlagDescription' @bar@, we should get+-- a 'Map.Map' containing those values:+--+-- >>> let flags = [(Cabal.emptyFlag (Cabal.mkFlagName "foo")) {Cabal.flagDescription = "bar"}]+-- >>> metaFlags flags+-- fromList [("foo","bar")]+metaFlags :: [Cabal.PackageFlag] -> Map.Map String String+metaFlags flags = Map.fromList $ zip (mangle_iuse . Cabal.unFlagName . Cabal.flagName <$> flags) (Cabal.flagDescription <$> flags)
Portage/Cabal.hs view
@@ -1,3 +1,11 @@+{-|+Module : Portage.Cabal+License : GPL-3++Maintainer : haskell@gentoo.org++Utilities to extract and manipulate information from a package's @.cabal@ file,+such as its license and dependencies.+-} module Portage.Cabal ( convertLicense , partition_depends@@ -5,19 +13,49 @@ import qualified Data.List as L -import qualified Distribution.License as Cabal-import qualified Distribution.SPDX.License as SPDX-import qualified Distribution.Package as Cabal-import qualified Distribution.Pretty as Cabal+import qualified Distribution.License as Cabal+import qualified Distribution.SPDX as SPDX+import qualified Distribution.Package as Cabal+import qualified Distribution.Pretty as Cabal --- map the cabal license type to the gentoo license string format+-- | Convert the Cabal 'SPDX.License' into the Gentoo format, as a 'String'.+--+-- Generally, if the license is one of the common free-software or+-- open-source licenses, 'convertLicense' should return the license+-- as a 'Right' 'String':+--+-- >>> convertLicense (SPDX.License $ SPDX.simpleLicenseExpression SPDX.GPL_3_0_or_later)+-- Right "GPL-3+"+--+-- >>> convertLicense (SPDX.License $ SPDX.simpleLicenseExpression SPDX.GPL_3_0_only)+-- Right "GPL-3"+--+-- If it is a more obscure license, this should alert the user by returning+-- a 'Left' 'String':+--+-- >>> convertLicense (SPDX.License $ SPDX.simpleLicenseExpression SPDX.EUPL_1_1)+-- Left ... convertLicense :: SPDX.License -> Either String String convertLicense l = case Cabal.licenseFromSPDX l of -- good ones- Cabal.AGPL mv -> Right $ "AGPL-" ++ (maybe "3" Cabal.prettyShow mv) -- almost certainly version 3- Cabal.GPL mv -> Right $ "GPL-" ++ (maybe "2" Cabal.prettyShow mv) -- almost certainly version 2- Cabal.LGPL mv -> Right $ "LGPL-" ++ (maybe "2.1" Cabal.prettyShow mv) -- probably version 2.1+ Cabal.AGPL mv -> Right $ "AGPL-" ++ case (Cabal.prettyShow <$> mv) of+ Just "3" -> "3"+ Just "3.0" -> "3+"+ _ -> "3" -- almost certainly version 3+ Cabal.GPL mv -> Right $ "GPL-" ++ case (Cabal.prettyShow <$> mv) of+ Just "2" -> "2"+ Just "2.0" -> "2+"+ Just "3" -> "3"+ Just "3.0" -> "3+"+ _ -> "2" -- possibly version 2+ Cabal.LGPL mv -> Right $ "LGPL-" ++ case (Cabal.prettyShow <$> mv) of+ Just "2" -> "2"+ -- Cabal can't handle 2.0+ properly+ Just "2.0" -> "2"+ Just "3" -> "3"+ Just "3.0" -> "3+"+ _ -> "2.1" -- probably version 2.1 Cabal.BSD2 -> Right "BSD-2" Cabal.BSD3 -> Right "BSD" Cabal.BSD4 -> Right "BSD-4"@@ -32,6 +70,7 @@ Cabal.OtherLicense -> Left "(Other) Please look at license file of package and pick it manually." Cabal.UnspecifiedLicense -> Left "(Unspecified) Please look at license file of package and pick it manually." +-- | Extract only the dependencies which are not bundled with @GHC@. partition_depends :: [Cabal.PackageName] -> Cabal.PackageName -> [Cabal.Dependency] -> ([Cabal.Dependency], [Cabal.Dependency]) partition_depends ghc_package_names merged_cabal_pkg_name = L.partition (not . is_internal_depend) where is_internal_depend (Cabal.Dependency pn _vr _lib) = is_itself || is_ghc_package
Portage/Dependency/Types.hs view
@@ -1,3 +1,10 @@+{-|+Module : Portage.Dependency.Types+License : GPL-3++Maintainer : haskell@gentoo.org++Functions and types related to processing Portage dependencies.+-} module Portage.Dependency.Types ( SlotDepend(..)@@ -16,14 +23,16 @@ import Portage.PackageId import Portage.Use -data SlotDepend = AnySlot -- nothing special- | AnyBuildTimeSlot -- ':='- | GivenSlot String -- ':slotno'+-- | Type of SLOT dependency of a dependency.+data SlotDepend = AnySlot -- ^ nothing special+ | AnyBuildTimeSlot -- ^ ':='+ | GivenSlot String -- ^ ':slotno' deriving (Eq, Show, Ord) -data LBound = StrictLB Version- | NonstrictLB Version- | ZeroB+-- | Type of lower bound of a dependency.+data LBound = StrictLB Version -- ^ greater than (>)+ | NonstrictLB Version -- ^ greater than or equal to (>=)+ | ZeroB -- ^ no lower bound deriving (Eq, Show) instance Ord LBound where@@ -38,10 +47,10 @@ compare (NonstrictLB lv) (StrictLB rv) = case compare lv rv of EQ -> LT r -> r--data UBound = StrictUB Version -- <- | NonstrictUB Version -- <=- | InfinityB+-- | Type of upper bound of a dependency.+data UBound = StrictUB Version -- ^ less than (<)+ | NonstrictUB Version -- ^ less than or equal to (<=)+ | InfinityB -- ^ no upper bound deriving (Eq, Show) instance Ord UBound where@@ -57,6 +66,10 @@ EQ -> GT r -> r +-- | Type of dependency version.+--+-- A dependency version may either be an exact 'Version' or a+-- version range between a given 'LBound' and 'UBound'. data DRange = DRange LBound UBound | DExact Version deriving (Eq, Show, Ord)@@ -66,7 +79,7 @@ | llow >= rlow && lup <= rup = True range_is_case_of _ _ = False --- True if 'left' "interval" covers at least as much as the 'right' "interval"+-- | True if left 'DRange' covers at least as much as the right 'DRange'. range_as_broad_as :: DRange -> DRange -> Bool range_as_broad_as (DRange llow lup) (DRange rlow rup) | llow <= rlow && lup >= rup = True@@ -83,7 +96,8 @@ data Atom = Atom PackageName DRange DAttr deriving (Eq, Show, Ord) --- returns 'True' if left constraint is the same as (or looser than) right+-- | True if left 'Dependency' constraint is the same as (or looser than) right+-- 'Dependency' constraint. dep_as_broad_as :: Dependency -> Dependency -> Bool dep_as_broad_as l r -- very broad (not only on atoms) special case
Portage/EBuild.hs view
@@ -1,9 +1,21 @@+{-|+Module : Portage.EBuild+License : GPL-3++Maintainer : haskell@gentoo.org++Functions and types related to interpreting and manipulating an ebuild,+as understood by the Portage package manager.+-} {-# LANGUAGE CPP #-} module Portage.EBuild ( EBuild(..) , ebuildTemplate , showEBuild , src_uri+ -- hspec exports+ , sort_iuse+ , drop_tdot+ , quote ) where import Portage.Dependency@@ -23,6 +35,7 @@ import qualified System.Locale as TC #endif +-- | Type representing the information contained in an @.ebuild@. data EBuild = EBuild { name :: String, category :: String,@@ -52,6 +65,7 @@ getHackportVersion Version {versionBranch=(x:s)} = foldl (\y z -> y ++ "." ++ (show z)) (show x) s getHackportVersion Version {versionBranch=[]} = "" +-- | Generate a minimal 'EBuild' template. ebuildTemplate :: EBuild ebuildTemplate = EBuild { name = "foobar",@@ -79,6 +93,9 @@ -- | Given an EBuild, give the URI to the tarball of the source code. -- Assumes that the server is always hackage.haskell.org.+-- +-- >>> src_uri ebuild_template+-- "https://hackage.haskell.org/package/${P}/${P}.tar.gz" src_uri :: EBuild -> String src_uri e = case my_pn e of@@ -89,6 +106,7 @@ -- package Just _ -> "https://hackage.haskell.org/package/${MY_P}/${MY_P}.tar.gz" +-- | Pretty-print an 'EBuild' as a 'String'. showEBuild :: TC.UTCTime -> EBuild -> String showEBuild now ebuild = ss ("# Copyright 1999-" ++ this_year ++ " Gentoo Authors"). nl.@@ -142,12 +160,19 @@ this_year = TC.formatTime TC.defaultTimeLocale "%Y" now replace old new = L.intercalate new . LS.splitOn old --- "+a" -> "a"--- "b" -> "b"+-- | Sort IUSE alphabetically+--+-- >>> sort_iuse ["+a","b"]+-- ["+a","b"] sort_iuse :: [String] -> [String] sort_iuse = L.sortBy (compare `F.on` dropWhile ( `elem` "+")) --- drops trailing dot+-- | Drop trailing dot(s).+--+-- >>> drop_tdot "foo."+-- "foo"+-- >>> drop_tdot "foo..."+-- "foo" drop_tdot :: String -> String drop_tdot = reverse . dropWhile (== '.') . reverse @@ -195,6 +220,7 @@ deps_s = tabify (dep2str indent $ PN.normalize_depend dep) drop_leadings = dropWhile (== '\t') +-- | Place a 'String' between quotes, and correctly handle special characters. quote :: String -> DString quote str = sc '"'. ss (esc str). sc '"' where@@ -215,18 +241,16 @@ sepBy _ [x] = ss x sepBy s (x:xs) = ss x. ss s. sepBy s xs -getRestIfPrefix ::- String -> -- ^ the prefix- String -> -- ^ the string- Maybe String+getRestIfPrefix :: String -- ^ the prefix+ -> String -- ^ the string+ -> Maybe String getRestIfPrefix (p:ps) (x:xs) = if p==x then getRestIfPrefix ps xs else Nothing getRestIfPrefix [] rest = Just rest getRestIfPrefix _ [] = Nothing -subStr ::- String -> -- ^ the search string- String -> -- ^ the string to be searched- Maybe (String,String) -- ^ Just (pre,post) if string is found+subStr :: String -- ^ the search string+ -> String -- ^ the string to be searched+ -> Maybe (String,String) -- ^ Just (pre,post) if string is found subStr sstr str = case getRestIfPrefix sstr str of Nothing -> if null str then Nothing else case subStr sstr (tail str) of Nothing -> Nothing@@ -234,9 +258,9 @@ Just rest -> Just ([],rest) replaceMultiVars ::- [(String,String)] -> -- ^ pairs of variable name and content- String -> -- ^ string to be searched- String -- ^ the result+ [(String,String)] -- ^ pairs of variable name and content+ -> String -- ^ string to be searched+ -> String -- ^ the result replaceMultiVars [] str = str replaceMultiVars whole@((pname,cont):rest) str = case subStr cont str of Nothing -> replaceMultiVars rest str
Portage/EBuild/CabalFeature.hs view
@@ -1,11 +1,12 @@ {-# LANGUAGE LambdaCase #-} --- CABAL_FEATURES="..." in haskell-cabal .ebuild files--- see haskell-cabal.eclass for details on each of those+-- | Support for CABAL_FEATURES="..." in haskell-cabal .ebuild files.+-- See haskell-cabal.eclass for details on each of those. module Portage.EBuild.CabalFeature (CabalFeature(..)) where import Portage.EBuild.Render +-- | Type representing @CABAL_FEATURES@ in an ebuild. data CabalFeature = Lib | Profile | Haddock
Portage/EMeta.hs view
@@ -1,3 +1,12 @@+{-|+Module : Portage.EMeta+License : GPL-3++Maintainer : haskell@gentoo.org++Functions to propagate existing ebuild information+(such as its licence, description, switched flags etc.) to+a new ebuild.+-} module Portage.EMeta ( EMeta(..) , findExistingMeta@@ -11,15 +20,15 @@ import System.FilePath ((</>)) import Text.Printf --- tries to extract value of variable in 'var="val"' format--- There should be exactly one variable assignment in ebuild--- It's a bit artificial limitation, but it's common for 'if / else' blocks+-- | Extract a value of variable in \'var=\"val\"\' format.+-- There should be exactly one variable assignment in the ebuild.+-- It's a bit of an artificial limitation, but it's common for \'if / else\' blocks. extract_quoted_string :: FilePath -> String -> String -> Maybe String extract_quoted_string ebuild_path s_ebuild var_name = case filter (L.isPrefixOf var_prefix . ltrim) $ lines s_ebuild of [] -> Nothing [kw_line] -> up_to_quote $ skip_prefix $ ltrim kw_line- other -> bail_out $ printf "strange '%s' assignmets:\n%s" var_name (unlines other)+ other -> bail_out $ printf "strange '%s' assignments:\n%s" var_name (unlines other) where ltrim :: String -> String ltrim = dropWhile isSpace@@ -32,8 +41,8 @@ bail_out :: String -> e bail_out msg = error $ printf "%s:extract_quoted_string %s" ebuild_path msg --- tries to extract value of variable in '#hackport: var: val' format--- There should be exactly one variable assignment in ebuild.+-- | Extract a value of variable in \'#hackport: var: val\' format.+-- There should be exactly one variable assignment in the ebuild. extract_hackport_var :: FilePath -> String -> String -> Maybe String extract_hackport_var ebuild_path s_ebuild var_name = case filter (L.isPrefixOf var_prefix) $ lines s_ebuild of@@ -46,29 +55,35 @@ bail_out :: String -> e bail_out msg = error $ printf "%s:extract_hackport_var %s" ebuild_path msg +-- | Extract the existing keywords from an ebuild. extractKeywords :: FilePath -> String -> Maybe [String] extractKeywords ebuild_path s_ebuild = words `fmap ` extract_quoted_string ebuild_path s_ebuild "KEYWORDS" +-- | Extract the existing license from an ebuild. extractLicense :: FilePath -> String -> Maybe String extractLicense ebuild_path s_ebuild = extract_quoted_string ebuild_path s_ebuild "LICENSE" +-- | Extract the existing Cabal flags from an ebuild. extractCabalFlags :: FilePath -> String -> Maybe String extractCabalFlags ebuild_path s_ebuild = extract_hackport_var ebuild_path s_ebuild "flags" +-- | Extract the existing description from an ebuild. extractDescription :: FilePath -> String -> Maybe String extractDescription ebuild_path s_ebuild = extract_quoted_string ebuild_path s_ebuild "DESCRIPTION" --- aggregated (best inferred) metadata for a new ebuild of package+-- | Type representing the aggregated (best inferred) metadata for a+-- new ebuild of a package. data EMeta = EMeta { keywords :: Maybe [String] , license :: Maybe String , cabal_flags :: Maybe String , description :: Maybe String } +-- | Find the existing package metadata from the last available ebuild. findExistingMeta :: FilePath -> IO EMeta findExistingMeta pkgdir = do ebuilds <- filter (L.isSuffixOf ".ebuild") `fmap` do b <- doesDirectoryExist pkgdir
Portage/GHCCore.hs view
@@ -1,5 +1,10 @@+{-|+Module : Portage.GHCCore+License : GPL-3++Maintainer : haskell@gentoo.org --- Guess GHC version from packages depended upon.+Guess the appropriate GHC version from packages depended upon.+-} module Portage.GHCCore ( minimumGHCVersionToBuildPackage , cabalFromGHC@@ -7,6 +12,8 @@ , finalizePD , platform , dependencySatisfiable+ -- hspec exports+ , packageIsCoreInAnyGHC ) where import qualified Distribution.Compiler as DC@@ -21,7 +28,6 @@ import Distribution.Compiler (CompilerId(..), CompilerFlavor(GHC)) import Distribution.System import Distribution.Types.ComponentRequestedSpec (defaultComponentRequestedSpec)-import Distribution.Types.Dependency (depPkgName, depVerRange) import Distribution.Pretty (prettyShow) @@ -30,12 +36,19 @@ import Debug.Trace --- ghcs tried in specified order.--- It means that first ghc in this list is a minimum default.+-- | Try each @GHC@ version in the specified order, from left to right.+-- The first @GHC@ version in this list is a minimum default. ghcs :: [(DC.CompilerInfo, InstalledPackageIndex)] ghcs = modern_ghcs- where modern_ghcs = [ghc741, ghc742, ghc762, ghc782, ghc7101, ghc7102, ghc801, ghc802, ghc821, ghc843, ghc863, ghc865, ghc881, ghc883, ghc8101]+ where modern_ghcs = [ghc741, ghc742, ghc762, ghc782, ghc7101, ghc7102, ghc801, ghc802, ghc821, ghc843, ghc863, ghc865, ghc881, ghc883, ghc884, ghc8101] +-- | Maybe determine the appropriate 'Cabal.Version' of the @Cabal@ package+-- from a given @GHC@ version.+--+-- >>> cabalFromGHC [8,8,3]+-- Just (mkVersion [3,0,1,0])+-- >>> cabalFromGHC [9,9,9,9]+-- Nothing cabalFromGHC :: [Int] -> Maybe Cabal.Version cabalFromGHC ver = lookup ver table where@@ -52,15 +65,25 @@ , ([8,6,5], Cabal.mkVersion [2,4,0,1]) , ([8,8,1], Cabal.mkVersion [3,0,0,0]) , ([8,8,3], Cabal.mkVersion [3,0,1,0])+ , ([8,8,4], Cabal.mkVersion [3,0,1,0]) , ([8,10,1], Cabal.mkVersion [3,2,0,0]) ] platform :: Platform platform = Platform X86_64 Linux +-- | Is the package a core dependency of a specific version of @GHC@?+--+-- >>> packageIsCore (mkIndex ghc883_pkgs) (Cabal.mkPackageName "binary")+-- True+-- >>> all (== True) ((packageIsCore (mkIndex ghc883_pkgs)) <$> (packageNamesFromPackageIndex (mkIndex ghc883_pkgs)))+-- True packageIsCore :: InstalledPackageIndex -> Cabal.PackageName -> Bool packageIsCore index pn = not . null $ lookupPackageName index pn +-- | Is the package a core dependency of any version of @GHC@?+-- >>> packageIsCoreInAnyGHC (Cabal.mkPackageName "array")+-- True packageIsCoreInAnyGHC :: Cabal.PackageName -> Bool packageIsCoreInAnyGHC pn = any (flip packageIsCore pn) (map snd ghcs) @@ -71,7 +94,7 @@ dependencySatisfiable :: InstalledPackageIndex -> Cabal.Dependency -> Bool dependencySatisfiable pindex dep@(Cabal.Dependency pn _rang _lib) | Cabal.unPackageName pn == "Win32" = False -- only exists on windows, not in linux- | not . null $ lookupDependency pindex (depPkgName dep) (depVerRange dep) = True -- the package index satisfies the dep+ | not . null $ lookupDependency pindex (Cabal.depPkgName dep) (Cabal.depVerRange dep) = True -- the package index satisfies the dep | packageIsCoreInAnyGHC pn = False -- some other ghcs support the dependency | otherwise = True -- the dep is not related with core packages, accept the dep @@ -107,6 +130,9 @@ | g@(cinfo, pix) <- ghcs , Right (pkg_desc, picked_flags) <- return (packageBuildableWithGHCVersion gpd user_specified_fas g)] +-- | Create an 'InstalledPackageIndex' from a ['Cabal.PackageIdentifier'].+-- This is used to generate an index of core @GHC@ packages from the provided+-- ['Cabal.PackageIdentifier'] functions, e.g. 'ghc883_pkgs'. mkIndex :: [Cabal.PackageIdentifier] -> InstalledPackageIndex mkIndex pids = fromList [ emptyInstalledPackageInfo@@ -125,6 +151,9 @@ ghc8101 :: (DC.CompilerInfo, InstalledPackageIndex) ghc8101 = (ghc [8,10,1], mkIndex ghc8101_pkgs) +ghc884 :: (DC.CompilerInfo, InstalledPackageIndex)+ghc884 = (ghc [8,8,4], mkIndex ghc884_pkgs)+ ghc883 :: (DC.CompilerInfo, InstalledPackageIndex) ghc883 = (ghc [8,8,3], mkIndex ghc883_pkgs) @@ -202,6 +231,39 @@ , p "template-haskell" [2,16,0,0] -- used by libghc -- , p "terminfo" [0,4,1,4] -- , p "text" [1,2,3,2] dependency of Cabal library+ , p "time" [1,9,3,0] -- used by unix, directory, hpc, ghc. unsafe to upgrade+ , p "transformers" [0,5,6,2] -- used by libghc+ , p "unix" [2,7,2,2]+-- , p "xhtml" [3000,2,2,1]+ ]++ghc884_pkgs :: [Cabal.PackageIdentifier]+ghc884_pkgs =+ [ p "array" [0,5,4,0]+ , p "base" [4,13,0,0]+ , p "binary" [0,8,7,0] -- used by libghc+ , p "bytestring" [0,10,10,1]+-- , p "Cabal" [3,0,1,0] package is upgradeable+ , p "containers" [0,6,2,1]+ , p "deepseq" [1,4,4,0] -- used by time+ , p "directory" [1,3,6,0]+ , p "filepath" [1,4,2,1]+ , p "ghc-boot" [8,8,4]+ , p "ghc-boot-th" [8,8,4]+ , p "ghc-compact" [0,1,0,0]+ , p "ghc-prim" [0,5,3,0]+ , p "ghci" [8,8,4]+-- , p "haskeline" [0,7,5,0] package is upgradeable+ , p "hpc" [0,6,0,3] -- used by libghc+ , p "integer-gmp" [1,0,2,0]+ -- , p "mtl" [2,2,2] package is upgradeable(?)+ -- , p "parsec" [3,1,14,0] package is upgradeable(?)+ , p "pretty" [1,1,3,6]+ , p "process" [1,6,9,0]+ -- , p "stm" [2,5,0,0] package is upgradeable(?)+ , p "template-haskell" [2,15,0,0] -- used by libghc+ -- , p "terminfo" [0,4,1,4]+ -- , p "text" [1,2,4,0] dependency of Cabal library , p "time" [1,9,3,0] -- used by unix, directory, hpc, ghc. unsafe to upgrade , p "transformers" [0,5,6,2] -- used by libghc , p "unix" [2,7,2,2]
Portage/Metadata.hs view
@@ -1,46 +1,109 @@+{-|+Module : Portage.Metadata+License : GPL-3++Maintainer : haskell@gentoo.org++Functions and types related to @metadata.xml@ processing+-} module Portage.Metadata ( Metadata(..) , metadataFromFile+ , pureMetadataFromFile+ , prettyPrintFlags -- exported for hspec+ , prettyPrintFlagsHuman , makeDefaultMetadata+ , makeMinimalMetadata ) where -import qualified Data.ByteString as B+import qualified AnsiColor as A +import qualified Data.Text as T+import qualified Data.Text.IO as T+import qualified Data.Map.Strict as Map+ import Text.XML.Light -newtype Metadata = Metadata- { metadata_emails :: [String]- -- , metadataMaintainers :: [String],- -- , metadataUseFlags :: [(String,String)]- } deriving (Show)+-- | A data type for the Gentoo-specific @metadata.xml@ file.+-- Currently defines functions for the maintainer email and+-- USE flags and their descriptions.+data Metadata = Metadata+ { metadataEmails :: [String] -- ^ This should /always/ be [\"haskell@gentoo.org\"].+ , metadataUseFlags :: Map.Map String String -- ^ Only /active/ USE flags, if any.+ } deriving (Eq, Show) +-- | Maybe return a 'Metadata' from a 'T.Text'.+--+-- Trying to parse an empty 'T.Text' should return 'Nothing':+--+-- prop> pureMetadataFromFile T.empty == Nothing+--+-- Parsing a @metadata.xml@ /without/ USE flags should /always/ be equivalent+-- to 'makeMinimalMetadata', no matter the package description:+--+-- prop> \desc -> pureMetadataFromFile (makeDefaultMetadata desc Map.empty) == Just makeMinimalMetadata+--+-- Parsing a @metadata.xml@ /with/ USE flags should /always/ be equivalent+-- to 'makeMinimalMetadata' /plus/ the supplied USE flags, no matter the+-- package description:+--+-- prop> \desc -> pureMetadataFromFile (makeDefaultMetadata desc (Map.fromList [("name","description")])) == Just (makeMinimalMetadata {metadataUseFlags = Map.fromList [("name","description")] } )+pureMetadataFromFile :: T.Text -> Maybe Metadata+pureMetadataFromFile file = parseXMLDoc file >>= \doc -> parseMetadata doc++-- | Apply 'pureMetadataFromFile' to a 'FilePath'. metadataFromFile :: FilePath -> IO (Maybe Metadata)-metadataFromFile fp = do- doc <- parseXMLDoc <$> B.readFile fp- return (doc >>= parseMetadata)+metadataFromFile fp = pureMetadataFromFile <$> T.readFile fp +-- | Extract the maintainer email and USE flags from a supplied XML 'Element'.+-- +-- If we're parsing a blank 'Element' or otherwise empty @metadata.xml@:+-- >>> parseMetadata blank_element+-- Just (Metadata {metadataEmails = [], metadataUseFlags = fromList []}) parseMetadata :: Element -> Maybe Metadata parseMetadata xml =- return Metadata { metadata_emails = map strContent (findElements (unqual "email") xml) }+ return Metadata { metadataEmails = strContent <$> findElements (unqual "email") xml+ , metadataUseFlags =+ -- find the flag name+ let x = findElement (unqual "use") xml+ y = onlyElems $ concatMap elContent x+ z = attrVal <$> concatMap elAttribs y+ -- find the flag description+ a = concatMap elContent y+ b = cdData <$> onlyText a+ in Map.fromList $ zip z b+ } -formatFlags :: (String, String) -> String-formatFlags (name, description) = "\t\t<flag name=\"" ++ name ++- "\">" ++ description ++ "</flag>"+-- | Pretty print as valid XML a list of flags and their descriptions+-- from a given 'Map.Map'.+prettyPrintFlags :: Map.Map String String -> [String]+prettyPrintFlags m = (\(name,description) -> "\t\t<flag name=\"" ++ name +++ "\">" ++ description ++ "</flag>")+ <$> Map.toAscList m +-- | Pretty print a human-readable list of flags and their descriptions+-- from a given 'Map.Map'.+prettyPrintFlagsHuman :: Map.Map String String -> [String]+prettyPrintFlagsHuman m = (\(name,description) -> A.bold (name ++ ": ") ++ description)+ <$> Map.toAscList m+ +-- | A minimal metadata for use as a fallback value.+makeMinimalMetadata :: Metadata+makeMinimalMetadata = Metadata { metadataEmails = ["haskell@gentoo.org"]+ , metadataUseFlags = Map.empty+ }+ -- don't use Text.XML.Light as we like our own pretty printer-makeDefaultMetadata :: String -> [(String, String)] -> String+-- | Pretty print the @metadata.xml@ string.+makeDefaultMetadata :: String -> Map.Map String String -> T.Text makeDefaultMetadata long_description flags =- unlines [ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"+ T.pack $ unlines [ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" , "<!DOCTYPE pkgmetadata SYSTEM \"http://www.gentoo.org/dtd/metadata.dtd\">" , "<pkgmetadata>" , "\t<maintainer type=\"project\">" , "\t\t<email>haskell@gentoo.org</email>" , "\t\t<name>Gentoo Haskell</name>" , "\t</maintainer>"- , if (formatFlags <$> flags) == [""]- then "\t<use>\n\t</use>"- else "\t<use>\n" ++ (unlines $ formatFlags <$> flags) ++- "\t</use>"+ , "\t<use>\n" ++ (unlines $ prettyPrintFlags flags) ++ "\t</use>" , (init {- strip trailing newline-} . unlines . map (\l -> if l `elem` ["<longdescription>", "</longdescription>"]
Portage/Overlay.hs view
@@ -40,12 +40,14 @@ instance Cabal.HasUnitId ExistingEbuild where installedUnitId _ = error "Portage.Cabal.installedUnitId: FIXME: should not be used" +-- | Type describing an overlay. data Overlay = Overlay { overlayPath :: FilePath, overlayMap :: Map Portage.PackageName [ExistingEbuild], overlayMetadata :: Map Portage.PackageName Portage.Metadata } deriving Show +-- | Is 'Cabal.PackageId' found in 'Overlay'? inOverlay :: Overlay -> Cabal.PackageId -> Bool inOverlay overlay pkgId = not (Map.null packages) where@@ -106,22 +108,21 @@ , overlayMap = pkgMap' } where- metadataMap' = Map.filter (p . Portage.metadata_emails) (overlayMetadata overlay)+ metadataMap' = Map.filter (p . Portage.metadataEmails) (overlayMetadata overlay) pkgMap' = Map.intersection (overlayMap overlay) metadataMap' --- make sure there is only one ebuild for each version number (by selecting+-- | Make sure there is only one ebuild for each version number (by selecting -- the highest ebuild version revision) reduceOverlay :: Overlay -> Overlay reduceOverlay overlay = overlay { overlayMap = Map.map reduceVersions (overlayMap overlay) } where versionNumbers (Portage.Version nums _ _ _) = nums reduceVersions :: [ExistingEbuild] -> [ExistingEbuild]- reduceVersions ebuilds = -- gah!+ reduceVersions = -- gah! map (maximumBy (comparing (Portage.pkgVersion . ebuildId))) . groupBy (equating (versionNumbers . Portage.pkgVersion . ebuildId))- . sortBy (comparing (Portage.pkgVersion . ebuildId))- $ ebuilds+ . sortOn (Portage.pkgVersion . ebuildId) readOverlayByPackage :: DirectoryTree -> [(Portage.PackageName, [Portage.Version])] readOverlayByPackage tree =
Portage/PackageId.hs view
@@ -1,7 +1,11 @@ {-# LANGUAGE CPP #-}+{-|+Module : Portage.PackageId+License : GPL-3++Maintainer : haskell@gentoo.org --- | Portage package identifiers, which unlike Cabal ones include a category.---+Portage package identifiers, which unlike Cabal ones include a category.+-} module Portage.PackageId ( Category(..), PackageName(..),@@ -18,19 +22,17 @@ cabal_pn_to_PN ) where -import qualified Distribution.Package as Cabal--import Distribution.Parsec (CabalParsing(..), Parsec(..), explicitEitherParsec) import qualified Distribution.Compat.CharParsing as P+import qualified Distribution.Package as Cabal+import Distribution.Parsec (CabalParsing(..), Parsec(..), explicitEitherParsec)+import Distribution.Pretty (Pretty(..), prettyShow) import qualified Portage.Version as Portage +import qualified Data.Char as Char import qualified Text.PrettyPrint as Disp-import Text.PrettyPrint ((<>))-import qualified Data.Char as Char (isAlphaNum, toLower)--import Distribution.Pretty (Pretty(..), prettyShow)-import System.FilePath ((</>))+import Text.PrettyPrint ((<>))+import System.FilePath ((</>)) #if MIN_VERSION_base(4,11,0) import Prelude hiding ((<>))@@ -39,9 +41,11 @@ newtype Category = Category { unCategory :: String } deriving (Eq, Ord, Show, Read) +-- | Portage-style 'PackageName', containing a 'Category' and a 'Cabal.PackageName'. data PackageName = PackageName { category :: Category, cabalPkgName :: Cabal.PackageName } deriving (Eq, Ord, Show, Read) +-- | Portage-style 'PackageId', containing a 'PackageName' and a 'Portage.Version'. data PackageId = PackageId { packageId :: PackageName, pkgVersion :: Portage.Version } deriving (Eq, Ord, Show, Read) @@ -54,15 +58,15 @@ categoryChar c = Char.isAlphaNum c || c == '-' instance Pretty PackageName where- pretty (PackageName category name) =- pretty category <> Disp.char '/' <> pretty name+ pretty (PackageName cat name) =+ pretty cat <> Disp.char '/' <> pretty name instance Parsec PackageName where parsec = do- category <- parsec+ cat <- parsec _ <- P.char '/' name <- parseCabalPackageName- return $ PackageName category name+ return $ PackageName cat name instance Pretty PackageId where pretty (PackageId name version) =@@ -75,6 +79,10 @@ version <- parsec return $ PackageId name version +-- | Transform a 'PackageId' into a 'FilePath'.+-- +-- >>> packageIdToFilePath (PackageId (PackageName (Category "dev-haskell") (Cabal.mkPackageName "foo-bar2")) (Portage.Version [3,0,0] (Just 'b') [Portage.RC 2] 1 ))+-- "dev-haskell/foo-bar2/foo-bar2-3.0.0b_rc2-r1.ebuild" packageIdToFilePath :: PackageId -> FilePath packageIdToFilePath (PackageId (PackageName cat pn) version) = prettyShow cat </> prettyShow pn </> prettyShow pn <-> prettyShow version <.> "ebuild"@@ -82,12 +90,11 @@ a <-> b = a ++ '-':b a <.> b = a ++ '.':b --- TODO: fix the parser such that it can tolerate malformed package strings,--- strings with ".ebuild" extensions and strings which are not in fact package--- strings at all (e.g. metadata.xml). Then we can eliminate the string manipulation--- present in Merge.getPreviousPackageId, which ensures this function is only fed--- well-formed package strings, i.e <name>-<version>.--- | Maybe generate a PackageId from a FilePath.+-- | Maybe generate a 'PackageId' from a 'FilePath'. Note that the 'FilePath' must have its+-- file extension stripped before being passed to 'filePathToPackageId'.+-- +-- >>> filePathToPackageId (Category "dev-haskell") "foo-bar2-3.0.0b_rc2-r1"+-- Just (PackageId {packageId = PackageName {category = Category {unCategory = "dev-haskell"}, cabalPkgName = PackageName "foo-bar2"}, pkgVersion = Version {versionNumber = [3,0,0], versionChar = Just 'b', versionSuffix = [RC 2], versionRevision = 1}}) filePathToPackageId :: Category -> FilePath -> Maybe PackageId filePathToPackageId cat fp = case explicitEitherParsec parser fp of@@ -100,27 +107,52 @@ v <- parsec return $ PackageId (PackageName cat pn) v +-- | Create a 'PackageName' from supplied category and package name 'String's. mkPackageName :: String -> String -> PackageName mkPackageName cat package = PackageName (Category cat) (Cabal.mkPackageName package) +-- | Create a 'PackageId' from a 'Category' and 'Cabal.PackageIdentifier'. fromCabalPackageId :: Category -> Cabal.PackageIdentifier -> PackageId-fromCabalPackageId category (Cabal.PackageIdentifier name version) =- PackageId (PackageName category (normalizeCabalPackageName name))+fromCabalPackageId cat (Cabal.PackageIdentifier name version) =+ PackageId (PackageName cat (normalizeCabalPackageName name)) (Portage.fromCabalVersion version) +-- | Convert a 'Cabal.PackageName' into lowercase. Internally uses+-- 'cabal_pn_to_PN'.+--+-- >>> normalizeCabalPackageName (Cabal.mkPackageName "FooBar1")+-- PackageName "foobar1" normalizeCabalPackageName :: Cabal.PackageName -> Cabal.PackageName normalizeCabalPackageName =- Cabal.mkPackageName . map Char.toLower . Cabal.unPackageName+ Cabal.mkPackageName . cabal_pn_to_PN +-- | Apply 'normalizeCabalPackageName' to the 'Cabal.PackageName' of+-- a supplied 'Cabal.PackageIdentifier'. normalizeCabalPackageId :: Cabal.PackageIdentifier -> Cabal.PackageIdentifier normalizeCabalPackageId (Cabal.PackageIdentifier name version) = Cabal.PackageIdentifier (normalizeCabalPackageName name) version +-- | Convert a 'PackageId' into a 'Maybe' 'Cabal.PackageIdentifier'. toCabalPackageId :: PackageId -> Maybe Cabal.PackageIdentifier toCabalPackageId (PackageId (PackageName _cat name) version) = fmap (Cabal.PackageIdentifier name) (Portage.toCabalVersion version) +-- | Parse a 'String' as a package in the form of @[category\/]name[-version]@:+--+-- Note that we /cannot/ use the 'parsec' function to parse the 'Cabal.PackageName',+-- since it fails the entire parse if it tries to parse a 'Version'.+-- See 'parseCabalPackageName' below.+--+-- If parsing a valid package string:+-- +-- >>> parseFriendlyPackage "category-name/package-name1-0.0.0.1a_beta2-r4"+-- Right (Just (Category {unCategory = "category-name"}),PackageName "package-name1",Just (Version {versionNumber = [0,0,0,1], versionChar = Just 'a', versionSuffix = [Beta 2], versionRevision = 4}))+--+-- If malformed, return an error string:+--+-- >>> parseFriendlyPackage "category-name/package-name-1-0.0.0.1a_beta2-r4"+-- Left ... parseFriendlyPackage :: String -> Either String (Maybe Category, Cabal.PackageName, Maybe Portage.Version) parseFriendlyPackage str = explicitEitherParsec parser str where@@ -136,18 +168,26 @@ return v return (mc, p, mv) --- | Parse a Cabal PackageName. Note that we cannot use the @parsec@--- method as defined in the @Parsec PackageName@ instance, since it--- fails the entire PackageName parse if it tries to parse a version--- number.+-- | Parse a 'Cabal.PackageName'.+--+-- This parser is a replacement for 'parsecUnqualComponentName' which fails when+-- trying to parse a 'Version'. parseCabalPackageName :: CabalParsing m => m Cabal.PackageName parseCabalPackageName = do pn <- P.some . P.try $ P.choice [ P.alphaNum+ , P.char '+' , P.char '-' <* P.notFollowedBy (P.some P.digit <* P.notFollowedBy P.letter) ] return $ Cabal.mkPackageName pn +-- | Pretty-print a lowercase 'Cabal.PackageName'.+--+-- Note the difference between this function and 'normalizeCabalPackageName':+-- this function returns a 'String', the other a 'Cabal.PackageName'.+--+-- >>> cabal_pn_to_PN (Cabal.mkPackageName "FooBar1")+-- "foobar1" cabal_pn_to_PN :: Cabal.PackageName -> String cabal_pn_to_PN = map Char.toLower . prettyShow
Portage/Tables.hs view
@@ -1,4 +1,10 @@--- | Tables of portage specific convertations+{-|+Module : Portage.Tables+License : GPL-3++Maintainer : haskell@gentoo.org++Tables of Portage-specific conversions.+-} module Portage.Tables ( set_build_slot ) where@@ -9,10 +15,11 @@ import Data.Monoid +-- | Set the @SLOT@ for a given 'Dependency'. set_build_slot :: Dependency -> Dependency set_build_slot = overAtom $ \a@(Atom pn dr (DAttr _ u)) -> - case mconcat $ map First $ map (matches a) slottedPkgs of+ case mconcat $ map (First . matches a) slottedPkgs of First (Just s) -> Atom pn dr (DAttr s u) First Nothing -> Atom pn dr (DAttr AnyBuildTimeSlot u) where@@ -20,6 +27,9 @@ | pn == nm = Just s | otherwise = Nothing +-- | List of 'PackageName's with their corresponding default 'SlotDepend's.+--+-- For example, dependency @QuickCheck@ has its @SLOT@ always set to @2@. slottedPkgs :: [(PackageName, SlotDepend)] slottedPkgs = [ (mkPackageName "dev-haskell" "quickcheck", GivenSlot "2=")
Portage/Version.hs view
@@ -1,5 +1,4 @@ {-# LANGUAGE CPP #-}- {-| Author : Andres Loeh <kosmikus@gentoo.org> Stability : provisional@@ -10,7 +9,6 @@ Shamelessly borrowed from exi, ported from Parsec to ReadP -}- module Portage.Version ( Version(..), Suffix(..),@@ -21,26 +19,27 @@ import qualified Distribution.Version as Cabal -import Distribution.Pretty (Pretty(..))+import Distribution.Pretty (Pretty(..)) -import Distribution.Parsec (Parsec(..))+import Distribution.Parsec (Parsec(..)) import qualified Distribution.Compat.CharParsing as P import qualified Text.PrettyPrint as Disp-import Text.PrettyPrint ((<>))-import qualified Data.Char as Char (isAlpha, isDigit)-import qualified Data.List.NonEmpty as NonEmpty+import Text.PrettyPrint ((<>))+import qualified Data.List.NonEmpty as NE #if MIN_VERSION_base(4,11,0) import Prelude hiding ((<>)) #endif -data Version = Version { versionNumber :: [Int] -- [1,42,3] ~= 1.42.3- , versionChar :: (Maybe Char) -- optional letter+-- | Portage-style version type.+data Version = Version { versionNumber :: [Int] -- ^ @[1,42,3]@ ~= 1.42.3+ , versionChar :: (Maybe Char) -- ^ optional letter , versionSuffix :: [Suffix]- , versionRevision :: Int -- revision, 0 means none+ , versionRevision :: Int -- ^ revision, 0 means none } deriving (Eq, Ord, Show, Read) +-- | Prints a valid Portage 'Version' string. instance Pretty Version where pretty (Version ver c suf rev) = dispVer ver <> dispC c <> dispSuf suf <> dispRev rev@@ -51,16 +50,32 @@ dispRev 0 = Disp.empty dispRev n = Disp.text "-r" <> Disp.int n +-- | 'Version' parser using 'Parsec'. instance Parsec Version where parsec = do ver <- P.sepByNonEmpty digits (P.char '.')- c <- P.optional $ P.satisfy Char.isAlpha+ c <- P.optional P.lower suf <- P.many parsec rev <- P.option 0 $ P.string "-r" *> digits- return $ Version (NonEmpty.toList ver) c suf rev- + return $ Version (NE.toList ver) c suf rev++-- | Check if the ebuild is a live ebuild, i.e. if its 'Version' is @9999@.+-- -- foo-9999* is treated as live ebuild -- Cabal-1.17.9999* as well+--+-- >>> let (c,s,r) = (Nothing,[],0)+-- >>> is_live (Version [1,0,0] c s r)+-- False+-- >>> is_live (Version [999] c s r)+-- False+-- >>> is_live (Version [1,0,0,9999] c s r)+-- True+-- >>> is_live (Version [9999] c s r)+-- True+--+-- $+-- prop> \verNum char rev -> is_live (Version verNum char [] rev) == if length verNum >= 1 && last verNum >= 9999 then True else False is_live :: Version -> Bool is_live v = case vs of@@ -72,6 +87,7 @@ is_big n = n >= 9999 all_nines n = (all (== '9') . show) n +-- | Various allowed suffixes in Portage versions. data Suffix = Alpha Int | Beta Int | Pre Int | RC Int | P Int deriving (Eq, Ord, Show, Read) @@ -90,22 +106,29 @@ instance Parsec Suffix where parsec = P.char '_'- >> P.choice- [ P.string "alpha" >> fmap Alpha maybeDigits- , P.string "beta" >> fmap Beta maybeDigits- , P.string "pre" >> fmap Pre maybeDigits- , P.string "rc" >> fmap RC maybeDigits- , P.string "p" >> fmap P maybeDigits+ *> P.choice+ [ P.string "alpha" >> fmap Alpha maybeDigits+ , P.string "beta" >> fmap Beta maybeDigits+ , P.try (P.string "pre") >> fmap Pre maybeDigits+ , P.string "rc" >> fmap RC maybeDigits+ , P.string "p" >> fmap P maybeDigits ] where maybeDigits = P.option 0 digits +-- | Convert from a 'Cabal.Version' to a Portage 'Version'.+-- +-- prop> \verNum -> fromCabalVersion (Cabal.mkVersion verNum) == Version verNum Nothing [] 0 fromCabalVersion :: Cabal.Version -> Version fromCabalVersion cabal_version = Version (Cabal.versionNumbers cabal_version) Nothing [] 0 +-- | Convert from a Portage 'Version' to a 'Cabal.Version'.+-- $+-- prop> \verNum char rev -> toCabalVersion (Version verNum char [] rev) == if char == Nothing then Just (Cabal.mkVersion verNum) else Nothing toCabalVersion :: Version -> Maybe Cabal.Version toCabalVersion (Version nums Nothing [] _) = Just (Cabal.mkVersion nums) toCabalVersion _ = Nothing +-- | Parser which munches digits. digits :: P.CharParsing m => m Int-digits = read <$> P.munch1 Char.isDigit+digits = read <$> P.some P.digit
README.rst view
@@ -1,6 +1,11 @@ Hackport ======== +.. image:: https://img.shields.io/hackage/v/hackport+ :target: https://hackage.haskell.org/package/hackport+.. image:: https://github.com/gentoo-haskell/hackport/workflows/Haskell%20CI/badge.svg+ :target: https://github.com/gentoo-haskell/hackport/actions?query=workflow%3A%22Haskell+CI%22+ About -----
Status.hs view
@@ -85,7 +85,7 @@ _ -> {- ambig -} Category "dev-haskell" pkg_infos = map ( reverse . take 3 . reverse -- hackage usually has a ton of older versions . map ((\p -> fromCabalPackageId (get_cat p) p)- . CabalInstall.packageInfoId))+ . CabalInstall.srcpkgPackageId)) (CabalInstall.allPackagesByName pindex) return pkg_infos
+ cabal/.docker/validate-7.10.3.dockerfile view
@@ -0,0 +1,78 @@+FROM phadej/ghc:7.10.3-bionic++# Install cabal-plan+RUN mkdir -p /root/.cabal/bin && \+ curl -L https://github.com/haskell-hvr/cabal-plan/releases/download/v0.6.2.0/cabal-plan-0.6.2.0-x86_64-linux.xz > cabal-plan.xz && \+ echo "de73600b1836d3f55e32d80385acc055fd97f60eaa0ab68a755302685f5d81bc cabal-plan.xz" | sha256sum -c - && \+ xz -d < cabal-plan.xz > /root/.cabal/bin/cabal-plan && \+ rm -f cabal-plan.xz && \+ chmod a+x /root/.cabal/bin/cabal-plan++# Install cabal-env+RUN curl -sL https://github.com/phadej/cabal-extras/releases/download/preview-20191225/cabal-env-snapshot-20191225-x86_64-linux.xz > cabal-env.xz && \+ echo "1b567d529c5f627fd8c956e57ae8f0d9f11ee66d6db34b7fb0cb1c370b4edf01 cabal-env.xz" | sha256sum -c - && \+ xz -d < cabal-env.xz > $HOME/.cabal/bin/cabal-env && \+ rm -f cabal-env.xz && \+ chmod a+x $HOME/.cabal/bin/cabal-env+++# Update index+RUN cabal v2-update --index-state="2020-06-12T23:36:15Z"++# We install happy, so it's in the store; we (hopefully) don't use it directly.+RUN cabal v2-install happy --constraint 'happy ^>=1.19.12'++# Install some other dependencies+# Remove $HOME/.ghc so there aren't any environments+RUN cabal v2-install -w ghc-7.10.3 --lib \+ Cabal \+ aeson \+ async \+ base-compat \+ base16-bytestring \+ base64-bytestring \+ cryptohash-sha256 \+ Diff \+ echo \+ ed25519 \+ edit-distance \+ HTTP \+ lukko \+ network \+ optparse-applicative \+ pretty-show \+ regex-compat-tdfa \+ regex-posix \+ regex-tdfa \+ rere \+ statistics \+ tar \+ tasty \+ tasty-golden \+ tasty-hunit \+ tasty-quickcheck \+ tree-diff \+ void \+ zlib \+ resolv \+ parsec \+ text \+ --constraint="rere -rere-cfg" \+ --constraint="these -assoc" \+ --constraint="bytestring installed" \+ --constraint="binary installed" \+ --constraint="containers installed" \+ --constraint="deepseq installed" \+ --constraint="directory installed" \+ --constraint="filepath installed" \+ --constraint="pretty installed" \+ --constraint="process installed" \+ --constraint="time installed" \+ --constraint="unix installed" \+ --constraint="transformers installed" \+ && rm -rf $HOME/.ghc++# Validate+WORKDIR /build+COPY . /build+RUN sh ./validate.sh -w ghc-7.10.3 -v
+ cabal/.docker/validate-7.6.3.dockerfile view
@@ -0,0 +1,79 @@+FROM phadej/ghc:7.6.3-xenial++# Install cabal-plan+RUN mkdir -p /root/.cabal/bin && \+ curl -L https://github.com/haskell-hvr/cabal-plan/releases/download/v0.6.2.0/cabal-plan-0.6.2.0-x86_64-linux.xz > cabal-plan.xz && \+ echo "de73600b1836d3f55e32d80385acc055fd97f60eaa0ab68a755302685f5d81bc cabal-plan.xz" | sha256sum -c - && \+ xz -d < cabal-plan.xz > /root/.cabal/bin/cabal-plan && \+ rm -f cabal-plan.xz && \+ chmod a+x /root/.cabal/bin/cabal-plan++# Install cabal-env+RUN curl -sL https://github.com/phadej/cabal-extras/releases/download/preview-20191225/cabal-env-snapshot-20191225-x86_64-linux.xz > cabal-env.xz && \+ echo "1b567d529c5f627fd8c956e57ae8f0d9f11ee66d6db34b7fb0cb1c370b4edf01 cabal-env.xz" | sha256sum -c - && \+ xz -d < cabal-env.xz > $HOME/.cabal/bin/cabal-env && \+ rm -f cabal-env.xz && \+ chmod a+x $HOME/.cabal/bin/cabal-env++# We need newer compiler, to install cabal-plan+RUN apt-get update+RUN apt-get install -y ghc-7.6.3-dyn++# Update index+RUN cabal v2-update --index-state="2020-06-12T23:36:15Z"++# We install happy, so it's in the store; we (hopefully) don't use it directly.+RUN cabal v2-install happy --constraint 'happy ^>=1.19.12'++# Install some other dependencies+# Remove $HOME/.ghc so there aren't any environments+RUN cabal v2-install -w ghc-7.6.3 --lib \+ Cabal \+ aeson \+ async \+ base-compat \+ base16-bytestring \+ base64-bytestring \+ cryptohash-sha256 \+ Diff \+ echo \+ ed25519 \+ edit-distance \+ HTTP \+ lukko \+ network \+ optparse-applicative \+ pretty-show \+ regex-compat-tdfa \+ regex-posix \+ regex-tdfa \+ rere \+ statistics \+ tar \+ tasty \+ tasty-golden \+ tasty-hunit \+ tasty-quickcheck \+ tree-diff \+ void \+ zlib \+ parsec \+ text \+ --constraint="rere -rere-cfg" \+ --constraint="these -assoc" \+ --constraint="bytestring installed" \+ --constraint="binary installed" \+ --constraint="containers installed" \+ --constraint="deepseq installed" \+ --constraint="directory installed" \+ --constraint="filepath installed" \+ --constraint="pretty installed" \+ --constraint="process installed" \+ --constraint="time installed" \+ --constraint="unix installed" \+ && rm -rf $HOME/.ghc++# Validate+WORKDIR /build+COPY . /build+RUN sh ./validate.sh --lib-only -w ghc-7.6.3 -v
+ cabal/.docker/validate-7.8.4.dockerfile view
@@ -0,0 +1,80 @@+FROM phadej/ghc:7.8.4-xenial++# Install cabal-plan+RUN mkdir -p /root/.cabal/bin && \+ curl -L https://github.com/haskell-hvr/cabal-plan/releases/download/v0.6.2.0/cabal-plan-0.6.2.0-x86_64-linux.xz > cabal-plan.xz && \+ echo "de73600b1836d3f55e32d80385acc055fd97f60eaa0ab68a755302685f5d81bc cabal-plan.xz" | sha256sum -c - && \+ xz -d < cabal-plan.xz > /root/.cabal/bin/cabal-plan && \+ rm -f cabal-plan.xz && \+ chmod a+x /root/.cabal/bin/cabal-plan++# Install cabal-env+RUN curl -sL https://github.com/phadej/cabal-extras/releases/download/preview-20191225/cabal-env-snapshot-20191225-x86_64-linux.xz > cabal-env.xz && \+ echo "1b567d529c5f627fd8c956e57ae8f0d9f11ee66d6db34b7fb0cb1c370b4edf01 cabal-env.xz" | sha256sum -c - && \+ xz -d < cabal-env.xz > $HOME/.cabal/bin/cabal-env && \+ rm -f cabal-env.xz && \+ chmod a+x $HOME/.cabal/bin/cabal-env++# We need newer compiler, to install cabal-plan+RUN apt-get update+RUN apt-get install -y ghc-7.8.4-dyn++# Update index+RUN cabal v2-update --index-state="2020-06-12T23:36:15Z"++# We install happy, so it's in the store; we (hopefully) don't use it directly.+RUN cabal v2-install happy --constraint 'happy ^>=1.19.12'++# Install some other dependencies+# Remove $HOME/.ghc so there aren't any environments+RUN cabal v2-install -w ghc-7.8.4 --lib \+ Cabal \+ aeson \+ async \+ base-compat \+ base16-bytestring \+ base64-bytestring \+ cryptohash-sha256 \+ Diff \+ echo \+ ed25519 \+ edit-distance \+ HTTP \+ lukko \+ network \+ optparse-applicative \+ pretty-show \+ regex-compat-tdfa \+ regex-posix \+ regex-tdfa \+ rere \+ statistics \+ tar \+ tasty \+ tasty-golden \+ tasty-hunit \+ tasty-quickcheck \+ tree-diff \+ void \+ zlib \+ parsec \+ text \+ --constraint="rere -rere-cfg" \+ --constraint="these -assoc" \+ --constraint="bytestring installed" \+ --constraint="binary installed" \+ --constraint="containers installed" \+ --constraint="deepseq installed" \+ --constraint="directory installed" \+ --constraint="filepath installed" \+ --constraint="pretty installed" \+ --constraint="process installed" \+ --constraint="time installed" \+ --constraint="unix installed" \+ --constraint="transformers installed" \+ && rm -rf $HOME/.ghc++# Validate+WORKDIR /build+COPY . /build+RUN sh ./validate.sh --lib-only -w ghc-7.8.4 -v
+ cabal/.docker/validate-8.0.2.dockerfile view
@@ -0,0 +1,69 @@+FROM phadej/ghc:8.0.2-bionic++# Install cabal-plan+RUN mkdir -p /root/.cabal/bin && \+ curl -L https://github.com/haskell-hvr/cabal-plan/releases/download/v0.6.2.0/cabal-plan-0.6.2.0-x86_64-linux.xz > cabal-plan.xz && \+ echo "de73600b1836d3f55e32d80385acc055fd97f60eaa0ab68a755302685f5d81bc cabal-plan.xz" | sha256sum -c - && \+ xz -d < cabal-plan.xz > /root/.cabal/bin/cabal-plan && \+ rm -f cabal-plan.xz && \+ chmod a+x /root/.cabal/bin/cabal-plan+++# Update index+RUN cabal v2-update --index-state="2020-06-12T23:36:15Z"++# We install happy, so it's in the store; we (hopefully) don't use it directly.+RUN cabal v2-install happy --constraint 'happy ^>=1.19.12'++# Install some other dependencies+# Remove $HOME/.ghc so there aren't any environments+RUN cabal v2-install -w ghc-8.0.2 --lib \+ Cabal \+ aeson \+ async \+ base-compat \+ base16-bytestring \+ base64-bytestring \+ cryptohash-sha256 \+ Diff \+ echo \+ ed25519 \+ edit-distance \+ HTTP \+ lukko \+ network \+ optparse-applicative \+ pretty-show \+ regex-compat-tdfa \+ regex-posix \+ regex-tdfa \+ rere \+ statistics \+ tar \+ tasty \+ tasty-golden \+ tasty-hunit \+ tasty-quickcheck \+ tree-diff \+ void \+ zlib \+ resolv \+ --constraint="rere -rere-cfg" \+ --constraint="these -assoc" \+ --constraint="bytestring installed" \+ --constraint="binary installed" \+ --constraint="containers installed" \+ --constraint="deepseq installed" \+ --constraint="directory installed" \+ --constraint="filepath installed" \+ --constraint="pretty installed" \+ --constraint="process installed" \+ --constraint="time installed" \+ --constraint="unix installed" \+ --constraint="transformers installed" \+ && rm -rf $HOME/.ghc++# Validate+WORKDIR /build+COPY . /build+RUN sh ./validate.sh -w ghc-8.0.2 -v
+ cabal/.docker/validate-8.10.1.dockerfile view
@@ -0,0 +1,76 @@+FROM phadej/ghc:8.10.1-bionic++# Install cabal-plan+RUN mkdir -p /root/.cabal/bin && \+ curl -L https://github.com/haskell-hvr/cabal-plan/releases/download/v0.6.2.0/cabal-plan-0.6.2.0-x86_64-linux.xz > cabal-plan.xz && \+ echo "de73600b1836d3f55e32d80385acc055fd97f60eaa0ab68a755302685f5d81bc cabal-plan.xz" | sha256sum -c - && \+ xz -d < cabal-plan.xz > /root/.cabal/bin/cabal-plan && \+ rm -f cabal-plan.xz && \+ chmod a+x /root/.cabal/bin/cabal-plan++# Install cabal-env+RUN curl -sL https://github.com/phadej/cabal-extras/releases/download/preview-20191225/cabal-env-snapshot-20191225-x86_64-linux.xz > cabal-env.xz && \+ echo "1b567d529c5f627fd8c956e57ae8f0d9f11ee66d6db34b7fb0cb1c370b4edf01 cabal-env.xz" | sha256sum -c - && \+ xz -d < cabal-env.xz > $HOME/.cabal/bin/cabal-env && \+ rm -f cabal-env.xz && \+ chmod a+x $HOME/.cabal/bin/cabal-env+++# Update index+RUN cabal v2-update --index-state="2020-06-12T23:36:15Z"++# We install happy, so it's in the store; we (hopefully) don't use it directly.+RUN cabal v2-install happy --constraint 'happy ^>=1.19.12'++# Install some other dependencies+# Remove $HOME/.ghc so there aren't any environments+RUN cabal v2-install -w ghc-8.10.1 --lib \+ Cabal \+ aeson \+ async \+ base-compat \+ base16-bytestring \+ base64-bytestring \+ cryptohash-sha256 \+ Diff \+ echo \+ ed25519 \+ edit-distance \+ HTTP \+ lukko \+ network \+ optparse-applicative \+ pretty-show \+ regex-compat-tdfa \+ regex-posix \+ regex-tdfa \+ rere \+ statistics \+ tar \+ tasty \+ tasty-golden \+ tasty-hunit \+ tasty-quickcheck \+ tree-diff \+ void \+ zlib \+ resolv \+ --constraint="rere -rere-cfg" \+ --constraint="these -assoc" \+ --constraint="bytestring installed" \+ --constraint="binary installed" \+ --constraint="containers installed" \+ --constraint="deepseq installed" \+ --constraint="directory installed" \+ --constraint="filepath installed" \+ --constraint="pretty installed" \+ --constraint="process installed" \+ --constraint="time installed" \+ --constraint="unix installed" \+ --constraint="transformers installed" \+ && rm -rf $HOME/.ghc++# Validate+WORKDIR /build+COPY . /build+RUN sh ./validate.sh -w ghc-8.10.1 -v
+ cabal/.docker/validate-8.2.2.dockerfile view
@@ -0,0 +1,78 @@+FROM phadej/ghc:8.2.2-bionic++# Install cabal-plan+RUN mkdir -p /root/.cabal/bin && \+ curl -L https://github.com/haskell-hvr/cabal-plan/releases/download/v0.6.2.0/cabal-plan-0.6.2.0-x86_64-linux.xz > cabal-plan.xz && \+ echo "de73600b1836d3f55e32d80385acc055fd97f60eaa0ab68a755302685f5d81bc cabal-plan.xz" | sha256sum -c - && \+ xz -d < cabal-plan.xz > /root/.cabal/bin/cabal-plan && \+ rm -f cabal-plan.xz && \+ chmod a+x /root/.cabal/bin/cabal-plan++# Install cabal-env+RUN curl -sL https://github.com/phadej/cabal-extras/releases/download/preview-20191225/cabal-env-snapshot-20191225-x86_64-linux.xz > cabal-env.xz && \+ echo "1b567d529c5f627fd8c956e57ae8f0d9f11ee66d6db34b7fb0cb1c370b4edf01 cabal-env.xz" | sha256sum -c - && \+ xz -d < cabal-env.xz > $HOME/.cabal/bin/cabal-env && \+ rm -f cabal-env.xz && \+ chmod a+x $HOME/.cabal/bin/cabal-env+++# Update index+RUN cabal v2-update --index-state="2020-06-12T23:36:15Z"++# We install happy, so it's in the store; we (hopefully) don't use it directly.+RUN cabal v2-install happy --constraint 'happy ^>=1.19.12'++# Install some other dependencies+# Remove $HOME/.ghc so there aren't any environments+RUN cabal v2-install -w ghc-8.2.2 --lib \+ Cabal \+ aeson \+ async \+ base-compat \+ base16-bytestring \+ base64-bytestring \+ cryptohash-sha256 \+ Diff \+ echo \+ ed25519 \+ edit-distance \+ HTTP \+ lukko \+ network \+ optparse-applicative \+ pretty-show \+ regex-compat-tdfa \+ regex-posix \+ regex-tdfa \+ rere \+ statistics \+ tar \+ tasty \+ tasty-golden \+ tasty-hunit \+ tasty-quickcheck \+ tree-diff \+ void \+ zlib \+ resolv \+ parsec \+ text \+ --constraint="rere -rere-cfg" \+ --constraint="these -assoc" \+ --constraint="bytestring installed" \+ --constraint="binary installed" \+ --constraint="containers installed" \+ --constraint="deepseq installed" \+ --constraint="directory installed" \+ --constraint="filepath installed" \+ --constraint="pretty installed" \+ --constraint="process installed" \+ --constraint="time installed" \+ --constraint="unix installed" \+ --constraint="transformers installed" \+ && rm -rf $HOME/.ghc++# Validate+WORKDIR /build+COPY . /build+RUN sh ./validate.sh -w ghc-8.2.2 -v
+ cabal/.docker/validate-8.4.4.dockerfile view
@@ -0,0 +1,76 @@+FROM phadej/ghc:8.4.4-bionic++# Install cabal-plan+RUN mkdir -p /root/.cabal/bin && \+ curl -L https://github.com/haskell-hvr/cabal-plan/releases/download/v0.6.2.0/cabal-plan-0.6.2.0-x86_64-linux.xz > cabal-plan.xz && \+ echo "de73600b1836d3f55e32d80385acc055fd97f60eaa0ab68a755302685f5d81bc cabal-plan.xz" | sha256sum -c - && \+ xz -d < cabal-plan.xz > /root/.cabal/bin/cabal-plan && \+ rm -f cabal-plan.xz && \+ chmod a+x /root/.cabal/bin/cabal-plan++# Install cabal-env+RUN curl -sL https://github.com/phadej/cabal-extras/releases/download/preview-20191225/cabal-env-snapshot-20191225-x86_64-linux.xz > cabal-env.xz && \+ echo "1b567d529c5f627fd8c956e57ae8f0d9f11ee66d6db34b7fb0cb1c370b4edf01 cabal-env.xz" | sha256sum -c - && \+ xz -d < cabal-env.xz > $HOME/.cabal/bin/cabal-env && \+ rm -f cabal-env.xz && \+ chmod a+x $HOME/.cabal/bin/cabal-env+++# Update index+RUN cabal v2-update --index-state="2020-06-12T23:36:15Z"++# We install happy, so it's in the store; we (hopefully) don't use it directly.+RUN cabal v2-install happy --constraint 'happy ^>=1.19.12'++# Install some other dependencies+# Remove $HOME/.ghc so there aren't any environments+RUN cabal v2-install -w ghc-8.4.4 --lib \+ Cabal \+ aeson \+ async \+ base-compat \+ base16-bytestring \+ base64-bytestring \+ cryptohash-sha256 \+ Diff \+ echo \+ ed25519 \+ edit-distance \+ HTTP \+ lukko \+ network \+ optparse-applicative \+ pretty-show \+ regex-compat-tdfa \+ regex-posix \+ regex-tdfa \+ rere \+ statistics \+ tar \+ tasty \+ tasty-golden \+ tasty-hunit \+ tasty-quickcheck \+ tree-diff \+ void \+ zlib \+ resolv \+ --constraint="rere -rere-cfg" \+ --constraint="these -assoc" \+ --constraint="bytestring installed" \+ --constraint="binary installed" \+ --constraint="containers installed" \+ --constraint="deepseq installed" \+ --constraint="directory installed" \+ --constraint="filepath installed" \+ --constraint="pretty installed" \+ --constraint="process installed" \+ --constraint="time installed" \+ --constraint="unix installed" \+ --constraint="transformers installed" \+ && rm -rf $HOME/.ghc++# Validate+WORKDIR /build+COPY . /build+RUN sh ./validate.sh -w ghc-8.4.4 -v
+ cabal/.docker/validate-8.6.5.dockerfile view
@@ -0,0 +1,76 @@+FROM phadej/ghc:8.6.5-bionic++# Install cabal-plan+RUN mkdir -p /root/.cabal/bin && \+ curl -L https://github.com/haskell-hvr/cabal-plan/releases/download/v0.6.2.0/cabal-plan-0.6.2.0-x86_64-linux.xz > cabal-plan.xz && \+ echo "de73600b1836d3f55e32d80385acc055fd97f60eaa0ab68a755302685f5d81bc cabal-plan.xz" | sha256sum -c - && \+ xz -d < cabal-plan.xz > /root/.cabal/bin/cabal-plan && \+ rm -f cabal-plan.xz && \+ chmod a+x /root/.cabal/bin/cabal-plan++# Install cabal-env+RUN curl -sL https://github.com/phadej/cabal-extras/releases/download/preview-20191225/cabal-env-snapshot-20191225-x86_64-linux.xz > cabal-env.xz && \+ echo "1b567d529c5f627fd8c956e57ae8f0d9f11ee66d6db34b7fb0cb1c370b4edf01 cabal-env.xz" | sha256sum -c - && \+ xz -d < cabal-env.xz > $HOME/.cabal/bin/cabal-env && \+ rm -f cabal-env.xz && \+ chmod a+x $HOME/.cabal/bin/cabal-env+++# Update index+RUN cabal v2-update --index-state="2020-06-12T23:36:15Z"++# We install happy, so it's in the store; we (hopefully) don't use it directly.+RUN cabal v2-install happy --constraint 'happy ^>=1.19.12'++# Install some other dependencies+# Remove $HOME/.ghc so there aren't any environments+RUN cabal v2-install -w ghc-8.6.5 --lib \+ Cabal \+ aeson \+ async \+ base-compat \+ base16-bytestring \+ base64-bytestring \+ cryptohash-sha256 \+ Diff \+ echo \+ ed25519 \+ edit-distance \+ HTTP \+ lukko \+ network \+ optparse-applicative \+ pretty-show \+ regex-compat-tdfa \+ regex-posix \+ regex-tdfa \+ rere \+ statistics \+ tar \+ tasty \+ tasty-golden \+ tasty-hunit \+ tasty-quickcheck \+ tree-diff \+ void \+ zlib \+ resolv \+ --constraint="rere -rere-cfg" \+ --constraint="these -assoc" \+ --constraint="bytestring installed" \+ --constraint="binary installed" \+ --constraint="containers installed" \+ --constraint="deepseq installed" \+ --constraint="directory installed" \+ --constraint="filepath installed" \+ --constraint="pretty installed" \+ --constraint="process installed" \+ --constraint="time installed" \+ --constraint="unix installed" \+ --constraint="transformers installed" \+ && rm -rf $HOME/.ghc++# Validate+WORKDIR /build+COPY . /build+RUN sh ./validate.sh -w ghc-8.6.5 -v
+ cabal/.docker/validate-8.8.3.dockerfile view
@@ -0,0 +1,76 @@+FROM phadej/ghc:8.8.3-bionic++# Install cabal-plan+RUN mkdir -p /root/.cabal/bin && \+ curl -L https://github.com/haskell-hvr/cabal-plan/releases/download/v0.6.2.0/cabal-plan-0.6.2.0-x86_64-linux.xz > cabal-plan.xz && \+ echo "de73600b1836d3f55e32d80385acc055fd97f60eaa0ab68a755302685f5d81bc cabal-plan.xz" | sha256sum -c - && \+ xz -d < cabal-plan.xz > /root/.cabal/bin/cabal-plan && \+ rm -f cabal-plan.xz && \+ chmod a+x /root/.cabal/bin/cabal-plan++# Install cabal-env+RUN curl -sL https://github.com/phadej/cabal-extras/releases/download/preview-20191225/cabal-env-snapshot-20191225-x86_64-linux.xz > cabal-env.xz && \+ echo "1b567d529c5f627fd8c956e57ae8f0d9f11ee66d6db34b7fb0cb1c370b4edf01 cabal-env.xz" | sha256sum -c - && \+ xz -d < cabal-env.xz > $HOME/.cabal/bin/cabal-env && \+ rm -f cabal-env.xz && \+ chmod a+x $HOME/.cabal/bin/cabal-env+++# Update index+RUN cabal v2-update --index-state="2020-06-12T23:36:15Z"++# We install happy, so it's in the store; we (hopefully) don't use it directly.+RUN cabal v2-install happy --constraint 'happy ^>=1.19.12'++# Install some other dependencies+# Remove $HOME/.ghc so there aren't any environments+RUN cabal v2-install -w ghc-8.8.3 --lib \+ Cabal \+ aeson \+ async \+ base-compat \+ base16-bytestring \+ base64-bytestring \+ cryptohash-sha256 \+ Diff \+ echo \+ ed25519 \+ edit-distance \+ HTTP \+ lukko \+ network \+ optparse-applicative \+ pretty-show \+ regex-compat-tdfa \+ regex-posix \+ regex-tdfa \+ rere \+ statistics \+ tar \+ tasty \+ tasty-golden \+ tasty-hunit \+ tasty-quickcheck \+ tree-diff \+ void \+ zlib \+ resolv \+ --constraint="rere -rere-cfg" \+ --constraint="these -assoc" \+ --constraint="bytestring installed" \+ --constraint="binary installed" \+ --constraint="containers installed" \+ --constraint="deepseq installed" \+ --constraint="directory installed" \+ --constraint="filepath installed" \+ --constraint="pretty installed" \+ --constraint="process installed" \+ --constraint="time installed" \+ --constraint="unix installed" \+ --constraint="transformers installed" \+ && rm -rf $HOME/.ghc++# Validate+WORKDIR /build+COPY . /build+RUN sh ./validate.sh --doctest --solver-benchmarks --complete-hackage -w ghc-8.8.3 -v
+ cabal/.docker/validate-old.dockerfile view
@@ -0,0 +1,72 @@+FROM phadej/ghc:8.8.3-xenial++# Install cabal-plan+RUN mkdir -p /root/.cabal/bin && \+ curl -L https://github.com/haskell-hvr/cabal-plan/releases/download/v0.6.2.0/cabal-plan-0.6.2.0-x86_64-linux.xz > cabal-plan.xz && \+ echo "de73600b1836d3f55e32d80385acc055fd97f60eaa0ab68a755302685f5d81bc cabal-plan.xz" | sha256sum -c - && \+ xz -d < cabal-plan.xz > /root/.cabal/bin/cabal-plan && \+ rm -f cabal-plan.xz && \+ chmod a+x /root/.cabal/bin/cabal-plan++# Install older compilers+RUN apt-get update+RUN apt-get install -y ghc-7.0.4 ghc-7.0.4-dyn ghc-7.2.2 ghc-7.2.2-dyn ghc-7.4.2 ghc-7.4.2-dyn++# Update index+RUN cabal v2-update --index-state="2020-06-12T23:36:15Z"++# We install happy, so it's in the store; we (hopefully) don't use it directly.+RUN cabal v2-install happy --constraint 'happy ^>=1.19.12'++# Install some other dependencies+# Remove $HOME/.ghc so there aren't any environments+RUN cabal v2-install -w ghc-8.8.3 --lib \+ Cabal \+ aeson \+ async \+ base-compat \+ base16-bytestring \+ base64-bytestring \+ cryptohash-sha256 \+ Diff \+ echo \+ ed25519 \+ edit-distance \+ HTTP \+ lukko \+ network \+ optparse-applicative \+ pretty-show \+ regex-compat-tdfa \+ regex-posix \+ regex-tdfa \+ rere \+ statistics \+ tar \+ tasty \+ tasty-golden \+ tasty-hunit \+ tasty-quickcheck \+ tree-diff \+ void \+ zlib \+ resolv \+ --constraint="rere -rere-cfg" \+ --constraint="these -assoc" \+ --constraint="bytestring installed" \+ --constraint="binary installed" \+ --constraint="containers installed" \+ --constraint="deepseq installed" \+ --constraint="directory installed" \+ --constraint="filepath installed" \+ --constraint="pretty installed" \+ --constraint="process installed" \+ --constraint="time installed" \+ --constraint="unix installed" \+ --constraint="transformers installed" \+ && rm -rf $HOME/.ghc++# Validate+WORKDIR /build+COPY . /build+RUN sh ./validate.sh -w ghc-8.8.3 -v --lib-only --extra-hc /opt/ghc/7.0.4/bin/ghc-7.0.4 --extra-hc /opt/ghc/7.2.2/bin/ghc-7.2.2 --extra-hc /opt/ghc/7.4.2/bin/ghc-7.4.2
+ cabal/.docker/validate.dockerfile.zinza view
@@ -0,0 +1,89 @@+FROM phadej/ghc:{{ image }}++# Install cabal-plan+RUN mkdir -p /root/.cabal/bin && \+ curl -L https://github.com/haskell-hvr/cabal-plan/releases/download/v0.6.2.0/cabal-plan-0.6.2.0-x86_64-linux.xz > cabal-plan.xz && \+ echo "de73600b1836d3f55e32d80385acc055fd97f60eaa0ab68a755302685f5d81bc cabal-plan.xz" | sha256sum -c - && \+ xz -d < cabal-plan.xz > /root/.cabal/bin/cabal-plan && \+ rm -f cabal-plan.xz && \+ chmod a+x /root/.cabal/bin/cabal-plan++# Install cabal-env+RUN curl -sL https://github.com/phadej/cabal-extras/releases/download/preview-20191225/cabal-env-snapshot-20191225-x86_64-linux.xz > cabal-env.xz && \+ echo "1b567d529c5f627fd8c956e57ae8f0d9f11ee66d6db34b7fb0cb1c370b4edf01 cabal-env.xz" | sha256sum -c - && \+ xz -d < cabal-env.xz > $HOME/.cabal/bin/cabal-env && \+ rm -f cabal-env.xz && \+ chmod a+x $HOME/.cabal/bin/cabal-env++{% if needsDynamic %}+# We need newer compiler, to install cabal-plan+RUN apt-get update+RUN apt-get install -y {{ ghc }}-dyn+{% endif %}++# Update index+RUN cabal v2-update --index-state="2020-06-12T23:36:15Z"++# We install happy, so it's in the store; we (hopefully) don't use it directly.+RUN cabal v2-install happy --constraint 'happy ^>=1.19.12'++# Install some other dependencies+# Remove $HOME/.ghc so there aren't any environments+RUN cabal v2-install -w {{ ghc }} --lib \+ Cabal \+ aeson \+ async \+ base-compat \+ base16-bytestring \+ base64-bytestring \+ cryptohash-sha256 \+ Diff \+ echo \+ ed25519 \+ edit-distance \+ HTTP \+ lukko \+ network \+ optparse-applicative \+ pretty-show \+ regex-compat-tdfa \+ regex-posix \+ regex-tdfa \+ rere \+ statistics \+ tar \+ tasty \+ tasty-golden \+ tasty-hunit \+ tasty-quickcheck \+ tree-diff \+ void \+ zlib \+{% if client %}+ resolv \+{% endif %}+{% if parsecCompat %}+ parsec \+ text \+{% endif %}+ --constraint="rere -rere-cfg" \+ --constraint="these -assoc" \+ --constraint="bytestring installed" \+ --constraint="binary installed" \+ --constraint="containers installed" \+ --constraint="deepseq installed" \+ --constraint="directory installed" \+ --constraint="filepath installed" \+ --constraint="pretty installed" \+ --constraint="process installed" \+ --constraint="time installed" \+ --constraint="unix installed" \+{% if hasTransformers %}+ --constraint="transformers installed" \+{% endif %}+ && rm -rf $HOME/.ghc++# Validate+WORKDIR /build+COPY . /build+RUN sh ./validate.sh {{ args }} -w {{ ghc }} -v
cabal/.dockerignore view
@@ -3,6 +3,8 @@ cabal.project.local .ghc.environment.* +.docker/+ **/.hpc **/*.hi **/*.o
cabal/.gitattributes view
@@ -1,3 +1,6 @@+# https://github.community/t5/GitHub-Actions/git-config-core-autocrlf-should-default-to-false/m-p/30731#M534+* -text+ /Cabal/ChangeLog.md merge=union /cabal-install/changelog merge=union /cabal-testsuite/PackageTests/NewBuild/CmdRun/Script/script.hs eol=crlf
cabal/.github/PULL_REQUEST_TEMPLATE.md view
@@ -3,8 +3,7 @@ Please include the following checklist in your PR: * [ ] Patches conform to the [coding conventions](https://github.com/haskell/cabal/blob/master/CONTRIBUTING.md#conventions).-* [ ] Any changes that could be relevant to users have been recorded in the changelog.+* [ ] Any changes that could be relevant to users have been recorded in the changelog (add file to `changelog.d` directory). * [ ] The documentation has been updated, if necessary.-* [ ] If the change is docs-only, `[ci skip]` is used to avoid triggering the build bots. Please also shortly describe how you tested your change. Bonus points for added tests!
+ cabal/.github/workflows/artifacts.yml view
@@ -0,0 +1,136 @@+name: Artifacts+on:+ push:+ branches:+ - master+ - "3.2"+ pull_request:+ branches:+ - master+ release:+ types:+ - created++jobs:+ artifact-linux:+ name: Artifact on Linux+ runs-on: ubuntu-18.04+ container:+ # Older Ubuntu for older glibc+ image: phadej/ghc:8.6.5-xenial+ steps:+ - name: Set PATH+ run: |+ echo "::add-path::$HOME/.cabal/bin"+ - name: Update Hackage index+ run: cabal v2-update+ - uses: actions/checkout@v2+ - name: Release project+ run: |+ cp cabal.project.release cabal.project+ rm -rf cabal.project.local cabal.project.freeze+ - name: Build+ run: |+ cabal v2-build cabal-install:exe:cabal+ cp $(find dist-newstyle -type f -executable -name cabal) cabal.exe+ - name: Smoke test+ run: |+ ./cabal.exe --version+ - name: Prepare for upload+ run: xz -c < cabal.exe > cabal-artifact.xz+ - uses: actions/upload-artifact@v1+ with:+ name: cabal-linux-x86_64.xz+ path: cabal-artifact.xz++ artifact-macos:+ name: Artifact on macOS+ runs-on: macos-latest+ steps:+ - name: Install GHC+ run: |+ cd $(mktemp -d)+ curl -sLO "https://downloads.haskell.org/~ghc/8.6.5/ghc-8.6.5-x86_64-apple-darwin.tar.xz"+ tar -xJf ghc-*.tar.xz+ cd ghc-*+ ./configure --prefix=/opt/ghc/8.6.5+ sudo make install+ - name: Install Cabal+ run: |+ cd $(mktemp -d)+ curl -sLO https://downloads.haskell.org/~cabal/cabal-install-3.0.0.0/cabal-install-3.0.0.0-x86_64-apple-darwin17.7.0.tar.xz+ tar -xJf cabal-install-*.tar.xz+ sudo mkdir -p /opt/cabal/3.0/bin+ sudo cp cabal /opt/cabal/3.0/bin/cabal+ sudo chmod 755 /opt/cabal/3.0/bin/cabal+ - name: Set PATH+ run: |+ echo "::add-path::/opt/ghc/8.6.5/bin"+ echo "::add-path::/opt/cabal/3.0/bin"+ echo "::add-path::$HOME/.cabal/bin"+ - name: Update Hackage index+ run: cabal v2-update+ - uses: actions/checkout@v2+ - name: Release project+ run: |+ cp cabal.project.release cabal.project+ rm -rf cabal.project.local cabal.project.freeze+ - name: Build+ run: |+ cabal v2-build cabal-install:exe:cabal+ # macOS find doesn't know -executable+ cp $(find dist-newstyle -type f -name cabal) cabal.exe+ - name: Smoke test+ run: |+ ./cabal.exe --version+ - name: Prepare for upload+ run: xz -c < cabal.exe > cabal-artifact.xz+ - uses: actions/upload-artifact@v1+ with:+ name: cabal-macos-x86_64.xz+ path: cabal-artifact.xz++ artifact-windows:+ name: Artifact on Windows+ runs-on: windows-latest+ steps:+ - name: Install Cabal+ run: choco install -fy cabal --version 3.0.0.0+ - name: Install GHC+ run: |+ choco uninstall -y ghc+ choco install -y ghc --version 8.6.5+ - name: Set PATH+ run: |+ [Environment]::GetEnvironmentVariable("Path")+ Write-Host "::add-path::C:\ProgramData\chocolatey\lib\cabal\tools\cabal-3.0.0.0"+ Write-Host "::add-path::C:\ProgramData\chocolatey\lib\ghc\tools\ghc-8.6.5\bin"+ - name: Print versions+ run: |+ ghc --version+ cabal --version+ cabal user-config init -a "http-transport: plain-http" -a "store-dir: C:\SR" -f -v3+ - name: Update Hackage index+ run: cabal v2-update+ - uses: actions/checkout@v2+ - name: Release project+ shell: bash+ run: |+ cp cabal.project.release cabal.project+ rm -rf cabal.project.local cabal.project.freeze+ - name: Build+ shell: bash+ run: |+ cabal v2-build cabal-install:exe:cabal+ cp dist-newstyle/build/x86_64-windows/ghc-8.6.5/cabal-install-3.3.0.0/x/cabal/build/cabal/cabal.exe cabal.exe+ - name: Smoke test+ shell: bash+ run: |+ ./cabal.exe --version+ - name: Prepare for upload+ shell: bash+ run: xz -c < cabal.exe > cabal-artifact.xz+ - uses: actions/upload-artifact@v1+ with:+ name: cabal-windows-x86_64.xz+ path: cabal-artifact.xz
+ cabal/.github/workflows/bootstrap.yml view
@@ -0,0 +1,64 @@+# This file is auto-generated+#+# To regenerate it run+#+# make github-actions+#+name: Bootstrap+on:+ push:+ branches:+ - master+ - "3.2"+ pull_request:+ branches:+ - master+ release:+ types:+ - created++jobs:+ boostrap-linux:+ name: Bootstrap on Linux+ runs-on: ubuntu-18.04+ steps:+ - name: Set PATH+ run: |+ echo "::add-path::/opt/ghc/8.6.5/bin"+ - uses: actions/checkout@v2+ - name: bootstrap.sh+ env:+ EXTRA_CONFIGURE_OPTS: ""+ run: |+ cd cabal-install+ sh ./bootstrap.sh --no-doc+ - name: Smoke test+ run: |+ $HOME/.cabal/bin/cabal --version++ boostrap-macos:+ name: Bootstrap on macOS+ runs-on: macos-latest+ steps:+ - name: Install GHC+ run: |+ cd $(mktemp -d)+ curl -sLO "https://downloads.haskell.org/~ghc/8.6.5/ghc-8.6.5-x86_64-apple-darwin.tar.xz"+ tar -xJf ghc-*.tar.xz+ cd ghc-*+ ./configure --prefix=/opt/ghc/8.6.5+ sudo make install+ - name: Set PATH+ run: |+ echo "::add-path::/opt/ghc/8.6.5/bin"+ echo "::add-path::$HOME/.cabal/bin"+ - uses: actions/checkout@v2+ - name: bootstrap.sh+ env:+ EXTRA_CONFIGURE_OPTS: ""+ run: |+ cd cabal-install+ sh ./bootstrap.sh --no-doc+ - name: Smoke test+ run: |+ $HOME/.cabal/bin/cabal --version
+ cabal/.github/workflows/linux.yml view
@@ -0,0 +1,497 @@+# This file is auto-generated+#+# To regenerate it run+#+# make github-actions+#+name: Linux+on:+ push:+ branches:+ - master+ - "3.2"+ pull_request:+ branches:+ - master+ release:+ types:+ - created++jobs:+ validate-8_10_1:+ name: validate.sh ghc-8.10.1+ runs-on: ubuntu-18.04+ needs: validate-8_8_3+ container:+ image: phadej/ghc:8.10.1-bionic+ steps:+ - name: System info+ run: |+ uname -a+ # https://help.github.com/en/actions/automating-your-workflow-with-github-actions/development-tools-for-github-actions#add-a-system-path-add-path+ - name: Set PATH+ run: |+ echo "::add-path::$HOME/.cabal/bin"+ - name: Install cabal-plan+ run: |+ mkdir -p $HOME/.cabal/bin+ curl -sL https://github.com/haskell-hvr/cabal-plan/releases/download/v0.6.2.0/cabal-plan-0.6.2.0-x86_64-linux.xz > cabal-plan.xz+ echo "de73600b1836d3f55e32d80385acc055fd97f60eaa0ab68a755302685f5d81bc cabal-plan.xz" | sha256sum -c -+ xz -d < cabal-plan.xz > $HOME/.cabal/bin/cabal-plan+ rm -f cabal-plan.xz+ chmod a+x $HOME/.cabal/bin/cabal-plan+ - name: Update Hackage index+ run: cabal v2-update+ # https://github.com/actions/checkout/issues/170+ # - uses: actions/checkout@v2+ - name: Checkout+ run: |+ echo $GITHUB_REF $GITHUB_SHA+ git clone --depth 1 https://github.com/$GITHUB_REPOSITORY.git .+ git fetch origin $GITHUB_SHA:temporary-ci-branch+ git checkout $GITHUB_SHA || (git fetch && git checkout $GITHUB_SHA)+ - name: Validate print-config+ run: sh validate.sh -j 2 -w ghc-8.10.1 -v -s print-config+ - name: Validate print-tool-versions+ run: sh validate.sh -j 2 -w ghc-8.10.1 -v -s print-tool-versions+ - name: Validate make-cabal-install-dev+ run: sh validate.sh -j 2 -w ghc-8.10.1 -v -s make-cabal-install-dev+ - name: Validate build+ run: sh validate.sh -j 2 -w ghc-8.10.1 -v -s build+ - name: Validate lib-tests+ run: sh validate.sh -j 2 -w ghc-8.10.1 -v -s lib-tests+ - name: Validate lib-suite+ run: sh validate.sh -j 2 -w ghc-8.10.1 -v -s lib-suite+ - name: Validate cli-tests+ run: sh validate.sh -j 2 -w ghc-8.10.1 -v -s cli-tests+ - name: Validate cli-suite+ run: sh validate.sh -j 2 -w ghc-8.10.1 -v -s cli-suite+ validate-8_8_3:+ name: validate.sh ghc-8.8.3+ runs-on: ubuntu-18.04+ container:+ image: phadej/ghc:8.8.3-bionic+ steps:+ - name: System info+ run: |+ uname -a+ # https://help.github.com/en/actions/automating-your-workflow-with-github-actions/development-tools-for-github-actions#add-a-system-path-add-path+ - name: Set PATH+ run: |+ echo "::add-path::$HOME/.cabal/bin"+ - name: Install cabal-plan+ run: |+ mkdir -p $HOME/.cabal/bin+ curl -sL https://github.com/haskell-hvr/cabal-plan/releases/download/v0.6.2.0/cabal-plan-0.6.2.0-x86_64-linux.xz > cabal-plan.xz+ echo "de73600b1836d3f55e32d80385acc055fd97f60eaa0ab68a755302685f5d81bc cabal-plan.xz" | sha256sum -c -+ xz -d < cabal-plan.xz > $HOME/.cabal/bin/cabal-plan+ rm -f cabal-plan.xz+ chmod a+x $HOME/.cabal/bin/cabal-plan+ - name: Update Hackage index+ run: cabal v2-update+ # https://github.com/actions/checkout/issues/170+ # - uses: actions/checkout@v2+ - name: Checkout+ run: |+ echo $GITHUB_REF $GITHUB_SHA+ git clone --depth 1 https://github.com/$GITHUB_REPOSITORY.git .+ git fetch origin $GITHUB_SHA:temporary-ci-branch+ git checkout $GITHUB_SHA || (git fetch && git checkout $GITHUB_SHA)+ - name: Validate print-config+ run: sh validate.sh -j 2 -w ghc-8.8.3 -v --solver-benchmarks -s print-config+ - name: Validate print-tool-versions+ run: sh validate.sh -j 2 -w ghc-8.8.3 -v --solver-benchmarks -s print-tool-versions+ - name: Validate make-cabal-install-dev+ run: sh validate.sh -j 2 -w ghc-8.8.3 -v --solver-benchmarks -s make-cabal-install-dev+ - name: Validate build+ run: sh validate.sh -j 2 -w ghc-8.8.3 -v --solver-benchmarks -s build+ - name: Validate lib-tests+ run: sh validate.sh -j 2 -w ghc-8.8.3 -v --solver-benchmarks -s lib-tests+ - name: Validate lib-suite+ run: sh validate.sh -j 2 -w ghc-8.8.3 -v --solver-benchmarks -s lib-suite+ - name: Validate cli-tests+ run: sh validate.sh -j 2 -w ghc-8.8.3 -v --solver-benchmarks -s cli-tests+ - name: Validate cli-suite+ run: sh validate.sh -j 2 -w ghc-8.8.3 -v --solver-benchmarks -s cli-suite+ validate-8_6_5:+ name: validate.sh ghc-8.6.5+ runs-on: ubuntu-18.04+ needs: validate-8_8_3+ container:+ image: phadej/ghc:8.6.5-bionic+ steps:+ - name: System info+ run: |+ uname -a+ # https://help.github.com/en/actions/automating-your-workflow-with-github-actions/development-tools-for-github-actions#add-a-system-path-add-path+ - name: Set PATH+ run: |+ echo "::add-path::$HOME/.cabal/bin"+ - name: Install cabal-plan+ run: |+ mkdir -p $HOME/.cabal/bin+ curl -sL https://github.com/haskell-hvr/cabal-plan/releases/download/v0.6.2.0/cabal-plan-0.6.2.0-x86_64-linux.xz > cabal-plan.xz+ echo "de73600b1836d3f55e32d80385acc055fd97f60eaa0ab68a755302685f5d81bc cabal-plan.xz" | sha256sum -c -+ xz -d < cabal-plan.xz > $HOME/.cabal/bin/cabal-plan+ rm -f cabal-plan.xz+ chmod a+x $HOME/.cabal/bin/cabal-plan+ - name: Update Hackage index+ run: cabal v2-update+ # https://github.com/actions/checkout/issues/170+ # - uses: actions/checkout@v2+ - name: Checkout+ run: |+ echo $GITHUB_REF $GITHUB_SHA+ git clone --depth 1 https://github.com/$GITHUB_REPOSITORY.git .+ git fetch origin $GITHUB_SHA:temporary-ci-branch+ git checkout $GITHUB_SHA || (git fetch && git checkout $GITHUB_SHA)+ - name: Validate print-config+ run: sh validate.sh -j 2 -w ghc-8.6.5 -v --complete-hackage-tests -s print-config+ - name: Validate print-tool-versions+ run: sh validate.sh -j 2 -w ghc-8.6.5 -v --complete-hackage-tests -s print-tool-versions+ - name: Validate make-cabal-install-dev+ run: sh validate.sh -j 2 -w ghc-8.6.5 -v --complete-hackage-tests -s make-cabal-install-dev+ - name: Validate build+ run: sh validate.sh -j 2 -w ghc-8.6.5 -v --complete-hackage-tests -s build+ - name: Validate lib-tests+ run: sh validate.sh -j 2 -w ghc-8.6.5 -v --complete-hackage-tests -s lib-tests+ - name: Validate lib-suite+ run: sh validate.sh -j 2 -w ghc-8.6.5 -v --complete-hackage-tests -s lib-suite+ - name: Validate cli-tests+ run: sh validate.sh -j 2 -w ghc-8.6.5 -v --complete-hackage-tests -s cli-tests+ - name: Validate cli-suite+ run: sh validate.sh -j 2 -w ghc-8.6.5 -v --complete-hackage-tests -s cli-suite+ validate-8_4_4:+ name: validate.sh ghc-8.4.4+ runs-on: ubuntu-18.04+ needs: validate-8_8_3+ container:+ image: phadej/ghc:8.4.4-bionic+ steps:+ - name: System info+ run: |+ uname -a+ # https://help.github.com/en/actions/automating-your-workflow-with-github-actions/development-tools-for-github-actions#add-a-system-path-add-path+ - name: Set PATH+ run: |+ echo "::add-path::$HOME/.cabal/bin"+ - name: Install cabal-plan+ run: |+ mkdir -p $HOME/.cabal/bin+ curl -sL https://github.com/haskell-hvr/cabal-plan/releases/download/v0.6.2.0/cabal-plan-0.6.2.0-x86_64-linux.xz > cabal-plan.xz+ echo "de73600b1836d3f55e32d80385acc055fd97f60eaa0ab68a755302685f5d81bc cabal-plan.xz" | sha256sum -c -+ xz -d < cabal-plan.xz > $HOME/.cabal/bin/cabal-plan+ rm -f cabal-plan.xz+ chmod a+x $HOME/.cabal/bin/cabal-plan+ - name: Update Hackage index+ run: cabal v2-update+ # https://github.com/actions/checkout/issues/170+ # - uses: actions/checkout@v2+ - name: Checkout+ run: |+ echo $GITHUB_REF $GITHUB_SHA+ git clone --depth 1 https://github.com/$GITHUB_REPOSITORY.git .+ git fetch origin $GITHUB_SHA:temporary-ci-branch+ git checkout $GITHUB_SHA || (git fetch && git checkout $GITHUB_SHA)+ - name: Validate print-config+ run: sh validate.sh -j 2 -w ghc-8.4.4 -v -s print-config+ - name: Validate print-tool-versions+ run: sh validate.sh -j 2 -w ghc-8.4.4 -v -s print-tool-versions+ - name: Validate make-cabal-install-dev+ run: sh validate.sh -j 2 -w ghc-8.4.4 -v -s make-cabal-install-dev+ - name: Validate build+ run: sh validate.sh -j 2 -w ghc-8.4.4 -v -s build+ - name: Validate lib-tests+ run: sh validate.sh -j 2 -w ghc-8.4.4 -v -s lib-tests+ - name: Validate lib-suite+ run: sh validate.sh -j 2 -w ghc-8.4.4 -v -s lib-suite+ - name: Validate cli-tests+ run: sh validate.sh -j 2 -w ghc-8.4.4 -v -s cli-tests+ - name: Validate cli-suite+ run: sh validate.sh -j 2 -w ghc-8.4.4 -v -s cli-suite+ validate-8_2_2:+ name: validate.sh ghc-8.2.2+ runs-on: ubuntu-18.04+ needs: validate-8_8_3+ container:+ image: phadej/ghc:8.2.2-bionic+ steps:+ - name: System info+ run: |+ uname -a+ # https://help.github.com/en/actions/automating-your-workflow-with-github-actions/development-tools-for-github-actions#add-a-system-path-add-path+ - name: Set PATH+ run: |+ echo "::add-path::$HOME/.cabal/bin"+ - name: Install cabal-plan+ run: |+ mkdir -p $HOME/.cabal/bin+ curl -sL https://github.com/haskell-hvr/cabal-plan/releases/download/v0.6.2.0/cabal-plan-0.6.2.0-x86_64-linux.xz > cabal-plan.xz+ echo "de73600b1836d3f55e32d80385acc055fd97f60eaa0ab68a755302685f5d81bc cabal-plan.xz" | sha256sum -c -+ xz -d < cabal-plan.xz > $HOME/.cabal/bin/cabal-plan+ rm -f cabal-plan.xz+ chmod a+x $HOME/.cabal/bin/cabal-plan+ - name: Update Hackage index+ run: cabal v2-update+ # https://github.com/actions/checkout/issues/170+ # - uses: actions/checkout@v2+ - name: Checkout+ run: |+ echo $GITHUB_REF $GITHUB_SHA+ git clone --depth 1 https://github.com/$GITHUB_REPOSITORY.git .+ git fetch origin $GITHUB_SHA:temporary-ci-branch+ git checkout $GITHUB_SHA || (git fetch && git checkout $GITHUB_SHA)+ - name: Validate print-config+ run: sh validate.sh -j 2 -w ghc-8.2.2 -v -s print-config+ - name: Validate print-tool-versions+ run: sh validate.sh -j 2 -w ghc-8.2.2 -v -s print-tool-versions+ - name: Validate make-cabal-install-dev+ run: sh validate.sh -j 2 -w ghc-8.2.2 -v -s make-cabal-install-dev+ - name: Validate build+ run: sh validate.sh -j 2 -w ghc-8.2.2 -v -s build+ - name: Validate lib-tests+ run: sh validate.sh -j 2 -w ghc-8.2.2 -v -s lib-tests+ - name: Validate lib-suite+ run: sh validate.sh -j 2 -w ghc-8.2.2 -v -s lib-suite+ - name: Validate cli-tests+ run: sh validate.sh -j 2 -w ghc-8.2.2 -v -s cli-tests+ - name: Validate cli-suite+ run: sh validate.sh -j 2 -w ghc-8.2.2 -v -s cli-suite+ validate-8_0_2:+ name: validate.sh ghc-8.0.2+ runs-on: ubuntu-18.04+ needs: validate-8_8_3+ container:+ image: phadej/ghc:8.0.2-bionic+ steps:+ - name: System info+ run: |+ uname -a+ # https://help.github.com/en/actions/automating-your-workflow-with-github-actions/development-tools-for-github-actions#add-a-system-path-add-path+ - name: Set PATH+ run: |+ echo "::add-path::$HOME/.cabal/bin"+ - name: Install cabal-plan+ run: |+ mkdir -p $HOME/.cabal/bin+ curl -sL https://github.com/haskell-hvr/cabal-plan/releases/download/v0.6.2.0/cabal-plan-0.6.2.0-x86_64-linux.xz > cabal-plan.xz+ echo "de73600b1836d3f55e32d80385acc055fd97f60eaa0ab68a755302685f5d81bc cabal-plan.xz" | sha256sum -c -+ xz -d < cabal-plan.xz > $HOME/.cabal/bin/cabal-plan+ rm -f cabal-plan.xz+ chmod a+x $HOME/.cabal/bin/cabal-plan+ - name: Update Hackage index+ run: cabal v2-update+ # https://github.com/actions/checkout/issues/170+ # - uses: actions/checkout@v2+ - name: Checkout+ run: |+ echo $GITHUB_REF $GITHUB_SHA+ git clone --depth 1 https://github.com/$GITHUB_REPOSITORY.git .+ git fetch origin $GITHUB_SHA:temporary-ci-branch+ git checkout $GITHUB_SHA || (git fetch && git checkout $GITHUB_SHA)+ - name: Validate print-config+ run: sh validate.sh -j 2 -w ghc-8.0.2 -v -s print-config+ - name: Validate print-tool-versions+ run: sh validate.sh -j 2 -w ghc-8.0.2 -v -s print-tool-versions+ - name: Validate make-cabal-install-dev+ run: sh validate.sh -j 2 -w ghc-8.0.2 -v -s make-cabal-install-dev+ - name: Validate build+ run: sh validate.sh -j 2 -w ghc-8.0.2 -v -s build+ - name: Validate lib-tests+ run: sh validate.sh -j 2 -w ghc-8.0.2 -v -s lib-tests+ - name: Validate lib-suite+ run: sh validate.sh -j 2 -w ghc-8.0.2 -v -s lib-suite+ - name: Validate cli-tests+ run: sh validate.sh -j 2 -w ghc-8.0.2 -v -s cli-tests+ - name: Validate cli-suite+ run: sh validate.sh -j 2 -w ghc-8.0.2 -v -s cli-suite+ validate-7_10_3:+ name: validate.sh ghc-7.10.3+ runs-on: ubuntu-18.04+ needs: validate-8_8_3+ container:+ image: phadej/ghc:7.10.3-bionic+ steps:+ - name: System info+ run: |+ uname -a+ # https://help.github.com/en/actions/automating-your-workflow-with-github-actions/development-tools-for-github-actions#add-a-system-path-add-path+ - name: Set PATH+ run: |+ echo "::add-path::$HOME/.cabal/bin"+ - name: Install cabal-plan+ run: |+ mkdir -p $HOME/.cabal/bin+ curl -sL https://github.com/haskell-hvr/cabal-plan/releases/download/v0.6.2.0/cabal-plan-0.6.2.0-x86_64-linux.xz > cabal-plan.xz+ echo "de73600b1836d3f55e32d80385acc055fd97f60eaa0ab68a755302685f5d81bc cabal-plan.xz" | sha256sum -c -+ xz -d < cabal-plan.xz > $HOME/.cabal/bin/cabal-plan+ rm -f cabal-plan.xz+ chmod a+x $HOME/.cabal/bin/cabal-plan+ - name: Update Hackage index+ run: cabal v2-update+ # https://github.com/actions/checkout/issues/170+ # - uses: actions/checkout@v2+ - name: Checkout+ run: |+ echo $GITHUB_REF $GITHUB_SHA+ git clone --depth 1 https://github.com/$GITHUB_REPOSITORY.git .+ git fetch origin $GITHUB_SHA:temporary-ci-branch+ git checkout $GITHUB_SHA || (git fetch && git checkout $GITHUB_SHA)+ - name: Validate print-config+ run: sh validate.sh -j 2 -w ghc-7.10.3 -v -s print-config+ - name: Validate print-tool-versions+ run: sh validate.sh -j 2 -w ghc-7.10.3 -v -s print-tool-versions+ - name: Validate make-cabal-install-dev+ run: sh validate.sh -j 2 -w ghc-7.10.3 -v -s make-cabal-install-dev+ - name: Validate build+ run: sh validate.sh -j 2 -w ghc-7.10.3 -v -s build+ - name: Validate lib-tests+ run: sh validate.sh -j 2 -w ghc-7.10.3 -v -s lib-tests+ - name: Validate lib-suite+ run: sh validate.sh -j 2 -w ghc-7.10.3 -v -s lib-suite+ - name: Validate cli-tests+ run: sh validate.sh -j 2 -w ghc-7.10.3 -v -s cli-tests+ - name: Validate cli-suite+ run: sh validate.sh -j 2 -w ghc-7.10.3 -v -s cli-suite+ validate-7_8_4:+ name: validate.sh ghc-7.8.4+ runs-on: ubuntu-18.04+ needs: validate-8_8_3+ container:+ image: phadej/ghc:7.8.4-bionic+ steps:+ - name: System info+ run: |+ uname -a+ # https://help.github.com/en/actions/automating-your-workflow-with-github-actions/development-tools-for-github-actions#add-a-system-path-add-path+ - name: Set PATH+ run: |+ echo "::add-path::$HOME/.cabal/bin"+ - name: Install cabal-plan+ run: |+ mkdir -p $HOME/.cabal/bin+ curl -sL https://github.com/haskell-hvr/cabal-plan/releases/download/v0.6.2.0/cabal-plan-0.6.2.0-x86_64-linux.xz > cabal-plan.xz+ echo "de73600b1836d3f55e32d80385acc055fd97f60eaa0ab68a755302685f5d81bc cabal-plan.xz" | sha256sum -c -+ xz -d < cabal-plan.xz > $HOME/.cabal/bin/cabal-plan+ rm -f cabal-plan.xz+ chmod a+x $HOME/.cabal/bin/cabal-plan+ - name: Update Hackage index+ run: cabal v2-update+ # https://github.com/actions/checkout/issues/170+ # - uses: actions/checkout@v2+ - name: Checkout+ run: |+ echo $GITHUB_REF $GITHUB_SHA+ git clone --depth 1 https://github.com/$GITHUB_REPOSITORY.git .+ git fetch origin $GITHUB_SHA:temporary-ci-branch+ git checkout $GITHUB_SHA || (git fetch && git checkout $GITHUB_SHA)+ - name: Validate print-config+ run: sh validate.sh -j 2 -w ghc-7.8.4 -v --lib-only -s print-config+ - name: Validate print-tool-versions+ run: sh validate.sh -j 2 -w ghc-7.8.4 -v --lib-only -s print-tool-versions+ - name: Validate build+ run: sh validate.sh -j 2 -w ghc-7.8.4 -v --lib-only -s build+ - name: Validate lib-tests+ run: sh validate.sh -j 2 -w ghc-7.8.4 -v --lib-only -s lib-tests+ - name: Validate lib-suite+ run: sh validate.sh -j 2 -w ghc-7.8.4 -v --lib-only -s lib-suite+ validate-7_6_3:+ name: validate.sh ghc-7.6.3+ runs-on: ubuntu-18.04+ needs: validate-8_8_3+ container:+ image: phadej/ghc:7.6.3-xenial+ steps:+ - name: System info+ run: |+ uname -a+ # https://help.github.com/en/actions/automating-your-workflow-with-github-actions/development-tools-for-github-actions#add-a-system-path-add-path+ - name: Set PATH+ run: |+ echo "::add-path::$HOME/.cabal/bin"+ - name: Install cabal-plan+ run: |+ mkdir -p $HOME/.cabal/bin+ curl -sL https://github.com/haskell-hvr/cabal-plan/releases/download/v0.6.2.0/cabal-plan-0.6.2.0-x86_64-linux.xz > cabal-plan.xz+ echo "de73600b1836d3f55e32d80385acc055fd97f60eaa0ab68a755302685f5d81bc cabal-plan.xz" | sha256sum -c -+ xz -d < cabal-plan.xz > $HOME/.cabal/bin/cabal-plan+ rm -f cabal-plan.xz+ chmod a+x $HOME/.cabal/bin/cabal-plan+ - name: apt-get update+ run: apt-get update+ - name: Install dynamic libraries+ run: apt-get install -y ghc-7.6.3-dyn+ - name: Update Hackage index+ run: cabal v2-update+ # https://github.com/actions/checkout/issues/170+ # - uses: actions/checkout@v2+ - name: Checkout+ run: |+ echo $GITHUB_REF $GITHUB_SHA+ git clone --depth 1 https://github.com/$GITHUB_REPOSITORY.git .+ git fetch origin $GITHUB_SHA:temporary-ci-branch+ git checkout $GITHUB_SHA || (git fetch && git checkout $GITHUB_SHA)+ - name: Validate print-config+ run: sh validate.sh -j 2 -w ghc-7.6.3 -v --lib-only -s print-config+ - name: Validate print-tool-versions+ run: sh validate.sh -j 2 -w ghc-7.6.3 -v --lib-only -s print-tool-versions+ - name: Validate build+ run: sh validate.sh -j 2 -w ghc-7.6.3 -v --lib-only -s build+ - name: Validate lib-tests+ run: sh validate.sh -j 2 -w ghc-7.6.3 -v --lib-only -s lib-tests+ - name: Validate lib-suite+ run: sh validate.sh -j 2 -w ghc-7.6.3 -v --lib-only -s lib-suite+ validate-8_8_3-old:+ name: validate.sh old GHCs+ runs-on: ubuntu-18.04+ needs: validate-8_8_3+ container:+ image: phadej/ghc:8.8.3-xenial+ steps:+ - name: System info+ run: |+ uname -a+ # https://help.github.com/en/actions/automating-your-workflow-with-github-actions/development-tools-for-github-actions#add-a-system-path-add-path+ - name: Set PATH+ run: |+ echo "::add-path::$HOME/.cabal/bin"+ - name: Install cabal-plan+ run: |+ mkdir -p $HOME/.cabal/bin+ curl -sL https://github.com/haskell-hvr/cabal-plan/releases/download/v0.6.2.0/cabal-plan-0.6.2.0-x86_64-linux.xz > cabal-plan.xz+ echo "de73600b1836d3f55e32d80385acc055fd97f60eaa0ab68a755302685f5d81bc cabal-plan.xz" | sha256sum -c -+ xz -d < cabal-plan.xz > $HOME/.cabal/bin/cabal-plan+ rm -f cabal-plan.xz+ chmod a+x $HOME/.cabal/bin/cabal-plan+ - name: apt-get update+ run: apt-get update+ - name: Install dynamic libraries+ run: apt-get install -y ghc-8.8.3-dyn+ - name: Install extra compilers+ run: apt-get install -y ghc-7.0.4-dyn ghc-7.2.2-dyn ghc-7.4.2-dyn+ - name: Update Hackage index+ run: cabal v2-update+ # https://github.com/actions/checkout/issues/170+ # - uses: actions/checkout@v2+ - name: Checkout+ run: |+ echo $GITHUB_REF $GITHUB_SHA+ git clone --depth 1 https://github.com/$GITHUB_REPOSITORY.git .+ git fetch origin $GITHUB_SHA:temporary-ci-branch+ git checkout $GITHUB_SHA || (git fetch && git checkout $GITHUB_SHA)+ - name: Validate print-config+ run: sh validate.sh -j 2 -w ghc-8.8.3 -v --lib-only -s print-config+ - name: Validate print-tool-versions+ run: sh validate.sh -j 2 -w ghc-8.8.3 -v --lib-only -s print-tool-versions+ - name: Validate build+ run: sh validate.sh -j 2 -w ghc-8.8.3 -v --lib-only -s build+ - name: Validate lib-tests+ run: sh validate.sh -j 2 -w ghc-8.8.3 -v --lib-only -s lib-tests+ - name: Validate lib-suite+ run: sh validate.sh -j 2 -w ghc-8.8.3 -v --lib-only -s lib-suite+ - name: Validate lib-suite-extras --extra-hc /opt/ghc/7.0.4/bin/ghc-7.0.4+ run: sh validate.sh -j 2 -w ghc-8.8.3 -v --lib-only -s lib-suite-extras --extra-hc /opt/ghc/7.0.4/bin/ghc-7.0.4+ - name: Validate lib-suite-extras --extra-hc /opt/ghc/7.2.2/bin/ghc-7.2.2+ run: sh validate.sh -j 2 -w ghc-8.8.3 -v --lib-only -s lib-suite-extras --extra-hc /opt/ghc/7.2.2/bin/ghc-7.2.2+ - name: Validate lib-suite-extras --extra-hc /opt/ghc/7.4.2/bin/ghc-7.4.2+ run: sh validate.sh -j 2 -w ghc-8.8.3 -v --lib-only -s lib-suite-extras --extra-hc /opt/ghc/7.4.2/bin/ghc-7.4.2
+ cabal/.github/workflows/macos.yml view
@@ -0,0 +1,129 @@+# This file is auto-generated+#+# To regenerate it run+#+# make github-actions+#+name: MacOS+on:+ push:+ branches:+ - master+ - "3.2"+ pull_request:+ branches:+ - master+ release:+ types:+ - created++jobs:+ validate-macos-8_8_3:+ name: validate.sh macos ghc-8.8.3+ runs-on: macos-latest+ steps:+ - name: System info+ run: |+ uname -a+ - name: Install Autotools+ run: |+ brew install automake+ - name: Install GHC+ run: |+ cd $(mktemp -d)+ curl -sLO https://downloads.haskell.org/~ghc/8.8.3/ghc-8.8.3-x86_64-apple-darwin.tar.xz+ tar -xJf ghc-*.tar.xz+ cd ghc-*+ ./configure --prefix=/opt/ghc/8.8.3+ sudo make install+ - name: Install Cabal+ run: |+ cd $(mktemp -d)+ curl -sLO https://downloads.haskell.org/~cabal/cabal-install-3.0.0.0/cabal-install-3.0.0.0-x86_64-apple-darwin17.7.0.tar.xz+ tar -xJf cabal-install-*.tar.xz+ sudo mkdir -p /opt/cabal/3.0/bin+ sudo cp cabal /opt/cabal/3.0/bin/cabal+ sudo chmod 755 /opt/cabal/3.0/bin/cabal+ - name: Set PATH+ run: |+ echo "::add-path::/opt/ghc/8.8.3/bin"+ echo "::add-path::/opt/cabal/3.0/bin"+ echo "::add-path::$HOME/.cabal/bin"+ - name: Update Hackage index+ run: cabal v2-update+ - name: Install cabal-plan+ run: |+ cd $(mktemp -d)+ cabal v2-install cabal-plan --constraint='cabal-plan ^>=0.6.2.0' --constraint='aeson +fast'+ - uses: actions/checkout@v2+ - name: Validate print-config+ run: sh validate.sh -j 2 -w ghc-8.8.3 -v -s print-config+ - name: Validate print-tool-versions+ run: sh validate.sh -j 2 -w ghc-8.8.3 -v -s print-tool-versions+ - name: Validate make-cabal-install-dev+ run: sh validate.sh -j 2 -w ghc-8.8.3 -v -s make-cabal-install-dev+ - name: Validate build+ run: sh validate.sh -j 2 -w ghc-8.8.3 -v -s build+ - name: Validate lib-tests+ run: sh validate.sh -j 2 -w ghc-8.8.3 -v -s lib-tests+ - name: Validate lib-suite+ run: sh validate.sh -j 2 -w ghc-8.8.3 -v -s lib-suite+ - name: Validate cli-tests+ run: sh validate.sh -j 2 -w ghc-8.8.3 -v -s cli-tests+ - name: Validate cli-suite+ run: sh validate.sh -j 2 -w ghc-8.8.3 -v -s cli-suite+ validate-macos-8_6_5:+ name: validate.sh macos ghc-8.6.5+ runs-on: macos-latest+ needs: validate-macos-8_8_3+ steps:+ - name: System info+ run: |+ uname -a+ - name: Install Autotools+ run: |+ brew install automake+ - name: Install GHC+ run: |+ cd $(mktemp -d)+ curl -sLO https://downloads.haskell.org/~ghc/8.6.5/ghc-8.6.5-x86_64-apple-darwin.tar.xz+ tar -xJf ghc-*.tar.xz+ cd ghc-*+ ./configure --prefix=/opt/ghc/8.6.5+ sudo make install+ - name: Install Cabal+ run: |+ cd $(mktemp -d)+ curl -sLO https://downloads.haskell.org/~cabal/cabal-install-3.0.0.0/cabal-install-3.0.0.0-x86_64-apple-darwin17.7.0.tar.xz+ tar -xJf cabal-install-*.tar.xz+ sudo mkdir -p /opt/cabal/3.0/bin+ sudo cp cabal /opt/cabal/3.0/bin/cabal+ sudo chmod 755 /opt/cabal/3.0/bin/cabal+ - name: Set PATH+ run: |+ echo "::add-path::/opt/ghc/8.6.5/bin"+ echo "::add-path::/opt/cabal/3.0/bin"+ echo "::add-path::$HOME/.cabal/bin"+ - name: Update Hackage index+ run: cabal v2-update+ - name: Install cabal-plan+ run: |+ cd $(mktemp -d)+ cabal v2-install cabal-plan --constraint='cabal-plan ^>=0.6.2.0' --constraint='aeson +fast'+ - uses: actions/checkout@v2+ - name: Validate print-config+ run: sh validate.sh -j 2 -w ghc-8.6.5 -v -s print-config+ - name: Validate print-tool-versions+ run: sh validate.sh -j 2 -w ghc-8.6.5 -v -s print-tool-versions+ - name: Validate make-cabal-install-dev+ run: sh validate.sh -j 2 -w ghc-8.6.5 -v -s make-cabal-install-dev+ - name: Validate build+ run: sh validate.sh -j 2 -w ghc-8.6.5 -v -s build+ - name: Validate lib-tests+ run: sh validate.sh -j 2 -w ghc-8.6.5 -v -s lib-tests+ - name: Validate lib-suite+ run: sh validate.sh -j 2 -w ghc-8.6.5 -v -s lib-suite+ - name: Validate cli-tests+ run: sh validate.sh -j 2 -w ghc-8.6.5 -v -s cli-tests+ - name: Validate cli-suite+ run: sh validate.sh -j 2 -w ghc-8.6.5 -v -s cli-suite
+ cabal/.github/workflows/quick-jobs.yml view
@@ -0,0 +1,84 @@+# This file is auto-generated+#+# To regenerate it run+#+# make github-actions+#+name: Quick jobs+on:+ push:+ branches:+ - master+ - "3.2"+ pull_request:+ branches:+ - master+ release:+ types:+ - created++jobs:+ meta:+ name: Meta checks+ runs-on: ubuntu-18.04+ # This job is not run in a container, any recent GHC should be fine+ steps:+ - name: Set PATH+ run: |+ echo "::add-path::$HOME/.cabal/bin"+ echo "::add-path::/opt/cabal/3.2/bin"+ echo "::add-path::/opt/ghc/8.6.5/bin"+ - uses: actions/cache@v1+ with:+ path: ~/.cabal/store+ key: linux-store-meta+ - name: Update Hackage index+ run: cabal v2-update+ - name: Install alex+ run: cabal v2-install alex+ - uses: actions/checkout@v2+ - name: Regenerate files+ run: |+ make lexer+ make gen-extra-source-files+ make spdx+ make templates+ make github-actions+ make cabal-install-cabal+ - name: Check that diff is clean+ run: |+ git status > /dev/null+ git diff-files -p --exit-code+ doctest:+ name: Doctest Cabal+ runs-on: ubuntu-18.04+ steps:+ - name: Set PATH+ run: |+ echo "::add-path::$HOME/.cabal/bin"+ echo "::add-path::/opt/cabal/3.2/bin"+ echo "::add-path::/opt/ghc/8.6.5/bin"+ - name: Install cabal-env+ run: |+ mkdir -p $HOME/.cabal/bin+ curl -sL https://github.com/phadej/cabal-extras/releases/download/preview-20191225/cabal-env-snapshot-20191225-x86_64-linux.xz > cabal-env.xz+ echo "1b567d529c5f627fd8c956e57ae8f0d9f11ee66d6db34b7fb0cb1c370b4edf01 cabal-env.xz" | sha256sum -c -+ xz -d < cabal-env.xz > $HOME/.cabal/bin/cabal-env+ rm -f cabal-env.xz+ chmod a+x $HOME/.cabal/bin/cabal-env+ - uses: actions/cache@v1+ with:+ path: ~/.cabal/store+ key: linux-store-doctest+ - name: Update Hackage index+ run: cabal v2-update+ - name: Install doctest+ run: cabal v2-install doctest+ - name: Install libraries+ run: |+ cabal-env --transitive QuickCheck+ cabal-env array bytestring containers deepseq directory filepath pretty process time binary unix text parsec mtl+ cat $HOME/.ghc/*/environments/default+ - uses: actions/checkout@v2+ - name: Doctest+ run: make doctest
+ cabal/.github/workflows/windows.yml view
@@ -0,0 +1,76 @@+# This file is auto-generated+#+# To regenerate it run+#+# make github-actions+#+name: Windows+on:+ push:+ branches:+ - master+ - "3.2"+ pull_request:+ branches:+ - master+ release:+ types:+ - created++jobs:++ test-windows-8_6_5:+ name: test ghc-8.6.5+ runs-on: windows-latest+ steps:+ - name: Install Cabal+ run: choco install -fy cabal --version 3.2.0.0+ - name: Install GHC+ run: |+ choco uninstall -y ghc --all-versions+ choco install -y ghc --version 8.6.5+ - name: Set PATH+ run: |+ [Environment]::GetEnvironmentVariable("Path")+ Write-Host "::add-path::C:\ProgramData\Chocolatey\lib\cabal\tools\cabal-3.2.0.0"+ Write-Host "::add-path::C:\ProgramData\Chocolatey\lib\ghc\tools\ghc-8.6.5\bin"+ [Environment]::GetEnvironmentVariable("Path")+ - name: Print versions+ run: |+ [Environment]::GetEnvironmentVariable("Path")+ cabal --version+ ghc --version+ cabal user-config init -a "http-transport: plain-http" -a "store-dir: C:\SR" -f -v3+ - uses: actions/cache@v1+ with:+ path: C:\SR+ key: windows-store-meta+ - name: Update Hackage index+ run: cabal v2-update+ - uses: actions/checkout@v2+ - name: make cabal-install-dev+ run: cp cabal-install/cabal-install.cabal.dev cabal-install/cabal-install.cabal+ # We cannot ask for all dependencies, but we can for Cabal.+ - name: cabal v2-build Cabal --only-dependencies+ run: cabal v2-build Cabal --only-dependencies+ - name: cabal v2-build+ run: cabal v2-build all+ - name: cabal-install memory-usage-tests+ run: |+ cd cabal-install+ cabal v2-run cabal-install:memory-usage-tests+ - name: cabal-install solver-quickcheck+ run: |+ cd cabal-install+ cabal v2-run cabal-install:solver-quickcheck+ - name: cabal-install integration-tests2+ run: |+ cd cabal-install+ cabal v2-run cabal-install:integration-tests2+ - name: cabal-install unit-tests+ run: |+ cd cabal-install+ cabal v2-run cabal-install:unit-tests -- --pattern "! (/FileMonitor/ || /VCS/ || /Get/)"+ - name: cabal-tests+ # Using only one job, -j1, to fail less.+ run: cabal v2-run cabal-tests -- -j1 --with-cabal=dist-newstyle\build\x86_64-windows\ghc-8.6.5\cabal-install-3.3.0.0\x\cabal\build\cabal\cabal.exe
cabal/.gitignore view
@@ -50,6 +50,7 @@ # stack artifacts /.stack-work/+stack.yaml.lock # Shake artifacts .shake*@@ -60,3 +61,6 @@ # python artifacts from documentation builds *.pyc++# macOS folder metadata+.DS_Store
+ cabal/.readthedocs.yml view
@@ -0,0 +1,9 @@+version: 2++sphinx:+ configuration: Cabal/doc/conf.py++python:+ version: 3.7+ install:+ - requirements: Cabal/doc/requirements.txt
− cabal/.travis.yml
@@ -1,177 +0,0 @@-# NB: don't set `language: haskell` here-# We specify language: c, so it doesn't default to e.g. ruby-language: c--dist: xenial--# This sets the default config for each job to use full VMs.-# The VMs have 2 cores and 8 gigs of ram. Larger VMs are also available.-sudo: true--# We whitelist branches, as we don't really need to build dev-branches.-# Except if those branches are in a fork.-# Remember to add release branches, both here and to appveyor.yml.-if: branch IN (master, 3.0, 2.4, 2.2, 2.0, 1.24, 1.22, 1.20, 1.18) OR repo != haskell/cabal--# The following enables several GHC versions to be tested; often it's enough to-# test only against the last release in a major GHC version. Feel free to omit-# lines listings versions you don't need/want testing for.-#-# NB: If you test the same GHC version/OS combo multiple times with-# SCRIPT=script (e.g., see PARSEC=YES below), you MUST supply a-# TAGSUFFIX to help travis/upload.sh disambiguate the matrix entry.-matrix:- include:- - env: GHCVER=8.4.4 SCRIPT=meta BUILDER=none- os: linux- sudo: required- # These don't have -dyn/-prof whitelisted yet, so we have to- # do the old-style installation- # NB: TEST_OTHER_VERSIONS doesn't work with USE_GOLD=YES.- - env: GHCVER=7.6.3 SCRIPT=script CABAL_LIB_ONLY=YES TEST_OTHER_VERSIONS=YES- os: linux- sudo: required- - env: GHCVER=7.8.4 SCRIPT=script CABAL_LIB_ONLY=YES TEST_OTHER_VERSIONS=YES- os: linux- sudo: required- # Ugh, we'd like to drop 'sudo: required' and use the- # apt plugin for the next two- # but the GCE instance we get has more memory, which makes- # a big difference- - env: GHCVER=7.10.3 SCRIPT=script USE_GOLD=YES- os: linux- sudo: required- - env: GHCVER=8.0.2 SCRIPT=script USE_GOLD=YES TEST_SOLVER_BENCHMARKS=YES- sudo: required- os: linux- - env: GHCVER=8.2.2 SCRIPT=script USE_GOLD=YES- os: linux- sudo: required- - env: GHCVER=8.4.4 SCRIPT=script USE_GOLD=YES DEPLOY_DOCS=YES- os: linux- sudo: required- - env: GHCVER=8.6.5 SCRIPT=script USE_GOLD=YES- os: linux- sudo: required- #- env: GHCVER=8.8.1 SCRIPT=script USE_GOLD=YES- # os: linux- # sudo: required-- - env: GHCVER=8.4.4 SCRIPT=solver-debug-flags USE_GOLD=YES- sudo: required- os: linux- - env: GHCVER=8.4.4 SCRIPT=script DEBUG_EXPENSIVE_ASSERTIONS=YES TAGSUFFIX="-fdebug-expensive-assertions" USE_GOLD=YES- os: linux- sudo: required- - env: GHCVER=8.0.2 SCRIPT=bootstrap USE_GOLD=YES- sudo: required- os: linux- - env: GHCVER=8.4.4 SCRIPT=bootstrap USE_GOLD=YES- sudo: required- os: linux-- # We axed GHC 7.6 and earlier because it's not worth the trouble to- # make older GHC work with clang's cpp. See- # https://ghc.haskell.org/trac/ghc/ticket/8493- - env: GHCVER=7.8.4 SCRIPT=script CABAL_LIB_ONLY=YES- os: osx- # Keep this synced with travis/upload.sh- osx_image: xcode6.4 # We need 10.10-- # TODO: We might want to specify OSX version- # https://docs.travis-ci.com/user/osx-ci-environment/#OS-X-Version- - env: GHCVER=7.10.3 SCRIPT=script- os: osx- - env: GHCVER=8.0.2 SCRIPT=script- os: osx- - env: GHCVER=8.0.2 SCRIPT=bootstrap- os: osx-- # It's been long known that CI with- # Stack does not work so it's disabled until further notice- # to reduce latency and avoid wasting CI slots for no reason.- #- #- env: GHCVER=via-stack SCRIPT=stack STACK_CONFIG=stack.yaml- # os: linux- #- # See https://github.com/haskell/cabal/pull/4667#issuecomment-321036564- # for why failures are allowed.- #- # OSX jobs timeout often, so they can fail- allow_failures:- # - env: GHCVER=via-stack SCRIPT=stack STACK_CONFIG=stack.yaml- - env: GHCVER=7.10.3 SCRIPT=script- os: osx- - env: GHCVER=8.0.2 SCRIPT=script- os: osx-- # TODO add PARSEC_BUNDLED=YES when it's so- # It seems pointless to run head if we're going to ignore the results.- #- GHCVER=head-- # Marks the build result as soon as all the non-"allow_failures" jobs finish, based on their results- # while the remaining `allow_failures` jobs continue to run.- fast_finish: true--# Note: the distinction between `before_install` and `install` is not important.-before_install:- - export PATH=/opt/ghc/$GHCVER/bin:$PATH- - export PATH=$HOME/.ghc-install/$GHCVER/bin:$PATH- - export PATH=$HOME/bin:$PATH- - export PATH=$HOME/.cabal/bin:$PATH- - export PATH=$HOME/.local/bin:$PATH- - export PATH=/opt/cabal/2.4/bin:$PATH- - if [ "$USE_GOLD" = "YES" ]; then sudo update-alternatives --install "/usr/bin/ld" "ld" "/usr/bin/ld.gold" 20; fi- - if [ "$USE_GOLD" = "YES" ]; then sudo update-alternatives --install "/usr/bin/ld" "ld" "/usr/bin/ld.bfd" 10; fi- - ld -v- - ./travis-install.sh--install:- # We intentionally do not install anything before trying to build Cabal because- # it should build with each supported GHC version out-of-the-box.--# Here starts the actual work to be performed for the package under test; any-# command which exits with a non-zero exit code causes the build to fail. Using-# ./dist/setup/setup here instead of cabal-install to avoid breakage when the-# build config format changed.-script:- - rm -rf dist-newstyle- - ./travis-${SCRIPT}.sh -j2--cache:- directories:- - $HOME/.cabal/packages- - $HOME/.cabal/store- - $HOME/.cabal/bin-- - $HOME/.stack/bin- - $HOME/.stack/precompiled- - $HOME/.stack/programs- - $HOME/.stack/setup-exe-cache- - $HOME/.stack/snapshots--# We remove the index because it churns quite a bit and we don't want-# to pay the cost of repeatedly caching it even though we don't care-# about most changing packages.-before_cache:- - rm -fv $HOME/.cabal/packages/hackage.haskell.org/build-reports.log- - rm -fv $HOME/.cabal/packages/hackage.haskell.org/00-index*- - rm -fv $HOME/.cabal/packages/hackage.haskell.org/01-index*- - rm -fv $HOME/.cabal/packages/hackage.haskell.org/*.json- # avoid clashing or stale locks being cached- - rm -rfv $HOME/.cabal/packages/hackage.haskell.org/hackage-security-lock--# Deploy Haddocks to the haskell/cabal-website repo.-after_success:- # Set up deployment to the haskell/cabal-website repo.- # NB: these commands MUST be in .travis.yml, otherwise the secret key can be- # leaked! See https://github.com/travis-ci/travis.rb/issues/423.- # umask to get the permissions to be 600.- - if [ "x$TRAVIS_REPO_SLUG" = "xhaskell/cabal" -a "x$TRAVIS_PULL_REQUEST" = "xfalse" -a "x$TRAVIS_BRANCH" = "xmaster" -a "x$DEPLOY_DOCS" = "xYES" ]; then (umask 177 && openssl aes-256-cbc -K $encrypted_edaf6551664d_key -iv $encrypted_edaf6551664d_iv -in id_rsa_cabal_website.aes256.enc -out ~/.ssh/id_rsa -d); fi- - ./travis-deploy.sh--notifications:- irc:- if: repo = haskell/cabal- channels:- - "chat.freenode.net##haskell-cabal"
cabal/CONTRIBUTING.md view
@@ -4,12 +4,12 @@ -------------------------- The current recommended way of developing Cabal is to use the-`new-build` feature which [shipped in cabal-install-1.24](http://blog.ezyang.com/2016/05/announcing-cabal-new-build-nix-style-local-builds/). Assuming+`v2-build` feature which [shipped in cabal-install-1.24](http://blog.ezyang.com/2016/05/announcing-cabal-new-build-nix-style-local-builds/). Assuming that you have a sufficiently recent cabal-install (see above), it is sufficient to run: ~~~~-cabal new-build cabal+cabal v2-build cabal ~~~~ To build a local, development copy of cabal-install. The location@@ -21,9 +21,9 @@ Here are some other useful variations on the commands: ~~~~-cabal new-build Cabal # build library only-cabal new-build Cabal:unit-tests # build Cabal's unit test suite-cabal new-build cabal-tests # etc...+cabal v2-build Cabal # build library only+cabal v2-build Cabal:unit-tests # build Cabal's unit test suite+cabal v2-build cabal-tests # etc... ~~~~ **Dogfooding HEAD.**@@ -45,7 +45,7 @@ ~~~~ cd ~/cabal-prod-/opt/cabal/2.4/bin/cabal new-build cabal+/opt/cabal/2.4/bin/cabal v2-build cabal ~~~~ This will produce a cabal binary (see also: [Where are my build products?](http://cabal.readthedocs.io/en/latest/nix-local-build.html#where-are-my-build-products)@@ -54,7 +54,7 @@ ~~~~ cd ~/cabal-dev-cabal new-build cabal+cabal v2-build cabal ~~~~ Running tests@@ -112,7 +112,7 @@ or continuous integration breakage; please file a bug. **Running tests locally.**-To run tests locally with `new-build`, you will need to know the+To run tests locally with `v2-build`, you will need to know the name of the test suite you want. Cabal and cabal-install have several. Also, you'll want to read [Where are my build products?](http://cabal.readthedocs.io/en/latest/nix-local-build.html#where-are-my-build-products)
+ cabal/Cabal/Cabal-QuickCheck/Cabal-QuickCheck.cabal view
@@ -0,0 +1,24 @@+cabal-version: 2.2+name: Cabal-QuickCheck+version: 3.3.0.0+synopsis: QuickCheck instances for types in Cabal+category: Testing+description:+ Provides QuickCheck Arbitrary instances for some types in Cabal++library+ default-language: Haskell2010+ hs-source-dirs: src+ ghc-options: -Wall+ build-depends:+ , base+ , bytestring+ , Cabal ^>=3.3.0.0+ , QuickCheck ^>=2.13.2 || ^>=2.14++ if !impl(ghc >= 8.0)+ build-depends: semigroups++ exposed-modules:+ Test.QuickCheck.GenericArbitrary+ Test.QuickCheck.Instances.Cabal
+ cabal/Cabal/Cabal-QuickCheck/src/Test/QuickCheck/GenericArbitrary.hs view
@@ -0,0 +1,49 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE TypeOperators #-}+module Test.QuickCheck.GenericArbitrary (+ genericArbitrary,+ GArbitrary,+) where++import GHC.Generics+import Test.QuickCheck++#if !MIN_VERSION_base(4,8,0)+import Control.Applicative (pure, (<$>), (<*>))+#endif++-- Generic arbitary for non-recursive types+genericArbitrary :: (Generic a, GArbitrary (Rep a)) => Gen a+genericArbitrary = fmap to garbitrary++class GArbitrary f where+ garbitrary :: Gen (f ())++class GArbitrarySum f where+ garbitrarySum :: [Gen (f ())]++class GArbitraryProd f where+ garbitraryProd :: Gen (f ())++instance (GArbitrarySum f, i ~ D) => GArbitrary (M1 i c f) where+ garbitrary = fmap M1 (oneof garbitrarySum)++instance (GArbitraryProd f, i ~ C) => GArbitrarySum (M1 i c f) where+ garbitrarySum = [fmap M1 garbitraryProd]++instance (GArbitrarySum f, GArbitrarySum g) => GArbitrarySum (f :+: g) where+ garbitrarySum = map (fmap L1) garbitrarySum ++ map (fmap R1) garbitrarySum++instance (GArbitraryProd f, i ~ S) => GArbitraryProd (M1 i c f) where+ garbitraryProd = fmap M1 garbitraryProd++instance GArbitraryProd U1 where+ garbitraryProd = pure U1++instance (GArbitraryProd f, GArbitraryProd g) => GArbitraryProd (f :*: g) where+ garbitraryProd = (:*:) <$> garbitraryProd <*> garbitraryProd++instance (Arbitrary a) => GArbitraryProd (K1 i a) where+ garbitraryProd = fmap K1 arbitrary
+ cabal/Cabal/Cabal-QuickCheck/src/Test/QuickCheck/Instances/Cabal.hs view
@@ -0,0 +1,513 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE TypeOperators #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+module Test.QuickCheck.Instances.Cabal () where++import Control.Applicative (liftA2)+import Data.Char (isAlphaNum, isDigit)+import Data.List (intercalate, isPrefixOf)+import Data.List.NonEmpty (NonEmpty (..))+import Distribution.Utils.Generic (lowercase)+import Test.QuickCheck++import Distribution.CabalSpecVersion+import Distribution.Compat.NonEmptySet (NonEmptySet)+import Distribution.Compiler+import Distribution.FieldGrammar.Newtypes+import Distribution.ModuleName+import Distribution.Simple.Compiler (DebugInfoLevel (..), OptimisationLevel (..), PackageDB (..), ProfDetailLevel (..), knownProfDetailLevels)+import Distribution.Simple.Flag (Flag (..))+import Distribution.Simple.InstallDirs+import Distribution.Simple.Setup (HaddockTarget (..), TestShowDetails (..))+import Distribution.SPDX+import Distribution.System+import Distribution.Types.Dependency+import Distribution.Types.Flag (FlagAssignment, FlagName, mkFlagAssignment, mkFlagName, unFlagAssignment)+import Distribution.Types.IncludeRenaming+import Distribution.Types.LibraryName+import Distribution.Types.LibraryVisibility+import Distribution.Types.Mixin+import Distribution.Types.ModuleRenaming+import Distribution.Types.PackageId+import Distribution.Types.PackageName+import Distribution.Types.PackageVersionConstraint+import Distribution.Types.PkgconfigVersion+import Distribution.Types.PkgconfigVersionRange+import Distribution.Types.SourceRepo+import Distribution.Types.UnqualComponentName+import Distribution.Types.VersionRange.Internal+import Distribution.Utils.NubList+import Distribution.Verbosity+import Distribution.Version++import Test.QuickCheck.GenericArbitrary++import qualified Data.ByteString.Char8 as BS8+import qualified Distribution.Compat.NonEmptySet as NES++#if !MIN_VERSION_base(4,8,0)+import Control.Applicative (pure, (<$>), (<*>))+#endif++-------------------------------------------------------------------------------+-- CabalSpecVersion+-------------------------------------------------------------------------------++instance Arbitrary CabalSpecVersion where+ arbitrary = arbitraryBoundedEnum++instance Arbitrary SpecVersion where+ arbitrary = fmap SpecVersion arbitrary++-------------------------------------------------------------------------------+-- PackageName and PackageIdentifier+-------------------------------------------------------------------------------++instance Arbitrary PackageName where+ arbitrary = mkPackageName . intercalate "-" <$> shortListOf1 2 nameComponent+ where+ nameComponent = shortListOf1 5 (elements packageChars)+ `suchThat` (not . all isDigit)+ packageChars = filter isAlphaNum ['\0'..'\127']++instance Arbitrary PackageIdentifier where+ arbitrary = PackageIdentifier <$> arbitrary <*> arbitrary++ shrink (PackageIdentifier pn vr) = uncurry PackageIdentifier <$> shrink (pn, vr)++-------------------------------------------------------------------------------+-- Version+-------------------------------------------------------------------------------++-- | Does *NOT* generate 'nullVersion'+instance Arbitrary Version where+ arbitrary = do+ branch <- smallListOf1 $+ frequency [(3, return 0)+ ,(3, return 1)+ ,(2, return 2)+ ,(2, return 3)+ ,(1, return 0xfffd)+ ,(1, return 0xfffe) -- max fitting into packed W64+ ,(1, return 0xffff)+ ,(1, return 999999998)+ ,(1, return 999999999)+ ,(1, return 0x10000)]+ return (mkVersion branch)+ where+ smallListOf1 = scale (\n -> min 6 (n `div` 3)) . listOf1++ shrink ver = [ mkVersion ns | ns <- shrink (versionNumbers ver)+ , not (null ns) ]++instance Arbitrary VersionRange where+ arbitrary = sized verRangeExp+ where+ verRangeExp n = frequency $+ [ (2, return anyVersion)+ , (1, fmap thisVersion arbitrary)+ , (1, fmap laterVersion arbitrary)+ , (1, fmap orLaterVersion arbitrary)+ , (1, fmap orLaterVersion' arbitrary)+ , (1, fmap earlierVersion arbitrary)+ , (1, fmap orEarlierVersion arbitrary)+ , (1, fmap orEarlierVersion' arbitrary)+ , (1, fmap withinVersion arbitraryV)+ , (1, fmap majorBoundVersion arbitrary)+ ] ++ if n == 0 then [] else+ [ (2, liftA2 unionVersionRanges verRangeExp2 verRangeExp2)+ , (2, liftA2 intersectVersionRanges verRangeExp2 verRangeExp2)+ ]+ where+ verRangeExp2 = verRangeExp (n `div` 2)++ arbitraryV :: Gen Version+ arbitraryV = arbitrary `suchThat` \v -> all (< 999999999) (versionNumbers v)++ orLaterVersion' v =+ unionVersionRanges (LaterVersion v) (ThisVersion v)+ orEarlierVersion' v =+ unionVersionRanges (EarlierVersion v) (ThisVersion v)++ shrink (ThisVersion v) = map ThisVersion (shrink v)+ shrink (LaterVersion v) = map LaterVersion (shrink v)+ shrink (EarlierVersion v) = map EarlierVersion (shrink v)+ shrink (OrLaterVersion v) = LaterVersion v : map OrLaterVersion (shrink v)+ shrink (OrEarlierVersion v) = EarlierVersion v : map OrEarlierVersion (shrink v)+ shrink (MajorBoundVersion v) = map MajorBoundVersion (shrink v)+ shrink (UnionVersionRanges a b) = a : b : map (uncurry UnionVersionRanges) (shrink (a, b))+ shrink (IntersectVersionRanges a b) = a : b : map (uncurry IntersectVersionRanges) (shrink (a, b))++-- | Generating VersionIntervals+--+-- This is a tad tricky as VersionIntervals is an abstract type, so we first+-- make a local type for generating the internal representation. Then we check+-- that this lets us construct valid 'VersionIntervals'.+--++instance Arbitrary VersionIntervals where+ arbitrary = fmap mkVersionIntervals' arbitrary+ where+ mkVersionIntervals' :: [(Version, Bound)] -> VersionIntervals+ mkVersionIntervals' = mkVersionIntervals . go version0+ where+ go :: Version -> [(Version, Bound)] -> [VersionInterval]+ go _ [] = []+ go v [(lv, lb)] =+ [(LowerBound (addVersion lv v) lb, NoUpperBound)]+ go v ((lv, lb) : (uv, ub) : rest) =+ (LowerBound lv' lb, UpperBound uv' ub) : go uv' rest+ where+ lv' = addVersion v lv+ uv' = addVersion lv' uv++ addVersion :: Version -> Version -> Version+ addVersion xs ys = mkVersion $ z (versionNumbers xs) (versionNumbers ys)+ where+ z [] ys' = ys'+ z xs' [] = xs'+ z (x : xs') (y : ys') = x + y : z xs' ys'++instance Arbitrary Bound where+ arbitrary = elements [ExclusiveBound, InclusiveBound]++-------------------------------------------------------------------------------+-- Backpack+-------------------------------------------------------------------------------++instance Arbitrary Mixin where+ arbitrary = normaliseMixin <$> genericArbitrary+ shrink = fmap normaliseMixin . genericShrink++instance Arbitrary IncludeRenaming where+ arbitrary = genericArbitrary+ shrink = genericShrink++instance Arbitrary ModuleRenaming where+ arbitrary = genericArbitrary+ shrink = genericShrink++-------------------------------------------------------------------------------+--+-------------------------------------------------------------------------------++instance Arbitrary LibraryVisibility where+ arbitrary = elements [LibraryVisibilityPrivate, LibraryVisibilityPublic]++ shrink LibraryVisibilityPublic = [LibraryVisibilityPrivate]+ shrink LibraryVisibilityPrivate = []++-------------------------------------------------------------------------------+-- ModuleName+-------------------------------------------------------------------------------++instance Arbitrary ModuleName where+ arbitrary = fromString . intercalate "." <$> shortListOf1 4 comp where+ comp = (:) <$> elements upper <*> shortListOf1 10 (elements moduleChar)+ upper = ['A'..'Z']+ moduleChar = [ c | c <- ['\0' .. '\255'], isAlphaNum c || c `elem` "_'" ]++-------------------------------------------------------------------------------+-- Dependency+-------------------------------------------------------------------------------++instance Arbitrary Dependency where+ arbitrary = mkDependency+ <$> arbitrary+ <*> arbitrary+ <*> (arbitrary `suchThat` const True) -- should be (not . null)++ shrink (Dependency pn vr lb) =+ [ mkDependency pn' vr' lb'+ | (pn', vr', lb') <- shrink (pn, vr, lb)+ ]++-------------------------------------------------------------------------------+-- PackageVersionConstraint+-------------------------------------------------------------------------------++instance Arbitrary PackageVersionConstraint where+ arbitrary = PackageVersionConstraint+ <$> arbitrary+ <*> arbitrary++ shrink (PackageVersionConstraint pn vr) =+ [ PackageVersionConstraint pn' vr'+ | (pn', vr') <- shrink (pn, vr)+ ]++-------------------------------------------------------------------------------+-- System+-------------------------------------------------------------------------------++instance Arbitrary OS where+ arbitrary = elements knownOSs++instance Arbitrary Arch where+ arbitrary = elements knownArches++instance Arbitrary Platform where+ arbitrary = Platform <$> arbitrary <*> arbitrary++-------------------------------------------------------------------------------+-- Various names+-------------------------------------------------------------------------------++instance Arbitrary UnqualComponentName where+ -- same rules as package names+ arbitrary = packageNameToUnqualComponentName <$> arbitrary++instance Arbitrary LibraryName where+ arbitrary = oneof+ [ LSubLibName <$> arbitrary+ , pure LMainLibName+ ]++ shrink (LSubLibName _) = [LMainLibName]+ shrink _ = []++-------------------------------------------------------------------------------+-- option flags+-------------------------------------------------------------------------------++instance Arbitrary a => Arbitrary (Flag a) where+ arbitrary = arbitrary1++ shrink NoFlag = []+ shrink (Flag x) = NoFlag : [ Flag x' | x' <- shrink x ]++instance Arbitrary1 Flag where+ liftArbitrary genA = sized $ \sz ->+ if sz <= 0+ then pure NoFlag+ else frequency [ (1, pure NoFlag)+ , (3, Flag <$> genA) ]++-------------------------------------------------------------------------------+-- GPD flags+-------------------------------------------------------------------------------++instance Arbitrary FlagName where+ arbitrary = mkFlagName <$> frequency+ [ (20, flagident)+ -- special nasty cases+ , (1, pure "none")+ , (1, pure "any")+ ]+ where+ flagident = lowercase <$> shortListOf1 5 (elements flagChars)+ `suchThat` (("-" /=) . take 1)+ flagChars = "-_" ++ ['a'..'z']++instance Arbitrary FlagAssignment where+ arbitrary = mkFlagAssignment <$> arbitrary+ shrink x = mkFlagAssignment <$> shrink (unFlagAssignment x)++-------------------------------------------------------------------------------+-- Verbosity+-------------------------------------------------------------------------------++instance Arbitrary Verbosity where+ arbitrary = do+ v <- elements [minBound..maxBound]+ -- verbose markoutput is left out on purpose+ flags <- listOf $ elements+ [ verboseCallSite+ , verboseCallStack+ , verboseNoWrap+ , verboseTimestamp+ , verboseStderr+ ]+ return (foldr ($) v flags)++-------------------------------------------------------------------------------+-- SourceRepo+-------------------------------------------------------------------------------++instance Arbitrary RepoType where+ arbitrary = elements (KnownRepoType <$> knownRepoTypes)++instance Arbitrary RepoKind where+ arbitrary = elements [RepoHead, RepoThis]++-------------------------------------------------------------------------------+-- SPDX+-------------------------------------------------------------------------------++instance Arbitrary LicenseId where+ arbitrary = elements $ licenseIdList currentLicenseListVersion++instance Arbitrary LicenseExceptionId where+ arbitrary = elements $ licenseExceptionIdList currentLicenseListVersion++currentLicenseListVersion :: LicenseListVersion+currentLicenseListVersion = cabalSpecVersionToSPDXListVersion cabalSpecLatest++instance Arbitrary LicenseRef where+ arbitrary = mkLicenseRef' <$> ids' <*> ids+ where+ ids = listOf1 $ elements $ ['a'..'z'] ++ ['A' .. 'Z'] ++ ['0'..'9'] ++ "_-"+ ids' = oneof [ pure Nothing, Just <$> ids ]++instance Arbitrary SimpleLicenseExpression where+ arbitrary = oneof+ [ ELicenseId <$> arbitrary+ , ELicenseIdPlus <$> arbitrary+ , ELicenseRef <$> arbitrary+ ]++instance Arbitrary LicenseExpression where+ arbitrary = sized arb+ where+ arb n+ | n <= 0 = ELicense <$> arbitrary <*> pure Nothing+ | otherwise = oneof+ [ ELicense <$> arbitrary <*> arbitrary+ , EAnd <$> arbA <*> arbB+ , EOr <$> arbA <*> arbB+ ]+ where+ m = n `div` 2+ arbA = arb m+ arbB = arb (n - m)++ shrink (EAnd a b) = a : b : map (uncurry EAnd) (shrink (a, b))+ shrink (EOr a b) = a : b : map (uncurry EOr) (shrink (a, b))+ shrink _ = []++-------------------------------------------------------------------------------+-- Compiler+-------------------------------------------------------------------------------++instance Arbitrary CompilerFlavor where+ arbitrary = elements knownCompilerFlavors++instance Arbitrary CompilerId where+ arbitrary = genericArbitrary+ shrink = genericShrink++instance Arbitrary ProfDetailLevel where+ arbitrary = elements [ d | (_,_,d) <- knownProfDetailLevels ]++instance Arbitrary OptimisationLevel where+ arbitrary = elements [minBound..maxBound]++instance Arbitrary DebugInfoLevel where+ arbitrary = elements [minBound..maxBound]++-------------------------------------------------------------------------------+-- NonEmptySet+-------------------------------------------------------------------------------++instance (Arbitrary a, Ord a) => Arbitrary (NonEmptySet a) where+ arbitrary = mk <$> arbitrary <*> arbitrary where+ mk x xs = NES.fromNonEmpty (x :| xs)++ shrink nes = case NES.toNonEmpty nes of+ x :| xs -> map mk (shrink (x, xs))+ where+ mk (x,xs) = NES.fromNonEmpty (x :| xs)++-------------------------------------------------------------------------------+-- NubList+-------------------------------------------------------------------------------++instance (Arbitrary a, Ord a) => Arbitrary (NubList a) where+ arbitrary = toNubList <$> arbitrary+ shrink xs = [ toNubList [] | (not . null) (fromNubList xs) ]+ -- try empty, otherwise don't shrink as it can loop++-------------------------------------------------------------------------------+-- InstallDirs+-------------------------------------------------------------------------------++instance Arbitrary a => Arbitrary (InstallDirs a) where+ arbitrary = InstallDirs+ <$> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary -- 4+ <*> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary -- 8+ <*> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary -- 12+ <*> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary -- 16++instance Arbitrary PathTemplate where+ arbitrary = toPathTemplate <$> arbitraryShortToken+ shrink t = [ toPathTemplate s+ | s <- shrink (fromPathTemplate t)+ , not (null s) ]++-------------------------------------------------------------------------------+-- Pkgconfig+-------------------------------------------------------------------------------++instance Arbitrary PkgconfigVersion where+ arbitrary = PkgconfigVersion . BS8.pack . dropDash . concat <$> listOf1 elems where+ elems = frequency+ [ (2, pure ".")+ , (1, pure "-")+ , (5, listOf1 $ elements ['0' .. '9'])+ , (1, listOf1 $ elements ['A' .. 'Z'])+ , (1, listOf1 $ elements ['a' .. 'z'])+ ]++ -- disallow versions starting with dash+ dropDash = notEmpty . dropWhile (== '-')+ notEmpty x+ | null x = "0"+ | otherwise = x++instance Arbitrary PkgconfigVersionRange where+ arbitrary = sized verRangeExp+ where+ verRangeExp n = frequency $+ [ (2, return PcAnyVersion)+ , (1, fmap PcThisVersion arbitrary)+ , (1, fmap PcLaterVersion arbitrary)+ , (1, fmap PcOrLaterVersion arbitrary)+ , (1, fmap orLaterVersion' arbitrary)+ , (1, fmap PcEarlierVersion arbitrary)+ , (1, fmap PcOrEarlierVersion arbitrary)+ , (1, fmap orEarlierVersion' arbitrary)+ ] ++ if n == 0 then [] else+ [ (2, liftA2 PcUnionVersionRanges verRangeExp2 verRangeExp2)+ , (2, liftA2 PcIntersectVersionRanges verRangeExp2 verRangeExp2)+ ]+ where+ verRangeExp2 = verRangeExp (n `div` 2)++ orLaterVersion' v =+ PcUnionVersionRanges (PcLaterVersion v) (PcThisVersion v)+ orEarlierVersion' v =+ PcUnionVersionRanges (PcEarlierVersion v) (PcThisVersion v)++-------------------------------------------------------------------------------+-- Setup+-------------------------------------------------------------------------------++instance Arbitrary HaddockTarget where+ arbitrary = elements [ForHackage, ForDevelopment]++instance Arbitrary TestShowDetails where+ arbitrary = arbitraryBoundedEnum++-------------------------------------------------------------------------------+-- PackageDB+-------------------------------------------------------------------------------++instance Arbitrary PackageDB where+ arbitrary = oneof [ pure GlobalPackageDB+ , pure UserPackageDB+ , SpecificPackageDB <$> arbitraryShortToken+ ]+++-------------------------------------------------------------------------------+-- Helpers+-------------------------------------------------------------------------------++shortListOf1 :: Int -> Gen a -> Gen [a]+shortListOf1 bound gen = sized $ \n -> do+ k <- choose (1, 1 `max` ((n `div` 2) `min` bound))+ vectorOf k gen++arbitraryShortToken :: Gen String+arbitraryShortToken =+ shortListOf1 5 (choose ('#', '~')) `suchThat` (not . ("[]" `isPrefixOf`))
+ cabal/Cabal/Cabal-described/Cabal-described.cabal view
@@ -0,0 +1,26 @@+cabal-version: 2.2+name: Cabal-described+version: 3.3.0.0+synopsis: Described functionality for types in Cabal+category: Testing, Parsec+description: Provides rere bindings++library+ default-language: Haskell2010+ hs-source-dirs: src+ ghc-options: -Wall+ build-depends:+ , base+ , Cabal ^>=3.3.0.0+ , containers+ , pretty+ , QuickCheck+ , rere ^>=0.1+ , tasty+ , tasty-quickcheck+ , transformers++ exposed-modules:+ Distribution.Described+ Distribution.Utils.CharSet+ Distribution.Utils.GrammarRegex
+ cabal/Cabal/Cabal-described/src/Distribution/Described.hs view
@@ -0,0 +1,577 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}+module Distribution.Described (+ Described (..),+ describeDoc,+ -- * Regular expressions+ GrammarRegex (..),+ reEps,+ reChar,+ reChars,+ reMunchCS,+ reMunch1CS,+ -- * Variables+ reVar0,+ reVar1,+ -- * Special expressions+ reDot,+ reComma,+ reSpacedComma,+ reHsString,+ reUnqualComponent,+ -- *+ describeFlagAssignmentNonEmpty,+ -- * Lists+ reSpacedList,+ reCommaList,+ reCommaNonEmpty,+ reOptCommaList,+ -- * Character Sets+ csChar,+ csAlpha,+ csAlphaNum,+ csUpper,+ csNotSpace,+ csNotSpaceOrComma,+ -- * tasty+ testDescribed,+ ) where++import Prelude+ (Bool (..), Char, Either (..), Enum (..), Eq (..), Ord (..), Show (..), String, elem, fmap, foldr, id, map, maybe, otherwise, return, undefined, ($),+ (.))++import Data.Functor.Identity (Identity (..))+import Data.Maybe (fromMaybe)+import Data.Proxy (Proxy (..))+import Data.String (IsString (..))+import Data.Typeable (Typeable, typeOf)+import Data.Void (Void, vacuous)+import Test.QuickCheck (Arbitrary (..), Property, counterexample)+import Test.Tasty (TestTree, testGroup)+import Test.Tasty.QuickCheck (testProperty)++import Distribution.Compat.Semigroup (Semigroup (..))+import Distribution.Parsec (Parsec, eitherParsec)+import Distribution.Pretty (Pretty, prettyShow)++import qualified Distribution.Utils.CharSet as CS+import qualified RERE as RE+import qualified RERE.CharSet as RE+import qualified Text.PrettyPrint as PP++import Distribution.Utils.GrammarRegex++-- Types+import Distribution.Compat.Newtype+import Distribution.Compiler (CompilerFlavor, CompilerId, knownCompilerFlavors)+import Distribution.FieldGrammar.Newtypes+import Distribution.ModuleName (ModuleName)+import Distribution.System (Arch, OS, knownArches, knownOSs)+import Distribution.Types.AbiDependency (AbiDependency)+import Distribution.Types.AbiHash (AbiHash)+import Distribution.Types.BenchmarkType (BenchmarkType)+import Distribution.Types.BuildType (BuildType)+import Distribution.Types.Dependency (Dependency)+import Distribution.Types.ExecutableScope (ExecutableScope)+import Distribution.Types.ExeDependency (ExeDependency)+import Distribution.Types.ExposedModule (ExposedModule)+import Distribution.Types.Flag (FlagAssignment, FlagName)+import Distribution.Types.ForeignLib (LibVersionInfo)+import Distribution.Types.ForeignLibOption (ForeignLibOption)+import Distribution.Types.ForeignLibType (ForeignLibType)+import Distribution.Types.IncludeRenaming (IncludeRenaming)+import Distribution.Types.LegacyExeDependency (LegacyExeDependency)+import Distribution.Types.LibraryVisibility (LibraryVisibility)+import Distribution.Types.Mixin (Mixin)+import Distribution.Types.ModuleReexport (ModuleReexport)+import Distribution.Types.ModuleRenaming (ModuleRenaming)+import Distribution.Types.MungedPackageName (MungedPackageName)+import Distribution.Types.PackageId (PackageIdentifier)+import Distribution.Types.PackageName (PackageName)+import Distribution.Types.PackageVersionConstraint (PackageVersionConstraint)+import Distribution.Types.PkgconfigDependency (PkgconfigDependency)+import Distribution.Types.SourceRepo (RepoType)+import Distribution.Types.TestType (TestType)+import Distribution.Types.UnitId (UnitId)+import Distribution.Types.UnqualComponentName (UnqualComponentName)+import Distribution.Verbosity (Verbosity)+import Distribution.Version (Version, VersionRange)+import Language.Haskell.Extension (Extension, Language)++-- | Class describing the pretty/parsec format of a.+class (Pretty a, Parsec a) => Described a where+ -- | A pretty document of "regex" describing the field format+ describe :: proxy a -> GrammarRegex void++-- | Pretty-print description.+--+-- >>> describeDoc ([] :: [Bool])+-- \left\{ \mathop{\mathord{``}\mathtt{True}\mathord{"}}\mid\mathop{\mathord{``}\mathtt{False}\mathord{"}} \right\}+--+describeDoc :: Described a => proxy a -> PP.Doc+describeDoc p = regexDoc (describe p)++instance Described Bool where+ describe _ = REUnion ["True", "False"]++instance Described a => Described (Identity a) where+ describe _ = describe ([] :: [a])++-------------------------------------------------------------------------------+-- Lists+------------------------------------------------------------------------------++reSpacedList :: GrammarRegex a -> GrammarRegex a+reSpacedList = REMunch RESpaces1++reCommaList :: GrammarRegex a -> GrammarRegex a+reCommaList = RECommaList++reCommaNonEmpty :: GrammarRegex a -> GrammarRegex a+reCommaNonEmpty = RECommaNonEmpty++reOptCommaList :: GrammarRegex a -> GrammarRegex a+reOptCommaList = REOptCommaList++-------------------------------------------------------------------------------+-- Specific grammars+-------------------------------------------------------------------------------++reHsString :: GrammarRegex a+reHsString = RENamed "hs-string" impl where+ impl = reChar '"' <> REMunch reEps (REUnion [strChar, escChar]) <> reChar '"'+ strChar = RECharSet $ CS.difference CS.universe (CS.fromList "\"\\")++ escChar = REUnion+ [ "\\&"+ , "\\\\"+ , REUnion ["\\n", RENamed "escapes" "\\n"] -- TODO+ , "\\" <> RECharSet "0123456789"+ , "\\o" <> RECharSet "01234567"+ , "\\x" <> RECharSet "0123456789abcdefABCDEF"+ , REUnion ["\\^@", RENamed "control" "\\^@"] -- TODO+ , REUnion ["\\NUL", RENamed "ascii" "\\NUL"] -- TODO+ ]++reUnqualComponent :: GrammarRegex a+reUnqualComponent = RENamed "unqual-name" $+ REMunch1 (reChar '-') component+ where+ component+ = REMunch reEps (RECharSet csAlphaNum)+ -- currently the parser accepts "csAlphaNum `difference` "0123456789"+ -- which is larger set than CS.alpha+ --+ -- Hackage rejects non ANSI names, so it's not so relevant.+ <> RECharSet CS.alpha+ <> REMunch reEps (RECharSet csAlphaNum)++reDot :: GrammarRegex a+reDot = reChar '.'++reComma :: GrammarRegex a+reComma = reChar ','++reSpacedComma :: GrammarRegex a+reSpacedComma = RESpaces <> reComma <> RESpaces++-------------------------------------------------------------------------------+-- Character sets+-------------------------------------------------------------------------------++csChar :: Char -> CS.CharSet+csChar = CS.singleton++csAlpha :: CS.CharSet+csAlpha = CS.alpha++csAlphaNum :: CS.CharSet+csAlphaNum = CS.alphanum++csUpper :: CS.CharSet+csUpper = CS.upper++csNotSpace :: CS.CharSet+csNotSpace = CS.difference CS.universe $ CS.singleton ' '++csNotSpaceOrComma :: CS.CharSet+csNotSpaceOrComma = CS.difference csNotSpace $ CS.singleton ','++-------------------------------------------------------------------------------+-- Special+-------------------------------------------------------------------------------++describeFlagAssignmentNonEmpty :: GrammarRegex void+describeFlagAssignmentNonEmpty = REMunch1 RESpaces1 $+ REUnion [fromString "+", fromString "-"] <> describe (Proxy :: Proxy FlagName)++-------------------------------------------------------------------------------+-- Conversion+-------------------------------------------------------------------------------++convert :: GrammarRegex Void -> RE.RE Void+convert = go id . vacuous where+ go :: Ord b => (a -> b) -> GrammarRegex a -> RE.RE b+ go f (REAppend rs) = foldr (\r acc -> go f r <> acc) RE.Eps rs+ go f (REUnion rs) = foldr (\r acc -> go f r RE.\/ acc) RE.Null rs+ go _ (RECharSet cs) = RE.Ch (convertCS cs)+ go _ (REString str) = RE.string_ str++ go f (REMunch sep r) = RE.Eps RE.\/ r' <> RE.star_ (sep' <> r') where+ sep' = go f sep+ r' = go f r+ go f (REMunch1 sep r) = r' <> RE.star_ (sep' <> r') where+ sep' = go f sep+ r' = go f r+ go f (REMunchR n sep r)+ | n <= 0 = RE.Eps+ | otherwise = RE.Eps RE.\/ r' <> go' (pred n)+ where+ sep' = go f sep+ r' = go f r++ go' m | m <= 0 = RE.Eps+ | otherwise = RE.Eps RE.\/ sep' <> r' <> go' (pred m)++ go f (REOpt r) = RE.Eps RE.\/ go f r++ go f (REVar a) = RE.Var (f a)+ go f (RENamed _ r) = go f r+ go f (RERec n r) = RE.fix_ (fromString n)+ (go (maybe RE.B (RE.F . f)) r)++ go _ RESpaces = RE.Eps RE.\/ RE.ch_ ' ' RE.\/ " " RE.\/ "\n"+ go _ RESpaces1 = RE.ch_ ' ' RE.\/ " " RE.\/ "\n"++ go f (RECommaList r) = go f (expandedCommaList r)+ go f (RECommaNonEmpty r)= go f (expandedCommaNonEmpty r)+ go f (REOptCommaList r) = go f (expandedOptCommaList r)++ go _ RETodo = RE.Null++expandedCommaList :: GrammarRegex a -> GrammarRegex a+expandedCommaList = REUnion . expandedCommaList'++expandedCommaNonEmpty :: GrammarRegex a -> GrammarRegex a+expandedCommaNonEmpty r = REUnion+ [ REMunch1 reSpacedComma r+ , reComma <> RESpaces <> REMunch1 reSpacedComma r+ , REMunch1 reSpacedComma r <> RESpaces <> reComma+ ]++expandedCommaList' :: GrammarRegex a -> [GrammarRegex a]+expandedCommaList' r =+ [ REMunch reSpacedComma r+ , reComma <> RESpaces <> REMunch1 reSpacedComma r+ , REMunch1 reSpacedComma r <> RESpaces <> reComma+ ]++expandedOptCommaList :: GrammarRegex a -> GrammarRegex a+expandedOptCommaList r = REUnion $ reSpacedList r : expandedCommaList' r++convertCS :: CS.CharSet -> RE.CharSet+convertCS = RE.fromIntervalList . CS.toIntervalList++-------------------------------------------------------------------------------+-- tasty+-------------------------------------------------------------------------------++testDescribed+ :: forall a. (Arbitrary a, Described a, Typeable a, Eq a, Show a)+ => Proxy a+ -> TestTree+testDescribed _ = testGroup name+ [ testProperty "parsec" propParsec+ , testProperty "pretty" propPretty+ , testProperty "roundtrip" propRoundtrip+ ]+ where+ name = show (typeOf (undefined :: a))++ propParsec :: Ex a -> Property+ propParsec (Example str) = counterexample (show res) $ case res of+ Right _ -> True+ Left _ -> False+ where+ res :: Either String a+ res = eitherParsec str++ rr :: RE.RE Void+ rr = convert $ describe (Proxy :: Proxy a)++ propPretty :: a -> Property+ propPretty x = counterexample str $ RE.matchR rr str+ where+ str = prettyShow x++ propRoundtrip :: a -> Property+ propRoundtrip x = counterexample (show (res, str)) $ case res of+ Right y -> x == y+ Left _ -> False+ where+ str = prettyShow x+ res = eitherParsec str++newtype Ex a = Example String+ deriving (Show)++instance Described a => Arbitrary (Ex a) where+ arbitrary+ = fmap Example+ $ fromMaybe (return "")+ $ RE.generate 10 5+ $ convert $ describe (Proxy :: Proxy a)++ shrink (Example s)+ | '\n' `elem` s = [ Example $ map (\c -> if c == '\n' then ' ' else c) s ]+ | otherwise = []++-------------------------------------------------------------------------------+-- Instances+-------------------------------------------------------------------------------++instance Described AbiDependency where+ describe _ =+ describe (Proxy :: Proxy UnitId) <>+ reChar '=' <>+ describe (Proxy :: Proxy AbiHash)++instance Described AbiHash where+ describe _ = reMunchCS csAlphaNum++instance Described Arch where+ describe _ = REUnion+ [ fromString (prettyShow arch)+ | arch <- knownArches+ ]++instance Described BenchmarkType where+ describe _ = "exitcode-stdio-1.0"++instance Described BuildType where+ describe _ = REUnion ["Simple","Configure","Custom","Make","Default"]++instance Described CompilerFlavor where+ describe _ = REUnion+ [ fromString (prettyShow c)+ | c <- knownCompilerFlavors+ ]++instance Described CompilerId where+ describe _ =+ describe (Proxy :: Proxy CompilerFlavor)+ <> fromString "-"+ <> describe (Proxy :: Proxy Version)++instance Described Dependency where+ describe _ = REAppend+ [ RENamed "pkg-name" (describe (Proxy :: Proxy PackageName))+ , REOpt $+ reChar ':'+ <> REUnion+ [ reUnqualComponent+ , REAppend+ [ reChar '{'+ , RESpaces+ -- no leading or trailing comma+ , REMunch1 reSpacedComma reUnqualComponent+ , RESpaces+ , reChar '}'+ ]+ ]++ , REOpt $ RESpaces <> vr+ ]+ where+ vr = RENamed "version-range" (describe (Proxy :: Proxy VersionRange))++instance Described ExecutableScope where+ describe _ = REUnion ["public","private"]++instance Described ExeDependency where+ describe _ = RETodo++instance Described ExposedModule where+ describe _ = RETodo++instance Described Extension where+ describe _ = RETodo++instance Described FlagAssignment where+ describe _ = REMunch RESpaces1 $+ REUnion [fromString "+", fromString "-"] <> describe (Proxy :: Proxy FlagName)++instance Described FlagName where+ describe _ = lead <> rest where+ lead = RECharSet $ csAlphaNum <> fromString "_"+ rest = reMunchCS $ csAlphaNum <> fromString "_-"++instance Described ForeignLibOption where+ describe _ = "standalone"++instance Described ForeignLibType where+ describe _ = REUnion ["native-shared","native-static"]++instance Described IncludeRenaming where+ describe _ = mr <> REOpt (RESpaces <> "requires" <> RESpaces1 <> mr)+ where+ mr = describe (Proxy :: Proxy ModuleRenaming)++instance Described Language where+ describe _ = REUnion ["Haskell98", "Haskell2010"]++instance Described LegacyExeDependency where+ describe _ = RETodo++instance Described LibraryVisibility where+ describe _ = REUnion ["public","private"]++instance Described LibVersionInfo where+ describe _ = reDigits <> REOpt (reChar ':' <> reDigits <> REOpt (reChar ':' <> reDigits)) where+ reDigits = reChars ['0'..'9']++instance Described Mixin where+ describe _ =+ RENamed "package-name" (describe (Proxy :: Proxy PackageName)) <>+ REOpt (reChar ':' <> RENamed "library-name" (describe (Proxy :: Proxy UnqualComponentName))) <>+ REOpt (RESpaces1 <> describe (Proxy :: Proxy IncludeRenaming))++instance Described ModuleName where+ describe _ = REMunch1 (reChar '.') component where+ component = RECharSet csUpper <> REMunch reEps (REUnion [RECharSet csAlphaNum, RECharSet (fromString "_'")])++instance Described ModuleReexport where+ describe _ = RETodo++instance Described ModuleRenaming where+ describe _ = REUnion+ [ reEps+ , "hiding" <> RESpaces <> bp (REMunch reSpacedComma mn)+ , bp (REMunch reSpacedComma entry)+ ]+ where+ bp r = "(" <> RESpaces <> r <> RESpaces <> ")"+ mn = RENamed "module-name" $ describe (Proxy :: Proxy ModuleName)++ entry = mn <> REOpt (RESpaces1 <> "as" <> RESpaces1 <> mn)++instance Described MungedPackageName where+ describe _ = RETodo++instance Described OS where+ describe _ = REUnion+ [ fromString (prettyShow os)+ | os <- knownOSs+ ]++instance Described PackageIdentifier where+ describe _ = describe (Proxy :: Proxy PackageName) <> fromString "-" <> describe (Proxy :: Proxy Version)++instance Described PackageName where+ describe _ = reUnqualComponent++instance Described PackageVersionConstraint where+ describe _ = describe (Proxy :: Proxy PackageName) <> REUnion+ [ fromString "-" <> describe (Proxy :: Proxy Version)+ , RESpaces <> describe (Proxy :: Proxy VersionRange)+ ]++instance Described PkgconfigDependency where+ describe _ = RETodo++instance Described RepoType where+ describe _ = reMunch1CS $ csAlphaNum <> csChar '_' <> csChar '-'++instance Described TestType where+ describe _ = REUnion ["exitcode-stdio-1.0", "detailed-0.9"]++instance Described Verbosity where+ describe _ = REUnion+ [ REUnion ["0", "1", "2", "3"]+ , REUnion ["silent", "normal", "verbose", "debug", "deafening"]+ <> REMunch reEps (RESpaces <> "+" <>+ -- markoutput is left out on purpose+ REUnion ["callsite", "callstack", "nowrap", "timestamp", "stderr", "stdout" ])+ ]++instance Described Version where+ describe _ = REMunch1 reDot reDigits where+ reDigits = REUnion+ [ reChar '0'+ , reChars ['1'..'9'] <> REMunchR 8 reEps (reChars ['0'..'9'])+ ]++instance Described VersionRange where+ describe _ = RERec "version-range" $ REUnion+ [ "==" <> RESpaces <> ver+ , ">" <> RESpaces <> ver+ , "<" <> RESpaces <> ver+ , "<=" <> RESpaces <> ver+ , ">=" <> RESpaces <> ver+ , "^>=" <> RESpaces <> ver++ -- ==0.1.*+ , "==" <> RESpaces <> wildVer++ , reVar0 <> RESpaces <> "||" <> RESpaces <> reVar0+ , reVar0 <> RESpaces <> "&&" <> RESpaces <> reVar0+ , "(" <> RESpaces <> reVar0 <> RESpaces <> ")"++ -- == { 0.1.2 }+ -- silly haddock: ^>= { 0.1.2, 3.4.5 }+ , "==" <> RESpaces <> verSet+ , "^>=" <> RESpaces <> verSet+ ]+ where+ ver' = describe (Proxy :: Proxy Version)+ ver = RENamed "version" ver'+ wildVer = ver' <> ".*"+ verSet = "{" <> RESpaces <> REMunch1 reSpacedComma ver <> RESpaces <> "}"++instance Described UnitId where+ describe _ = reMunch1CS $ csAlphaNum <> csChar '-' <> csChar '_' <> csChar '.' <> csChar '+'++instance Described UnqualComponentName where+ describe _ = reUnqualComponent++-------------------------------------------------------------------------------+-- Instances: Newtypes+-------------------------------------------------------------------------------++class Sep sep => DescribeSep sep where+ describeSep :: Proxy sep -> GrammarRegex a -> GrammarRegex a++instance DescribeSep CommaVCat where describeSep _ = reCommaList+instance DescribeSep CommaFSep where describeSep _ = reCommaList+instance DescribeSep VCat where describeSep _ = reCommaList+instance DescribeSep FSep where describeSep _ = reOptCommaList+instance DescribeSep NoCommaFSep where describeSep _ = reSpacedList++instance (Newtype a b, DescribeSep sep, Described b) => Described (List sep b a) where+ describe _ = describeSep (Proxy :: Proxy sep) (describe (Proxy :: Proxy b))++instance (Newtype a b, Ord a, DescribeSep sep, Described b) => Described (Set' sep b a) where+ describe _ = describeSep (Proxy :: Proxy sep) (describe (Proxy :: Proxy b))++instance Described Token where+ describe _ = REUnion [reHsString, reMunch1CS csNotSpaceOrComma]++instance Described Token' where+ describe _ = REUnion [reHsString, reMunch1CS csNotSpace]++instance Described a => Described (MQuoted a) where+ -- TODO: this is simplification+ describe _ = describe ([] :: [a])++instance Described SpecVersion where+ describe _ = "3.4" -- :)++instance Described SpecLicense where+ describe _ = RETodo++instance Described TestedWith where+ describe _ = RETodo++instance Described FilePathNT where+ describe _ = describe ([] :: [Token])
+ cabal/Cabal/Cabal-described/src/Distribution/Utils/CharSet.hs view
@@ -0,0 +1,242 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE CPP #-}+-- | Sets of characters.+--+-- Using this is more efficint than 'RE.Type.Alt':ng individual characters.+module Distribution.Utils.CharSet (+ -- * Set of characters+ CharSet,+ -- * Construction+ empty,+ universe,+ singleton,+ insert,+ union,+ intersection,+ complement,+ difference,+ -- * Query+ size,+ null,+ member,+ -- * Conversions+ fromList,+ toList,+ fromIntervalList,+ toIntervalList,+ -- * Special lists+ alpha,+ alphanum,+ upper,+ ) where++import Data.Char (chr, isAlpha, isAlphaNum, isUpper, ord)+import Data.List (foldl', sortBy)+import Data.Monoid (Monoid (..))+import Data.String (IsString (..))+import Distribution.Compat.Semigroup (Semigroup (..))+import Prelude+ (Bool (..), Bounded (..), Char, Enum (..), Eq (..), Int, Maybe (..), Num (..), Ord (..), Show (..), String, concatMap, flip, fst, otherwise, showParen,+ showString, uncurry, ($), (.))++#if MIN_VERSION_containers(0,5,0)+import qualified Data.IntMap.Strict as IM+#else+import qualified Data.IntMap as IM+#endif++-- | A set of 'Char's.+--+-- We use range set, which works great with 'Char'.+newtype CharSet = CS { unCS :: IM.IntMap Int }+ deriving (Eq, Ord)++instance IsString CharSet where+ fromString = fromList++instance Show CharSet where+ showsPrec d cs+ | size cs < 20+ = showsPrec d (toList cs)+ | otherwise+ = showParen (d > 10)+ $ showString "CS "+ . showsPrec 11 (unCS cs)++instance Semigroup CharSet where+ (<>) = union++instance Monoid CharSet where+ mempty = empty+ mappend = (<>)++-- | Empty character set.+empty :: CharSet+empty = CS IM.empty++-- | universe+universe :: CharSet+universe = CS $ IM.singleton 0 0x10ffff++-- | Check whether 'CharSet' is 'empty'.+null :: CharSet -> Bool+null (CS cs) = IM.null cs++-- | Size of 'CharSet'+--+-- >>> size $ fromIntervalList [('a','f'), ('0','9')]+-- 16+--+-- >>> length $ toList $ fromIntervalList [('a','f'), ('0','9')]+-- 16+--+size :: CharSet -> Int+size (CS m) = foldl' (\ !acc (lo, hi) -> acc + (hi - lo) + 1) 0 (IM.toList m)++-- | Singleton character set.+singleton :: Char -> CharSet+singleton c = CS (IM.singleton (ord c) (ord c))++-- | Test whether character is in the set.+member :: Char -> CharSet -> Bool+#if MIN_VERSION_containers(0,5,0)+member c (CS m) = case IM.lookupLE i m of+ Nothing -> False+ Just (_, hi) -> i <= hi+ where+#else+member c (CS m) = go (IM.toList m)+ where+ go [] = False+ go ((x,y):zs) = (x <= i && i <= y) || go zs+#endif+ i = ord c++-- | Insert 'Char' into 'CharSet'.+insert :: Char -> CharSet -> CharSet+insert c (CS m) = normalise (IM.insert (ord c) (ord c) m)++-- | Union of two 'CharSet's.+union :: CharSet -> CharSet -> CharSet+union (CS xs) (CS ys) = normalise (IM.unionWith max xs ys)++-- | Intersection of two 'CharSet's+intersection :: CharSet -> CharSet -> CharSet+intersection (CS xs) (CS ys) = CS $+ IM.fromList (intersectRangeList (IM.toList xs) (IM.toList ys))++-- | Compute the intersection.+intersectRangeList :: Ord a => [(a, a)] -> [(a, a)] -> [(a, a)]+intersectRangeList aset@((x,y):as) bset@((u,v):bs)+ | y < u = intersectRangeList as bset+ | v < x = intersectRangeList aset bs+ | y < v = (max x u, y) : intersectRangeList as bset+ | otherwise = (max x u, v) : intersectRangeList aset bs+intersectRangeList _ [] = []+intersectRangeList [] _ = []++-- | Complement of a CharSet+complement :: CharSet -> CharSet+complement (CS xs) = CS $ IM.fromList $ complementRangeList (IM.toList xs)++-- | Compute the complement intersected with @[x,)@ assuming @x<u@.+complementRangeList' :: Int -> [(Int, Int)] -> [(Int, Int)]+complementRangeList' x ((u,v):s) = (x,pred u) : complementRangeList'' v s+complementRangeList' x [] = [(x,0x10ffff)]++-- | Compute the complement intersected with @(x,)@.+complementRangeList'' :: Int -> [(Int, Int)] -> [(Int, Int)]+complementRangeList'' x s+ | x == 0x10ffff = []+ | otherwise = complementRangeList' (succ x) s++-- | Compute the complement.+--+-- Note: we treat Ints as codepoints, i.e minBound is 0, and maxBound is 0x10ffff+complementRangeList :: [(Int, Int)] -> [(Int, Int)]+complementRangeList s@((x,y):s')+ | x == 0 = complementRangeList'' y s'+ | otherwise = complementRangeList' 0 s+complementRangeList [] = [(0, 0x10ffff)]++-- | Difference of two 'CharSet's.+difference :: CharSet -> CharSet -> CharSet+difference xs ys = intersection xs (complement ys)++-- | Make 'CharSet' from a list of characters, i.e. 'String'.+fromList :: String -> CharSet+fromList = normalise . foldl' (\ acc c -> IM.insert (ord c) (ord c) acc) IM.empty++-- | Convert 'CharSet' to a list of characters i.e. 'String'.+toList :: CharSet -> String+toList = concatMap (uncurry enumFromTo) . toIntervalList++-- | Convert to interval list+--+-- >>> toIntervalList $ union "01234" "56789"+-- [('0','9')]+--+toIntervalList :: CharSet -> [(Char, Char)]+toIntervalList (CS m) = [ (chr lo, chr hi) | (lo, hi) <- IM.toList m ]++-- | Convert from interval pairs.+--+-- >>> fromIntervalList []+-- ""+--+-- >>> fromIntervalList [('a','f'), ('0','9')]+-- "0123456789abcdef"+--+-- >>> fromIntervalList [('Z','A')]+-- ""+--+fromIntervalList :: [(Char,Char)] -> CharSet+fromIntervalList xs = normalise' $ sortBy (\a b -> compare (fst a) (fst b))+ [ (ord lo, ord hi)+ | (lo, hi) <- xs+ , lo <= hi+ ]++-------------------------------------------------------------------------------+-- Normalisation+-------------------------------------------------------------------------------++normalise :: IM.IntMap Int -> CharSet+normalise = normalise'. IM.toList++normalise' :: [(Int,Int)] -> CharSet+normalise' = CS . IM.fromList . go where+ go :: [(Int,Int)] -> [(Int,Int)]+ go [] = []+ go ((x,y):zs) = go' x y zs++ go' :: Int -> Int -> [(Int, Int)] -> [(Int, Int)]+ go' lo hi [] = [(lo, hi)]+ go' lo hi ws0@((u,v):ws)+ | u <= succ hi = go' lo (max v hi) ws+ | otherwise = (lo,hi) : go ws0++-------------------------------------------------------------------------------+-- Alpha Numeric character list+-------------------------------------------------------------------------------++-- Computing this takes some time,+-- but they are not used in-non testing in Cabal's normal operation.++-- | Note: this set varies depending on @base@ version.+--+alpha :: CharSet+alpha = foldl' (flip insert) empty [ c | c <- [ minBound .. maxBound ], isAlpha c ]+{-# NOINLINE alpha #-}++-- | Note: this set varies depending on @base@ version.+--+alphanum :: CharSet+alphanum = foldl' (flip insert) empty [ c | c <- [ minBound .. maxBound ], isAlphaNum c ]+{-# NOINLINE alphanum #-}++-- | Note: this set varies depending on @base@ version.+--+upper :: CharSet+upper = foldl' (flip insert) empty [ c | c <- [ minBound .. maxBound ], isUpper c ]+{-# NOINLINE upper #-}
+ cabal/Cabal/Cabal-described/src/Distribution/Utils/GrammarRegex.hs view
@@ -0,0 +1,215 @@+{-# LANGUAGE DeriveFoldable #-}+{-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE DeriveTraversable #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}+module Distribution.Utils.GrammarRegex (+ -- * Regular expressions+ GrammarRegex (..),+ reEps,+ reChar,+ reChars,+ reMunchCS,+ reMunch1CS,+ -- * Variables+ reVar0,+ reVar1,+ -- * Pretty-printing+ regexDoc,+ ) where++import Data.Char (isAlphaNum, isControl, ord)+import Data.Foldable (Foldable)+import Data.Maybe (fromMaybe)+import Data.Monoid (Monoid (..))+import Data.String (IsString (..))+import Data.Traversable (Traversable)+import Data.Void (Void, vacuous)+import Distribution.Compat.Semigroup (Semigroup (..))+import Prelude (Bool (..), Char, Eq (..), Functor, Int, Maybe (..), Ord (..), Show, String, fmap, length, map, otherwise, ($), (++), (.))++import qualified Distribution.Utils.CharSet as CS+import qualified Text.PrettyPrint as PP++(<<>>) :: PP.Doc -> PP.Doc -> PP.Doc+(<<>>) = (PP.<>)++-------------------------------------------------------------------------------+-- GrammarRegex+-------------------------------------------------------------------------------++-- | Recursive regular expressions tuned for 'Described' use-case.+data GrammarRegex a+ = REAppend [GrammarRegex a] -- ^ append @ab@+ | REUnion [GrammarRegex a] -- ^ union @a|b@++ -- repetition+ | REMunch (GrammarRegex a) (GrammarRegex a) -- ^ star @a*@, with a separator+ | REMunch1 (GrammarRegex a) (GrammarRegex a) -- ^ plus @a+@, with a separator+ | REMunchR Int (GrammarRegex a) (GrammarRegex a) -- ^ 1-n, with a separator+ | REOpt (GrammarRegex a) -- ^ optional @r?@++ | REString String -- ^ literal string @abcd@+ | RECharSet CS.CharSet -- ^ charset @[:alnum:]@+ | REVar a -- ^ variable+ | RENamed String (GrammarRegex a) -- ^ named expression+ | RERec String (GrammarRegex (Maybe a)) -- ^ recursive expressions++ -- cabal syntax specifics+ | RESpaces -- ^ zero-or-more spaces+ | RESpaces1 -- ^ one-or-more spaces+ | RECommaList (GrammarRegex a) -- ^ comma list (note, leading or trailing commas)+ | RECommaNonEmpty (GrammarRegex a) -- ^ comma non-empty list (note, leading or trailing commas)+ | REOptCommaList (GrammarRegex a) -- ^ opt comma list++ | RETodo -- ^ unspecified+ deriving (Eq, Ord, Show, Functor, Foldable, Traversable)++-------------------------------------------------------------------------------+-- Instances+-------------------------------------------------------------------------------++instance IsString (GrammarRegex a) where+ fromString = REString++instance Semigroup (GrammarRegex a) where+ x <> y = REAppend (unAppend x ++ unAppend y) where+ unAppend (REAppend rs) = rs+ unAppend r = [r]++instance Monoid (GrammarRegex a) where+ mempty = REAppend []+ mappend = (<>)++-------------------------------------------------------------------------------+-- Smart constructors+-------------------------------------------------------------------------------++reEps :: GrammarRegex a+reEps = REAppend []++reChar :: Char -> GrammarRegex a+reChar = RECharSet . CS.singleton++reChars :: [Char] -> GrammarRegex a+reChars = RECharSet . CS.fromList++reMunch1CS :: CS.CharSet -> GrammarRegex a+reMunch1CS = REMunch1 reEps . RECharSet++reMunchCS :: CS.CharSet -> GrammarRegex a+reMunchCS = REMunch reEps . RECharSet++-------------------------------------------------------------------------------+-- Variables+-------------------------------------------------------------------------------++reVar0 :: GrammarRegex (Maybe a)+reVar0 = REVar Nothing++reVar1 :: GrammarRegex (Maybe (Maybe a))+reVar1 = REVar (Just Nothing)++-------------------------------------------------------------------------------+-- Pretty-printing+-------------------------------------------------------------------------------++-- |+--+-- >>> regexDoc $ REString "True"+-- \mathop{\mathord{``}\mathtt{True}\mathord{"}}+--+-- Note: we don't simplify regexps yet:+--+-- >>> regexDoc $ REString "foo" <> REString "bar"+-- \mathop{\mathord{``}\mathtt{foo}\mathord{"}}\mathop{\mathord{``}\mathtt{bar}\mathord{"}}+--+regexDoc :: GrammarRegex Void -> PP.Doc+regexDoc = go 0 . vacuous where+ go :: Int -> GrammarRegex PP.Doc -> PP.Doc+ go _ (REAppend []) = ""+ go d (REAppend rs) = parensIf (d > 2) $ PP.hcat (map (go 2) rs)+ go d (REUnion [r]) = go d r+ go _ (REUnion rs) = PP.hsep+ [ "\\left\\{"+ , if length rs < 4+ then PP.hcat (PP.punctuate (PP.text "\\mid") (map (go 0) rs))+ else "\\begin{gathered}" <<>>+ PP.hcat (PP.punctuate "\\\\" (map (go 0) rs)) <<>>+ "\\end{gathered}"+ , "\\right\\}" ]++ go d (REMunch sep r) = parensIf (d > 3) $+ PP.text "{" <<>> go 4 r <<>> PP.text "}^\\ast_{" <<>> go 4 sep <<>> PP.text "}"+ go d (REMunch1 sep r) = parensIf (d > 3) $+ PP.text "{" <<>> go 4 r <<>> PP.text "}^+_{" <<>> go 4 sep <<>> PP.text "}"+ go d (REMunchR n sep r) = parensIf (d > 3) $+ PP.text "{" <<>> go 4 r <<>> PP.text "}^{\\in [0\\ldots" <<>> PP.int n <<>> "]}_{" <<>> go 4 sep <<>> PP.text "}"+ go d (REOpt r) = parensIf (d > 3) $+ PP.text "{" <<>> go 4 r <<>> PP.text "}^?"++ go _ (REString s) = PP.text "\\mathop{\\mathord{``}\\mathtt{" <<>> PP.hcat (map charDoc s) <<>> PP.text "}\\mathord{\"}}"+ go _ (RECharSet cs) = charsetDoc cs++ go _ RESpaces = "\\circ"+ go _ RESpaces1 = "\\bullet"++ go _ (RECommaList r) =+ "\\mathrm{commalist}" <<>> go 4 r+ go _ (RECommaNonEmpty r) =+ "\\mathrm{commanonempty}" <<>> go 4 r+ go _ (REOptCommaList r) =+ "\\mathrm{optcommalist}" <<>> go 4 r++ go _ (REVar a) = a+ go _ (RENamed n _) = terminalDoc n+ go d (RERec n r) = parensIf (d > 0) $+ "\\mathbf{fix}\\;" <<>> n' <<>> "\\;\\mathbf{in}\\;" <<>>+ go 0 (fmap (fromMaybe n') r)+ where+ n' = terminalDoc n++ go _ RETodo = PP.text "\\mathsf{\\color{red}{TODO}}"++ parensIf :: Bool -> PP.Doc -> PP.Doc+ parensIf True d = PP.text "\\left(" <<>> d <<>> PP.text "\\right)"+ parensIf False d = d++terminalDoc :: String -> PP.Doc+terminalDoc s = PP.text "\\mathop{\\mathit{" <<>> PP.hcat (map charDoc s) <<>> PP.text "}}"++charDoc :: Char -> PP.Doc+charDoc ' ' = PP.text "\\ "+charDoc '{' = PP.text "\\{"+charDoc '}' = PP.text "\\}"+charDoc '\\' = PP.text "\\text{\\\\}"+charDoc c+ | isAlphaNum c = PP.char c+ | isControl c = PP.int (ord c) -- TODO: some syntax+ | otherwise = PP.text ("\\text{" ++ c : "}")++inquotes :: PP.Doc -> PP.Doc+inquotes d = "\\mathop{\\mathord{``}" <<>> d <<>> "\\mathord{\"}}"++mathtt :: PP.Doc -> PP.Doc+mathtt d = "\\mathtt{" <<>> d <<>> "}"++charsetDoc :: CS.CharSet -> PP.Doc+charsetDoc acs+ | acs == CS.alpha = terminalDoc "alpha"+ | acs == CS.alphanum = terminalDoc "alpha-num"+ | acs == CS.upper = terminalDoc "upper"+charsetDoc acs = case CS.toIntervalList acs of+ [] -> "\\emptyset"+ [(x,y)] | x == y -> inquotes $ mathtt $ charDoc x+ rs+ | CS.size acs <= CS.size notAcs+ -> PP.brackets $ PP.hcat $ map rangeDoc rs+ | otherwise+ -> PP.braces $ PP.brackets (PP.hcat $ map rangeDoc (CS.toIntervalList notAcs)) <<>> PP.text "^c"+ where+ notAcs = CS.complement acs++ rangeDoc :: (Char, Char) -> PP.Doc+ rangeDoc (x, y) | x == y = inquotes (mathtt $ charDoc x)+ | otherwise = inquotes (mathtt $ charDoc x) <<>> PP.text "\\cdots" <<>> inquotes (mathtt $ charDoc y)
+ cabal/Cabal/Cabal-tree-diff/Cabal-tree-diff.cabal view
@@ -0,0 +1,21 @@+cabal-version: 2.2+name: Cabal-tree-diff+version: 3.3.0.0+synopsis: QuickCheck instances for types in Cabal+category: Testing+description: Provides tree-diff ToExpr instances for some types in Cabal++library+ default-language: Haskell2010+ hs-source-dirs: src+ ghc-options: -Wall+ build-depends:+ , base+ , Cabal ^>=3.3.0.0+ , tree-diff ^>=0.1++ exposed-modules: Data.TreeDiff.Instances.Cabal+ other-modules:+ Data.TreeDiff.Instances.CabalLanguage+ Data.TreeDiff.Instances.CabalSPDX+ Data.TreeDiff.Instances.CabalVersion
+ cabal/Cabal/Cabal-tree-diff/src/Data/TreeDiff/Instances/Cabal.hs view
@@ -0,0 +1,135 @@+{-# LANGUAGE CPP #-}+#if __GLASGOW_HASKELL__ >= 800+{-# OPTIONS_GHC -freduction-depth=0 #-}+#else+{-# OPTIONS_GHC -fcontext-stack=151 #-}+#endif+{-# OPTIONS_GHC -fno-warn-orphans #-}+module Data.TreeDiff.Instances.Cabal () where++import Data.TreeDiff++import Data.TreeDiff.Instances.CabalLanguage ()+import Data.TreeDiff.Instances.CabalSPDX ()+import Data.TreeDiff.Instances.CabalVersion ()++-------------------------------------------------------------------------------++import Distribution.Backpack (OpenModule, OpenUnitId)+import Distribution.CabalSpecVersion (CabalSpecVersion)+import Distribution.Compiler (CompilerFlavor, CompilerId, PerCompilerFlavor)+import Distribution.InstalledPackageInfo (AbiDependency, ExposedModule, InstalledPackageInfo)+import Distribution.ModuleName (ModuleName)+import Distribution.PackageDescription+import Distribution.Simple.Compiler (DebugInfoLevel, OptimisationLevel, ProfDetailLevel)+import Distribution.Simple.Flag (Flag)+import Distribution.Simple.InstallDirs+import Distribution.Simple.InstallDirs.Internal+import Distribution.Simple.Setup (HaddockTarget, TestShowDetails)+import Distribution.System+import Distribution.Types.AbiHash (AbiHash)+import Distribution.Types.ComponentId (ComponentId)+import Distribution.Types.IncludeRenaming (IncludeRenaming)+import Distribution.Types.Mixin+import Distribution.Types.ModuleReexport+import Distribution.Types.ModuleRenaming+import Distribution.Types.PackageVersionConstraint+import Distribution.Types.PkgconfigName (PkgconfigName)+import Distribution.Types.PkgconfigVersion (PkgconfigVersion)+import Distribution.Types.PkgconfigVersionRange (PkgconfigVersionRange)+import Distribution.Types.UnitId (DefUnitId, UnitId)+import Distribution.Utils.NubList (NubList)+import Distribution.Utils.ShortText (ShortText, fromShortText)+import Distribution.Verbosity+import Distribution.Verbosity.Internal++import qualified Distribution.Compat.NonEmptySet as NES++-------------------------------------------------------------------------------+-- instances+-------------------------------------------------------------------------------++instance (Eq a, Show a) => ToExpr (Condition a) where toExpr = defaultExprViaShow+instance (Show a, ToExpr b, ToExpr c, Show b, Show c, Eq a, Eq c, Eq b) => ToExpr (CondTree a b c)+instance (Show a, ToExpr b, ToExpr c, Show b, Show c, Eq a, Eq c, Eq b) => ToExpr (CondBranch a b c)+instance (ToExpr a) => ToExpr (NubList a)+instance (ToExpr a) => ToExpr (Flag a)+instance ToExpr a => ToExpr (NES.NonEmptySet a) where+ toExpr xs = App "NonEmptySet.fromNonEmpty" [toExpr $ NES.toNonEmpty xs]++instance ToExpr a => ToExpr (PerCompilerFlavor a)++instance ToExpr Dependency where+ toExpr d@(Dependency pn vr cs)+ | cs == mainLibSet = App "Dependency" [toExpr pn, toExpr vr, App "mainLibSet" []]+ | otherwise = genericToExpr d++instance ToExpr AbiDependency+instance ToExpr AbiHash+instance ToExpr Arch+instance ToExpr Benchmark+instance ToExpr BenchmarkInterface+instance ToExpr BenchmarkType+instance ToExpr BuildInfo+instance ToExpr BuildType+instance ToExpr CabalSpecVersion+instance ToExpr CompilerFlavor+instance ToExpr CompilerId+instance ToExpr ComponentId+instance ToExpr DebugInfoLevel+instance ToExpr DefUnitId+instance ToExpr ExeDependency+instance ToExpr Executable+instance ToExpr ExecutableScope+instance ToExpr ExposedModule+instance ToExpr FlagAssignment+instance ToExpr FlagName+instance ToExpr ForeignLib+instance ToExpr ForeignLibOption+instance ToExpr ForeignLibType+instance ToExpr GenericPackageDescription+instance ToExpr HaddockTarget+instance ToExpr IncludeRenaming+instance ToExpr InstalledPackageInfo+instance ToExpr KnownRepoType+instance ToExpr LegacyExeDependency+instance ToExpr LibVersionInfo+instance ToExpr Library+instance ToExpr LibraryName+instance ToExpr LibraryVisibility+instance ToExpr Mixin+instance ToExpr ModuleName+instance ToExpr ModuleReexport+instance ToExpr ModuleRenaming+instance ToExpr OS+instance ToExpr OpenModule+instance ToExpr OpenUnitId+instance ToExpr OptimisationLevel+instance ToExpr PackageDescription+instance ToExpr PackageFlag+instance ToExpr PackageIdentifier+instance ToExpr PackageName+instance ToExpr PackageVersionConstraint+instance ToExpr PathComponent+instance ToExpr PathTemplate+instance ToExpr PathTemplateVariable+instance ToExpr PkgconfigDependency+instance ToExpr PkgconfigName+instance ToExpr PkgconfigVersion+instance ToExpr PkgconfigVersionRange+instance ToExpr ProfDetailLevel+instance ToExpr RepoKind+instance ToExpr RepoType+instance ToExpr SetupBuildInfo+instance ToExpr SourceRepo+instance ToExpr TestShowDetails+instance ToExpr TestSuite+instance ToExpr TestSuiteInterface+instance ToExpr TestType+instance ToExpr UnitId+instance ToExpr UnqualComponentName+instance ToExpr Verbosity+instance ToExpr VerbosityFlag+instance ToExpr VerbosityLevel++instance ToExpr ShortText where toExpr = toExpr . fromShortText
+ cabal/Cabal/Cabal-tree-diff/src/Data/TreeDiff/Instances/CabalLanguage.hs view
@@ -0,0 +1,17 @@+{-# LANGUAGE CPP #-}+#if __GLASGOW_HASKELL__ >= 800+{-# OPTIONS_GHC -freduction-depth=0 #-}+#else+{-# OPTIONS_GHC -fcontext-stack=151 #-}+#endif+{-# OPTIONS_GHC -fno-warn-orphans #-}+module Data.TreeDiff.Instances.CabalLanguage () where++import Data.TreeDiff+import Language.Haskell.Extension (Extension, KnownExtension, Language)++-- These are big enums, so they are in separate file.+--+instance ToExpr Extension+instance ToExpr KnownExtension+instance ToExpr Language
+ cabal/Cabal/Cabal-tree-diff/src/Data/TreeDiff/Instances/CabalSPDX.hs view
@@ -0,0 +1,28 @@+{-# LANGUAGE CPP #-}+#if __GLASGOW_HASKELL__ >= 800+{-# OPTIONS_GHC -freduction-depth=0 #-}+#else+{-# OPTIONS_GHC -fcontext-stack=151 #-}+#endif+{-# OPTIONS_GHC -fno-warn-orphans #-}+module Data.TreeDiff.Instances.CabalSPDX () where++import Data.TreeDiff+import Distribution.License (License)++import Data.TreeDiff.Instances.CabalVersion ()++import qualified Distribution.SPDX as SPDX++-- 'License' almost belongs here.++instance ToExpr License++-- Generics instance is too heavy+instance ToExpr SPDX.LicenseId where toExpr = defaultExprViaShow+instance ToExpr SPDX.LicenseExceptionId where toExpr = defaultExprViaShow++instance ToExpr SPDX.License+instance ToExpr SPDX.LicenseExpression+instance ToExpr SPDX.LicenseRef+instance ToExpr SPDX.SimpleLicenseExpression
+ cabal/Cabal/Cabal-tree-diff/src/Data/TreeDiff/Instances/CabalVersion.hs view
@@ -0,0 +1,14 @@+{-# LANGUAGE CPP #-}+#if __GLASGOW_HASKELL__ >= 800+{-# OPTIONS_GHC -freduction-depth=0 #-}+#else+{-# OPTIONS_GHC -fcontext-stack=151 #-}+#endif+{-# OPTIONS_GHC -fno-warn-orphans #-}+module Data.TreeDiff.Instances.CabalVersion where++import Data.TreeDiff+import Distribution.Version (Version, VersionRange, versionNumbers)++instance ToExpr Version where toExpr v = App "mkVersion" [toExpr $ versionNumbers v]+instance ToExpr VersionRange
cabal/Cabal/Cabal.cabal view
@@ -1,7 +1,7 @@ cabal-version: >=1.10 name: Cabal-version: 3.1.0.0-copyright: 2003-2019, Cabal Development Team (see AUTHORS file)+version: 3.3.0.0+copyright: 2003-2020, Cabal Development Team (see AUTHORS file) license: BSD3 license-file: LICENSE author: Cabal Development Team <cabal-devel@haskell.org>@@ -35,6 +35,8 @@ -- BEGIN gen-extra-source-files tests/ParserTests/errors/MiniAgda.cabal tests/ParserTests/errors/MiniAgda.errors+ tests/ParserTests/errors/anynone.cabal+ tests/ParserTests/errors/anynone.errors tests/ParserTests/errors/big-version.cabal tests/ParserTests/errors/big-version.errors tests/ParserTests/errors/common1.cabal@@ -110,6 +112,9 @@ tests/ParserTests/regressions/Octree-0.5.cabal tests/ParserTests/regressions/Octree-0.5.expr tests/ParserTests/regressions/Octree-0.5.format+ tests/ParserTests/regressions/anynone.cabal+ tests/ParserTests/regressions/anynone.expr+ tests/ParserTests/regressions/anynone.format tests/ParserTests/regressions/assoc-cpp-options.cabal tests/ParserTests/regressions/assoc-cpp-options.check tests/ParserTests/regressions/bad-glob-syntax.cabal@@ -151,6 +156,9 @@ tests/ParserTests/regressions/ghc-option-j.check tests/ParserTests/regressions/haddock-api-2.18.1-check.cabal tests/ParserTests/regressions/haddock-api-2.18.1-check.check+ tests/ParserTests/regressions/hasktorch.cabal+ tests/ParserTests/regressions/hasktorch.expr+ tests/ParserTests/regressions/hasktorch.format tests/ParserTests/regressions/hidden-main-lib.cabal tests/ParserTests/regressions/hidden-main-lib.expr tests/ParserTests/regressions/hidden-main-lib.format@@ -169,6 +177,30 @@ tests/ParserTests/regressions/issue-5846.cabal tests/ParserTests/regressions/issue-5846.expr tests/ParserTests/regressions/issue-5846.format+ tests/ParserTests/regressions/issue-6083-a.cabal+ tests/ParserTests/regressions/issue-6083-a.expr+ tests/ParserTests/regressions/issue-6083-a.format+ tests/ParserTests/regressions/issue-6083-b.cabal+ tests/ParserTests/regressions/issue-6083-b.expr+ tests/ParserTests/regressions/issue-6083-b.format+ tests/ParserTests/regressions/issue-6083-c.cabal+ tests/ParserTests/regressions/issue-6083-c.expr+ tests/ParserTests/regressions/issue-6083-c.format+ tests/ParserTests/regressions/issue-6083-pkg-pkg.cabal+ tests/ParserTests/regressions/issue-6083-pkg-pkg.expr+ tests/ParserTests/regressions/issue-6083-pkg-pkg.format+ tests/ParserTests/regressions/issue-6288-a.cabal+ tests/ParserTests/regressions/issue-6288-a.check+ tests/ParserTests/regressions/issue-6288-b.cabal+ tests/ParserTests/regressions/issue-6288-b.check+ tests/ParserTests/regressions/issue-6288-c.cabal+ tests/ParserTests/regressions/issue-6288-c.check+ tests/ParserTests/regressions/issue-6288-d.cabal+ tests/ParserTests/regressions/issue-6288-d.check+ tests/ParserTests/regressions/issue-6288-e.cabal+ tests/ParserTests/regressions/issue-6288-e.check+ tests/ParserTests/regressions/issue-6288-f.cabal+ tests/ParserTests/regressions/issue-6288-f.check tests/ParserTests/regressions/issue-774.cabal tests/ParserTests/regressions/issue-774.check tests/ParserTests/regressions/issue-774.expr@@ -197,6 +229,9 @@ tests/ParserTests/regressions/mixin-3.cabal tests/ParserTests/regressions/mixin-3.expr tests/ParserTests/regressions/mixin-3.format+ tests/ParserTests/regressions/monad-param.cabal+ tests/ParserTests/regressions/monad-param.expr+ tests/ParserTests/regressions/monad-param.format tests/ParserTests/regressions/multiple-libs-2.cabal tests/ParserTests/regressions/multiple-libs-2.check tests/ParserTests/regressions/multiple-libs-2.expr@@ -212,6 +247,10 @@ tests/ParserTests/regressions/pre-1.6-glob.check tests/ParserTests/regressions/pre-2.4-globstar.cabal tests/ParserTests/regressions/pre-2.4-globstar.check+ tests/ParserTests/regressions/public-multilib-1.cabal+ tests/ParserTests/regressions/public-multilib-1.check+ tests/ParserTests/regressions/public-multilib-2.cabal+ tests/ParserTests/regressions/public-multilib-2.check tests/ParserTests/regressions/shake.cabal tests/ParserTests/regressions/shake.expr tests/ParserTests/regressions/shake.format@@ -243,6 +282,10 @@ tests/ParserTests/warnings/nbsp.cabal tests/ParserTests/warnings/newsyntax.cabal tests/ParserTests/warnings/oldsyntax.cabal+ tests/ParserTests/warnings/operator.cabal+ tests/ParserTests/warnings/specversion-a.cabal+ tests/ParserTests/warnings/specversion-b.cabal+ tests/ParserTests/warnings/specversion-c.cabal tests/ParserTests/warnings/subsection.cabal tests/ParserTests/warnings/tab.cabal tests/ParserTests/warnings/trailingfield.cabal@@ -250,6 +293,7 @@ tests/ParserTests/warnings/unknownsection.cabal tests/ParserTests/warnings/utf8.cabal tests/ParserTests/warnings/versiontag.cabal+ tests/ParserTests/warnings/wildcard.cabal tests/cbits/rpmvercmp.c tests/hackage/check.sh tests/hackage/download.sh@@ -276,7 +320,7 @@ filepath >= 1.3.0.1 && < 1.5, pretty >= 1.1.1 && < 1.2, process >= 1.1.0.2 && < 1.7,- time >= 1.4.0.1 && < 1.10+ time >= 1.4.0.1 && < 1.11 if flag(bundled-binary-generic) build-depends: binary >= 0.5.1.1 && < 0.7@@ -288,16 +332,21 @@ else build-depends: unix >= 2.6.0.0 && < 2.8 - ghc-options: -Wall -fno-ignore-asserts -fwarn-tabs+ ghc-options: -Wall -fno-ignore-asserts -fwarn-tabs -fwarn-incomplete-uni-patterns if impl(ghc >= 8.0) ghc-options: -Wcompat -Wnoncanonical-monad-instances- -Wnoncanonical-monadfail-instances + if impl(ghc <8.8)+ ghc-options: -Wnoncanonical-monadfail-instances+ if !impl(ghc >= 8.0) -- at least one of lib:Cabal's dependency (i.e. `parsec`) -- already depends on `fail` and `semigroups` transitively build-depends: fail == 4.9.*, semigroups >= 0.18.3 && < 0.20 + if !impl(ghc >= 7.10)+ build-depends: void >= 0.7.3 && < 0.8+ if !impl(ghc >= 7.8) -- semigroups depends on tagged. build-depends: tagged >=0.8.6 && <0.9@@ -317,6 +366,8 @@ Distribution.Utils.IOData Distribution.Utils.LogProgress Distribution.Utils.MapAccum+ Distribution.Utils.MD5+ Distribution.Utils.Structured Distribution.Compat.CreatePipe Distribution.Compat.Directory Distribution.Compat.Environment@@ -325,11 +376,14 @@ Distribution.Compat.Graph Distribution.Compat.Internal.TempFile Distribution.Compat.Newtype+ Distribution.Compat.NonEmptySet Distribution.Compat.ResponseFile Distribution.Compat.Prelude.Internal+ Distribution.Compat.Process Distribution.Compat.Semigroup Distribution.Compat.Stack Distribution.Compat.Time+ Distribution.Compat.Typeable Distribution.Compat.DList Distribution.Compiler Distribution.InstalledPackageInfo@@ -496,6 +550,7 @@ Distribution.FieldGrammar Distribution.FieldGrammar.Class Distribution.FieldGrammar.FieldDescrs+ Distribution.FieldGrammar.Newtypes Distribution.FieldGrammar.Parsec Distribution.FieldGrammar.Pretty Distribution.PackageDescription.FieldGrammar@@ -503,7 +558,6 @@ Distribution.PackageDescription.Quirks Distribution.Parsec Distribution.Parsec.Error- Distribution.Parsec.Newtypes Distribution.Parsec.Position Distribution.Parsec.Warning Distribution.Parsec.FieldLineStream@@ -545,17 +599,18 @@ Distribution.Compat.Async Distribution.Compat.CopyFile Distribution.Compat.GetShortPathName- Distribution.Compat.MD5 Distribution.Compat.MonadFail Distribution.Compat.Prelude Distribution.Compat.SnocList Distribution.GetOpt Distribution.Lex Distribution.Utils.String+ Distribution.Simple.Build.Macros.Z Distribution.Simple.GHC.EnvironmentParser Distribution.Simple.GHC.Internal Distribution.Simple.GHC.ImplInfo Distribution.Simple.Utils.Json+ Distribution.ZinzaPrelude Paths_Cabal if flag(bundled-binary-generic)@@ -601,9 +656,11 @@ other-modules: Test.Laws Test.QuickCheck.Utils+ UnitTests.Distribution.CabalSpecVersion UnitTests.Distribution.Compat.CreatePipe UnitTests.Distribution.Compat.Graph UnitTests.Distribution.Compat.Time+ UnitTests.Distribution.Described UnitTests.Distribution.Simple.Glob UnitTests.Distribution.Simple.Program.GHC UnitTests.Distribution.Simple.Program.Internal@@ -611,34 +668,61 @@ UnitTests.Distribution.SPDX UnitTests.Distribution.System UnitTests.Distribution.Types.GenericPackageDescription+ UnitTests.Distribution.Utils.CharSet UnitTests.Distribution.Utils.Generic UnitTests.Distribution.Utils.NubList UnitTests.Distribution.Utils.ShortText+ UnitTests.Distribution.Utils.Structured UnitTests.Distribution.Version UnitTests.Distribution.PkgconfigVersion+ UnitTests.Orphans++ -- Cabal-quickcheck+ hs-source-dirs: Cabal-QuickCheck/src+ other-modules:+ Test.QuickCheck.GenericArbitrary+ Test.QuickCheck.Instances.Cabal++ -- Cabal-described+ hs-source-dirs: Cabal-described/src+ other-modules:+ Distribution.Described+ Distribution.Utils.CharSet+ Distribution.Utils.GrammarRegex+ main-is: UnitTests.hs build-depends: array,+ async >= 2.2.2 && <2.3, base, binary, bytestring, containers,+ deepseq, directory, filepath, integer-logarithms >= 1.0.2 && <1.1,- tasty >= 1.2.3 && < 1.3,+ pretty,+ rere >=0.1 && <0.2,+ tagged,+ tasty >= 1.2.3 && < 1.4, tasty-hunit, tasty-quickcheck,- tagged, temporary, text,- pretty,+ transformers, Diff >=0.4 && <0.5,- QuickCheck >= 2.13.2 && < 2.14,+ QuickCheck >= 2.14 && < 2.15, Cabal ghc-options: -Wall default-language: Haskell2010 + if !impl(ghc >= 7.10)+ build-depends: void++ if !impl(ghc >= 8.0)+ build-depends: semigroups+ test-suite parser-tests type: exitcode-stdio-1.0 hs-source-dirs: tests@@ -649,7 +733,7 @@ bytestring, directory, filepath,- tasty >= 1.2.3 && < 1.3,+ tasty >= 1.2.3 && < 1.4, tasty-hunit, tasty-quickcheck, tasty-golden >=2.3.1.1 && <2.4,@@ -659,16 +743,17 @@ default-language: Haskell2010 if !impl(ghc >= 8.0)- build-depends: semigroups+ build-depends: semigroups if impl(ghc >= 7.8) build-depends: tree-diff >= 0.1 && <0.2+ hs-source-dirs: Cabal-tree-diff/src other-modules:- Instances.TreeDiff- Instances.TreeDiff.Language- Instances.TreeDiff.SPDX- Instances.TreeDiff.Version+ Data.TreeDiff.Instances.Cabal+ Data.TreeDiff.Instances.CabalLanguage+ Data.TreeDiff.Instances.CabalSPDX+ Data.TreeDiff.Instances.CabalVersion test-suite check-tests type: exitcode-stdio-1.0@@ -679,7 +764,7 @@ bytestring, directory, filepath,- tasty >= 1.2.3 && < 1.3,+ tasty >= 1.2.3 && < 1.4, tasty-golden >=2.3.1.1 && <2.4, Diff >=0.4 && <0.5, Cabal@@ -725,6 +810,7 @@ build-depends: base-compat >=0.11.0 && <0.12, base-orphans >=0.6 && <0.9,+ clock >=0.8 && <0.9, optparse-applicative >=0.13.2.0 && <0.16, stm >=2.4.5.0 && <2.6, tar >=0.5.0.3 && <0.6@@ -732,11 +818,12 @@ if impl(ghc >= 7.8) build-depends: tree-diff >= 0.1 && <0.2+ hs-source-dirs: Cabal-tree-diff/src other-modules:- Instances.TreeDiff- Instances.TreeDiff.Language- Instances.TreeDiff.SPDX- Instances.TreeDiff.Version+ Data.TreeDiff.Instances.Cabal+ Data.TreeDiff.Instances.CabalLanguage+ Data.TreeDiff.Instances.CabalSPDX+ Data.TreeDiff.Instances.CabalVersion ghc-options: -Wall -rtsopts -threaded default-extensions: CPP@@ -753,7 +840,7 @@ bytestring build-depends:- tasty >= 1.2.3 && < 1.3,+ tasty >= 1.2.3 && < 1.4, tasty-hunit, tasty-quickcheck, QuickCheck
cabal/Cabal/ChangeLog.md view
@@ -1,9 +1,41 @@-# 3.1.0.0 (current development version)+# 3.2.0.0 [Herbert Valerio Riedel](mailto:hvr@gnu.org) April 2020+ * Change free text `String` fields to use `ShortText` in package description+ and installed package info.+ * Split `Distribution.Types.Flag` and `Distribution.Types.ConfVar`+ `Distribution.Types.GenericPackageDescription`.+ * Add GHC-8.10 support, including new extensions to+ `Language.Haskell.Extension`.+ * Use more `NonEmpty` instead of ordinary lists.+ * Add `Distribution.Utils.Structured` for fingeprinting `Binary` blobs.+ * Add `null`, `length` and `unsafeFromUTF8BS` to `Distribution.Utils.ShortText`.+ * Refactor `Distribution.Utils.IOData` module.+ * Rename `Distribution.Compat.MD5` to `Distribution.Utils.MD5`.+ * Add `safeHead`, `safeTail`, `safeLast` to `Distribution.Utils.Generic`.+ * Add `unsnoc` and `unsnocNE` to `Distribution.Utils.Generic`.+ * Add `Set'` modifier to `Distribution.Parsec.Newtypes`.+ * Add `Distribution.Compat.Async`.++# 3.0.2.0 [Herbert Valerio Riedel](mailto:hvr@gnu.org) April 2020+ * Disallow spaces around colon `:` in Dependency `build-depends` syntax+ ([#6538](https://github.com/haskell/cabal/pull/6538)).+ * Make `configure` accept any `pkg-config --modversion` output+ ([#6541](https://github.com/haskell/cabal/pull/6541)).++# 3.0.1.0 [Herbert Valerio Riedel](mailto:hvr@gnu.org) April 2020+ * Add GHC-8.8 flags to `normaliseGhcFlags`+ ([#6379](https://github.com/haskell/cabal/pull/6379)).+ * Typo fixes+ ([#6372](https://github.com/haskell/cabal/pull/6372)).+ * Limit version number parts to contain at most 9 digits+ ([#6386](https://github.com/haskell/cabal/pull/6386)).+ * Fix boundless sublibrary dependency parse failure+ ([#5846](https://github.com/haskell/cabal/issues/5846)). * `cabal check` verifies `cpp-options` more pedantically, allowing only options starting with `-D` and `-U`.- * TODO-- ----+ * Don’t rebuild world when new ghc flags that affect how error+ messages are presented is specified.+ * Fix dropExeExtension behaviour on Windows+ ([#6287](https://github.com/haskell/cabal/pull/6287)). # 3.0.0.0 [Mikhail Glushenkov](mailto:mikhail.glushenkov@gmail.com) August 2019 * The 3.0 migration guide gives advice on adapting Custom setup@@ -133,7 +165,7 @@ [#784](https://github.com/haskell/cabal/issues/784), [#5057](https://github.com/haskell/cabal/issues/5057)). * Wildcard syntax errors (misplaced `*`, etc), wildcards that- refer to missing directoies, and wildcards that do not match+ refer to missing directories, and wildcards that do not match anything are now all detected by `cabal check`. * Wildcard ('globbing') functions have been moved from `Distribution.Simple.Utils` to `Distribution.Simple.Glob` and@@ -594,7 +626,7 @@ * Support for finding installed packages for hugs * Cabal version macros now have proper parenthesis * Reverted change to filter out deps of non-buildable components- * Fix for registering implace when using a specific package db+ * Fix for registering inplace when using a specific package db * Fix mismatch between $os and $arch path template variables * Fix for finding ar.exe on Windows, always pick ghc's version * Fix for intra-package dependencies with ghc-6.12@@ -756,7 +788,7 @@ # 1.2.0 [Duncan Coutts](mailto:duncan.coutts@worc.ox.ac.uk) Sept 2007 * To be included in GHC 6.8.x * New configurations feature- * Can make haddock docs link to hilighted sources (with hscolour)+ * Can make haddock docs link to highlighted sources (with hscolour) * New flag to allow linking to haddock docs on the web * Supports pkg-config * New field `build-tools` for tool dependencies@@ -796,7 +828,7 @@ * Released with GHC 6.6 * Added support for hoogle- * Allow profiling and normal builds of libs to be chosen indepentantly+ * Allow profiling and normal builds of libs to be chosen independently * Default installation directories on Win32 changed * Register haddock docs with ghc-pkg * Get haddock to make hyperlinks to dependent package docs@@ -876,7 +908,7 @@ * Lots of bug fixes * spaces can sometimes be used instead of commas * A user manual has appeared (Thanks, ross!)- * for ghc 6.4, configures versionsed depends properly+ * for ghc 6.4, configures versioned depends properly * more features to `./setup haddock` ----
cabal/Cabal/Distribution/Backpack.hs view
@@ -98,7 +98,7 @@ -- TODO: cache holes? instance Binary OpenUnitId-+instance Structured OpenUnitId instance NFData OpenUnitId where rnf (IndefFullUnitId cid subst) = rnf cid `seq` rnf subst rnf (DefiniteUnitId uid) = rnf uid@@ -117,7 +117,7 @@ --Right (DefiniteUnitId (DefUnitId {unDefUnitId = UnitId "foobar"})) -- -- >>> eitherParsec "foo[Str=text-1.2.3:Data.Text.Text]" :: Either String OpenUnitId--- Right (IndefFullUnitId (ComponentId "foo") (fromList [(ModuleName ["Str"],OpenModule (DefiniteUnitId (DefUnitId {unDefUnitId = UnitId "text-1.2.3"})) (ModuleName ["Data","Text","Text"]))]))+-- Right (IndefFullUnitId (ComponentId "foo") (fromList [(ModuleName "Str",OpenModule (DefiniteUnitId (DefUnitId {unDefUnitId = UnitId "text-1.2.3"})) (ModuleName "Data.Text.Text"))])) -- instance Parsec OpenUnitId where parsec = P.try parseOpenUnitId <|> fmap DefiniteUnitId parsec@@ -165,6 +165,7 @@ deriving (Generic, Read, Show, Eq, Ord, Typeable, Data) instance Binary OpenModule+instance Structured OpenModule instance NFData OpenModule where rnf (OpenModule uid mod_name) = rnf uid `seq` rnf mod_name@@ -179,7 +180,7 @@ -- | -- -- >>> eitherParsec "Includes2-0.1.0.0-inplace-mysql:Database.MySQL" :: Either String OpenModule--- Right (OpenModule (DefiniteUnitId (DefUnitId {unDefUnitId = UnitId "Includes2-0.1.0.0-inplace-mysql"})) (ModuleName ["Database","MySQL"]))+-- Right (OpenModule (DefiniteUnitId (DefUnitId {unDefUnitId = UnitId "Includes2-0.1.0.0-inplace-mysql"})) (ModuleName "Database.MySQL")) -- instance Parsec OpenModule where parsec = parsecModuleVar <|> parsecOpenModule
cabal/Cabal/Distribution/Backpack/ComponentsGraph.hs view
@@ -12,13 +12,13 @@ import Distribution.Compat.Prelude import Distribution.Package-import Distribution.PackageDescription as PD hiding (Flag)+import Distribution.PackageDescription import Distribution.Simple.BuildToolDepends import Distribution.Simple.LocalBuildInfo import Distribution.Types.ComponentRequestedSpec-import Distribution.Types.UnqualComponentName import Distribution.Compat.Graph (Graph, Node(..)) import qualified Distribution.Compat.Graph as Graph+import qualified Distribution.Compat.NonEmptySet as NES import Distribution.Utils.Generic import Distribution.Pretty (pretty)@@ -63,21 +63,19 @@ where -- The dependencies for the given component componentDeps component =- (CExeName <$> getAllInternalToolDependencies pkg_descr bi)-- ++ [ if pkgname == packageName pkg_descr- then CLibName LMainLibName- else CLibName (LSubLibName toolname)- | Dependency pkgname _ _ <- targetBuildDepends bi- , let toolname = packageNameToUnqualComponentName pkgname- , toolname `elem` internalPkgDeps ]+ toolDependencies ++ libDependencies where bi = componentBuildInfo component- internalPkgDeps = map (conv . libName) (allLibraries pkg_descr) - conv LMainLibName = packageNameToUnqualComponentName $ packageName pkg_descr- conv (LSubLibName s) = s+ toolDependencies = CExeName <$> getAllInternalToolDependencies pkg_descr bi + libDependencies = do+ Dependency pkgname _ lns <- targetBuildDepends bi+ guard (pkgname == packageName pkg_descr)++ ln <- NES.toList lns+ return (CLibName ln)+ -- | Given the package description and a 'PackageDescription' (used -- to determine if a package name is internal or not), sort the -- components in dependency order (fewest dependencies first). This is@@ -90,9 +88,10 @@ map (\(N c _ cs) -> (c, cs)) . Graph.revTopSort -- | Error message when there is a cycle; takes the SCC of components.-componentCycleMsg :: [ComponentName] -> Doc-componentCycleMsg cnames =- text $ "Components in the package depend on each other in a cyclic way:\n "- ++ intercalate " depends on "+componentCycleMsg :: PackageIdentifier -> [ComponentName] -> Doc+componentCycleMsg pn cnames =+ text "Components in the package" <+> pretty pn <+> text "depend on each other in a cyclic way:"+ $$+ text (intercalate " depends on " [ "'" ++ showComponentName cname ++ "'"- | cname <- cnames ++ maybeToList (safeHead cnames) ]+ | cname <- cnames ++ maybeToList (safeHead cnames) ])
cabal/Cabal/Distribution/Backpack/Configure.hs view
@@ -27,14 +27,14 @@ import Distribution.Backpack.ComponentsGraph import Distribution.Backpack.Id -import Distribution.Simple.Compiler hiding (Flag)+import Distribution.Simple.Compiler import Distribution.Package import qualified Distribution.InstalledPackageInfo as Installed import Distribution.InstalledPackageInfo (InstalledPackageInfo ,emptyInstalledPackageInfo) import qualified Distribution.Simple.PackageIndex as PackageIndex import Distribution.Simple.PackageIndex (InstalledPackageIndex)-import Distribution.PackageDescription as PD hiding (Flag)+import Distribution.PackageDescription import Distribution.ModuleName import Distribution.Simple.Setup as Setup import Distribution.Simple.LocalBuildInfo@@ -78,7 +78,7 @@ -- NB: In single component mode, this returns a *single* component. -- In this graph, the graph is NOT closed. graph0 <- case mkComponentsGraph enabled pkg_descr of- Left ccycle -> dieProgress (componentCycleMsg ccycle)+ Left ccycle -> dieProgress (componentCycleMsg (package pkg_descr) ccycle) Right g -> return (componentsGraphToList g) infoProgress $ hang (text "Source component graph:") 4 (dispComponentsWithDeps graph0)@@ -162,7 +162,8 @@ . map Right $ graph combined_graph = Graph.unionRight external_graph internal_graph- Just local_graph = Graph.closure combined_graph (map nodeKey graph)+ local_graph = fromMaybe (error "toComponentLocalBuildInfos: closure returned Nothing")+ $ Graph.closure combined_graph (map nodeKey graph) -- The database of transitively reachable installed packages that the -- external components the package (as a whole) depends on. This will be -- used in several ways:
cabal/Cabal/Distribution/Backpack/ConfiguredComponent.hs view
@@ -21,6 +21,7 @@ import Distribution.Backpack.Id +import Distribution.CabalSpecVersion import Distribution.Types.AnnotatedId import Distribution.Types.Dependency import Distribution.Types.ExeDependency@@ -31,23 +32,23 @@ import Distribution.Types.Mixin import Distribution.Types.ComponentName import Distribution.Types.LibraryName-import Distribution.Types.UnqualComponentName import Distribution.Types.ComponentInclude import Distribution.Package-import Distribution.PackageDescription as PD hiding (Flag)+import Distribution.PackageDescription import Distribution.Simple.BuildToolDepends import Distribution.Simple.Setup as Setup import Distribution.Simple.LocalBuildInfo-import Distribution.Version import Distribution.Utils.LogProgress import Distribution.Utils.MapAccum import Distribution.Utils.Generic import Control.Monad import qualified Data.Set as Set+import qualified Distribution.Compat.NonEmptySet as NonEmptySet import qualified Data.Map as Map import Distribution.Pretty-import Text.PrettyPrint+import Text.PrettyPrint (Doc, hang, text, vcat, hsep, quotes, ($$))+import qualified Text.PrettyPrint as PP -- | A configured component, we know exactly what its 'ComponentId' is, -- and the 'ComponentId's of the things it depends on.@@ -111,13 +112,12 @@ mkConfiguredComponent pkg_descr this_cid lib_deps exe_deps component = do -- Resolve each @mixins@ into the actual dependency -- from @lib_deps@.- explicit_includes <- forM (mixins bi) $ \(Mixin name rns) -> do- let keys = fixFakePkgName pkg_descr name- aid <- case Map.lookup keys deps_map of+ explicit_includes <- forM (mixins bi) $ \(Mixin pn ln rns) -> do+ aid <- case Map.lookup (pn, CLibName ln) deps_map of Nothing -> dieProgress $- text "Mix-in refers to non-existent package" <+>- quotes (pretty name) $$+ text "Mix-in refers to non-existent library" <+>+ quotes (pretty pn <<>> prettyLN ln) $$ text "(did you forget to add the package to build-depends?)" Just r -> return r return ComponentInclude {@@ -149,9 +149,17 @@ cc_includes = explicit_includes ++ implicit_includes } where+ bi :: BuildInfo bi = componentBuildInfo component++ prettyLN :: LibraryName -> Doc+ prettyLN LMainLibName = PP.empty+ prettyLN (LSubLibName n) = PP.colon <<>> pretty n++ deps_map :: Map (PackageName, ComponentName) (AnnotatedId ComponentId) deps_map = Map.fromList [ ((packageName dep, ann_cname dep), dep) | dep <- lib_deps ]+ is_public = componentName component == CLibName LMainLibName type ConfiguredComponentMap =@@ -169,27 +177,21 @@ if newPackageDepsBehaviour pkg_descr then fmap concat $ forM (targetBuildDepends bi) $ \(Dependency name _ sublibs) -> do- -- The package name still needs fixing in case of legacy- -- sublibrary dependency syntax- let (pn, _) = fixFakePkgName pkg_descr name- pkg <- case Map.lookup pn lib_dep_map of+ pkg <- case Map.lookup name lib_dep_map of Nothing -> dieProgress $ text "Dependency on unbuildable" <+>- text "package" <+> pretty pn+ text "package" <+> pretty name Just p -> return p -- Return all library components- forM (Set.toList sublibs) $ \lib ->+ forM (NonEmptySet.toList sublibs) $ \lib -> let comp = CLibName lib in- case Map.lookup (CLibName $ LSubLibName $- packageNameToUnqualComponentName name) pkg- <|> Map.lookup comp pkg- of+ case Map.lookup comp pkg of Nothing -> dieProgress $ text "Dependency on unbuildable" <+> text (showLibraryName lib) <+>- text "from" <+> pretty pn+ text "from" <+> pretty name Just v -> return v else return old_style_lib_deps mkConfiguredComponent@@ -292,8 +294,8 @@ m component return (extendConfiguredComponentMap cc m, cc) -newPackageDepsBehaviourMinVersion :: Version-newPackageDepsBehaviourMinVersion = mkVersion [1,7,1]+newPackageDepsBehaviourMinVersion :: CabalSpecVersion+newPackageDepsBehaviourMinVersion = CabalSpecV1_8 -- In older cabal versions, there was only one set of package dependencies for@@ -304,19 +306,3 @@ newPackageDepsBehaviour :: PackageDescription -> Bool newPackageDepsBehaviour pkg = specVersion pkg >= newPackageDepsBehaviourMinVersion---- | 'build-depends:' stanzas are currently ambiguous as the external packages--- and internal libraries are specified the same. For now, we assume internal--- libraries shadow, and this function disambiguates accordingly, but soon the--- underlying ambiguity will be addressed.--- Multiple public libraries (cabal 3.0) added an unambiguous way of specifying--- sublibraries, but we still have to support the old syntax for bc reasons.-fixFakePkgName :: PackageDescription -> PackageName -> (PackageName, ComponentName)-fixFakePkgName pkg_descr pn =- if subLibName `elem` internalLibraries- then (packageName pkg_descr, CLibName (LSubLibName subLibName))- else (pn, CLibName LMainLibName )- where- subLibName = packageNameToUnqualComponentName pn- internalLibraries = mapMaybe (libraryNameString . libName)- (allLibraries pkg_descr)
cabal/Cabal/Distribution/Backpack/Id.hs view
@@ -11,13 +11,12 @@ import Distribution.Compat.Prelude import Distribution.Types.UnqualComponentName-import Distribution.Simple.Compiler hiding (Flag)-import Distribution.PackageDescription as PD hiding (Flag)+import Distribution.Simple.Compiler+import Distribution.PackageDescription import Distribution.Simple.Setup as Setup import qualified Distribution.Simple.InstallDirs as InstallDirs import Distribution.Simple.LocalBuildInfo import Distribution.Types.ComponentId-import Distribution.Types.PackageId import Distribution.Types.UnitId import Distribution.Types.MungedPackageName import Distribution.Utils.Base62@@ -125,8 +124,8 @@ -> UnitId -> String computeCompatPackageKey comp pkg_name pkg_version uid- | not (packageKeySupported comp) =- prettyShow pkg_name ++ "-" ++ prettyShow pkg_version+ | not (packageKeySupported comp || unitIdSupported comp)+ = prettyShow pkg_name ++ "-" ++ prettyShow pkg_version | not (unifiedIPIDRequired comp) = let str = unUnitId uid -- assume no Backpack support mb_verbatim_key
cabal/Cabal/Distribution/Backpack/LinkedComponent.hs view
@@ -29,13 +29,14 @@ import Distribution.Types.AnnotatedId import Distribution.Types.ComponentName+import Distribution.Types.ModuleReexport import Distribution.Types.ModuleRenaming import Distribution.Types.IncludeRenaming import Distribution.Types.ComponentInclude import Distribution.Types.ComponentId import Distribution.Types.PackageId import Distribution.Package-import Distribution.PackageDescription as PD hiding (Flag)+import Distribution.PackageDescription import Distribution.ModuleName import Distribution.Simple.LocalBuildInfo import Distribution.Verbosity@@ -43,11 +44,8 @@ import qualified Data.Set as Set import qualified Data.Map as Map-import Data.Traversable- ( mapM ) import Distribution.Pretty (pretty)-import Text.PrettyPrint-import Data.Either+import Text.PrettyPrint (Doc, hang, text, vcat, ($+$), hsep, quotes) -- | A linked component is a component that has been mix-in linked, at -- which point we have determined how all the dependencies of the@@ -187,19 +185,19 @@ m_u <- convertModule (OpenModule this_uid m) return (Map.singleton m [WithSource (from m) m_u], Map.empty) -- Handle 'exposed-modules'- exposed_mod_shapes_u <- mapM (convertMod FromExposedModules) src_provs+ exposed_mod_shapes_u <- traverse (convertMod FromExposedModules) src_provs -- Handle 'other-modules'- other_mod_shapes_u <- mapM (convertMod FromOtherModules) src_hidden+ other_mod_shapes_u <- traverse (convertMod FromOtherModules) src_hidden -- Handle 'signatures' let convertReq :: ModuleName -> UnifyM s (ModuleScopeU s) convertReq req = do req_u <- convertModule (OpenModuleVar req) return (Map.empty, Map.singleton req [WithSource (FromSignatures req) req_u])- req_shapes_u <- mapM convertReq src_reqs+ req_shapes_u <- traverse convertReq src_reqs -- Handle 'mixins'- (incl_shapes_u, all_includes_u) <- fmap unzip (mapM convertInclude unlinked_includes)+ (incl_shapes_u, all_includes_u) <- fmap unzip (traverse convertInclude unlinked_includes) failIfErrs -- Prevent error cascade -- Mix-in link everything! mixLink is the real workhorse.@@ -208,7 +206,7 @@ ++ req_shapes_u ++ incl_shapes_u - -- src_reqs_u <- mapM convertReq src_reqs+ -- src_reqs_u <- traverse convertReq src_reqs -- Read out all the final results by converting back -- into a pure representation. let convertIncludeU (ComponentInclude dep_aid rns i) = do@@ -220,8 +218,8 @@ }) shape <- convertModuleScopeU shape_u let (includes_u, sig_includes_u) = partitionEithers all_includes_u- incls <- mapM convertIncludeU includes_u- sig_incls <- mapM convertIncludeU sig_includes_u+ incls <- traverse convertIncludeU includes_u+ sig_incls <- traverse convertIncludeU sig_includes_u return (shape, incls, sig_incls) let isNotLib (CLib _) = False
cabal/Cabal/Distribution/Backpack/ModuleShape.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric #-} -- | See <https://github.com/ezyang/ghc-proposals/blob/backpack/proposals/0000-backpack.rst> module Distribution.Backpack.ModuleShape (@@ -29,9 +30,10 @@ modShapeProvides :: OpenModuleSubst, modShapeRequires :: Set ModuleName }- deriving (Eq, Show, Generic)+ deriving (Eq, Show, Generic, Typeable) instance Binary ModuleShape+instance Structured ModuleShape instance ModSubst ModuleShape where modSubst subst (ModuleShape provs reqs)
cabal/Cabal/Distribution/Backpack/ReadyComponent.hs view
@@ -39,9 +39,6 @@ import Distribution.Package import Distribution.Simple.Utils -import qualified Control.Applicative as A-import qualified Data.Traversable as T- import Control.Monad import Text.PrettyPrint import qualified Data.Map as Map@@ -198,14 +195,14 @@ fmap f (InstM m) = InstM $ \s -> let (x, s') = m s in (f x, s') -instance A.Applicative InstM where+instance Applicative InstM where pure a = InstM $ \s -> (a, s) InstM f <*> InstM x = InstM $ \s -> let (f', s') = f s (x', s'') = x s' in (f' x', s'') instance Monad InstM where- return = A.pure+ return = pure InstM m >>= f = InstM $ \s -> let (x, s') = m s in runInstM (f x) s' @@ -259,20 +256,20 @@ -> InstM (Maybe ReadyComponent) instantiateComponent uid cid insts | Just lc <- Map.lookup cid cmap = do- provides <- T.mapM (substModule insts) (modShapeProvides (lc_shape lc))+ provides <- traverse (substModule insts) (modShapeProvides (lc_shape lc)) -- NB: lc_sig_includes is omitted here, because we don't -- need them to build includes <- forM (lc_includes lc) $ \ci -> do uid' <- substUnitId insts (ci_id ci) return ci { ci_ann_id = fmap (const uid') (ci_ann_id ci) }- exe_deps <- mapM (substExeDep insts) (lc_exe_deps lc)+ exe_deps <- traverse (substExeDep insts) (lc_exe_deps lc) s <- InstM $ \s -> (s, s) let getDep (Module dep_def_uid _) | let dep_uid = unDefUnitId dep_def_uid -- Lose DefUnitId invariant for rc_depends = [(dep_uid, fromMaybe err_pid $- Map.lookup dep_uid pid_map A.<|>+ Map.lookup dep_uid pid_map <|> fmap rc_munged_id (join (Map.lookup dep_uid s)))] where err_pid = MungedPackageId@@ -313,7 +310,7 @@ substSubst :: Map ModuleName Module -> Map ModuleName OpenModule -> InstM (Map ModuleName Module)- substSubst subst insts = T.mapM (substModule subst) insts+ substSubst subst insts = traverse (substModule subst) insts substModule :: Map ModuleName Module -> OpenModule -> InstM Module substModule subst (OpenModuleVar mod_name)@@ -346,7 +343,7 @@ then do uid' <- substUnitId Map.empty (ci_id ci) return $ ci { ci_ann_id = fmap (const (DefiniteUnitId uid')) (ci_ann_id ci) } else return ci- exe_deps <- mapM (substExeDep Map.empty) (lc_exe_deps lc)+ exe_deps <- traverse (substExeDep Map.empty) (lc_exe_deps lc) let indefc = IndefiniteComponent { indefc_requires = map fst (lc_insts lc), indefc_provides = modShapeProvides (lc_shape lc),
cabal/Cabal/Distribution/Backpack/UnifyM.hs view
@@ -60,7 +60,7 @@ import Distribution.Types.IncludeRenaming import Distribution.Types.ComponentInclude import Distribution.Types.AnnotatedId-import Distribution.Types.ComponentName+import Distribution.Types.ModuleRenaming import Distribution.Verbosity import Data.STRef@@ -70,7 +70,6 @@ import qualified Data.Set as Set import Data.IntMap (IntMap) import qualified Data.IntMap as IntMap-import qualified Data.Traversable as T import Text.PrettyPrint -- TODO: more detailed trace output on high verbosity would probably@@ -321,7 +320,7 @@ convertUnitId' stk (IndefFullUnitId cid insts) = do fs <- fmap unify_uniq getUnifEnv x <- liftST $ UnionFind.fresh (error "convertUnitId") -- tie the knot later- insts_u <- T.forM insts $ convertModule' (extendMuEnv stk x)+ insts_u <- for insts $ convertModule' (extendMuEnv stk x) u <- readUnifRef fs writeUnifRef fs (u+1) y <- liftST $ UnionFind.fresh (UnitIdU u cid insts_u)@@ -359,11 +358,11 @@ -- | Conversion of 'ModuleSubst' to 'ModuleSubstU' convertModuleSubst :: Map ModuleName OpenModule -> UnifyM s (Map ModuleName (ModuleU s))-convertModuleSubst = T.mapM convertModule+convertModuleSubst = traverse convertModule -- | Conversion of 'ModuleSubstU' to 'ModuleSubst' convertModuleSubstU :: ModuleSubstU s -> UnifyM s OpenModuleSubst-convertModuleSubstU = T.mapM convertModuleU+convertModuleSubstU = traverse convertModuleU ----------------------------------------------------------------------- -- Conversion from the unifiable data types@@ -400,7 +399,7 @@ failWith (text "Unsupported mutually recursive unit identifier") -- return (UnitIdVar i) Nothing -> do- insts <- T.forM insts_u $ convertModuleU' (extendMooEnv stk u)+ insts <- for insts_u $ convertModuleU' (extendMooEnv stk u) return (IndefFullUnitId cid insts) convertModuleU' :: MooEnv -> ModuleU s -> UnifyM s OpenModule@@ -615,11 +614,11 @@ -- | Convert a 'ModuleProvides' to a 'ModuleProvidesU' convertModuleProvides :: ModuleProvides -> UnifyM s (ModuleProvidesU s)-convertModuleProvides = T.mapM (mapM (T.mapM convertModule))+convertModuleProvides = traverse (traverse (traverse convertModule)) -- | Convert a 'ModuleProvidesU' to a 'ModuleProvides' convertModuleProvidesU :: ModuleProvidesU s -> UnifyM s ModuleProvides-convertModuleProvidesU = T.mapM (mapM (T.mapM convertModuleU))+convertModuleProvidesU = traverse (traverse (traverse convertModuleU)) convertModuleRequires :: ModuleRequires -> UnifyM s (ModuleRequiresU s) convertModuleRequires = convertModuleProvides
cabal/Cabal/Distribution/CabalSpecVersion.hs view
@@ -26,14 +26,19 @@ | CabalSpecV2_2 | CabalSpecV2_4 | CabalSpecV3_0- | CabalSpecV3_2+ -- 3.2: no changes+ | CabalSpecV3_4 deriving (Eq, Ord, Show, Read, Enum, Bounded, Typeable, Data, Generic) +instance Binary CabalSpecVersion+instance Structured CabalSpecVersion+instance NFData CabalSpecVersion where rnf = genericRnf+ -- | Show cabal spec version, but not the way in the .cabal files -- -- @since 3.0.0.0 showCabalSpecVersion :: CabalSpecVersion -> String-showCabalSpecVersion CabalSpecV3_2 = "3.2"+showCabalSpecVersion CabalSpecV3_4 = "3.4" showCabalSpecVersion CabalSpecV3_0 = "3.0" showCabalSpecVersion CabalSpecV2_4 = "2.4" showCabalSpecVersion CabalSpecV2_2 = "2.2"@@ -51,26 +56,69 @@ showCabalSpecVersion CabalSpecV1_0 = "1.0" cabalSpecLatest :: CabalSpecVersion-cabalSpecLatest = CabalSpecV3_2+cabalSpecLatest = CabalSpecV3_4 -cabalSpecFromVersionDigits :: [Int] -> CabalSpecVersion+-- | Parse 'CabalSpecVersion' from version digits.+--+-- It may fail if for recent versions the version is not exact.+--+cabalSpecFromVersionDigits :: [Int] -> Maybe CabalSpecVersion cabalSpecFromVersionDigits v- | v >= [3,1] = CabalSpecV3_2- | v >= [2,5] = CabalSpecV3_0- | v >= [2,3] = CabalSpecV2_4- | v >= [2,1] = CabalSpecV2_2- | v >= [1,25] = CabalSpecV2_0- | v >= [1,23] = CabalSpecV1_24- | v >= [1,21] = CabalSpecV1_22- | v >= [1,19] = CabalSpecV1_20- | v >= [1,17] = CabalSpecV1_18- | v >= [1,11] = CabalSpecV1_12- | v >= [1,9] = CabalSpecV1_10- | v >= [1,7] = CabalSpecV1_8- | v >= [1,5] = CabalSpecV1_6- | v >= [1,3] = CabalSpecV1_4- | v >= [1,1] = CabalSpecV1_2- | otherwise = CabalSpecV1_0+ | v == [3,4] = Just CabalSpecV3_4+ | v == [3,0] = Just CabalSpecV3_0+ | v == [2,4] = Just CabalSpecV2_4+ | v == [2,2] = Just CabalSpecV2_2+ | v == [2,0] = Just CabalSpecV2_0+ | v >= [1,25] = Nothing+ | v >= [1,23] = Just CabalSpecV1_24+ | v >= [1,21] = Just CabalSpecV1_22+ | v >= [1,19] = Just CabalSpecV1_20+ | v >= [1,17] = Just CabalSpecV1_18+ | v >= [1,11] = Just CabalSpecV1_12+ | v >= [1,9] = Just CabalSpecV1_10+ | v >= [1,7] = Just CabalSpecV1_8+ | v >= [1,5] = Just CabalSpecV1_6+ | v >= [1,3] = Just CabalSpecV1_4+ | v >= [1,1] = Just CabalSpecV1_2+ | otherwise = Just CabalSpecV1_0++-- | @since 3.4.0.0+cabalSpecToVersionDigits :: CabalSpecVersion -> [Int]+cabalSpecToVersionDigits CabalSpecV3_4 = [3,4]+cabalSpecToVersionDigits CabalSpecV3_0 = [3,0]+cabalSpecToVersionDigits CabalSpecV2_4 = [2,4]+cabalSpecToVersionDigits CabalSpecV2_2 = [2,2]+cabalSpecToVersionDigits CabalSpecV2_0 = [2,0]+cabalSpecToVersionDigits CabalSpecV1_24 = [1,24]+cabalSpecToVersionDigits CabalSpecV1_22 = [1,22]+cabalSpecToVersionDigits CabalSpecV1_20 = [1,20]+cabalSpecToVersionDigits CabalSpecV1_18 = [1,18]+cabalSpecToVersionDigits CabalSpecV1_12 = [1,12]+cabalSpecToVersionDigits CabalSpecV1_10 = [1,10]+cabalSpecToVersionDigits CabalSpecV1_8 = [1,8]+cabalSpecToVersionDigits CabalSpecV1_6 = [1,6]+cabalSpecToVersionDigits CabalSpecV1_4 = [1,4]+cabalSpecToVersionDigits CabalSpecV1_2 = [1,2]+cabalSpecToVersionDigits CabalSpecV1_0 = [1,0]++-- | What is the minimum Cabal library version which knows how handle+-- this spec version.+--+-- /Note:/ this is a point where we could decouple cabal-spec and Cabal+-- versions, if we ever want that.+--+-- >>> cabalSpecMinimumLibraryVersion CabalSpecV3_0+-- [2,5]+--+-- >>> cabalSpecMinimumLibraryVersion CabalSpecV2_4+-- [2,3]+--+-- @since 3.4.0.0+cabalSpecMinimumLibraryVersion :: CabalSpecVersion -> [Int]+cabalSpecMinimumLibraryVersion CabalSpecV1_0 = [1,0]+cabalSpecMinimumLibraryVersion csv = case cabalSpecToVersionDigits (pred csv) of+ [x,y] -> [x, y+1]+ xs -> xs specHasCommonStanzas :: CabalSpecVersion -> HasCommonStanzas specHasCommonStanzas v =
cabal/Cabal/Distribution/Compat/Async.hs view
@@ -6,6 +6,8 @@ -- Copyright (c) 2012, Simon Marlow -- Licensed under BSD-3-Clause --+-- @since 3.2.0.0+-- module Distribution.Compat.Async ( AsyncM, withAsync, waitCatch,
cabal/Cabal/Distribution/Compat/Binary.hs view
@@ -18,12 +18,7 @@ #endif ) where -import Control.Exception (catch, evaluate)-#if __GLASGOW_HASKELL__ >= 711-import Control.Exception (pattern ErrorCall)-#else-import Control.Exception (ErrorCall(..))-#endif+import Control.Exception (ErrorCall (..), catch, evaluate) import Data.ByteString.Lazy (ByteString) #if __GLASGOW_HASKELL__ >= 708 || MIN_VERSION_binary(0,7,0)@@ -67,5 +62,10 @@ decodeOrFailIO :: Binary a => ByteString -> IO (Either String a) decodeOrFailIO bs =- catch (evaluate (decode bs) >>= return . Right)- $ \(ErrorCall str) -> return $ Left str+ catch (evaluate (decode bs) >>= return . Right) handler+ where+#if MIN_VERSION_base(4,9,0)+ handler (ErrorCallWithLocation str _) = return $ Left str+#else+ handler (ErrorCall str) = return $ Left str+#endif
cabal/Cabal/Distribution/Compat/CharParsing.hs view
@@ -38,6 +38,7 @@ , CharParsing(..) -- * Cabal additions , integral+ , signedIntegral , munch1 , munch , skipSpaces1@@ -330,6 +331,14 @@ f '9' = 9 f _ = error "panic! integral" {-# INLINE integral #-}++-- | Accepts negative (starting with @-@) and positive (without sign) integral+-- numbers.+-- +-- @since 3.4.0.0+signedIntegral :: (CharParsing m, Integral a) => m a+signedIntegral = negate <$ char '-' <*> integral <|> integral+{-# INLINE signedIntegral #-} -- | Greedily munch characters while predicate holds. -- Require at least one character.
cabal/Cabal/Distribution/Compat/CopyFile.hs view
@@ -14,13 +14,11 @@ import Prelude () import Distribution.Compat.Prelude -import Distribution.Compat.Exception- #ifndef mingw32_HOST_OS import Distribution.Compat.Internal.TempFile import Control.Exception- ( bracketOnError, throwIO )+ ( bracketOnError ) import qualified Data.ByteString.Lazy as BSL import System.IO.Error ( ioeSetLocation )@@ -43,8 +41,6 @@ #else /* else mingw32_HOST_OS */ -import Control.Exception- ( throwIO ) import qualified Data.ByteString.Lazy as BSL import System.IO.Error ( ioeSetLocation )@@ -69,16 +65,16 @@ import qualified System.Win32.File as Win32 ( copyFile ) #endif /* mingw32_HOST_OS */ -copyOrdinaryFile, copyExecutableFile :: FilePath -> FilePath -> NoCallStackIO ()+copyOrdinaryFile, copyExecutableFile :: FilePath -> FilePath -> IO () copyOrdinaryFile src dest = copyFile src dest >> setFileOrdinary dest copyExecutableFile src dest = copyFile src dest >> setFileExecutable dest -setFileOrdinary, setFileExecutable, setDirOrdinary :: FilePath -> NoCallStackIO ()+setFileOrdinary, setFileExecutable, setDirOrdinary :: FilePath -> IO () #ifndef mingw32_HOST_OS setFileOrdinary path = setFileMode path 0o644 -- file perms -rw-r--r-- setFileExecutable path = setFileMode path 0o755 -- file perms -rwxr-xr-x -setFileMode :: FilePath -> FileMode -> NoCallStackIO ()+setFileMode :: FilePath -> FileMode -> IO () setFileMode name m = withFilePath name $ \s -> do throwErrnoPathIfMinus1_ "setFileMode" name (c_chmod s m)@@ -91,7 +87,7 @@ -- | Copies a file to a new destination. -- Often you should use `copyFileChanged` instead.-copyFile :: FilePath -> FilePath -> NoCallStackIO ()+copyFile :: FilePath -> FilePath -> IO () copyFile fromFPath toFPath = copy `catchIO` (\ioe -> throwIO (ioeSetLocation ioe "copyFile"))@@ -229,7 +225,7 @@ -- | Like `copyFile`, but does not touch the target if source and destination -- are already byte-identical. This is recommended as it is useful for -- time-stamp based recompilation avoidance.-copyFileChanged :: FilePath -> FilePath -> NoCallStackIO ()+copyFileChanged :: FilePath -> FilePath -> IO () copyFileChanged src dest = do equal <- filesEqual src dest unless equal $ copyFile src dest@@ -237,7 +233,7 @@ -- | Checks if two files are byte-identical. -- Returns False if either of the files do not exist or if files -- are of different size.-filesEqual :: FilePath -> FilePath -> NoCallStackIO Bool+filesEqual :: FilePath -> FilePath -> IO Bool filesEqual f1 f2 = do ex1 <- doesFileExist f1 ex2 <- doesFileExist f2
cabal/Cabal/Distribution/Compat/CreatePipe.hs view
@@ -4,7 +4,10 @@ module Distribution.Compat.CreatePipe (createPipe) where -import System.IO (Handle, hSetEncoding, localeEncoding)+#if MIN_VERSION_process(1,2,1)+import System.Process (createPipe)+#else+import System.IO (Handle, hSetBinaryMode) import Prelude () import Distribution.Compat.Prelude@@ -40,11 +43,11 @@ return (readfd, writefd) (do readh <- fdToHandle readfd ReadMode writeh <- fdToHandle writefd WriteMode- hSetEncoding readh localeEncoding- hSetEncoding writeh localeEncoding+ hSetBinaryMode readh True+ hSetBinaryMode writeh True return (readh, writeh)) `onException` (close readfd >> close writefd) where- fdToHandle :: CInt -> IOMode -> NoCallStackIO Handle+ fdToHandle :: CInt -> IOMode -> IO Handle fdToHandle fd mode = do (fd', deviceType) <- mkFD fd mode (Just (Stream, 0, 0)) False False mkHandleFromFD fd' deviceType "" mode False Nothing@@ -69,9 +72,10 @@ (readfd, writefd) <- Posix.createPipe readh <- fdToHandle readfd writeh <- fdToHandle writefd- hSetEncoding readh localeEncoding- hSetEncoding writeh localeEncoding+ hSetBinaryMode readh True+ hSetBinaryMode writeh True return (readh, writeh) where _ = callStack+#endif #endif
cabal/Cabal/Distribution/Compat/DList.hs view
@@ -12,6 +12,7 @@ module Distribution.Compat.DList ( DList, runDList,+ empty, singleton, fromList, toList,@@ -19,7 +20,7 @@ ) where import Prelude ()-import Distribution.Compat.Prelude hiding (toList)+import Distribution.Compat.Prelude hiding (toList, empty) -- | Difference list. newtype DList a = DList ([a] -> [a])@@ -31,6 +32,10 @@ singleton :: a -> DList a singleton a = DList (a:) +-- | @since 3.4.0.0+empty :: DList a+empty = DList id+ fromList :: [a] -> DList a fromList as = DList (as ++) @@ -41,7 +46,7 @@ snoc xs x = xs <> singleton x instance Monoid (DList a) where- mempty = DList id+ mempty = empty mappend = (<>) instance Semigroup (DList a) where
cabal/Cabal/Distribution/Compat/Environment.hs view
@@ -39,7 +39,7 @@ import System.Posix.Internals ( withFilePath ) #endif /* mingw32_HOST_OS */ -getEnvironment :: NoCallStackIO [(String, String)]+getEnvironment :: IO [(String, String)] #ifdef mingw32_HOST_OS -- On Windows, the names of environment variables are case-insensitive, but are -- often given in mixed-case (e.g. "PATH" is "Path"), so we have to normalise
cabal/Cabal/Distribution/Compat/Exception.hs view
@@ -6,22 +6,32 @@ displayException, ) where +#ifdef MIN_VERSION_base+#define MINVER_base_48 MIN_VERSION_base(4,8,0)+#else+#define MINVER_base_48 (__GLASGOW_HASKELL__ >= 710)+#endif+ import System.Exit import qualified Control.Exception as Exception-#if __GLASGOW_HASKELL__ >= 710++#if MINVER_base_48 import Control.Exception (displayException) #endif +-- | Try 'IOException'. tryIO :: IO a -> IO (Either Exception.IOException a) tryIO = Exception.try +-- | Catch 'IOException'. catchIO :: IO a -> (Exception.IOException -> IO a) -> IO a catchIO = Exception.catch +-- | Catch 'ExitCode' catchExit :: IO a -> (ExitCode -> IO a) -> IO a catchExit = Exception.catch -#if __GLASGOW_HASKELL__ < 710+#if !MINVER_base_48 displayException :: Exception.Exception e => e -> String displayException = show #endif
cabal/Cabal/Distribution/Compat/GetShortPathName.hs view
@@ -40,7 +40,7 @@ -- will always return the required buffer size for a -- specified lpszLongPath. ---getShortPathName :: FilePath -> NoCallStackIO FilePath+getShortPathName :: FilePath -> IO FilePath getShortPathName path = Win32.withTString path $ \c_path -> do c_len <- Win32.failIfZero "GetShortPathName #1 failed!" $@@ -53,7 +53,7 @@ #else -getShortPathName :: FilePath -> NoCallStackIO FilePath+getShortPathName :: FilePath -> IO FilePath getShortPathName path = return path #endif
cabal/Cabal/Distribution/Compat/Graph.hs view
@@ -1,9 +1,10 @@-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE CPP #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilies #-} {-# LANGUAGE UndecidableInstances #-}-{-# LANGUAGE BangPatterns #-} ----------------------------------------------------------------------------- -- | -- Module : Distribution.Compat.Graph@@ -83,20 +84,20 @@ nodeValue, ) where +import Distribution.Compat.Prelude hiding (empty, lookup, null, toList) import Prelude ()-import qualified Distribution.Compat.Prelude as Prelude-import Distribution.Compat.Prelude hiding (lookup, null, empty, toList) -import Data.Graph (SCC(..))-import qualified Data.Graph as G+import Data.Array ((!))+import Data.Graph (SCC (..))+import Distribution.Utils.Structured (Structure (..), Structured (..)) -import qualified Data.Map.Strict as Map-import qualified Data.Set as Set-import qualified Data.Array as Array-import Data.Array ((!))-import qualified Data.Tree as Tree-import Data.Either (partitionEithers)-import qualified Data.Foldable as Foldable+import qualified Data.Array as Array+import qualified Data.Foldable as Foldable+import qualified Data.Graph as G+import qualified Data.Map.Strict as Map+import qualified Data.Set as Set+import qualified Data.Tree as Tree+import qualified Distribution.Compat.Prelude as Prelude -- | A graph of nodes @a@. The nodes are expected to have instance -- of class 'IsNode'.@@ -128,6 +129,9 @@ instance (IsNode a, Binary a, Show (Key a)) => Binary (Graph a) where put x = put (toList x) get = fmap fromDistinctList get++instance Structured a => Structured (Graph a) where+ structure p = Nominal (typeRep p) 0 "Graph" [structure (Proxy :: Proxy a)] instance (Eq (Key a), Eq a) => Eq (Graph a) where g1 == g2 = graphMap g1 == graphMap g2
cabal/Cabal/Distribution/Compat/Internal/TempFile.hs view
@@ -10,17 +10,22 @@ import Distribution.Compat.Exception import System.FilePath ((</>))-import Foreign.C (CInt, eEXIST, getErrno, errnoToIOError) import System.IO (Handle, openTempFile, openBinaryTempFile)+#if defined(__IO_MANAGER_WINIO__)+import System.IO (openBinaryTempFileWithDefaultPermissions)+#else+import Control.Exception (onException) import Data.Bits ((.|.))-import System.Posix.Internals (c_open, c_close, o_CREAT, o_EXCL, o_RDWR,- o_BINARY, o_NONBLOCK, o_NOCTTY,- withFilePath, c_getpid)-import System.IO.Error (isAlreadyExistsError)+import Foreign.C (CInt, eEXIST, getErrno, errnoToIOError) import GHC.IO.Handle.FD (fdToHandle)-import Control.Exception (onException)+import System.Posix.Internals (c_open, c_close, o_EXCL, o_BINARY, withFilePath,+ o_CREAT, o_RDWR, o_NONBLOCK, o_NOCTTY)+#endif +import System.Posix.Internals (c_getpid)+import System.IO.Error (isAlreadyExistsError)+ #if defined(mingw32_HOST_OS) || defined(ghcjs_HOST_OS) import System.Directory ( createDirectory ) #else@@ -36,10 +41,17 @@ -- TODO: This file should probably be removed. -- This is a copy/paste of the openBinaryTempFile definition, but--- if uses 666 rather than 600 for the permissions. The base library--- needs to be changed to make this better.+-- it uses 666 rather than 600 for the permissions. Newer versions+-- of base have a new function with this behavior which we use on+-- Windows when the new IO manager is used. openNewBinaryFile :: FilePath -> String -> IO (FilePath, Handle) openNewBinaryFile dir template = do+ -- This method can't be used under WINIO. Also the current implementation has+ -- thread safety issues depending on which GHC is used. On newer GHC's let's+ -- use the built in one.+#if defined(__IO_MANAGER_WINIO__)+ openBinaryTempFileWithDefaultPermissions dir template+#else pid <- c_getpid findTempName pid where@@ -88,6 +100,12 @@ | last a == pathSeparator = a ++ b | otherwise = a ++ [pathSeparator] ++ b +-- FIXME: Copied from GHC.Handle+std_flags, output_flags, rw_flags :: CInt+std_flags = o_NONBLOCK .|. o_NOCTTY+output_flags = std_flags .|. o_CREAT+rw_flags = output_flags .|. o_RDWR+ -- FIXME: Should use System.FilePath library pathSeparator :: Char #ifdef mingw32_HOST_OS@@ -95,12 +113,8 @@ #else pathSeparator = '/' #endif---- FIXME: Copied from GHC.Handle-std_flags, output_flags, rw_flags :: CInt-std_flags = o_NONBLOCK .|. o_NOCTTY-output_flags = std_flags .|. o_CREAT-rw_flags = output_flags .|. o_RDWR+-- /* __IO_MANAGER_WINIO__ */+#endif createTempDirectory :: FilePath -> String -> IO FilePath createTempDirectory dir template = do
cabal/Cabal/Distribution/Compat/Lens.hs view
@@ -50,7 +50,6 @@ import Prelude() import Distribution.Compat.Prelude -import Control.Applicative (Const (..)) import Control.Monad.State.Class (MonadState (..), gets, modify) import qualified Distribution.Compat.DList as DList
− cabal/Cabal/Distribution/Compat/MD5.hs
@@ -1,50 +0,0 @@-module Distribution.Compat.MD5 (- MD5,- showMD5,- md5,- -- * Binary- binaryPutMD5,- binaryGetMD5,- ) where--import Data.Binary (Get, Put)-import Data.Binary.Get (getWord64le)-import Data.Binary.Put (putWord64le)-import Foreign.Ptr (castPtr)-import GHC.Fingerprint (Fingerprint (..), fingerprintData)-import Numeric (showHex)-import System.IO.Unsafe (unsafeDupablePerformIO)--import qualified Data.ByteString as BS-import qualified Data.ByteString.Unsafe as BS--type MD5 = Fingerprint---- | Show 'MD5' in human readable form------ >>> showMD5 (Fingerprint 123 456)--- "000000000000007b00000000000001c8"------ >>> showMD5 $ md5 $ BS.pack [0..127]--- "37eff01866ba3f538421b30b7cbefcac"----showMD5 :: MD5 -> String-showMD5 (Fingerprint a b) = pad a' ++ pad b' where- a' = showHex a ""- b' = showHex b ""- pad s = replicate (16 - length s) '0' ++ s--md5 :: BS.ByteString -> MD5-md5 bs = unsafeDupablePerformIO $ BS.unsafeUseAsCStringLen bs $ \(ptr, len) ->- fingerprintData (castPtr ptr) len--binaryPutMD5 :: MD5 -> Put-binaryPutMD5 (Fingerprint a b) = do- putWord64le a- putWord64le b--binaryGetMD5 :: Get MD5-binaryGetMD5 = do- a <- getWord64le- b <- getWord64le- return (Fingerprint a b)
+ cabal/Cabal/Distribution/Compat/NonEmptySet.hs view
@@ -0,0 +1,155 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE DeriveDataTypeable #-}+module Distribution.Compat.NonEmptySet (+ NonEmptySet,+ -- * Construction+ singleton,+ -- * Insertion+ insert,+ -- * Deletion+ delete,+ -- * Conversions+ toNonEmpty,+ fromNonEmpty,+ toList,+ toSet,+ -- * Query+ member,+ -- * Map+ map,+) where++import Prelude (Bool (..), Eq, Maybe (..), Ord (..), Read, Show (..), String, error, otherwise, return, showParen, showString, ($), (++), (.))++import Control.DeepSeq (NFData (..))+import Data.Data (Data)+import Data.List.NonEmpty (NonEmpty (..))+import Data.Semigroup (Semigroup (..))+import Data.Typeable (Typeable)++import qualified Data.Foldable as F+import qualified Data.Set as Set++import Distribution.Compat.Binary (Binary (..))+import Distribution.Utils.Structured++#if MIN_VERSION_binary(0,6,0)+import Control.Applicative (empty)+#else+import Control.Monad (fail)+#endif++-- | @since 3.4.0.0+newtype NonEmptySet a = NES (Set.Set a)+ deriving (Eq, Ord, Typeable, Data, Read)++-------------------------------------------------------------------------------+-- Instances+-------------------------------------------------------------------------------++instance Show a => Show (NonEmptySet a) where+ showsPrec d s = showParen (d > 10)+ $ showString "fromNonEmpty "+ . showsPrec 11 (toNonEmpty s)++instance Binary a => Binary (NonEmptySet a) where+ put (NES s) = put s+ get = do+ xs <- get+ if Set.null xs+#if MIN_VERSION_binary(0,6,0)+ then empty+#else+ then fail "NonEmptySet: empty"+#endif+ else return (NES xs)++instance Structured a => Structured (NonEmptySet a) where+ structure = containerStructure++instance NFData a => NFData (NonEmptySet a) where+ rnf (NES x) = rnf x++-- | Note: there aren't @Monoid@ instance.+instance Ord a => Semigroup (NonEmptySet a) where+ NES x <> NES y = NES (Set.union x y)++instance F.Foldable NonEmptySet where+ foldMap f (NES s) = F.foldMap f s+ foldr f z (NES s) = F.foldr f z s++#if MIN_VERSION_base(4,8,0)+ toList = toList+ null _ = False+ length (NES s) = F.length s+#endif++-------------------------------------------------------------------------------+-- Constructors+-------------------------------------------------------------------------------++singleton :: a -> NonEmptySet a+singleton = NES . Set.singleton++-------------------------------------------------------------------------------+-- Insertion+-------------------------------------------------------------------------------++insert :: Ord a => a -> NonEmptySet a -> NonEmptySet a+insert x (NES xs) = NES (Set.insert x xs)++-------------------------------------------------------------------------------+-- Deletion+-------------------------------------------------------------------------------++delete :: Ord a => a -> NonEmptySet a -> Maybe (NonEmptySet a)+delete x (NES xs)+ | Set.null res = Nothing+ | otherwise = Just (NES xs)+ where+ res = Set.delete x xs++-------------------------------------------------------------------------------+-- Conversions+-------------------------------------------------------------------------------++fromNonEmpty :: Ord a => NonEmpty a -> NonEmptySet a+fromNonEmpty (x :| xs) = NES (Set.fromList (x : xs))++toNonEmpty :: NonEmptySet a -> NonEmpty a+toNonEmpty (NES s) = case Set.toList s of+ [] -> panic "toNonEmpty"+ x:xs -> x :| xs++toList :: NonEmptySet a -> [a]+toList (NES s) = Set.toList s++toSet :: NonEmptySet a -> Set.Set a+toSet (NES s) = s++-------------------------------------------------------------------------------+-- Query+-------------------------------------------------------------------------------++member :: Ord a => a -> NonEmptySet a -> Bool+member x (NES xs) = Set.member x xs++-------------------------------------------------------------------------------+-- Map+-------------------------------------------------------------------------------++map+ :: ( Ord b+#if !MIN_VERSION_containers(0,5,2)+ , Ord a+#endif+ )+ => (a -> b) -> NonEmptySet a -> NonEmptySet b+map f (NES x) = NES (Set.map f x)++-------------------------------------------------------------------------------+-- Internal+-------------------------------------------------------------------------------++panic :: String -> a+panic msg = error $ "NonEmptySet invariant violated: " ++ msg
cabal/Cabal/Distribution/Compat/Prelude.hs view
@@ -1,7 +1,8 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE TypeOperators #-}-{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE CPP #-} {-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE Trustworthy #-}+{-# LANGUAGE TypeOperators #-} #ifdef MIN_VERSION_base #define MINVER_base_411 MIN_VERSION_base(4,11,0)@@ -33,22 +34,28 @@ -- * Common type-classes Semigroup (..), gmappend, gmempty,- Typeable,+ Typeable, TypeRep, typeRep, Data, Generic, NFData (..), genericRnf, Binary (..),+ Structured, Alternative (..), MonadPlus (..), IsString (..), -- * Some types- IO, NoCallStackIO, Map, Set,+ NonEmptySet, Identity (..), Proxy (..),+ Const (..),+ Void, + -- * Data.Either+ partitionEithers,+ -- * Data.Maybe catMaybes, mapMaybe, fromMaybe,@@ -61,6 +68,7 @@ intercalate, intersperse, sort, sortBy, nub, nubBy,+ partition, -- * Data.List.NonEmpty NonEmpty((:|)), foldl1, foldr1,@@ -78,6 +86,12 @@ Traversable, traverse, sequenceA, for, + -- * Data.Function+ on,++ -- * Data.Ord+ comparing,+ -- * Control.Arrow first, @@ -86,26 +100,49 @@ unless, when, ap, void, foldM, filterM,+ join, guard, + -- * Control.Exception+ catch, throwIO, evaluate,+ Exception (..), IOException, SomeException (..),+#if !MINVER_base_48+ displayException,+#endif+ tryIO, catchIO, catchExit,++ -- * Control.DeepSeq+ deepseq, force,+ -- * Data.Char isSpace, isDigit, isUpper, isAlpha, isAlphaNum, chr, ord, toLower, toUpper, + -- * Data.Void+ absurd, vacuous,+ -- * Data.Word & Data.Int Word, Word8, Word16, Word32, Word64, Int8, Int16, Int32, Int64, -- * Text.PrettyPrint- (<<>>),+ (<<>>), (Disp.<+>), + -- * System.Exit+ ExitCode (..),+ exitWith, exitSuccess, exitFailure,+ -- * Text.Read readMaybe,++ -- * Debug.Trace (as deprecated functions)+ trace, traceShow, traceShowId, ) where+ -- We also could hide few partial function import Prelude as BasePrelude hiding- ( IO, mapM, mapM_, sequence, null, length, foldr, any, all, head, tail, last, init+ ( mapM, mapM_, sequence, null, length, foldr, any, all, head, tail, last, init -- partial functions , read , foldr1, foldl1@@ -122,53 +159,57 @@ #endif ) +-- AMP #if !MINVER_base_48 import Control.Applicative (Applicative (..), (<$), (<$>))-import Distribution.Compat.Semigroup (Monoid (..)) import Data.Foldable (toList)+import Distribution.Compat.Semigroup (Monoid (..)) #else-import Data.Foldable (length, null, Foldable(toList))+import Data.Foldable (Foldable (toList), length, null) #endif -import Data.Foldable (Foldable (foldMap, foldr), find, foldl', for_, traverse_, any, all)-import Data.Traversable (Traversable (traverse, sequenceA), for)+import Data.Foldable (Foldable (foldMap, foldr), all, any, find, foldl', for_, traverse_)+import Data.Traversable (Traversable (sequenceA, traverse), for)+ import qualified Data.Foldable +-- Extra exports import Control.Applicative (Alternative (..))-import Control.DeepSeq (NFData (..))+import Control.Applicative (Const (..))+import Control.Arrow (first)+import Control.DeepSeq (NFData (..), deepseq, force)+import Control.Exception (Exception (..), IOException, SomeException (..), catch, evaluate, throwIO)+import Control.Monad (MonadPlus (..), ap, filterM, foldM, guard, join, liftM, liftM2, unless, void, when)+import Data.Char (chr, isAlpha, isAlphaNum, isDigit, isSpace, isUpper, ord, toLower, toUpper) import Data.Data (Data)-import Data.Typeable (Typeable)-import Distribution.Compat.Binary (Binary (..))-import Distribution.Compat.Semigroup (Semigroup (..), gmappend, gmempty)-import GHC.Generics (Generic, Rep(..),- V1, U1(U1), K1(unK1), M1(unM1),- (:*:)((:*:)), (:+:)(L1,R1))-+import Data.Either (partitionEithers)+import Data.Function (on) import Data.Functor.Identity (Identity (..))+import Data.Int (Int16, Int32, Int64, Int8)+import Data.List (intercalate, intersperse, isPrefixOf, isSuffixOf, nub, nubBy, partition, sort, sortBy, unfoldr)+import Data.List.NonEmpty (NonEmpty ((:|)), head, init, last, tail) import Data.Map (Map)+import Data.Maybe (catMaybes, fromMaybe, isJust, isNothing, listToMaybe, mapMaybe, maybeToList)+import Data.Ord (comparing) import Data.Proxy (Proxy (..)) import Data.Set (Set)--import Control.Arrow (first)-import Control.Monad hiding (mapM)-import Data.Char-import Data.List (intercalate, intersperse, isPrefixOf,- isSuffixOf, nub, nubBy, sort, sortBy,- unfoldr)-import Data.List.NonEmpty (NonEmpty((:|)), head, tail, init, last)-import Data.Maybe import Data.String (IsString (..))-import Data.Int-import Data.Word+import Data.Void (Void, absurd, vacuous)+import Data.Word (Word, Word16, Word32, Word64, Word8)+import Distribution.Compat.Binary (Binary (..))+import Distribution.Compat.Semigroup (Semigroup (..), gmappend, gmempty)+import Distribution.Compat.Typeable (TypeRep, Typeable, typeRep)+import GHC.Generics ((:*:) ((:*:)), (:+:) (L1, R1), Generic, K1 (unK1), M1 (unM1), Rep (..), U1 (U1), V1)+import System.Exit (ExitCode (..), exitFailure, exitSuccess, exitWith) import Text.Read (readMaybe) import qualified Text.PrettyPrint as Disp -import qualified Prelude as OrigPrelude-import Distribution.Compat.Stack+import Distribution.Compat.Exception+import Distribution.Compat.NonEmptySet (NonEmptySet)+import Distribution.Utils.Structured (Structured) -type IO a = WithCallStack (OrigPrelude.IO a)-type NoCallStackIO a = OrigPrelude.IO a+import qualified Debug.Trace -- | New name for 'Text.PrettyPrint.<>' (<<>>) :: Disp.Doc -> Disp.Doc -> Disp.Doc@@ -254,3 +295,22 @@ {-# INLINE foldl1 #-} foldl1 :: (a -> a -> a) -> NonEmpty a -> a foldl1 = Data.Foldable.foldl1++-------------------------------------------------------------------------------+-- Trace+-------------------------------------------------------------------------------++-- Functions from Debug.Trace+-- but with DEPRECATED pragma, so -Werror will scream on them.++trace :: String -> a -> a+trace = Debug.Trace.trace+{-# DEPRECATED trace "Don't leave me in the code" #-}++traceShowId :: Show a => a -> a+traceShowId x = Debug.Trace.traceShow x x+{-# DEPRECATED traceShowId "Don't leave me in the code" #-}++traceShow :: Show a => a -> b -> b+traceShow = Debug.Trace.traceShow+{-# DEPRECATED traceShow "Don't leave me in the code" #-}
+ cabal/Cabal/Distribution/Compat/Process.hs view
@@ -0,0 +1,82 @@+{-# LANGUAGE CPP #-}+module Distribution.Compat.Process (+ -- * Redefined functions+ createProcess,+ runInteractiveProcess,+ rawSystem,+ -- * Additions+ enableProcessJobs,+ ) where++import System.Exit (ExitCode (..))+import System.IO (Handle)++import System.Process (CreateProcess, ProcessHandle)+import qualified System.Process as Process++#if MIN_VERSION_process(1,2,0)+import System.Process (waitForProcess)+#endif++-------------------------------------------------------------------------------+-- enableProcessJobs+-------------------------------------------------------------------------------++-- | Enable process jobs to ensure accurate determination of process completion+-- in the presence of @exec(3)@ on Windows.+--+-- Unfortunately the process job support is badly broken in @process@ releases+-- prior to 1.6.8, so we disable it in these versions, despite the fact that+-- this means we may see sporatic build failures without jobs.+enableProcessJobs :: CreateProcess -> CreateProcess+#ifdef MIN_VERSION_process+#if MIN_VERSION_process(1,6,8)+enableProcessJobs cp = cp {Process.use_process_jobs = True}+#else+enableProcessJobs cp = cp+#endif+#else+enableProcessJobs cp = cp+#endif++-------------------------------------------------------------------------------+-- process redefinitions+-------------------------------------------------------------------------------++-- | 'System.Process.createProcess' with process jobs enabled when appropriate.+-- See 'enableProcessJobs'.+createProcess :: CreateProcess+ -> IO (Maybe Handle, Maybe Handle, Maybe Handle, ProcessHandle)+createProcess = Process.createProcess . enableProcessJobs++-- | 'System.Process.rawSystem' with process jobs enabled when appropriate.+-- See 'enableProcessJobs'.+rawSystem :: String -> [String] -> IO ExitCode+rawSystem cmd args = do+#if MIN_VERSION_process(1,2,0)+ (_,_,_,p) <- createProcess (Process.proc cmd args) { Process.delegate_ctlc = True }+ waitForProcess p+#else+ -- With very old 'process', just do its rawSystem+ Process.rawSystem cmd args+#endif++-- | 'System.Process.runInteractiveProcess' with process jobs enabled when+-- appropriate. See 'enableProcessJobs'.+runInteractiveProcess+ :: FilePath -- ^ Filename of the executable (see 'RawCommand' for details)+ -> [String] -- ^ Arguments to pass to the executable+ -> Maybe FilePath -- ^ Optional path to the working directory+ -> Maybe [(String,String)] -- ^ Optional environment (otherwise inherit)+ -> IO (Handle,Handle,Handle,ProcessHandle)+runInteractiveProcess cmd args mb_cwd mb_env = do+ (mb_in, mb_out, mb_err, p) <-+ createProcess (Process.proc cmd args)+ { Process.std_in = Process.CreatePipe,+ Process.std_out = Process.CreatePipe,+ Process.std_err = Process.CreatePipe,+ Process.env = mb_env,+ Process.cwd = mb_cwd }+ return (fromJust mb_in, fromJust mb_out, fromJust mb_err, p)+ where+ fromJust = maybe (error "runInteractiveProcess: fromJust") id
cabal/Cabal/Distribution/Compat/ResponseFile.hs view
@@ -1,68 +1,67 @@-{-# LANGUAGE CPP, RankNTypes, FlexibleContexts #-} - --- Compatibility layer for GHC.ResponseFile --- Implementation from base 4.12.0 is used. --- http://hackage.haskell.org/package/base-4.12.0.0/src/LICENSE -module Distribution.Compat.ResponseFile (expandResponse) where - -import Prelude (mapM) -import Distribution.Compat.Prelude - -import System.Exit -import System.FilePath -import System.IO (hPutStrLn, stderr) -import System.IO.Error - -#if MIN_VERSION_base(4,12,0) -import GHC.ResponseFile (unescapeArgs) -#else - -unescapeArgs :: String -> [String] -unescapeArgs = filter (not . null) . unescape - -data Quoting = NoneQ | SngQ | DblQ - -unescape :: String -> [String] -unescape args = reverse . map reverse $ go args NoneQ False [] [] - where - -- n.b., the order of these cases matters; these are cribbed from gcc - -- case 1: end of input - go [] _q _bs a as = a:as - -- case 2: back-slash escape in progress - go (c:cs) q True a as = go cs q False (c:a) as - -- case 3: no back-slash escape in progress, but got a back-slash - go (c:cs) q False a as - | '\\' == c = go cs q True a as - -- case 4: single-quote escaping in progress - go (c:cs) SngQ False a as - | '\'' == c = go cs NoneQ False a as - | otherwise = go cs SngQ False (c:a) as - -- case 5: double-quote escaping in progress - go (c:cs) DblQ False a as - | '"' == c = go cs NoneQ False a as - | otherwise = go cs DblQ False (c:a) as - -- case 6: no escaping is in progress - go (c:cs) NoneQ False a as - | isSpace c = go cs NoneQ False [] (a:as) - | '\'' == c = go cs SngQ False a as - | '"' == c = go cs DblQ False a as - | otherwise = go cs NoneQ False (c:a) as - -#endif - -expandResponse :: [String] -> IO [String] -expandResponse = go recursionLimit "." - where - recursionLimit = 100 - - go :: Int -> FilePath -> [String] -> IO [String] - go n dir - | n >= 0 = fmap concat . mapM (expand n dir) - | otherwise = const $ hPutStrLn stderr "Error: response file recursion limit exceeded." >> exitFailure - - expand :: Int -> FilePath -> String -> IO [String] - expand n dir arg@('@':f) = readRecursively n (dir </> f) `catchIOError` (const $ print "?" >> return [arg]) - expand _n _dir x = return [x] - - readRecursively :: Int -> FilePath -> IO [String] - readRecursively n f = go (n - 1) (takeDirectory f) =<< unescapeArgs <$> readFile f +{-# LANGUAGE CPP, RankNTypes, FlexibleContexts #-}++-- Compatibility layer for GHC.ResponseFile+-- Implementation from base 4.12.0 is used.+-- http://hackage.haskell.org/package/base-4.12.0.0/src/LICENSE+module Distribution.Compat.ResponseFile (expandResponse) where++import Distribution.Compat.Prelude+import Prelude ()++import System.FilePath+import System.IO (hPutStrLn, stderr)+import System.IO.Error++#if MIN_VERSION_base(4,12,0)+import GHC.ResponseFile (unescapeArgs)+#else++unescapeArgs :: String -> [String]+unescapeArgs = filter (not . null) . unescape++data Quoting = NoneQ | SngQ | DblQ++unescape :: String -> [String]+unescape args = reverse . map reverse $ go args NoneQ False [] []+ where+ -- n.b., the order of these cases matters; these are cribbed from gcc+ -- case 1: end of input+ go [] _q _bs a as = a:as+ -- case 2: back-slash escape in progress+ go (c:cs) q True a as = go cs q False (c:a) as+ -- case 3: no back-slash escape in progress, but got a back-slash+ go (c:cs) q False a as+ | '\\' == c = go cs q True a as+ -- case 4: single-quote escaping in progress+ go (c:cs) SngQ False a as+ | '\'' == c = go cs NoneQ False a as+ | otherwise = go cs SngQ False (c:a) as+ -- case 5: double-quote escaping in progress+ go (c:cs) DblQ False a as+ | '"' == c = go cs NoneQ False a as+ | otherwise = go cs DblQ False (c:a) as+ -- case 6: no escaping is in progress+ go (c:cs) NoneQ False a as+ | isSpace c = go cs NoneQ False [] (a:as)+ | '\'' == c = go cs SngQ False a as+ | '"' == c = go cs DblQ False a as+ | otherwise = go cs NoneQ False (c:a) as++#endif++expandResponse :: [String] -> IO [String]+expandResponse = go recursionLimit "."+ where+ recursionLimit = 100++ go :: Int -> FilePath -> [String] -> IO [String]+ go n dir+ | n >= 0 = fmap concat . traverse (expand n dir)+ | otherwise = const $ hPutStrLn stderr "Error: response file recursion limit exceeded." >> exitFailure++ expand :: Int -> FilePath -> String -> IO [String]+ expand n dir arg@('@':f) = readRecursively n (dir </> f) `catchIOError` (const $ print "?" >> return [arg])+ expand _n _dir x = return [x]++ readRecursively :: Int -> FilePath -> IO [String]+ readRecursively n f = go (n - 1) (takeDirectory f) =<< unescapeArgs <$> readFile f
cabal/Cabal/Distribution/Compat/Semigroup.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE CPP #-}+{-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-}@@ -21,6 +22,8 @@ ) where import Distribution.Compat.Binary (Binary)+import Distribution.Utils.Structured (Structured)+import Data.Typeable (Typeable) import GHC.Generics -- Data.Semigroup is available since GHC 8.0/base-4.9 in `base`@@ -38,8 +41,10 @@ -- | A copy of 'Data.Semigroup.Last'. newtype Last' a = Last' { getLast' :: a }- deriving (Eq, Ord, Read, Show, Binary)+ deriving (Eq, Ord, Read, Show, Generic, Binary, Typeable) +instance Structured a => Structured (Last' a)+ instance Semigroup (Last' a) where _ <> b = b @@ -49,7 +54,9 @@ -- | A wrapper around 'Maybe', providing the 'Semigroup' and 'Monoid' instances -- implemented for 'Maybe' since @base-4.11@. newtype Option' a = Option' { getOption' :: Maybe a }- deriving (Eq, Ord, Read, Show, Binary, Functor)+ deriving (Eq, Ord, Read, Show, Binary, Generic, Functor, Typeable)++instance Structured a => Structured (Option' a) instance Semigroup a => Semigroup (Option' a) where Option' (Just a) <> Option' (Just b) = Option' (Just (a <> b))
cabal/Cabal/Distribution/Compat/Time.hs view
@@ -1,4 +1,6 @@ {-# LANGUAGE CPP #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE FlexibleContexts #-}@@ -55,8 +57,10 @@ -- | An opaque type representing a file's modification time, represented -- internally as a 64-bit unsigned integer in the Windows UTC format. newtype ModTime = ModTime Word64- deriving (Binary, Bounded, Eq, Ord)+ deriving (Binary, Generic, Bounded, Eq, Ord, Typeable) +instance Structured ModTime+ instance Show ModTime where show (ModTime x) = show x @@ -68,7 +72,7 @@ -- -- This is a modified version of the code originally written for Shake by Neil -- Mitchell. See module Development.Shake.FileInfo.-getModTime :: FilePath -> NoCallStackIO ModTime+getModTime :: FilePath -> IO ModTime #if defined mingw32_HOST_OS @@ -106,7 +110,7 @@ foreign import CALLCONV "windows.h GetFileAttributesExW" c_getFileAttributesEx :: LPCTSTR -> Int32 -> LPVOID -> Prelude.IO BOOL -getFileAttributesEx :: String -> LPVOID -> NoCallStackIO BOOL+getFileAttributesEx :: String -> LPVOID -> IO BOOL getFileAttributesEx path lpFileInformation = withTString path $ \c_path -> c_getFileAttributesEx c_path getFileExInfoStandard lpFileInformation@@ -150,14 +154,14 @@ + (secToUnixEpoch * windowsTick) -- | Return age of given file in days.-getFileAge :: FilePath -> NoCallStackIO Double+getFileAge :: FilePath -> IO Double getFileAge file = do t0 <- getModificationTime file t1 <- getCurrentTime return $ realToFrac (t1 `diffUTCTime` t0) / realToFrac posixDayLength -- | Return the current time as 'ModTime'.-getCurTime :: NoCallStackIO ModTime+getCurTime :: IO ModTime getCurTime = posixTimeToModTime `fmap` getPOSIXTime -- Uses 'gettimeofday'. -- | Based on code written by Neil Mitchell for Shake. See
+ cabal/Cabal/Distribution/Compat/Typeable.hs view
@@ -0,0 +1,18 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE ScopedTypeVariables #-}+module Distribution.Compat.Typeable (+ Typeable,+ TypeRep,+ typeRep,+ ) where++#if MIN_VERSION_base(4,7,0)+import Data.Typeable (Typeable, TypeRep, typeRep)+#else+import Data.Typeable (Typeable, TypeRep, typeOf)+#endif++#if !MIN_VERSION_base(4,7,0)+typeRep :: forall a proxy. Typeable a => proxy a -> TypeRep+typeRep _ = typeOf (undefined :: a)+#endif
cabal/Cabal/Distribution/Compiler.hs view
@@ -1,5 +1,8 @@ {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE DeriveFoldable #-}+{-# LANGUAGE DeriveTraversable #-} ----------------------------------------------------------------------------- -- |@@ -66,7 +69,7 @@ deriving (Generic, Show, Read, Eq, Ord, Typeable, Data) instance Binary CompilerFlavor-+instance Structured CompilerFlavor instance NFData CompilerFlavor where rnf = genericRnf knownCompilerFlavors :: [CompilerFlavor]@@ -122,9 +125,11 @@ -- Cabal parses only @ghc-options@ and @ghcjs-options@, others are omitted. -- data PerCompilerFlavor v = PerCompilerFlavor v v- deriving (Generic, Show, Read, Eq, Typeable, Data)+ deriving (Generic, Show, Read, Eq, Typeable, Data, Functor, Foldable+ , Traversable) instance Binary a => Binary (PerCompilerFlavor a)+instance Structured a => Structured (PerCompilerFlavor a) instance NFData a => NFData (PerCompilerFlavor a) perCompilerFlavorToList :: PerCompilerFlavor v -> [(CompilerFlavor, v)]@@ -143,10 +148,10 @@ -- ------------------------------------------------------------ data CompilerId = CompilerId CompilerFlavor Version- deriving (Eq, Generic, Ord, Read, Show)+ deriving (Eq, Generic, Ord, Read, Show, Typeable) instance Binary CompilerId-+instance Structured CompilerId instance NFData CompilerId where rnf = genericRnf instance Pretty CompilerId where@@ -192,9 +197,10 @@ data AbiTag = NoAbiTag | AbiTag String- deriving (Eq, Generic, Show, Read)+ deriving (Eq, Generic, Show, Read, Typeable) instance Binary AbiTag+instance Structured AbiTag instance Pretty AbiTag where pretty NoAbiTag = Disp.empty
cabal/Cabal/Distribution/FieldGrammar.hs view
@@ -25,6 +25,9 @@ takeFields, runFieldParser, runFieldParser',+ defaultFreeTextFieldDefST,+ -- * Newtypes+ module Distribution.FieldGrammar.Newtypes, ) where import Distribution.Compat.Prelude@@ -33,10 +36,11 @@ import qualified Data.Map.Strict as Map import Distribution.FieldGrammar.Class+import Distribution.FieldGrammar.Newtypes import Distribution.FieldGrammar.Parsec import Distribution.FieldGrammar.Pretty import Distribution.Fields.Field-import Distribution.Utils.Generic (spanMaybe)+import Distribution.Utils.Generic (spanMaybe) type ParsecFieldGrammar' a = ParsecFieldGrammar a a type PrettyFieldGrammar' a = PrettyFieldGrammar a a
cabal/Cabal/Distribution/FieldGrammar/Class.hs view
@@ -1,20 +1,31 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FunctionalDependencies #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+#if __GLASGOW_HASKELL__ >= 800+{-# LANGUAGE UndecidableSuperClasses #-}+#else+{-# LANGUAGE UndecidableInstances #-}+#endif module Distribution.FieldGrammar.Class ( FieldGrammar (..), uniqueField, optionalField, optionalFieldDef, monoidalField,- ) where+ defaultFreeTextFieldDefST,+) where import Distribution.Compat.Lens import Distribution.Compat.Prelude import Prelude () -import Distribution.CabalSpecVersion (CabalSpecVersion)-import Distribution.Compat.Newtype (Newtype)+import Distribution.CabalSpecVersion (CabalSpecVersion)+import Distribution.Compat.Newtype (Newtype)+import Distribution.FieldGrammar.Newtypes import Distribution.Fields.Field-import Distribution.Parsec (Parsec)-import Distribution.Pretty (Pretty)+import Distribution.Utils.ShortText -- | 'FieldGrammar' is parametrised by --@@ -25,13 +36,17 @@ -- -- /Note:/ We'd like to have @forall s. Applicative (f s)@ context. ---class FieldGrammar g where+class+ ( c SpecVersion, c TestedWith, c SpecLicense, c Token, c Token', c FilePathNT+ )+ => FieldGrammar c g | g -> c+ where -- | Unfocus, zoom out, /blur/ 'FieldGrammar'.- blurFieldGrammar :: ALens' a b -> g b c -> g a c+ blurFieldGrammar :: ALens' a b -> g b d -> g a d -- | Field which should be defined, exactly once. uniqueFieldAla- :: (Parsec b, Pretty b, Newtype a b)+ :: (c b, Newtype a b) => FieldName -- ^ field name -> (a -> b) -- ^ 'Newtype' pack -> ALens' s a -- ^ lens into the field@@ -46,7 +61,7 @@ -- | Optional field. optionalFieldAla- :: (Parsec b, Pretty b, Newtype a b)+ :: (c b, Newtype a b) => FieldName -- ^ field name -> (a -> b) -- ^ 'pack' -> ALens' s (Maybe a) -- ^ lens into the field@@ -54,7 +69,7 @@ -- | Optional field with default value. optionalFieldDefAla- :: (Parsec b, Pretty b, Newtype a b, Eq a)+ :: (c b, Newtype a b, Eq a) => FieldName -- ^ field name -> (a -> b) -- ^ 'Newtype' pack -> ALens' s a -- ^ @'Lens'' s a@: lens into the field@@ -79,6 +94,12 @@ -> ALens' s String -- ^ lens into the field -> g s String + -- | @since 3.2.0.0+ freeTextFieldDefST+ :: FieldName+ -> ALens' s ShortText -- ^ lens into the field+ -> g s ShortText+ -- | Monoidal field. -- -- Values are combined with 'mappend'.@@ -86,7 +107,7 @@ -- /Note:/ 'optionalFieldAla' is a @monoidalField@ with 'Last' monoid. -- monoidalFieldAla- :: (Parsec b, Pretty b, Monoid a, Newtype a b)+ :: (c b, Monoid a, Newtype a b) => FieldName -- ^ field name -> (a -> b) -- ^ 'pack' -> ALens' s a -- ^ lens into the field@@ -127,33 +148,45 @@ -- | Field which can be defined at most once. uniqueField- :: (FieldGrammar g, Parsec a, Pretty a)+ :: (FieldGrammar c g, c (Identity a)) => FieldName -- ^ field name -> ALens' s a -- ^ lens into the field -> g s a-uniqueField fn = uniqueFieldAla fn Identity+uniqueField fn l = uniqueFieldAla fn Identity l -- | Field which can be defined at most once. optionalField- :: (FieldGrammar g, Parsec a, Pretty a)+ :: (FieldGrammar c g, c (Identity a)) => FieldName -- ^ field name -> ALens' s (Maybe a) -- ^ lens into the field -> g s (Maybe a)-optionalField fn = optionalFieldAla fn Identity+optionalField fn l = optionalFieldAla fn Identity l -- | Optional field with default value. optionalFieldDef- :: (FieldGrammar g, Functor (g s), Parsec a, Pretty a, Eq a)+ :: (FieldGrammar c g, Functor (g s), c (Identity a), Eq a) => FieldName -- ^ field name -> ALens' s a -- ^ @'Lens'' s a@: lens into the field -> a -- ^ default value -> g s a-optionalFieldDef fn = optionalFieldDefAla fn Identity+optionalFieldDef fn l x = optionalFieldDefAla fn Identity l x -- | Field which can be define multiple times, and the results are @mappend@ed. monoidalField- :: (FieldGrammar g, Parsec a, Pretty a, Monoid a)+ :: (FieldGrammar c g, c (Identity a), Monoid a) => FieldName -- ^ field name -> ALens' s a -- ^ lens into the field -> g s a-monoidalField fn = monoidalFieldAla fn Identity+monoidalField fn l = monoidalFieldAla fn Identity l++-- | Default implementation for 'freeTextFieldDefST'.+defaultFreeTextFieldDefST+ :: (Functor (g s), FieldGrammar c g)+ => FieldName+ -> ALens' s ShortText -- ^ lens into the field+ -> g s ShortText+defaultFreeTextFieldDefST fn l =+ toShortText <$> freeTextFieldDef fn (cloneLens l . st)+ where+ st :: Lens' ShortText String+ st f s = toShortText <$> f (fromShortText s)
cabal/Cabal/Distribution/FieldGrammar/FieldDescrs.hs view
@@ -1,6 +1,9 @@-{-# LANGUAGE DeriveFunctor #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE NoMonoLocalBinds #-}+{-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE NoMonoLocalBinds #-} module Distribution.FieldGrammar.FieldDescrs ( FieldDescrs, fieldDescrPretty,@@ -15,7 +18,7 @@ import Distribution.Compat.Lens (aview, cloneLens) import Distribution.Compat.Newtype import Distribution.FieldGrammar-import Distribution.Pretty (pretty, showFreeText)+import Distribution.Pretty (Pretty (..), showFreeText) import qualified Data.Map as Map import qualified Distribution.Compat.CharParsing as C@@ -46,7 +49,7 @@ -- | Lookup a field value parser. fieldDescrParse :: P.CabalParsing m => FieldDescrs s a -> P.FieldName -> Maybe (s -> m s)-fieldDescrParse (F m) fn = pParse <$> Map.lookup fn m+fieldDescrParse (F m) fn = (\f -> pParse f) <$> Map.lookup fn m fieldDescrsToList :: P.CabalParsing m@@ -56,7 +59,7 @@ mk (name, SP ppr parse) = (name, ppr, parse) -- | /Note:/ default values are printed.-instance FieldGrammar FieldDescrs where+instance FieldGrammar ParsecPretty FieldDescrs where blurFieldGrammar l (F m) = F (fmap blur m) where blur (SP f g) = SP (f . aview l) (cloneLens l g) @@ -85,6 +88,8 @@ f s = showFreeText (aview l s) g s = cloneLens l (const parsecFreeText) s + freeTextFieldDefST = defaultFreeTextFieldDefST+ monoidalFieldAla fn _pack l = singletonF fn f g where f s = pretty (pack' _pack (aview l s)) g s = cloneLens l (\x -> mappend x . unpack' _pack <$> P.parsec) s@@ -112,3 +117,6 @@ trim :: String -> String trim = dropWhile isSpace . dropWhileEnd isSpace++class (P.Parsec a, Pretty a) => ParsecPretty a+instance (P.Parsec a, Pretty a) => ParsecPretty a
+ cabal/Cabal/Distribution/FieldGrammar/Newtypes.hs view
@@ -0,0 +1,339 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FunctionalDependencies #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+-- | This module provides @newtype@ wrappers to be used with "Distribution.FieldGrammar".+module Distribution.FieldGrammar.Newtypes (+ -- * List+ alaList,+ alaList',+ -- ** Modifiers+ CommaVCat (..),+ CommaFSep (..),+ VCat (..),+ FSep (..),+ NoCommaFSep (..),+ Sep (..),+ -- ** Type+ List,+ -- * Set+ alaSet,+ alaSet',+ Set',+ -- * Version & License+ SpecVersion (..),+ TestedWith (..),+ SpecLicense (..),+ -- * Identifiers+ Token (..),+ Token' (..),+ MQuoted (..),+ FilePathNT (..),+ ) where++import Distribution.Compat.Newtype+import Distribution.Compat.Prelude+import Prelude ()++import Distribution.CabalSpecVersion+import Distribution.Compiler (CompilerFlavor)+import Distribution.License (License)+import Distribution.Parsec+import Distribution.Pretty+import Distribution.Version+ (LowerBound (..), Version, VersionRange, VersionRangeF (..), anyVersion, asVersionIntervals, cataVersionRange, mkVersion, version0, versionNumbers)+import Text.PrettyPrint (Doc, comma, fsep, punctuate, text, vcat)++import qualified Data.Set as Set+import qualified Distribution.Compat.CharParsing as P+import qualified Distribution.SPDX as SPDX++-- | Vertical list with commas. Displayed with 'vcat'+data CommaVCat = CommaVCat++-- | Paragraph fill list with commas. Displayed with 'fsep'+data CommaFSep = CommaFSep++-- | Vertical list with optional commas. Displayed with 'vcat'.+data VCat = VCat++-- | Paragraph fill list with optional commas. Displayed with 'fsep'.+data FSep = FSep++-- | Paragraph fill list without commas. Displayed with 'fsep'.+data NoCommaFSep = NoCommaFSep++class Sep sep where+ prettySep :: Proxy sep -> [Doc] -> Doc++ parseSep :: CabalParsing m => Proxy sep -> m a -> m [a]++instance Sep CommaVCat where+ prettySep _ = vcat . punctuate comma+ parseSep _ p = do+ v <- askCabalSpecVersion+ if v >= CabalSpecV2_2 then parsecLeadingCommaList p else parsecCommaList p+instance Sep CommaFSep where+ prettySep _ = fsep . punctuate comma+ parseSep _ p = do+ v <- askCabalSpecVersion+ if v >= CabalSpecV2_2 then parsecLeadingCommaList p else parsecCommaList p+instance Sep VCat where+ prettySep _ = vcat+ parseSep _ p = do+ v <- askCabalSpecVersion+ if v >= CabalSpecV3_0 then parsecLeadingOptCommaList p else parsecOptCommaList p+instance Sep FSep where+ prettySep _ = fsep+ parseSep _ p = do+ v <- askCabalSpecVersion+ if v >= CabalSpecV3_0 then parsecLeadingOptCommaList p else parsecOptCommaList p+instance Sep NoCommaFSep where+ prettySep _ = fsep+ parseSep _ p = many (p <* P.spaces)++-- | List separated with optional commas. Displayed with @sep@, arguments of+-- type @a@ are parsed and pretty-printed as @b@.+newtype List sep b a = List { _getList :: [a] }++-- | 'alaList' and 'alaList'' are simply 'List', with additional phantom+-- arguments to constraint the resulting type+--+-- >>> :t alaList VCat+-- alaList VCat :: [a] -> List VCat (Identity a) a+--+-- >>> :t alaList' FSep Token+-- alaList' FSep Token :: [String] -> List FSep Token String+--+alaList :: sep -> [a] -> List sep (Identity a) a+alaList _ = List++-- | More general version of 'alaList'.+alaList' :: sep -> (a -> b) -> [a] -> List sep b a+alaList' _ _ = List++instance Newtype [a] (List sep wrapper a)++instance (Newtype a b, Sep sep, Parsec b) => Parsec (List sep b a) where+ parsec = pack . map (unpack :: b -> a) <$> parseSep (Proxy :: Proxy sep) parsec++instance (Newtype a b, Sep sep, Pretty b) => Pretty (List sep b a) where+ pretty = prettySep (Proxy :: Proxy sep) . map (pretty . (pack :: a -> b)) . unpack++--+-- | Like 'List', but for 'Set'.+--+-- @since 3.2.0.0+newtype Set' sep b a = Set' { _getSet :: Set a }++-- | 'alaSet' and 'alaSet'' are simply 'Set'' constructor, with additional phantom+-- arguments to constraint the resulting type+--+-- >>> :t alaSet VCat+-- alaSet VCat :: Set a -> Set' VCat (Identity a) a+--+-- >>> :t alaSet' FSep Token+-- alaSet' FSep Token :: Set String -> Set' FSep Token String+--+-- >>> unpack' (alaSet' FSep Token) <$> eitherParsec "foo bar foo"+-- Right (fromList ["bar","foo"])+--+-- @since 3.2.0.0+alaSet :: sep -> Set a -> Set' sep (Identity a) a+alaSet _ = Set'++-- | More general version of 'alaSet'.+--+-- @since 3.2.0.0+alaSet' :: sep -> (a -> b) -> Set a -> Set' sep b a+alaSet' _ _ = Set'++instance Newtype (Set a) (Set' sep wrapper a)++instance (Newtype a b, Ord a, Sep sep, Parsec b) => Parsec (Set' sep b a) where+ parsec = pack . Set.fromList . map (unpack :: b -> a) <$> parseSep (Proxy :: Proxy sep) parsec++instance (Newtype a b, Sep sep, Pretty b) => Pretty (Set' sep b a) where+ pretty = prettySep (Proxy :: Proxy sep) . map (pretty . (pack :: a -> b)) . Set.toList . unpack++-------------------------------------------------------------------------------+-- Identifiers+-------------------------------------------------------------------------------++-- | Haskell string or @[^ ,]+@+newtype Token = Token { getToken :: String }++instance Newtype String Token++instance Parsec Token where+ parsec = pack <$> parsecToken++instance Pretty Token where+ pretty = showToken . unpack++-- | Haskell string or @[^ ]+@+newtype Token' = Token' { getToken' :: String }++instance Newtype String Token'++instance Parsec Token' where+ parsec = pack <$> parsecToken'++instance Pretty Token' where+ pretty = showToken . unpack++-- | Either @"quoted"@ or @un-quoted@.+newtype MQuoted a = MQuoted { getMQuoted :: a }++instance Newtype a (MQuoted a)++instance Parsec a => Parsec (MQuoted a) where+ parsec = pack <$> parsecMaybeQuoted parsec++instance Pretty a => Pretty (MQuoted a) where+ pretty = pretty . unpack++-- | Filepath are parsed as 'Token'.+newtype FilePathNT = FilePathNT { getFilePathNT :: String }++instance Newtype String FilePathNT++instance Parsec FilePathNT where+ parsec = pack <$> parsecToken++instance Pretty FilePathNT where+ pretty = showFilePath . unpack++-------------------------------------------------------------------------------+-- SpecVersion+-------------------------------------------------------------------------------++-- | Version range or just version, i.e. @cabal-version@ field.+--+-- There are few things to consider:+--+-- * Starting with 2.2 the cabal-version field should be the first field in the+-- file and only exact version is accepted. Therefore if we get e.g.+-- @>= 2.2@, we fail.+-- See <https://github.com/haskell/cabal/issues/4899>+--+-- We have this newtype, as writing Parsec and Pretty instances+-- for CabalSpecVersion would cause cycle in modules:+-- Version -> CabalSpecVersion -> Parsec -> ...+--+newtype SpecVersion = SpecVersion { getSpecVersion :: CabalSpecVersion }+ deriving (Eq, Show) -- instances needed for tests++instance Newtype CabalSpecVersion SpecVersion++instance Parsec SpecVersion where+ parsec = do+ e <- parsecSpecVersion+ let ver :: Version+ ver = either id specVersionFromRange e++ digits :: [Int]+ digits = versionNumbers ver++ case cabalSpecFromVersionDigits digits of+ Nothing -> fail $ "Unknown cabal spec version specified: " ++ prettyShow ver+ Just csv -> do+ -- Check some warnings:+ case e of+ -- example: cabal-version: 1.10+ -- should be cabal-version: >=1.10+ Left _v | csv < CabalSpecV1_12 -> parsecWarning PWTSpecVersion $ concat+ [ "With 1.10 or earlier, the 'cabal-version' field must use "+ , "range syntax rather than a simple version number. Use "+ , "'cabal-version: >= " ++ prettyShow ver ++ "'."+ ]++ -- example: cabal-version: >=1.12+ -- should be cabal-version: 1.12+ Right _vr | csv >= CabalSpecV1_12 -> parsecWarning PWTSpecVersion $ concat+ [ "Packages with 'cabal-version: 1.12' or later should specify a "+ , "specific version of the Cabal spec of the form "+ , "'cabal-version: x.y'. "+ , "Use 'cabal-version: " ++ prettyShow ver ++ "'."+ ]++ -- example: cabal-version: >=1.10 && <1.12+ -- should be cabal-version: >=1.10+ Right vr | csv < CabalSpecV1_12+ , not (simpleSpecVersionRangeSyntax vr) -> parsecWarning PWTSpecVersion $ concat+ [ "It is recommended that the 'cabal-version' field only specify a "+ , "version range of the form '>= x.y' for older cabal versions. Use "+ , "'cabal-version: >= " ++ prettyShow ver ++ "'. "+ , "Tools based on Cabal 1.10 and later will ignore upper bounds."+ ]++ -- otherwise no warnings+ _ -> pure ()++ return (pack csv)+ where+ parsecSpecVersion = Left <$> parsec <|> Right <$> range++ range = do+ vr <- parsec+ if specVersionFromRange vr >= mkVersion [2,1]+ then fail "cabal-version higher than 2.2 cannot be specified as a range. See https://github.com/haskell/cabal/issues/4899"+ else return vr++ specVersionFromRange :: VersionRange -> Version+ specVersionFromRange versionRange = case asVersionIntervals versionRange of+ [] -> version0+ ((LowerBound version _, _):_) -> version++ simpleSpecVersionRangeSyntax = cataVersionRange alg where+ alg (OrLaterVersionF _) = True+ alg _ = False+++instance Pretty SpecVersion where+ pretty (SpecVersion csv)+ | csv >= CabalSpecV1_12 = text (showCabalSpecVersion csv)+ | otherwise = text ">=" <<>> text (showCabalSpecVersion csv)++-------------------------------------------------------------------------------+-- SpecLicense+-------------------------------------------------------------------------------++-- | SPDX License expression or legacy license+newtype SpecLicense = SpecLicense { getSpecLicense :: Either SPDX.License License }++instance Newtype (Either SPDX.License License) SpecLicense++instance Parsec SpecLicense where+ parsec = do+ v <- askCabalSpecVersion+ if v >= CabalSpecV2_2+ then SpecLicense . Left <$> parsec+ else SpecLicense . Right <$> parsec++instance Pretty SpecLicense where+ pretty = either pretty pretty . unpack++-------------------------------------------------------------------------------+-- TestedWith+-------------------------------------------------------------------------------++-- | Version range or just version+newtype TestedWith = TestedWith { getTestedWith :: (CompilerFlavor, VersionRange) }++instance Newtype (CompilerFlavor, VersionRange) TestedWith++instance Parsec TestedWith where+ parsec = pack <$> parsecTestedWith++instance Pretty TestedWith where+ pretty x = case unpack x of+ (compiler, vr) -> pretty compiler <+> pretty vr++parsecTestedWith :: CabalParsing m => m (CompilerFlavor, VersionRange)+parsecTestedWith = do+ name <- lexemeParsec+ ver <- parsec <|> pure anyVersion+ return (name, ver)
cabal/Cabal/Distribution/FieldGrammar/Parsec.hs view
@@ -1,6 +1,7 @@-{-# LANGUAGE DeriveFunctor #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-} -- | This module provides a 'FieldGrammarParser', one way to parse -- @.cabal@ -like files. --@@ -65,18 +66,18 @@ ) where import Data.List (dropWhileEnd)-import Data.Ord (comparing) import Distribution.Compat.Newtype import Distribution.Compat.Prelude import Distribution.Simple.Utils (fromUTF8BS) import Prelude () -import qualified Data.ByteString as BS-import qualified Data.List.NonEmpty as NE-import qualified Data.Map.Strict as Map-import qualified Data.Set as Set-import qualified Text.Parsec as P-import qualified Text.Parsec.Error as P+import qualified Data.ByteString as BS+import qualified Data.List.NonEmpty as NE+import qualified Data.Map.Strict as Map+import qualified Data.Set as Set+import qualified Distribution.Utils.ShortText as ShortText+import qualified Text.Parsec as P+import qualified Text.Parsec.Error as P import Distribution.CabalSpecVersion import Distribution.FieldGrammar.Class@@ -84,7 +85,7 @@ import Distribution.Fields.ParseResult import Distribution.Parsec import Distribution.Parsec.FieldLineStream-import Distribution.Parsec.Position (positionRow, positionCol)+import Distribution.Parsec.Position (positionCol, positionRow) ------------------------------------------------------------------------------- -- Auxiliary types@@ -150,7 +151,7 @@ parseWarning pos PWTMultipleSingularField $ "The field " <> show fn <> " is specified more than once at positions " ++ intercalate ", " (map showPos (pos : poss)) -instance FieldGrammar ParsecFieldGrammar where+instance FieldGrammar Parsec ParsecFieldGrammar where blurFieldGrammar _ (ParsecFG s s' parser) = ParsecFG s s' parser uniqueFieldAla fn _pack _extract = ParsecFG (Set.singleton fn) Set.empty parser@@ -233,6 +234,22 @@ | null fls = pure "" | v >= CabalSpecV3_0 = pure (fieldlinesToFreeText3 pos fls) | otherwise = pure (fieldlinesToFreeText fls)++ -- freeTextFieldDefST = defaultFreeTextFieldDefST+ freeTextFieldDefST fn _ = ParsecFG (Set.singleton fn) Set.empty parser where+ parser v fields = case Map.lookup fn fields of+ Nothing -> pure mempty+ Just [] -> pure mempty+ Just [x] -> parseOne v x+ Just xs@(_:y:ys) -> do+ warnMultipleSingularFields fn xs+ NE.last <$> traverse (parseOne v) (y:|ys)++ parseOne v (MkNamelessField pos fls) = case fls of+ [] -> pure mempty+ [FieldLine _ bs] -> pure (ShortText.unsafeFromUTF8BS bs)+ _ | v >= CabalSpecV3_0 -> pure (ShortText.toShortText $ fieldlinesToFreeText3 pos fls)+ | otherwise -> pure (ShortText.toShortText $ fieldlinesToFreeText fls) monoidalFieldAla fn _pack _extract = ParsecFG (Set.singleton fn) Set.empty parser where
cabal/Cabal/Distribution/FieldGrammar/Pretty.hs view
@@ -1,4 +1,5 @@-{-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE MultiParamTypeClasses #-} module Distribution.FieldGrammar.Pretty ( PrettyFieldGrammar, prettyFieldGrammar,@@ -33,7 +34,7 @@ prettyFieldGrammar :: CabalSpecVersion -> PrettyFieldGrammar s a -> s -> [PrettyField ()] prettyFieldGrammar = flip fieldGrammarPretty -instance FieldGrammar PrettyFieldGrammar where+instance FieldGrammar Pretty PrettyFieldGrammar where blurFieldGrammar f (PrettyFG pp) = PrettyFG (\v -> pp v . aview f) uniqueFieldAla fn _pack l = PrettyFG $ \_v s ->@@ -71,6 +72,8 @@ pp v s = ppField fn (showFT (aview l s)) where showFT | v >= CabalSpecV3_0 = showFreeTextV3 | otherwise = showFreeText++ freeTextFieldDefST = defaultFreeTextFieldDefST monoidalFieldAla fn _pack l = PrettyFG pp where
cabal/Cabal/Distribution/Fields/ConfVar.hs view
@@ -2,14 +2,14 @@ {-# LANGUAGE NoMonoLocalBinds #-} module Distribution.Fields.ConfVar (parseConditionConfVar) where -import Distribution.Compat.CharParsing (char, integral)+import Distribution.Compat.CharParsing (char, integral) import Distribution.Compat.Prelude-import Distribution.Parsec (Parsec (..), runParsecParser, Position (..))-import Distribution.Parsec.FieldLineStream (fieldLineStreamFromBS)-import Distribution.Fields.Field (SectionArg (..))+import Distribution.Fields.Field (SectionArg (..)) import Distribution.Fields.ParseResult+import Distribution.Parsec (Parsec (..), Position (..), runParsecParser)+import Distribution.Parsec.FieldLineStream (fieldLineStreamFromBS) import Distribution.Types.Condition-import Distribution.Types.ConfVar (ConfVar (..))+import Distribution.Types.ConfVar (ConfVar (..)) import Distribution.Version (anyVersion, earlierVersion, intersectVersionRanges, laterVersion, majorBoundVersion, mkVersion, noVersion, orEarlierVersion, orLaterVersion, thisVersion, unionVersionRanges,@@ -53,7 +53,7 @@ boolLiteral = Lit <$> boolLiteral' osCond = Var . OS <$ string "os" <*> parens fromParsec- flagCond = Var . Flag <$ string "flag" <*> parens fromParsec+ flagCond = Var . PackageFlag <$ string "flag" <*> parens fromParsec archCond = Var . Arch <$ string "arch" <*> parens fromParsec implCond = Var <$ string "impl" <*> parens implCond'
cabal/Cabal/Distribution/Fields/Field.hs view
@@ -73,7 +73,7 @@ -- | Section arguments, e.g. name of the library data SectionArg ann = SecArgName !ann !ByteString- -- ^ identifier, or omething which loos like number. Also many dot numbers, i.e. "7.6.3"+ -- ^ identifier, or something which looks like number. Also many dot numbers, i.e. "7.6.3" | SecArgStr !ann !ByteString -- ^ quoted string | SecArgOther !ann !ByteString
cabal/Cabal/Distribution/Fields/ParseResult.hs view
@@ -15,7 +15,8 @@ getCabalSpecVersion, setCabalSpecVersion, readAndParseFile,- parseString+ parseString,+ withoutWarnings, ) where import qualified Data.ByteString.Char8 as BS@@ -42,10 +43,20 @@ -> r } +-- Note: we have version here, as we could get any version. data PRState = PRState ![PWarning] ![PError] !(Maybe Version) emptyPRState :: PRState emptyPRState = PRState [] [] Nothing++-- | Forget 'ParseResult's warnings.+--+-- @since 3.4.0.0+withoutWarnings :: ParseResult a -> ParseResult a+withoutWarnings m = PR $ \s failure success ->+ unPR m s failure $ \ !s1 -> success (s1 `withWarningsOf` s)+ where+ withWarningsOf (PRState _ e v) (PRState w _ _) = PRState w e v -- | Destruct a 'ParseResult' into the emitted warnings and either -- a successful value or
cabal/Cabal/Distribution/Fields/Parser.hs view
@@ -27,7 +27,6 @@ #endif ) where -import Control.Monad (guard) import qualified Data.ByteString.Char8 as B8 import Data.Functor.Identity import Distribution.Compat.Prelude
cabal/Cabal/Distribution/Fields/Pretty.hs view
@@ -45,11 +45,21 @@ -- between comment lines. -- showFields :: (ann -> [String]) -> [PrettyField ann] -> String-showFields rann = showFields' rann 4+showFields rann = showFields' rann (const id) 4 -- | 'showFields' with user specified indentation.-showFields' :: (ann -> [String]) -> Int -> [PrettyField ann] -> String-showFields' rann n = unlines . renderFields (Opts rann indent) where+showFields'+ :: (ann -> [String])+ -- ^ Convert an annotation to lined to preceed the field or section.+ -> (ann -> [String] -> [String])+ -- ^ Post-process non-annotation produced lines.+ -> Int+ -- ^ Indentation level.+ -> [PrettyField ann]+ -- ^ Fields/sections to show.+ -> String+showFields' rann post n = unlines . renderFields (Opts rann indent post)+ where -- few hardcoded, "unrolled" variants. indent | n == 4 = indent4 | n == 2 = indent2@@ -63,7 +73,11 @@ indent2 [] = [] indent2 xs = ' ' : ' ' : xs -data Opts ann = Opts (ann -> [String]) (String -> String)+data Opts ann = Opts+ { _optAnnotation ::(ann -> [String])+ , _optIndent ::(String -> String)+ , _optPostprocess :: ann -> [String] -> [String]+ } renderFields :: Opts ann -> [PrettyField ann] -> [String] renderFields opts fields = flattenBlocks $ map (renderField opts len) fields@@ -97,8 +111,8 @@ | otherwise = id renderField :: Opts ann -> Int -> PrettyField ann -> Block-renderField (Opts rann indent) fw (PrettyField ann name doc) =- Block before after $ comments ++ lines'+renderField (Opts rann indent post) fw (PrettyField ann name doc) =+ Block before after $ comments ++ post ann lines' where comments = rann ann before = if null comments then NoMargin else Margin@@ -115,10 +129,10 @@ narrowStyle :: PP.Style narrowStyle = PP.style { PP.lineLength = PP.lineLength PP.style - fw } -renderField opts@(Opts rann indent) _ (PrettySection ann name args fields) = Block Margin Margin $+renderField opts@(Opts rann indent post) _ (PrettySection ann name args fields) = Block Margin Margin $ rann ann- ++ - [ PP.render $ PP.hsep $ PP.text (fromUTF8BS name) : args ]+ +++ post ann [ PP.render $ PP.hsep $ PP.text (fromUTF8BS name) : args ] ++ (map indent $ renderFields opts fields)
cabal/Cabal/Distribution/InstalledPackageInfo.hs view
@@ -52,6 +52,8 @@ import Distribution.Types.ComponentName import Distribution.Utils.Generic (toUTF8BS) +import Data.ByteString (ByteString)+ import qualified Data.Map as Map import qualified Distribution.Fields as P import qualified Text.PrettyPrint as Disp@@ -59,7 +61,8 @@ import Distribution.Types.InstalledPackageInfo import Distribution.Types.InstalledPackageInfo.FieldGrammar -+-- $setup+-- >>> :set -XOverloadedStrings installedComponentId :: InstalledPackageInfo -> ComponentId installedComponentId ipi =@@ -91,17 +94,19 @@ -- Parsing -- | Return either errors, or IPI with list of warnings------ /Note:/ errors array /may/ be empty, but the parse is still failed (it's a bug though) parseInstalledPackageInfo- :: String+ :: ByteString -> Either (NonEmpty String) ([String], InstalledPackageInfo)-parseInstalledPackageInfo s = case P.readFields (toUTF8BS s) of+parseInstalledPackageInfo s = case P.readFields s of Left err -> Left (show err :| []) Right fs -> case partitionFields fs of (fs', _) -> case P.runParseResult $ parseFieldGrammar cabalSpecLatest fs' ipiFieldGrammar of- (ws, Right x) -> Right (ws', x) where- ws' = map (P.showPWarning "") ws+ (ws, Right x) -> x `deepseq` Right (ws', x) where+ ws' = [ P.showPWarning "" w+ | w@(P.PWarning wt _ _) <- ws+ -- filter out warnings about experimental features+ , wt /= P.PWTExperimental+ ] (_, Left (_, errs)) -> Left errs' where errs' = fmap (P.showPError "") errs
cabal/Cabal/Distribution/License.hs view
@@ -128,7 +128,7 @@ deriving (Generic, Read, Show, Eq, Typeable, Data) instance Binary License-+instance Structured License instance NFData License where rnf = genericRnf -- | The list of all currently recognised licenses.
cabal/Cabal/Distribution/Make.hs view
@@ -67,7 +67,6 @@ import Distribution.Compat.Prelude -- local-import Distribution.Compat.Exception import Distribution.Package import Distribution.Simple.Program import Distribution.Simple.Setup@@ -80,7 +79,6 @@ import Distribution.Pretty import System.Environment (getArgs, getProgName)-import System.Exit defaultMain :: IO () defaultMain = getArgs >>= defaultMainArgs
cabal/Cabal/Distribution/ModuleName.hs view
@@ -1,6 +1,7 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE ScopedTypeVariables #-} ----------------------------------------------------------------------------- -- | -- Module : Distribution.ModuleName@@ -13,7 +14,7 @@ -- Data type for Haskell module names. module Distribution.ModuleName (- ModuleName (..), -- TODO: move Parsec instance here, don't export constructor+ ModuleName, fromString, fromComponents, components,@@ -23,47 +24,70 @@ validModuleComponent, ) where -import Prelude () import Distribution.Compat.Prelude--import Distribution.Utils.ShortText-import System.FilePath ( pathSeparator )+import Prelude () -import Distribution.Pretty import Distribution.Parsec+import Distribution.Pretty+import Distribution.Utils.ShortText (ShortText, fromShortText, toShortText)+import System.FilePath (pathSeparator) import qualified Distribution.Compat.CharParsing as P-import qualified Text.PrettyPrint as Disp+import qualified Distribution.Compat.DList as DList+import qualified Text.PrettyPrint as Disp -- | A valid Haskell module name. ---newtype ModuleName = ModuleName ShortTextLst+newtype ModuleName = ModuleName ShortText deriving (Eq, Generic, Ord, Read, Show, Typeable, Data) +unModuleName :: ModuleName -> String+unModuleName (ModuleName s) = fromShortText s+ instance Binary ModuleName+instance Structured ModuleName instance NFData ModuleName where rnf (ModuleName ms) = rnf ms instance Pretty ModuleName where- pretty (ModuleName ms) =- Disp.hcat (intersperse (Disp.char '.') (map Disp.text $ stlToStrings ms))+ pretty = Disp.text . unModuleName instance Parsec ModuleName where- parsec = fromComponents <$> toList <$> P.sepByNonEmpty component (P.char '.')- where- component = do- c <- P.satisfy isUpper- cs <- P.munch validModuleChar- return (c:cs)+ parsec = parsecModuleName +parsecModuleName :: forall m. CabalParsing m => m ModuleName+parsecModuleName = state0 DList.empty where+ upper :: m Char+ !upper = P.satisfy isUpper++ ch :: m Char+ !ch = P.satisfy (\c -> validModuleChar c || c == '.')++ alt :: m ModuleName -> m ModuleName -> m ModuleName+ !alt = (<|>)++ state0 :: DList.DList Char -> m ModuleName+ state0 acc = do+ c <- upper+ state1 (DList.snoc acc c)++ state1 :: DList.DList Char -> m ModuleName+ state1 acc = state1' acc `alt` return (fromString (DList.toList acc))++ state1' :: DList.DList Char -> m ModuleName+ state1' acc = do+ c <- ch+ case c of+ '.' -> state0 (DList.snoc acc c)+ _ -> state1 (DList.snoc acc c)+ validModuleChar :: Char -> Bool validModuleChar c = isAlphaNum c || c == '_' || c == '\'' validModuleComponent :: String -> Bool validModuleComponent [] = False-validModuleComponent (c:cs) = isUpper c- && all validModuleChar cs+validModuleComponent (c:cs) = isUpper c && all validModuleChar cs -- | Construct a 'ModuleName' from a valid module name 'String'. --@@ -72,34 +96,29 @@ -- are parsing user input then use 'Distribution.Text.simpleParse' instead. -- instance IsString ModuleName where- fromString string = fromComponents (split string)- where- split cs = case break (=='.') cs of- (chunk,[]) -> chunk : []- (chunk,_:rest) -> chunk : split rest+ fromString = ModuleName . toShortText -- | Construct a 'ModuleName' from valid module components, i.e. parts -- separated by dots. fromComponents :: [String] -> ModuleName-fromComponents components'- | null components' = error zeroComponents- | all validModuleComponent components' = ModuleName (stlFromStrings components')- | otherwise = error badName- where- zeroComponents = "ModuleName.fromComponents: zero components"- badName = "ModuleName.fromComponents: invalid components " ++ show components'+fromComponents comps = fromString (intercalate "." comps)+{-# DEPRECATED fromComponents "Exists for cabal-install only" #-} -- | The module name @Main@. -- main :: ModuleName-main = ModuleName (stlFromStrings ["Main"])+main = ModuleName (fromString "Main") -- | The individual components of a hierarchical module name. For example -- -- > components (fromString "A.B.C") = ["A", "B", "C"] -- components :: ModuleName -> [String]-components (ModuleName ms) = stlToStrings ms+components mn = split (unModuleName mn)+ where+ split cs = case break (=='.') cs of+ (chunk,[]) -> chunk : []+ (chunk,_:rest) -> chunk : split rest -- | Convert a module name to a file path, but without any file extension. -- For example:@@ -107,40 +126,6 @@ -- > toFilePath (fromString "A.B.C") = "A/B/C" -- toFilePath :: ModuleName -> FilePath-toFilePath = intercalate [pathSeparator] . components--------------------------------------------------------------------------------- internal helper---- | Strict/unpacked representation of @[ShortText]@-data ShortTextLst = STLNil- | STLCons !ShortText !ShortTextLst- deriving (Eq, Generic, Ord, Typeable, Data)--instance NFData ShortTextLst where- rnf = flip seq ()--instance Show ShortTextLst where- showsPrec p = showsPrec p . stlToList---instance Read ShortTextLst where- readsPrec p = map (first stlFromList) . readsPrec p--instance Binary ShortTextLst where- put = put . stlToList- get = stlFromList <$> get--stlToList :: ShortTextLst -> [ShortText]-stlToList STLNil = []-stlToList (STLCons st next) = st : stlToList next--stlToStrings :: ShortTextLst -> [String]-stlToStrings = map fromShortText . stlToList--stlFromList :: [ShortText] -> ShortTextLst-stlFromList [] = STLNil-stlFromList (x:xs) = STLCons x (stlFromList xs)--stlFromStrings :: [String] -> ShortTextLst-stlFromStrings = stlFromList . map toShortText+toFilePath = map f . unModuleName where+ f '.' = pathSeparator+ f c = c
cabal/Cabal/Distribution/PackageDescription.hs view
@@ -10,135 +10,91 @@ -- Maintainer : cabal-devel@haskell.org -- Portability : portable ----- Backwards compatibility reexport of everything you need to know+-- Backwards compatibility reexport of most things you need to know -- about @.cabal@ files. module Distribution.PackageDescription (- -- * Package descriptions- PackageDescription(..),- emptyPackageDescription,- specVersion,- buildType,- license,- BuildType(..),- knownBuildTypes,- allLibraries,-- -- ** Renaming (syntactic)- ModuleRenaming(..),- defaultRenaming,-- -- ** Libraries- Library(..),- ModuleReexport(..),- emptyLibrary,- withLib,- hasPublicLib,- hasLibs,- explicitLibModules,- libModulesAutogen,-- -- ** Executables- Executable(..),- emptyExecutable,- withExe,- hasExes,- exeModules,- exeModulesAutogen,-- -- * Tests- TestSuite(..),- TestSuiteInterface(..),- TestType(..),- testType,- knownTestTypes,- emptyTestSuite,- hasTests,- withTest,- testModules,- testModulesAutogen,-- -- * Benchmarks- Benchmark(..),- BenchmarkInterface(..),- BenchmarkType(..),- benchmarkType,- knownBenchmarkTypes,- emptyBenchmark,- hasBenchmarks,- withBenchmark,- benchmarkModules,- benchmarkModulesAutogen,-- -- * Build information- BuildInfo(..),- emptyBuildInfo,- allBuildInfo,- allLanguages,- allExtensions,- usedExtensions,- usesTemplateHaskellOrQQ,- hcOptions,- hcProfOptions,- hcSharedOptions,- hcStaticOptions,-- -- ** Supplementary build information- allBuildDepends,- enabledBuildDepends,- ComponentName(..),- LibraryName(..),- defaultLibName,- HookedBuildInfo,- emptyHookedBuildInfo,- updatePackageDescription,-- -- * package configuration- GenericPackageDescription(..),- Flag(..), emptyFlag,- FlagName, mkFlagName, unFlagName,- FlagAssignment, mkFlagAssignment, unFlagAssignment,- nullFlagAssignment, showFlagValue,- diffFlagAssignment, lookupFlagAssignment, insertFlagAssignment,- dispFlagAssignment, parsecFlagAssignment,- findDuplicateFlagAssignments,- CondTree(..), ConfVar(..), Condition(..),- cNot, cAnd, cOr,-- -- * Source repositories- SourceRepo(..),- RepoKind(..),- RepoType(..),- knownRepoTypes,- emptySourceRepo,-- -- * Custom setup build information- SetupBuildInfo(..),+ -- * PD and GPD+ module Distribution.Types.PackageDescription,+ module Distribution.Types.GenericPackageDescription,+ -- * Components+ module Distribution.Types.ComponentName,+ -- ** Library+ module Distribution.Types.Library,+ module Distribution.Types.LibraryName,+ module Distribution.Types.LibraryVisibility,+ -- ** Executable+ module Distribution.Types.Executable,+ module Distribution.Types.ExecutableScope,+ -- ** TestSuite+ module Distribution.Types.TestSuite,+ module Distribution.Types.TestType,+ module Distribution.Types.TestSuiteInterface,+ -- ** Benchmark+ module Distribution.Types.Benchmark,+ module Distribution.Types.BenchmarkType,+ module Distribution.Types.BenchmarkInterface,+ -- ** Foreign library+ module Distribution.Types.ForeignLib,+ module Distribution.Types.ForeignLibType,+ module Distribution.Types.ForeignLibOption,+ -- * BuildInfo+ module Distribution.Types.BuildType,+ module Distribution.Types.BuildInfo,+ module Distribution.Types.HookedBuildInfo,+ module Distribution.Types.SetupBuildInfo,+ -- * Flags+ module Distribution.Types.Flag,+ -- * Identifiers+ module Distribution.Types.PackageId,+ module Distribution.Types.PackageName,+ module Distribution.Types.UnqualComponentName,+ -- * Dependencies+ module Distribution.Types.Dependency,+ module Distribution.Types.ExeDependency,+ module Distribution.Types.LegacyExeDependency,+ module Distribution.Types.PkgconfigDependency,+ -- * Condition trees+ module Distribution.Types.CondTree,+ module Distribution.Types.Condition,+ module Distribution.Types.ConfVar,+ -- * Source repository+ module Distribution.Types.SourceRepo, ) where import Prelude () --import Distribution.Compat.Prelude -import Distribution.Types.Library-import Distribution.Types.TestSuite-import Distribution.Types.Executable import Distribution.Types.Benchmark-import Distribution.Types.TestType-import Distribution.Types.TestSuiteInterface-import Distribution.Types.BenchmarkType import Distribution.Types.BenchmarkInterface-import Distribution.Types.ModuleRenaming-import Distribution.Types.ModuleReexport+import Distribution.Types.BenchmarkType import Distribution.Types.BuildInfo-import Distribution.Types.SetupBuildInfo import Distribution.Types.BuildType-import Distribution.Types.GenericPackageDescription-import Distribution.Types.CondTree-import Distribution.Types.Condition-import Distribution.Types.PackageDescription import Distribution.Types.ComponentName-import Distribution.Types.LibraryName+import Distribution.Types.Condition+import Distribution.Types.CondTree+import Distribution.Types.ConfVar+import Distribution.Types.Dependency+import Distribution.Types.Executable+import Distribution.Types.ExecutableScope+import Distribution.Types.ExeDependency+import Distribution.Types.Flag+import Distribution.Types.ForeignLib+import Distribution.Types.ForeignLibOption+import Distribution.Types.ForeignLibType+import Distribution.Types.GenericPackageDescription import Distribution.Types.HookedBuildInfo+import Distribution.Types.LegacyExeDependency+import Distribution.Types.Library+import Distribution.Types.LibraryName+import Distribution.Types.LibraryVisibility+import Distribution.Types.PackageDescription+import Distribution.Types.PackageId+import Distribution.Types.PackageName+import Distribution.Types.PkgconfigDependency+import Distribution.Types.SetupBuildInfo import Distribution.Types.SourceRepo-import Distribution.Types.Flag-import Distribution.Types.ConfVar+import Distribution.Types.TestSuite+import Distribution.Types.TestSuiteInterface+import Distribution.Types.TestType+import Distribution.Types.UnqualComponentName
cabal/Cabal/Distribution/PackageDescription/Check.hs view
@@ -15,7 +15,7 @@ -- like to encourage. There is a 'PackageCheck' type that distinguishes the -- different kinds of check so we can see which ones are appropriate to report -- in different situations. This code gets uses when configuring a package when--- we consider only basic problems. The higher standard is uses when when+-- we consider only basic problems. The higher standard is uses when -- preparing a source tarball and by Hackage when uploading new packages. The -- reason for this is that we want to hold packages that are expected to be -- distributed to a higher standard than packages that are only ever expected@@ -37,8 +37,8 @@ import Distribution.Compat.Prelude import Prelude () -import Control.Monad (mapM) import Data.List (group)+import Distribution.CabalSpecVersion import Distribution.Compat.Lens import Distribution.Compiler import Distribution.License@@ -53,11 +53,8 @@ import Distribution.Simple.Utils hiding (findPackageDesc, notice) import Distribution.System import Distribution.Types.ComponentRequestedSpec-import Distribution.Types.CondTree-import Distribution.Types.ExeDependency-import Distribution.Types.LibraryName-import Distribution.Types.UnqualComponentName-import Distribution.Utils.Generic (isAscii, safeInit)+import Distribution.Types.ModuleReexport+import Distribution.Utils.Generic (isAscii) import Distribution.Verbosity import Distribution.Version import Language.Haskell.Extension@@ -74,6 +71,7 @@ import qualified System.FilePath.Windows as FilePath.Windows (isValid) import qualified Data.Set as Set+import qualified Distribution.Utils.ShortText as ShortText import qualified Distribution.Types.BuildInfo.Lens as L import qualified Distribution.Types.GenericPackageDescription.Lens as L@@ -122,11 +120,11 @@ check False _ = Nothing check True pc = Just pc -checkSpecVersion :: PackageDescription -> [Int] -> Bool -> PackageCheck+checkSpecVersion :: PackageDescription -> CabalSpecVersion -> Bool -> PackageCheck -> Maybe PackageCheck checkSpecVersion pkg specver cond pc- | specVersion pkg >= mkVersion specver = Nothing- | otherwise = check cond pc+ | specVersion pkg >= specver = Nothing+ | otherwise = check cond pc -- ------------------------------------------------------------ -- * Standard checks@@ -226,14 +224,6 @@ ++ concatMap (checkTestSuite pkg) (testSuites pkg) ++ concatMap (checkBenchmark pkg) (benchmarks pkg) - ++ catMaybes [-- check (specVersion pkg > cabalVersion) $- PackageBuildImpossible $- "This package description follows version "- ++ prettyShow (specVersion pkg) ++ " of the Cabal specification. This "- ++ "tool only supports up to version " ++ prettyShow cabalVersion ++ "."- ] where -- The public 'library' gets special dispensation, because it -- is common practice to export a library and name the executable@@ -259,7 +249,7 @@ showLibraryName (libName lib) ++ " does not expose any modules" -- check use of signatures sections- , checkVersion [1,25] (not (null (signatures lib))) $+ , checkVersion CabalSpecV2_0 (not (null (signatures lib))) $ PackageDistInexcusable $ "To use the 'signatures' field the package needs to specify " ++ "at least 'cabal-version: 2.0'."@@ -280,10 +270,10 @@ ] where- checkVersion :: [Int] -> Bool -> PackageCheck -> Maybe PackageCheck+ checkVersion :: CabalSpecVersion -> Bool -> PackageCheck -> Maybe PackageCheck checkVersion ver cond pc- | specVersion pkg >= mkVersion ver = Nothing- | otherwise = check cond pc+ | specVersion pkg >= ver = Nothing+ | otherwise = check cond pc -- TODO: not sure if this check is always right in Backpack moduleDuplicates = dups (explicitLibModules lib ++@@ -307,7 +297,7 @@ ++ "(even if it is generated by a preprocessor), " ++ "or it may specify a C/C++/obj-C source file." - , checkSpecVersion pkg [1,17]+ , checkSpecVersion pkg CabalSpecV1_18 (fileExtensionSupportedLanguage (modulePath exe) && takeExtension (modulePath exe) `notElem` [".hs", ".lhs"]) $ PackageDistInexcusable $@@ -363,7 +353,7 @@ ++ "(even if it is generated by a preprocessor), " ++ "or it may specify a C/C++/obj-C source file." - , checkSpecVersion pkg [1,17] (mainIsNotHsExt && not mainIsWrongExt) $+ , checkSpecVersion pkg CabalSpecV1_18 (mainIsNotHsExt && not mainIsWrongExt) $ PackageDistInexcusable $ "The package uses a C/C++/obj-C source file for the 'main-is' field. " ++ "To use this feature you must specify 'cabal-version: >= 1.18'."@@ -458,7 +448,7 @@ "Package names with the prefix 'z-' are reserved by Cabal and " ++ "cannot be used." - , check (isNothing (buildTypeRaw pkg) && specVersion pkg < mkVersion [2,1]) $+ , check (isNothing (buildTypeRaw pkg) && specVersion pkg < CabalSpecV2_2) $ PackageBuildWarning $ "No 'build-type' specified. If you do not need a custom Setup.hs or " ++ "./configure script then use 'build-type: Simple'."@@ -498,32 +488,32 @@ ++ "' use '" ++ prettyShow replacement ++ "'." | (ext, Just replacement) <- ourDeprecatedExtensions ] - , check (null (category pkg)) $+ , check (ShortText.null (category pkg)) $ PackageDistSuspicious "No 'category' field." - , check (null (maintainer pkg)) $+ , check (ShortText.null (maintainer pkg)) $ PackageDistSuspicious "No 'maintainer' field." - , check (null (synopsis pkg) && null (description pkg)) $+ , check (ShortText.null (synopsis pkg) && ShortText.null (description pkg)) $ PackageDistInexcusable "No 'synopsis' or 'description' field." - , check (null (description pkg) && not (null (synopsis pkg))) $+ , check (ShortText.null (description pkg) && not (ShortText.null (synopsis pkg))) $ PackageDistSuspicious "No 'description' field." - , check (null (synopsis pkg) && not (null (description pkg))) $+ , check (ShortText.null (synopsis pkg) && not (ShortText.null (description pkg))) $ PackageDistSuspicious "No 'synopsis' field." --TODO: recommend the bug reports URL, author and homepage fields --TODO: recommend not using the stability field --TODO: recommend specifying a source repo - , check (length (synopsis pkg) >= 80) $+ , check (ShortText.length (synopsis pkg) >= 80) $ PackageDistSuspicious "The 'synopsis' field is rather long (max 80 chars is recommended)." -- See also https://github.com/haskell/cabal/pull/3479- , check (not (null (description pkg))- && length (description pkg) <= length (synopsis pkg)) $+ , check (not (ShortText.null (description pkg))+ && ShortText.length (description pkg) <= ShortText.length (synopsis pkg)) $ PackageDistSuspicious $ "The 'description' field should be longer than the 'synopsis' " ++ "field. "@@ -601,7 +591,7 @@ , name `elem` map prettyShow knownLanguages ] testedWithImpossibleRanges =- [ Dependency (mkPackageName (prettyShow compiler)) vr Set.empty+ [ Dependency (mkPackageName (prettyShow compiler)) vr mainLibSet | (compiler, vr) <- testedWith pkg , isNoVersion vr ] @@ -680,7 +670,7 @@ PackageDistSuspicious "The 'license' is AllRightsReserved. Is that really what you want?" - , checkVersion [1,4] (lic `notElem` compatLicenses) $+ , checkVersion CabalSpecV1_4 (lic `notElem` compatLicenses) $ PackageDistInexcusable $ "Unfortunately the license " ++ quote (prettyShow (license pkg)) ++ " messes up the parser in earlier Cabal versions so you need to "@@ -733,10 +723,10 @@ where knownVersions = [ v' | Apache (Just v') <- knownLicenses ] unknownLicenseVersion _ = Nothing - checkVersion :: [Int] -> Bool -> PackageCheck -> Maybe PackageCheck+ checkVersion :: CabalSpecVersion -> Bool -> PackageCheck -> Maybe PackageCheck checkVersion ver cond pc- | specVersion pkg >= mkVersion ver = Nothing- | otherwise = check cond pc+ | specVersion pkg >= ver = Nothing+ | otherwise = check cond pc compatLicenses = [ GPL Nothing, LGPL Nothing, AGPL Nothing, BSD3, BSD4 , PublicDomain, AllRightsReserved@@ -760,7 +750,7 @@ PackageDistInexcusable "The source-repository 'location' is a required field." - , check (repoType repo == Just CVS && isNothing (repoModule repo)) $+ , check (repoType repo == Just (KnownRepoType CVS) && isNothing (repoModule repo)) $ PackageDistInexcusable "For a CVS source-repository, the 'module' is a required field." @@ -807,7 +797,7 @@ , checkFlags ["-fhpc"] $ PackageDistInexcusable $- "'" ++ fieldName ++ ": -fhpc' is not not necessary. Use the configure flag "+ "'" ++ fieldName ++ ": -fhpc' is not necessary. Use the configure flag " ++ " --enable-coverage instead." , checkFlags ["-prof"] $@@ -1146,41 +1136,8 @@ checkCabalVersion pkg = catMaybes [ - -- check syntax of cabal-version field- check (specVersion pkg >= mkVersion [1,10]- && not simpleSpecVersionRangeSyntax) $- PackageBuildWarning $- "Packages relying on Cabal 1.10 or later must only specify a "- ++ "version range of the form 'cabal-version: >= x.y'. Use "- ++ "'cabal-version: >= " ++ prettyShow (specVersion pkg) ++ "'."-- -- check syntax of cabal-version field- , check (specVersion pkg < mkVersion [1,9]- && not simpleSpecVersionRangeSyntax) $- PackageDistSuspicious $- "It is recommended that the 'cabal-version' field only specify a "- ++ "version range of the form '>= x.y'. Use "- ++ "'cabal-version: >= " ++ prettyShow (specVersion pkg) ++ "'. "- ++ "Tools based on Cabal 1.10 and later will ignore upper bounds."-- -- check syntax of cabal-version field- , checkVersion [1,12] simpleSpecVersionSyntax $- PackageBuildWarning $- "With Cabal 1.10 or earlier, the 'cabal-version' field must use "- ++ "range syntax rather than a simple version number. Use "- ++ "'cabal-version: >= " ++ prettyShow (specVersion pkg) ++ "'."-- -- check syntax of cabal-version field- , check (specVersion pkg >= mkVersion [1,12]- && not simpleSpecVersionSyntax) $- (if specVersion pkg >= mkVersion [2,0] then PackageDistSuspicious else PackageDistSuspiciousWarn) $- "Packages relying on Cabal 1.12 or later should specify a "- ++ "specific version of the Cabal spec of the form "- ++ "'cabal-version: x.y'. "- ++ "Use 'cabal-version: " ++ prettyShow (specVersion pkg) ++ "'."- -- check use of test suite sections- , checkVersion [1,8] (not (null $ testSuites pkg)) $+ checkVersion CabalSpecV1_8 (not (null $ testSuites pkg)) $ PackageDistInexcusable $ "The 'test-suite' section is new in Cabal 1.10. " ++ "Unfortunately it messes up the parser in older Cabal versions "@@ -1190,47 +1147,47 @@ -- check use of default-language field -- note that we do not need to do an equivalent check for the -- other-language field since that one does not change behaviour- , checkVersion [1,10] (any isJust (buildInfoField defaultLanguage)) $+ , checkVersion CabalSpecV1_10 (any isJust (buildInfoField defaultLanguage)) $ PackageBuildWarning $ "To use the 'default-language' field the package needs to specify " ++ "at least 'cabal-version: >= 1.10'." - , check (specVersion pkg >= mkVersion [1,10]+ , check (specVersion pkg >= CabalSpecV1_10 && specVersion pkg < CabalSpecV3_4 && (any isNothing (buildInfoField defaultLanguage))) $ PackageBuildWarning $- "Packages using 'cabal-version: >= 1.10' must specify the "+ "Packages using 'cabal-version: >= 1.10' and before 'cabal-version: 3.4' must specify the " ++ "'default-language' field for each component (e.g. Haskell98 or " ++ "Haskell2010). If a component uses different languages in " ++ "different modules then list the other ones in the " ++ "'other-languages' field." - , checkVersion [1,18]+ , checkVersion CabalSpecV1_18 (not . null $ extraDocFiles pkg) $ PackageDistInexcusable $ "To use the 'extra-doc-files' field the package needs to specify " ++ "at least 'cabal-version: >= 1.18'." - , checkVersion [2,0]+ , checkVersion CabalSpecV2_0 (not (null (subLibraries pkg))) $ PackageDistInexcusable $ "To use multiple 'library' sections or a named library section " ++ "the package needs to specify at least 'cabal-version: 2.0'." -- check use of reexported-modules sections- , checkVersion [1,21]+ , checkVersion CabalSpecV1_22 (any (not.null.reexportedModules) (allLibraries pkg)) $ PackageDistInexcusable $ "To use the 'reexported-module' field the package needs to specify " ++ "at least 'cabal-version: >= 1.22'." -- check use of thinning and renaming- , checkVersion [1,25] usesBackpackIncludes $+ , checkVersion CabalSpecV2_0 usesBackpackIncludes $ PackageDistInexcusable $ "To use the 'mixins' field the package needs to specify " ++ "at least 'cabal-version: 2.0'." -- check use of 'extra-framework-dirs' field- , checkVersion [1,23] (any (not . null) (buildInfoField extraFrameworkDirs)) $+ , checkVersion CabalSpecV1_24 (any (not . null) (buildInfoField extraFrameworkDirs)) $ -- Just a warning, because this won't break on old Cabal versions. PackageDistSuspiciousWarn $ "To use the 'extra-framework-dirs' field the package needs to specify"@@ -1238,13 +1195,13 @@ -- check use of default-extensions field -- don't need to do the equivalent check for other-extensions- , checkVersion [1,10] (any (not . null) (buildInfoField defaultExtensions)) $+ , checkVersion CabalSpecV1_10 (any (not . null) (buildInfoField defaultExtensions)) $ PackageBuildWarning $ "To use the 'default-extensions' field the package needs to specify " ++ "at least 'cabal-version: >= 1.10'." -- check use of extensions field- , check (specVersion pkg >= mkVersion [1,10]+ , check (specVersion pkg >= CabalSpecV1_10 && (any (not . null) (buildInfoField oldExtensions))) $ PackageBuildWarning $ "For packages using 'cabal-version: >= 1.10' the 'extensions' "@@ -1253,41 +1210,7 @@ ++ "the 'other-extensions' field lists extensions that are used in " ++ "some modules, e.g. via the {-# LANGUAGE #-} pragma." - -- check use of "foo (>= 1.0 && < 1.4) || >=1.8 " version-range syntax- , checkVersion [1,8] (not (null versionRangeExpressions)) $- PackageDistInexcusable $- "The package uses full version-range expressions "- ++ "in a 'build-depends' field: "- ++ commaSep (map displayRawDependency versionRangeExpressions)- ++ ". To use this new syntax the package needs to specify at least "- ++ "'cabal-version: >= 1.8'. Alternatively, if broader compatibility "- ++ "is important, then convert to conjunctive normal form, and use "- ++ "multiple 'build-depends:' lines, one conjunct per line."-- -- check use of "build-depends: foo == 1.*" syntax- , checkVersion [1,6] (not (null depsUsingWildcardSyntax)) $- PackageDistInexcusable $- "The package uses wildcard syntax in the 'build-depends' field: "- ++ commaSep (map prettyShow depsUsingWildcardSyntax)- ++ ". To use this new syntax the package need to specify at least "- ++ "'cabal-version: >= 1.6'. Alternatively, if broader compatibility "- ++ "is important then use: " ++ commaSep- [ prettyShow (Dependency name (eliminateWildcardSyntax versionRange) Set.empty)- | Dependency name versionRange _ <- depsUsingWildcardSyntax ]-- -- check use of "build-depends: foo ^>= 1.2.3" syntax- , checkVersion [2,0] (not (null depsUsingMajorBoundSyntax)) $- PackageDistInexcusable $- "The package uses major bounded version syntax in the "- ++ "'build-depends' field: "- ++ commaSep (map prettyShow depsUsingMajorBoundSyntax)- ++ ". To use this new syntax the package need to specify at least "- ++ "'cabal-version: 2.0'. Alternatively, if broader compatibility "- ++ "is important then use: " ++ commaSep- [ prettyShow (Dependency name (eliminateMajorBoundSyntax versionRange) Set.empty)- | Dependency name versionRange _ <- depsUsingMajorBoundSyntax ]-- , checkVersion [2,1] (any (not . null)+ , checkVersion CabalSpecV3_0 (any (not . null) (concatMap buildInfoField [ asmSources , cmmSources@@ -1296,60 +1219,40 @@ PackageDistInexcusable $ "The use of 'asm-sources', 'cmm-sources', 'extra-bundled-libraries' " ++ " and 'extra-library-flavours' requires the package "- ++ " to specify at least 'cabal-version: >= 2.1'."+ ++ " to specify at least 'cabal-version: 3.0'." - , checkVersion [2,5] (any (not . null) $ buildInfoField extraDynLibFlavours) $+ , checkVersion CabalSpecV3_0 (any (not . null) $ buildInfoField extraDynLibFlavours) $ PackageDistInexcusable $ "The use of 'extra-dynamic-library-flavours' requires the package "- ++ " to specify at least 'cabal-version: >= 2.5'. The flavours are: "+ ++ " to specify at least 'cabal-version: 3.0'. The flavours are: " ++ commaSep [ flav | flavs <- buildInfoField extraDynLibFlavours , flav <- flavs ] - , checkVersion [2,1] (any (not . null)+ , checkVersion CabalSpecV2_2 (any (not . null) (buildInfoField virtualModules)) $ PackageDistInexcusable $ "The use of 'virtual-modules' requires the package "- ++ " to specify at least 'cabal-version: >= 2.1'."-- -- check use of "tested-with: GHC (>= 1.0 && < 1.4) || >=1.8 " syntax- , checkVersion [1,8] (not (null testedWithVersionRangeExpressions)) $- PackageDistInexcusable $- "The package uses full version-range expressions "- ++ "in a 'tested-with' field: "- ++ commaSep (map displayRawDependency testedWithVersionRangeExpressions)- ++ ". To use this new syntax the package needs to specify at least "- ++ "'cabal-version: >= 1.8'."-- -- check use of "tested-with: GHC == 6.12.*" syntax- , checkVersion [1,6] (not (null testedWithUsingWildcardSyntax)) $- PackageDistInexcusable $- "The package uses wildcard syntax in the 'tested-with' field: "- ++ commaSep (map prettyShow testedWithUsingWildcardSyntax)- ++ ". To use this new syntax the package need to specify at least "- ++ "'cabal-version: >= 1.6'. Alternatively, if broader compatibility "- ++ "is important then use: " ++ commaSep- [ prettyShow (Dependency name (eliminateWildcardSyntax versionRange) Set.empty)- | Dependency name versionRange _ <- testedWithUsingWildcardSyntax ]+ ++ " to specify at least 'cabal-version: 2.2'." -- check use of "source-repository" section- , checkVersion [1,6] (not (null (sourceRepos pkg))) $+ , checkVersion CabalSpecV1_6 (not (null (sourceRepos pkg))) $ PackageDistInexcusable $ "The 'source-repository' section is new in Cabal 1.6. " ++ "Unfortunately it messes up the parser in earlier Cabal versions " ++ "so you need to specify 'cabal-version: >= 1.6'." -- check for new language extensions- , checkVersion [1,2,3] (not (null mentionedExtensionsThatNeedCabal12)) $+ , checkVersion CabalSpecV1_4 (not (null mentionedExtensionsThatNeedCabal12)) $ PackageDistInexcusable $ "Unfortunately the language extensions " ++ commaSep (map (quote . prettyShow) mentionedExtensionsThatNeedCabal12) ++ " break the parser in earlier Cabal versions so you need to "- ++ "specify 'cabal-version: >= 1.2.3'. Alternatively if you require "+ ++ "specify 'cabal-version: >= 1.4'. Alternatively if you require " ++ "compatibility with earlier Cabal versions then you may be able to " ++ "use an equivalent compiler-specific flag." - , checkVersion [1,4] (not (null mentionedExtensionsThatNeedCabal14)) $+ , checkVersion CabalSpecV1_4 (not (null mentionedExtensionsThatNeedCabal14)) $ PackageDistInexcusable $ "Unfortunately the language extensions " ++ commaSep (map (quote . prettyShow) mentionedExtensionsThatNeedCabal14)@@ -1358,7 +1261,7 @@ ++ "compatibility with earlier Cabal versions then you may be able to " ++ "use an equivalent compiler-specific flag." - , check (specVersion pkg >= mkVersion [1,23]+ , check (specVersion pkg >= CabalSpecV1_24 && isNothing (setupBuildInfo pkg) && buildType pkg == Custom) $ PackageBuildWarning $@@ -1368,7 +1271,7 @@ ++ "The 'setup-depends' field uses the same syntax as 'build-depends', " ++ "so a simple example would be 'setup-depends: base, Cabal'." - , check (specVersion pkg < mkVersion [1,23]+ , check (specVersion pkg < CabalSpecV1_24 && isNothing (setupBuildInfo pkg) && buildType pkg == Custom) $ PackageDistSuspiciousWarn $@@ -1379,7 +1282,7 @@ ++ "The 'setup-depends' field uses the same syntax as 'build-depends', " ++ "so a simple example would be 'setup-depends: base, Cabal'." - , check (specVersion pkg >= mkVersion [1,25]+ , check (specVersion pkg >= CabalSpecV2_0 && elem (autogenPathsModuleName pkg) allModuleNames && not (elem (autogenPathsModuleName pkg) allModuleNamesAutogen) ) $ PackageDistInexcusable $@@ -1396,89 +1299,15 @@ -- the version given. This is for cases where a new Cabal version adds -- a new feature and we want to check that it is not used prior to that -- version.- checkVersion :: [Int] -> Bool -> PackageCheck -> Maybe PackageCheck+ checkVersion :: CabalSpecVersion -> Bool -> PackageCheck -> Maybe PackageCheck checkVersion ver cond pc- | specVersion pkg >= mkVersion ver = Nothing- | otherwise = check cond pc+ | specVersion pkg >= ver = Nothing+ | otherwise = check cond pc buildInfoField field = map field (allBuildInfo pkg) - versionRangeExpressions =- [ dep | dep@(Dependency _ vr _) <- allBuildDepends pkg- , usesNewVersionRangeSyntax vr ]-- testedWithVersionRangeExpressions =- [ Dependency (mkPackageName (prettyShow compiler)) vr Set.empty- | (compiler, vr) <- testedWith pkg- , usesNewVersionRangeSyntax vr ]-- simpleSpecVersionRangeSyntax =- either (const True) (cataVersionRange alg) (specVersionRaw pkg)- where- alg (OrLaterVersionF _) = True- alg _ = False-- -- is the cabal-version field a simple version number, rather than a range- simpleSpecVersionSyntax =- either (const True) (const False) (specVersionRaw pkg)-- usesNewVersionRangeSyntax :: VersionRange -> Bool- usesNewVersionRangeSyntax- = (> 2) -- uses the new syntax if depth is more than 2- . cataVersionRange alg- where- alg (UnionVersionRangesF a b) = a + b- alg (IntersectVersionRangesF a b) = a + b- alg (VersionRangeParensF _) = 3- alg _ = 1 :: Int-- depsUsingWildcardSyntax = [ dep | dep@(Dependency _ vr _) <- allBuildDepends pkg- , usesWildcardSyntax vr ]-- depsUsingMajorBoundSyntax = [ dep | dep@(Dependency _ vr _) <- allBuildDepends pkg- , usesMajorBoundSyntax vr ]- usesBackpackIncludes = any (not . null . mixins) (allBuildInfo pkg) - testedWithUsingWildcardSyntax =- [ Dependency (mkPackageName (prettyShow compiler)) vr Set.empty- | (compiler, vr) <- testedWith pkg- , usesWildcardSyntax vr ]-- usesWildcardSyntax :: VersionRange -> Bool- usesWildcardSyntax = cataVersionRange alg- where- alg (WildcardVersionF _) = True- alg (UnionVersionRangesF a b) = a || b- alg (IntersectVersionRangesF a b) = a || b- alg (VersionRangeParensF a) = a- alg _ = False-- -- NB: this eliminates both, WildcardVersion and MajorBoundVersion- -- because when WildcardVersion is not support, neither is MajorBoundVersion- eliminateWildcardSyntax = hyloVersionRange embed projectVersionRange- where- embed (WildcardVersionF v) = intersectVersionRanges- (orLaterVersion v) (earlierVersion (wildcardUpperBound v))- embed (MajorBoundVersionF v) = intersectVersionRanges- (orLaterVersion v) (earlierVersion (majorUpperBound v))- embed vr = embedVersionRange vr-- usesMajorBoundSyntax :: VersionRange -> Bool- usesMajorBoundSyntax = cataVersionRange alg- where- alg (MajorBoundVersionF _) = True- alg (UnionVersionRangesF a b) = a || b- alg (IntersectVersionRangesF a b) = a || b- alg (VersionRangeParensF a) = a- alg _ = False-- eliminateMajorBoundSyntax = hyloVersionRange embed projectVersionRange- where- embed (MajorBoundVersionF v) = intersectVersionRanges- (orLaterVersion v) (earlierVersion (majorUpperBound v))- embed vr = embedVersionRange vr- mentionedExtensions = [ ext | bi <- allBuildInfo pkg , ext <- allExtensions bi ] mentionedExtensionsThatNeedCabal12 =@@ -1529,16 +1358,11 @@ allModuleNamesAutogen = concatMap autogenModules (allBuildInfo pkg) -displayRawDependency :: Dependency -> String-displayRawDependency (Dependency pkg vr _sublibs) =- prettyShow pkg ++ " " ++ prettyShow vr-- -- ------------------------------------------------------------ -- * Checks on the GenericPackageDescription -- ------------------------------------------------------------ --- | Check the build-depends fields for any weirdness or bad practise.+-- | Check the build-depends fields for any weirdness or bad practice. -- checkPackageVersions :: GenericPackageDescription -> [PackageCheck] checkPackageVersions pkg =@@ -1553,7 +1377,7 @@ "The dependency 'build-depends: base' does not specify an upper " ++ "bound on the version number. Each major release of the 'base' " ++ "package changes the API in various ways and most packages will "- ++ "need some changes to compile with it. The recommended practise "+ ++ "need some changes to compile with it. The recommended practice " ++ "is to specify an upper bound on the version of the 'base' " ++ "package. This ensures your package will continue to build when a " ++ "new major version of the 'base' package is released. If you are "@@ -1673,12 +1497,12 @@ used :: Set.Set FlagName used = mconcat- [ toSetOf (L.condLibrary . traverse . traverseCondTreeV . L._Flag) gpd- , toSetOf (L.condSubLibraries . traverse . _2 . traverseCondTreeV . L._Flag) gpd- , toSetOf (L.condForeignLibs . traverse . _2 . traverseCondTreeV . L._Flag) gpd- , toSetOf (L.condExecutables . traverse . _2 . traverseCondTreeV . L._Flag) gpd- , toSetOf (L.condTestSuites . traverse . _2 . traverseCondTreeV . L._Flag) gpd- , toSetOf (L.condBenchmarks . traverse . _2 . traverseCondTreeV . L._Flag) gpd+ [ toSetOf (L.condLibrary . traverse . traverseCondTreeV . L._PackageFlag) gpd+ , toSetOf (L.condSubLibraries . traverse . _2 . traverseCondTreeV . L._PackageFlag) gpd+ , toSetOf (L.condForeignLibs . traverse . _2 . traverseCondTreeV . L._PackageFlag) gpd+ , toSetOf (L.condExecutables . traverse . _2 . traverseCondTreeV . L._PackageFlag) gpd+ , toSetOf (L.condTestSuites . traverse . _2 . traverseCondTreeV . L._PackageFlag) gpd+ , toSetOf (L.condBenchmarks . traverse . _2 . traverseCondTreeV . L._PackageFlag) gpd ] checkUnicodeXFields :: GenericPackageDescription -> [PackageCheck]@@ -1702,7 +1526,7 @@ -- | cabal-version <2.2 + Paths_module + default-extensions: doesn't build. checkPathsModuleExtensions :: PackageDescription -> [PackageCheck] checkPathsModuleExtensions pd- | specVersion pd >= mkVersion [2,1] = []+ | specVersion pd >= CabalSpecV2_2 = [] | any checkBI (allBuildInfo pd) || any checkLib (allLibraries pd) = return $ PackageBuildImpossible $ unwords [ "The package uses RebindableSyntax with OverloadedStrings or OverloadedLists"@@ -1823,14 +1647,14 @@ -- We've basically got three-values logic here: True, False or unknown -- hence this pattern to propagate the unknown cases properly.- definitelyFalse (Var (Flag n)) = maybe False not (Map.lookup n manualFlags)+ definitelyFalse (Var (PackageFlag n)) = maybe False not (Map.lookup n manualFlags) definitelyFalse (Var _) = False definitelyFalse (Lit b) = not b definitelyFalse (CNot c) = definitelyTrue c definitelyFalse (COr c1 c2) = definitelyFalse c1 && definitelyFalse c2 definitelyFalse (CAnd c1 c2) = definitelyFalse c1 || definitelyFalse c2 - definitelyTrue (Var (Flag n)) = fromMaybe False (Map.lookup n manualFlags)+ definitelyTrue (Var (PackageFlag n)) = fromMaybe False (Map.lookup n manualFlags) definitelyTrue (Var _) = False definitelyTrue (Lit b) = b definitelyTrue (CNot c) = definitelyFalse c@@ -1886,7 +1710,7 @@ -- | Sanity check things that requires IO. It looks at the files in the -- package and expects to find the package unpacked in at the given file path. ---checkPackageFiles :: Verbosity -> PackageDescription -> FilePath -> NoCallStackIO [PackageCheck]+checkPackageFiles :: Verbosity -> PackageDescription -> FilePath -> IO [PackageCheck] checkPackageFiles verbosity pkg root = do contentChecks <- checkPackageContent checkFilesIO pkg preDistributionChecks <- checkPackageFilesPreDistribution verbosity pkg root@@ -1920,7 +1744,8 @@ -- The point of this extra generality is to allow doing checks in some virtual -- file system, for example a tarball in memory. ---checkPackageContent :: Monad m => CheckPackageContentOps m+checkPackageContent :: (Monad m, Applicative m)+ => CheckPackageContentOps m -> PackageDescription -> m [PackageCheck] checkPackageContent ops pkg = do@@ -2011,11 +1836,12 @@ ++ "Please use only one of: " ++ intercalate ", " l -checkLicensesExist :: Monad m => CheckPackageContentOps m+checkLicensesExist :: (Monad m, Applicative m)+ => CheckPackageContentOps m -> PackageDescription -> m [PackageCheck] checkLicensesExist ops pkg = do- exists <- mapM (doesFileExist ops) (licenseFiles pkg)+ exists <- traverse (doesFileExist ops) (licenseFiles pkg) return [ PackageBuildWarning $ "The '" ++ fieldname ++ "' field refers to the file "@@ -2068,17 +1894,18 @@ } | (dir, kind) <- missing ] -checkMissingVcsInfo :: Monad m => CheckPackageContentOps m+checkMissingVcsInfo :: (Monad m, Applicative m)+ => CheckPackageContentOps m -> PackageDescription -> m [PackageCheck] checkMissingVcsInfo ops pkg | null (sourceRepos pkg) = do- vcsInUse <- liftM or $ mapM (doesDirectoryExist ops) repoDirnames+ vcsInUse <- liftM or $ traverse (doesDirectoryExist ops) repoDirnames if vcsInUse then return [ PackageDistSuspicious message ] else return [] where repoDirnames = [ dirname | repo <- knownRepoTypes- , dirname <- repoTypeDirname repo ]+ , dirname <- repoTypeDirname repo] message = "When distributing packages it is encouraged to specify source " ++ "control information in the .cabal file using one or more " ++ "'source-repository' sections. See the Cabal user guide for "@@ -2086,17 +1913,16 @@ checkMissingVcsInfo _ _ = return [] -repoTypeDirname :: RepoType -> [FilePath]-repoTypeDirname Darcs = ["_darcs"]-repoTypeDirname Git = [".git"]-repoTypeDirname SVN = [".svn"]-repoTypeDirname CVS = ["CVS"]-repoTypeDirname Mercurial = [".hg"]-repoTypeDirname GnuArch = [".arch-params"]-repoTypeDirname Bazaar = [".bzr"]-repoTypeDirname Monotone = ["_MTN"]-repoTypeDirname _ = []-+repoTypeDirname :: KnownRepoType -> [FilePath]+repoTypeDirname Darcs = ["_darcs"]+repoTypeDirname Git = [".git"]+repoTypeDirname SVN = [".svn"]+repoTypeDirname CVS = ["CVS"]+repoTypeDirname Mercurial = [".hg"]+repoTypeDirname GnuArch = [".arch-params"]+repoTypeDirname Bazaar = [".bzr"]+repoTypeDirname Monotone = ["_MTN"]+repoTypeDirname Pijul = [".pijul"] -- ------------------------------------------------------------ -- * Checks involving files in the package@@ -2202,7 +2028,7 @@ -- check these on the server; these checks only make sense in the development -- and package-creation environment. Hence we can use IO, rather than needing -- to pass a 'CheckPackageContentOps' dictionary around.-checkPackageFilesPreDistribution :: Verbosity -> PackageDescription -> FilePath -> NoCallStackIO [PackageCheck]+checkPackageFilesPreDistribution :: Verbosity -> PackageDescription -> FilePath -> IO [PackageCheck] -- Note: this really shouldn't return any 'Inexcusable' warnings, -- because that will make us say that Hackage would reject the package. -- But, because Hackage doesn't run these tests, that will be a lie!@@ -2212,7 +2038,7 @@ checkGlobFiles :: Verbosity -> PackageDescription -> FilePath- -> NoCallStackIO [PackageCheck]+ -> IO [PackageCheck] checkGlobFiles verbosity pkg root = fmap concat $ for allGlobs $ \(field, dir, glob) -> -- Note: we just skip over parse errors here; they're reported elsewhere.
cabal/Cabal/Distribution/PackageDescription/Configuration.hs view
@@ -32,42 +32,36 @@ mapTreeConstrs, transformAllBuildInfos, transformAllBuildDepends,+ transformAllBuildDependsN, ) where -import Prelude () import Distribution.Compat.Prelude+import Prelude () -- lens-import qualified Distribution.Types.BuildInfo.Lens as L+import qualified Distribution.Types.BuildInfo.Lens as L import qualified Distribution.Types.GenericPackageDescription.Lens as L-import qualified Distribution.Types.PackageDescription.Lens as L-import qualified Distribution.Types.SetupBuildInfo.Lens as L+import qualified Distribution.Types.PackageDescription.Lens as L+import qualified Distribution.Types.SetupBuildInfo.Lens as L -import Distribution.PackageDescription-import Distribution.PackageDescription.Utils-import Distribution.Version-import Distribution.Compiler-import Distribution.System-import Distribution.Parsec-import Distribution.Pretty-import Distribution.Compat.CharParsing hiding (char)-import qualified Distribution.Compat.CharParsing as P-import Distribution.Simple.Utils-import Distribution.Compat.Lens-import Distribution.Types.ComponentRequestedSpec-import Distribution.Types.ForeignLib-import Distribution.Types.Component-import Distribution.Types.Dependency-import Distribution.Types.PackageName-import Distribution.Types.UnqualComponentName-import Distribution.Types.CondTree-import Distribution.Types.Condition-import Distribution.Types.DependencyMap+import Distribution.Compat.CharParsing hiding (char)+import qualified Distribution.Compat.CharParsing as P+import Distribution.Compat.Lens+import Distribution.Compiler+import Distribution.PackageDescription+import Distribution.PackageDescription.Utils+import Distribution.Parsec+import Distribution.Pretty+import Distribution.Simple.Utils+import Distribution.System+import Distribution.Types.Component+import Distribution.Types.ComponentRequestedSpec+import Distribution.Types.DependencyMap+import Distribution.Types.PackageVersionConstraint+import Distribution.Version -import qualified Data.Map.Strict as Map.Strict-import qualified Data.Map.Lazy as Map-import qualified Data.Set as Set-import Data.Tree ( Tree(Node) )+import qualified Data.Map.Lazy as Map+import Data.Tree (Tree (Node)) ------------------------------------------------------------------------------ @@ -89,7 +83,7 @@ Just compat -> Right (any matchImpl compat) where matchImpl (CompilerId c v) = comp == c && v `withinRange` vr- interp (Flag f) = Left f+ interp (PackageFlag f) = Left f -- TODO: Add instances and check --@@ -126,10 +120,10 @@ boolLiteral = fmap Lit parsec archIdent = fmap Arch parsec osIdent = fmap OS parsec- flagIdent = fmap (Flag . mkFlagName . lowercase) (munch1 isIdentChar)+ flagIdent = fmap (PackageFlag . mkFlagName . lowercase) (munch1 isIdentChar) isIdentChar c = isAlphaNum c || c == '_' || c == '-' oper s = sp >> string s >> sp- sp = spaces + sp = spaces implIdent = do i <- parsec vr <- sp >> option anyVersion parsec return $ Impl i vr@@ -178,7 +172,7 @@ -> OS -- ^ OS as returned by Distribution.System.buildOS -> Arch -- ^ Arch as returned by Distribution.System.buildArch -> CompilerInfo -- ^ Compiler information- -> [Dependency] -- ^ Additional constraints+ -> [PackageVersionConstraint] -- ^ Additional constraints -> [CondTree ConfVar [Dependency] PDTagged] -> ([Dependency] -> DepTestRslt [Dependency]) -- ^ Dependency test function. -> Either [Dependency] (TargetSet PDTagged, FlagAssignment)@@ -187,8 +181,6 @@ resolveWithFlags dom enabled os arch impl constrs trees checkDeps = either (Left . fromDepMapUnion) Right $ explore (build mempty dom) where- extraConstrs = toDepMap constrs- -- simplify trees by (partially) evaluating all conditions and converting -- dependencies to dependency maps. simplifiedTrees :: [CondTree FlagName DependencyMap PDTagged]@@ -207,7 +199,7 @@ explore (Node flags ts) = let targetSet = TargetSet $ flip map simplifiedTrees $ -- apply additional constraints to all dependencies- first (`constrainBy` extraConstrs) .+ first (`constrainBy` constrs) . simplifyCondTree (env flags) deps = overallDependencies enabled targetSet in case checkDeps (fromDepMap deps) of@@ -229,11 +221,7 @@ mp :: Either DepMapUnion a -> Either DepMapUnion a -> Either DepMapUnion a mp m@(Right _) _ = m mp _ m@(Right _) = m- mp (Left xs) (Left ys) =- let union = Map.foldrWithKey (Map.Strict.insertWith combine)- (unDepMapUnion xs) (unDepMapUnion ys)- combine x y = (\(vr, cs) -> (simplifyVersionRange vr,cs)) $ unionVersionRanges' x y- in union `seq` Left (DepMapUnion union)+ mp (Left xs) (Left ys) = Left (xs <> ys) -- `mzero' mz :: Either DepMapUnion a@@ -309,26 +297,29 @@ ] --- | A map of dependencies that combines version ranges using 'unionVersionRanges'.-newtype DepMapUnion = DepMapUnion { unDepMapUnion :: Map PackageName (VersionRange, Set LibraryName) }+-- | A map of package constraints that combines version ranges using 'unionVersionRanges'.+newtype DepMapUnion = DepMapUnion { unDepMapUnion :: Map PackageName (VersionRange, NonEmptySet LibraryName) } --- An union of versions should correspond to an intersection of the components.--- The intersection may not be necessary.-unionVersionRanges' :: (VersionRange, Set LibraryName)- -> (VersionRange, Set LibraryName)- -> (VersionRange, Set LibraryName)-unionVersionRanges' (vra, csa) (vrb, csb) =- (unionVersionRanges vra vrb, Set.intersection csa csb)+instance Semigroup DepMapUnion where+ DepMapUnion x <> DepMapUnion y = DepMapUnion $+ Map.unionWith unionVersionRanges' x y +unionVersionRanges'+ :: (VersionRange, NonEmptySet LibraryName)+ -> (VersionRange, NonEmptySet LibraryName)+ -> (VersionRange, NonEmptySet LibraryName)+unionVersionRanges' (vr, cs) (vr', cs') = (unionVersionRanges vr vr', cs <> cs')+ toDepMapUnion :: [Dependency] -> DepMapUnion toDepMapUnion ds = DepMapUnion $ Map.fromListWith unionVersionRanges' [ (p,(vr,cs)) | Dependency p vr cs <- ds ] + fromDepMapUnion :: DepMapUnion -> [Dependency] fromDepMapUnion m = [ Dependency p vr cs | (p,(vr,cs)) <- Map.toList (unDepMapUnion m) ] freeVars :: CondTree ConfVar c a -> [FlagName]-freeVars t = [ f | Flag f <- freeVars' t ]+freeVars t = [ f | PackageFlag f <- freeVars' t ] where freeVars' (CondNode _ _ ifs) = concatMap compfv ifs compfv (CondBranch c ct mct) = condfv c ++ freeVars' ct ++ maybe [] freeVars' mct@@ -439,7 +430,7 @@ -- True. -> Platform -- ^ The 'Arch' and 'OS' -> CompilerInfo -- ^ Compiler information- -> [Dependency] -- ^ Additional constraints+ -> [PackageVersionConstraint] -- ^ Additional constraints -> GenericPackageDescription -> Either [Dependency] (PackageDescription, FlagAssignment)@@ -447,7 +438,7 @@ -- description along with the flag assignments chosen. finalizePD userflags enabled satisfyDep (Platform arch os) impl constraints- (GenericPackageDescription pkg flags mb_lib0 sub_libs0 flibs0 exes0 tests0 bms0) = do+ (GenericPackageDescription pkg _ver flags mb_lib0 sub_libs0 flibs0 exes0 tests0 bms0) = do (targetSet, flagVals) <- resolveWithFlags flagChoices enabled os arch impl constraints condTrees check let@@ -479,7 +470,7 @@ ++ map (\(name,tree) -> mapTreeData (SubComp name . CTest) tree) tests0 ++ map (\(name,tree) -> mapTreeData (SubComp name . CBench) tree) bms0 - flagChoices = map (\(MkFlag n _ d manual) -> (n, d2c manual n d)) flags+ flagChoices = map (\(MkPackageFlag n _ d manual) -> (n, d2c manual n d)) flags d2c manual n b = case lookupFlagAssignment n userflags of Just val -> [val] Nothing@@ -516,7 +507,7 @@ -- function. flattenPackageDescription :: GenericPackageDescription -> PackageDescription flattenPackageDescription- (GenericPackageDescription pkg _ mlib0 sub_libs0 flibs0 exes0 tests0 bms0) =+ (GenericPackageDescription pkg _ _ mlib0 sub_libs0 flibs0 exes0 tests0 bms0) = pkg { library = mlib , subLibraries = reverse sub_libs , foreignLibs = reverse flibs@@ -596,3 +587,14 @@ . over (L.packageDescription . L.setupBuildInfo . traverse . L.setupDepends . traverse) f -- cannot be point-free as normal because of higher rank . over (\f' -> L.allCondTrees $ traverseCondTreeC f') (map f)++-- | Walk a 'GenericPackageDescription' and apply @f@ to all nested+-- @build-depends@ fields.+transformAllBuildDependsN :: ([Dependency] -> [Dependency])+ -> GenericPackageDescription+ -> GenericPackageDescription+transformAllBuildDependsN f =+ over (L.traverseBuildInfos . L.targetBuildDepends) f+ . over (L.packageDescription . L.setupBuildInfo . traverse . L.setupDepends) f+ -- cannot be point-free as normal because of higher rank+ . over (\f' -> L.allCondTrees $ traverseCondTreeC f') f
cabal/Cabal/Distribution/PackageDescription/FieldGrammar.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE ConstraintKinds #-} {-# LANGUAGE OverloadedStrings #-} -- | 'GenericPackageDescription' Field descriptions module Distribution.PackageDescription.FieldGrammar (@@ -24,6 +25,14 @@ benchmarkFieldGrammar, validateBenchmark, unvalidateBenchmark,+ -- * Field grammars+ formatDependencyList,+ formatExposedModules,+ formatExtraSourceFiles,+ formatHsSourceDirs,+ formatMixinList,+ formatOtherExtensions,+ formatOtherModules, -- ** Lenses benchmarkStanzaBenchmarkType, benchmarkStanzaMainIs,@@ -39,26 +48,24 @@ buildInfoFieldGrammar, ) where + import Distribution.Compat.Lens import Distribution.Compat.Prelude+import Language.Haskell.Extension import Prelude () import Distribution.CabalSpecVersion import Distribution.Compiler (CompilerFlavor (..), PerCompilerFlavor (..)) import Distribution.FieldGrammar+import Distribution.Fields import Distribution.ModuleName (ModuleName) import Distribution.Package import Distribution.PackageDescription import Distribution.Parsec-import Distribution.Parsec.Newtypes-import Distribution.Fields import Distribution.Pretty (prettyShow)-import Distribution.Types.ExecutableScope-import Distribution.Types.ForeignLib-import Distribution.Types.ForeignLibType-import Distribution.Types.LibraryVisibility-import Distribution.Types.UnqualComponentName-import Distribution.Version (anyVersion)+import Distribution.Types.ModuleReexport+import Distribution.Types.Mixin (Mixin)+import Distribution.Version (Version, VersionRange) import qualified Distribution.SPDX as SPDX @@ -69,25 +76,35 @@ ------------------------------------------------------------------------------- packageDescriptionFieldGrammar- :: (FieldGrammar g, Applicative (g PackageDescription), Applicative (g PackageIdentifier))+ :: ( FieldGrammar c g, Applicative (g PackageDescription), Applicative (g PackageIdentifier)+ , c (Identity BuildType)+ , c (Identity PackageName)+ , c (Identity Version)+ , c (List FSep FilePathNT String)+ , c (List FSep TestedWith (CompilerFlavor, VersionRange))+ , c (List VCat FilePathNT String)+ , c FilePathNT+ , c SpecLicense+ , c SpecVersion+ ) => g PackageDescription PackageDescription packageDescriptionFieldGrammar = PackageDescription- <$> optionalFieldDefAla "cabal-version" SpecVersion L.specVersionRaw (Right anyVersion)+ <$> optionalFieldDefAla "cabal-version" SpecVersion L.specVersion CabalSpecV1_0 <*> blurFieldGrammar L.package packageIdentifierGrammar <*> optionalFieldDefAla "license" SpecLicense L.licenseRaw (Left SPDX.NONE) <*> licenseFilesGrammar- <*> freeTextFieldDef "copyright" L.copyright- <*> freeTextFieldDef "maintainer" L.maintainer- <*> freeTextFieldDef "author" L.author- <*> freeTextFieldDef "stability" L.stability+ <*> freeTextFieldDefST "copyright" L.copyright+ <*> freeTextFieldDefST "maintainer" L.maintainer+ <*> freeTextFieldDefST "author" L.author+ <*> freeTextFieldDefST "stability" L.stability <*> monoidalFieldAla "tested-with" (alaList' FSep TestedWith) L.testedWith- <*> freeTextFieldDef "homepage" L.homepage- <*> freeTextFieldDef "package-url" L.pkgUrl- <*> freeTextFieldDef "bug-reports" L.bugReports+ <*> freeTextFieldDefST "homepage" L.homepage+ <*> freeTextFieldDefST "package-url" L.pkgUrl+ <*> freeTextFieldDefST "bug-reports" L.bugReports <*> pure [] -- source-repos are stanza- <*> freeTextFieldDef "synopsis" L.synopsis- <*> freeTextFieldDef "description" L.description- <*> freeTextFieldDef "category" L.category+ <*> freeTextFieldDefST "synopsis" L.synopsis+ <*> freeTextFieldDefST "description" L.description+ <*> freeTextFieldDefST "category" L.category <*> prefixedFields "x-" L.customFieldsPD <*> optionalField "build-type" L.buildTypeRaw <*> pure Nothing -- custom-setup@@ -101,7 +118,7 @@ -- * Files <*> monoidalFieldAla "data-files" (alaList' VCat FilePathNT) L.dataFiles <*> optionalFieldDefAla "data-dir" FilePathNT L.dataDir ""- <*> monoidalFieldAla "extra-source-files" (alaList' VCat FilePathNT) L.extraSrcFiles+ <*> monoidalFieldAla "extra-source-files" formatExtraSourceFiles L.extraSrcFiles <*> monoidalFieldAla "extra-tmp-files" (alaList' VCat FilePathNT) L.extraTmpFiles <*> monoidalFieldAla "extra-doc-files" (alaList' VCat FilePathNT) L.extraDocFiles where@@ -122,11 +139,28 @@ ------------------------------------------------------------------------------- libraryFieldGrammar- :: (FieldGrammar g, Applicative (g Library), Applicative (g BuildInfo))+ :: ( FieldGrammar c g, Applicative (g Library), Applicative (g BuildInfo)+ , c (Identity LibraryVisibility)+ , c (List CommaFSep (Identity ExeDependency) ExeDependency)+ , c (List CommaFSep (Identity LegacyExeDependency) LegacyExeDependency)+ , c (List CommaFSep (Identity PkgconfigDependency) PkgconfigDependency)+ , c (List CommaVCat (Identity Dependency) Dependency)+ , c (List CommaVCat (Identity Mixin) Mixin)+ , c (List CommaVCat (Identity ModuleReexport) ModuleReexport)+ , c (List FSep (MQuoted Extension) Extension)+ , c (List FSep (MQuoted Language) Language)+ , c (List FSep FilePathNT String)+ , c (List FSep Token String)+ , c (List NoCommaFSep Token' String)+ , c (List VCat (MQuoted ModuleName) ModuleName)+ , c (List VCat FilePathNT String)+ , c (List VCat Token String)+ , c (MQuoted Language)+ ) => LibraryName -> g Library Library libraryFieldGrammar n = Library n- <$> monoidalFieldAla "exposed-modules" (alaList' VCat MQuoted) L.exposedModules+ <$> monoidalFieldAla "exposed-modules" formatExposedModules L.exposedModules <*> monoidalFieldAla "reexported-modules" (alaList CommaVCat) L.reexportedModules <*> monoidalFieldAla "signatures" (alaList' VCat MQuoted) L.signatures ^^^ availableSince CabalSpecV2_0 []@@ -150,7 +184,25 @@ ------------------------------------------------------------------------------- foreignLibFieldGrammar- :: (FieldGrammar g, Applicative (g ForeignLib), Applicative (g BuildInfo))+ :: ( FieldGrammar c g, Applicative (g ForeignLib), Applicative (g BuildInfo)+ , c (Identity ForeignLibType)+ , c (Identity LibVersionInfo)+ , c (Identity Version)+ , c (List CommaFSep (Identity ExeDependency) ExeDependency)+ , c (List CommaFSep (Identity LegacyExeDependency) LegacyExeDependency)+ , c (List CommaFSep (Identity PkgconfigDependency) PkgconfigDependency)+ , c (List CommaVCat (Identity Dependency) Dependency)+ , c (List CommaVCat (Identity Mixin) Mixin)+ , c (List FSep (Identity ForeignLibOption) ForeignLibOption)+ , c (List FSep (MQuoted Extension) Extension)+ , c (List FSep (MQuoted Language) Language)+ , c (List FSep FilePathNT String)+ , c (List FSep Token String)+ , c (List NoCommaFSep Token' String)+ , c (List VCat (MQuoted ModuleName) ModuleName)+ , c (List VCat FilePathNT String), c (List VCat Token String)+ , c (MQuoted Language)+ ) => UnqualComponentName -> g ForeignLib ForeignLib foreignLibFieldGrammar n = ForeignLib n <$> optionalFieldDef "type" L.foreignLibType ForeignLibTypeUnknown@@ -167,7 +219,23 @@ ------------------------------------------------------------------------------- executableFieldGrammar- :: (FieldGrammar g, Applicative (g Executable), Applicative (g BuildInfo))+ :: ( FieldGrammar c g, Applicative (g Executable), Applicative (g BuildInfo)+ , c (Identity ExecutableScope),+ c (List CommaFSep (Identity ExeDependency) ExeDependency),+ c (List+ CommaFSep (Identity LegacyExeDependency) LegacyExeDependency),+ c (List+ CommaFSep (Identity PkgconfigDependency) PkgconfigDependency),+ c (List CommaVCat (Identity Dependency) Dependency),+ c (List CommaVCat (Identity Mixin) Mixin),+ c (List FSep (MQuoted Extension) Extension),+ c (List FSep (MQuoted Language) Language),+ c (List FSep FilePathNT String), c (List FSep Token String),+ c (List NoCommaFSep Token' String),+ c (List VCat (MQuoted ModuleName) ModuleName),+ c (List VCat FilePathNT String), c (List VCat Token String),+ c (MQuoted Language)+ ) => UnqualComponentName -> g Executable Executable executableFieldGrammar n = Executable n -- main-is is optional as conditional blocks don't have it@@ -211,7 +279,24 @@ {-# INLINE testStanzaBuildInfo #-} testSuiteFieldGrammar- :: (FieldGrammar g, Applicative (g TestSuiteStanza), Applicative (g BuildInfo))+ :: ( FieldGrammar c g, Applicative (g TestSuiteStanza), Applicative (g BuildInfo)+ , c (Identity ModuleName)+ , c (Identity TestType)+ , c (List CommaFSep (Identity ExeDependency) ExeDependency)+ , c (List CommaFSep (Identity LegacyExeDependency) LegacyExeDependency)+ , c (List CommaFSep (Identity PkgconfigDependency) PkgconfigDependency)+ , c (List CommaVCat (Identity Dependency) Dependency)+ , c (List CommaVCat (Identity Mixin) Mixin)+ , c (List FSep (MQuoted Extension) Extension)+ , c (List FSep (MQuoted Language) Language)+ , c (List FSep FilePathNT String)+ , c (List FSep Token String)+ , c (List NoCommaFSep Token' String)+ , c (List VCat (MQuoted ModuleName) ModuleName)+ , c (List VCat FilePathNT String)+ , c (List VCat Token String)+ , c (MQuoted Language)+ ) => g TestSuiteStanza TestSuiteStanza testSuiteFieldGrammar = TestSuiteStanza <$> optionalField "type" testStanzaTestType@@ -313,7 +398,24 @@ {-# INLINE benchmarkStanzaBuildInfo #-} benchmarkFieldGrammar- :: (FieldGrammar g, Applicative (g BenchmarkStanza), Applicative (g BuildInfo))+ :: ( FieldGrammar c g, Applicative (g BenchmarkStanza), Applicative (g BuildInfo)+ , c (Identity BenchmarkType)+ , c (Identity ModuleName)+ , c (List CommaFSep (Identity ExeDependency) ExeDependency)+ , c (List CommaFSep (Identity LegacyExeDependency) LegacyExeDependency)+ , c (List CommaFSep (Identity PkgconfigDependency) PkgconfigDependency)+ , c (List CommaVCat (Identity Dependency) Dependency)+ , c (List CommaVCat (Identity Mixin) Mixin)+ , c (List FSep (MQuoted Extension) Extension)+ , c (List FSep (MQuoted Language) Language)+ , c (List FSep FilePathNT String)+ , c (List FSep Token String)+ , c (List NoCommaFSep Token' String)+ , c (List VCat (MQuoted ModuleName) ModuleName)+ , c (List VCat FilePathNT String)+ , c (List VCat Token String)+ , c (MQuoted Language)+ ) => g BenchmarkStanza BenchmarkStanza benchmarkFieldGrammar = BenchmarkStanza <$> optionalField "type" benchmarkStanzaBenchmarkType@@ -373,7 +475,22 @@ ------------------------------------------------------------------------------- buildInfoFieldGrammar- :: (FieldGrammar g, Applicative (g BuildInfo))+ :: ( FieldGrammar c g, Applicative (g BuildInfo)+ , c (List CommaFSep (Identity ExeDependency) ExeDependency)+ , c (List CommaFSep (Identity LegacyExeDependency) LegacyExeDependency)+ , c (List CommaFSep (Identity PkgconfigDependency) PkgconfigDependency)+ , c (List CommaVCat (Identity Dependency) Dependency)+ , c (List CommaVCat (Identity Mixin) Mixin)+ , c (List FSep (MQuoted Extension) Extension)+ , c (List FSep (MQuoted Language) Language)+ , c (List FSep FilePathNT String)+ , c (List FSep Token String)+ , c (List NoCommaFSep Token' String)+ , c (List VCat (MQuoted ModuleName) ModuleName)+ , c (List VCat FilePathNT String)+ , c (List VCat Token String)+ , c (MQuoted Language)+ ) => g BuildInfo BuildInfo buildInfoFieldGrammar = BuildInfo <$> booleanFieldDef "buildable" L.buildable True@@ -409,14 +526,19 @@ ^^^ availableSince CabalSpecV2_2 [] <*> monoidalFieldAla "js-sources" (alaList' VCat FilePathNT) L.jsSources <*> hsSourceDirsGrammar- <*> monoidalFieldAla "other-modules" (alaList' VCat MQuoted) L.otherModules+ <*> monoidalFieldAla "other-modules" formatOtherModules L.otherModules <*> monoidalFieldAla "virtual-modules" (alaList' VCat MQuoted) L.virtualModules ^^^ availableSince CabalSpecV2_2 [] <*> monoidalFieldAla "autogen-modules" (alaList' VCat MQuoted) L.autogenModules+ ^^^ availableSince CabalSpecV2_0 [] <*> optionalFieldAla "default-language" MQuoted L.defaultLanguage+ ^^^ availableSince CabalSpecV1_10 Nothing <*> monoidalFieldAla "other-languages" (alaList' FSep MQuoted) L.otherLanguages+ ^^^ availableSince CabalSpecV1_10 [] <*> monoidalFieldAla "default-extensions" (alaList' FSep MQuoted) L.defaultExtensions- <*> monoidalFieldAla "other-extensions" (alaList' FSep MQuoted) L.otherExtensions+ ^^^ availableSince CabalSpecV1_10 []+ <*> monoidalFieldAla "other-extensions" formatOtherExtensions L.otherExtensions+ ^^^ availableSince CabalSpecV1_10 [] <*> monoidalFieldAla "extensions" (alaList' FSep MQuoted) L.oldExtensions ^^^ deprecatedSince CabalSpecV1_12 "Please use 'default-extensions' or 'other-extensions' fields."@@ -439,17 +561,17 @@ <*> sharedOptionsFieldGrammar <*> pure mempty -- static-options ??? <*> prefixedFields "x-" L.customFieldsBI- <*> monoidalFieldAla "build-depends" (alaList CommaVCat) L.targetBuildDepends- <*> monoidalFieldAla "mixins" (alaList CommaVCat) L.mixins+ <*> monoidalFieldAla "build-depends" formatDependencyList L.targetBuildDepends+ <*> monoidalFieldAla "mixins" formatMixinList L.mixins ^^^ availableSince CabalSpecV2_0 [] {-# SPECIALIZE buildInfoFieldGrammar :: ParsecFieldGrammar' BuildInfo #-} {-# SPECIALIZE buildInfoFieldGrammar :: PrettyFieldGrammar' BuildInfo #-} hsSourceDirsGrammar- :: (FieldGrammar g, Applicative (g BuildInfo))+ :: (FieldGrammar c g, Applicative (g BuildInfo), c (List FSep FilePathNT FilePath)) => g BuildInfo [FilePath] hsSourceDirsGrammar = (++)- <$> monoidalFieldAla "hs-source-dirs" (alaList' FSep FilePathNT) L.hsSourceDirs+ <$> monoidalFieldAla "hs-source-dirs" formatHsSourceDirs L.hsSourceDirs <*> monoidalFieldAla "hs-source-dir" (alaList' FSep FilePathNT) wrongLens --- https://github.com/haskell/cabal/commit/49e3cdae3bdf21b017ccd42e66670ca402e22b44 ^^^ deprecatedSince CabalSpecV1_2 "Please use 'hs-source-dirs'"@@ -460,7 +582,7 @@ wrongLens f bi = (\fps -> set L.hsSourceDirs fps bi) <$> f [] optionsFieldGrammar- :: (FieldGrammar g, Applicative (g BuildInfo))+ :: (FieldGrammar c g, Applicative (g BuildInfo), c (List NoCommaFSep Token' String)) => g BuildInfo (PerCompilerFlavor [String]) optionsFieldGrammar = PerCompilerFlavor <$> monoidalFieldAla "ghc-options" (alaList' NoCommaFSep Token') (extract GHC)@@ -476,7 +598,7 @@ extract flavor = L.options . lookupLens flavor profOptionsFieldGrammar- :: (FieldGrammar g, Applicative (g BuildInfo))+ :: (FieldGrammar c g, Applicative (g BuildInfo), c (List NoCommaFSep Token' String)) => g BuildInfo (PerCompilerFlavor [String]) profOptionsFieldGrammar = PerCompilerFlavor <$> monoidalFieldAla "ghc-prof-options" (alaList' NoCommaFSep Token') (extract GHC)@@ -486,7 +608,7 @@ extract flavor = L.profOptions . lookupLens flavor sharedOptionsFieldGrammar- :: (FieldGrammar g, Applicative (g BuildInfo))+ :: (FieldGrammar c g, Applicative (g BuildInfo), c (List NoCommaFSep Token' String)) => g BuildInfo (PerCompilerFlavor [String]) sharedOptionsFieldGrammar = PerCompilerFlavor <$> monoidalFieldAla "ghc-shared-options" (alaList' NoCommaFSep Token') (extract GHC)@@ -506,21 +628,21 @@ ------------------------------------------------------------------------------- flagFieldGrammar- :: (FieldGrammar g, Applicative (g Flag))- => FlagName -> g Flag Flag-flagFieldGrammar name = MkFlag name+ :: (FieldGrammar c g, Applicative (g PackageFlag))+ => FlagName -> g PackageFlag PackageFlag+flagFieldGrammar name = MkPackageFlag name <$> freeTextFieldDef "description" L.flagDescription <*> booleanFieldDef "default" L.flagDefault True <*> booleanFieldDef "manual" L.flagManual False-{-# SPECIALIZE flagFieldGrammar :: FlagName -> ParsecFieldGrammar' Flag #-}-{-# SPECIALIZE flagFieldGrammar :: FlagName -> PrettyFieldGrammar' Flag #-}+{-# SPECIALIZE flagFieldGrammar :: FlagName -> ParsecFieldGrammar' PackageFlag #-}+{-# SPECIALIZE flagFieldGrammar :: FlagName -> PrettyFieldGrammar' PackageFlag #-} ------------------------------------------------------------------------------- -- SourceRepo ------------------------------------------------------------------------------- sourceRepoFieldGrammar- :: (FieldGrammar g, Applicative (g SourceRepo))+ :: (FieldGrammar c g, Applicative (g SourceRepo), c (Identity RepoType), c Token, c FilePathNT) => RepoKind -> g SourceRepo SourceRepo sourceRepoFieldGrammar kind = SourceRepo kind <$> optionalField "type" L.repoType@@ -530,16 +652,41 @@ <*> optionalFieldAla "tag" Token L.repoTag <*> optionalFieldAla "subdir" FilePathNT L.repoSubdir {-# SPECIALIZE sourceRepoFieldGrammar :: RepoKind -> ParsecFieldGrammar' SourceRepo #-}-{-# SPECIALIZE sourceRepoFieldGrammar :: RepoKind ->PrettyFieldGrammar' SourceRepo #-}+{-# SPECIALIZE sourceRepoFieldGrammar :: RepoKind -> PrettyFieldGrammar' SourceRepo #-} ------------------------------------------------------------------------------- -- SetupBuildInfo ------------------------------------------------------------------------------- setupBInfoFieldGrammar- :: (FieldGrammar g, Functor (g SetupBuildInfo))+ :: (FieldGrammar c g, Functor (g SetupBuildInfo), c (List CommaVCat (Identity Dependency) Dependency)) => Bool -> g SetupBuildInfo SetupBuildInfo setupBInfoFieldGrammar def = flip SetupBuildInfo def <$> monoidalFieldAla "setup-depends" (alaList CommaVCat) L.setupDepends {-# SPECIALIZE setupBInfoFieldGrammar :: Bool -> ParsecFieldGrammar' SetupBuildInfo #-}-{-# SPECIALIZE setupBInfoFieldGrammar :: Bool ->PrettyFieldGrammar' SetupBuildInfo #-}+{-# SPECIALIZE setupBInfoFieldGrammar :: Bool -> PrettyFieldGrammar' SetupBuildInfo #-}++-------------------------------------------------------------------------------+-- Define how field values should be formatted for 'pretty'.+-------------------------------------------------------------------------------++formatDependencyList :: [Dependency] -> List CommaVCat (Identity Dependency) Dependency+formatDependencyList = alaList CommaVCat++formatMixinList :: [Mixin] -> List CommaVCat (Identity Mixin) Mixin+formatMixinList = alaList CommaVCat++formatExtraSourceFiles :: [FilePath] -> List VCat FilePathNT FilePath+formatExtraSourceFiles = alaList' VCat FilePathNT++formatExposedModules :: [ModuleName] -> List VCat (MQuoted ModuleName) ModuleName+formatExposedModules = alaList' VCat MQuoted++formatHsSourceDirs :: [FilePath] -> List FSep FilePathNT FilePath+formatHsSourceDirs = alaList' FSep FilePathNT++formatOtherExtensions :: [Extension] -> List FSep (MQuoted Extension) Extension+formatOtherExtensions = alaList' FSep MQuoted++formatOtherModules :: [ModuleName] -> List VCat (MQuoted ModuleName) ModuleName+formatOtherModules = alaList' VCat MQuoted
cabal/Cabal/Distribution/PackageDescription/Parsec.hs view
@@ -35,11 +35,8 @@ import Distribution.Compat.Prelude import Prelude () -import Control.Applicative (Const (..))-import Control.Monad (guard) import Control.Monad.State.Strict (StateT, execStateT) import Control.Monad.Trans.Class (lift)-import Data.List (partition) import Distribution.CabalSpecVersion import Distribution.Compat.Lens import Distribution.FieldGrammar@@ -50,40 +47,32 @@ import Distribution.Fields.Parser import Distribution.Fields.ParseResult import Distribution.PackageDescription-import Distribution.PackageDescription.Configuration (freeVars)+import Distribution.PackageDescription.Configuration (freeVars, transformAllBuildInfos) import Distribution.PackageDescription.FieldGrammar import Distribution.PackageDescription.Quirks (patchQuirks)-import Distribution.Parsec (parsec, simpleParsec)+import Distribution.Parsec (parsec, simpleParsecBS) import Distribution.Parsec.FieldLineStream (fieldLineStreamFromBS)-import Distribution.Parsec.Newtypes (CommaFSep, List, SpecVersion (..), Token) import Distribution.Parsec.Position (Position (..), zeroPos) import Distribution.Parsec.Warning (PWarnType (..)) import Distribution.Pretty (prettyShow)-import Distribution.Simple.Utils (fromUTF8BS)-import Distribution.Types.CondTree-import Distribution.Types.Dependency (Dependency)-import Distribution.Types.ForeignLib-import Distribution.Types.ForeignLibType (knownForeignLibTypes)-import Distribution.Types.GenericPackageDescription (emptyGenericPackageDescription)-import Distribution.Types.LibraryVisibility (LibraryVisibility (..))-import Distribution.Types.PackageDescription (specVersion')-import Distribution.Types.UnqualComponentName (UnqualComponentName, mkUnqualComponentName)+import Distribution.Simple.Utils (fromUTF8BS, toUTF8BS)+import Distribution.Types.Mixin (Mixin (..), mkMixin) import Distribution.Utils.Generic (breakMaybe, unfoldrM, validateUTF8) import Distribution.Verbosity (Verbosity)-import Distribution.Version- (LowerBound (..), Version, asVersionIntervals, mkVersion, orLaterVersion, version0,- versionNumbers)+import Distribution.Version (Version, mkVersion, versionNumbers) import qualified Data.ByteString as BS import qualified Data.ByteString.Char8 as BS8 import qualified Data.Map.Strict as Map import qualified Data.Set as Set import qualified Distribution.Compat.Newtype as Newtype+import qualified Distribution.Compat.NonEmptySet as NES import qualified Distribution.Types.BuildInfo.Lens as L import qualified Distribution.Types.Executable.Lens as L import qualified Distribution.Types.ForeignLib.Lens as L import qualified Distribution.Types.GenericPackageDescription.Lens as L import qualified Distribution.Types.PackageDescription.Lens as L+import qualified Distribution.Types.SetupBuildInfo.Lens as L import qualified Text.Parsec as P -- ---------------------------------------------------------------@@ -104,18 +93,21 @@ parseGenericPackageDescription bs = do -- set scanned version setCabalSpecVersion ver- -- if we get too new version, fail right away- case ver of- Just v | v > mkVersion [3,0] -> parseFailure zeroPos- "Unsupported cabal-version. See https://github.com/haskell/cabal/issues/4899."- _ -> pure () - case readFields' bs' of+ csv <- case ver of+ -- if we get too new version, fail right away+ Just v -> case cabalSpecFromVersionDigits (versionNumbers v) of+ Just csv -> return (Just csv)+ Nothing -> parseFatalFailure zeroPos $+ "Unsupported cabal-version " ++ prettyShow v ++ ". See https://github.com/haskell/cabal/issues/4899."+ _ -> pure Nothing++ case readFields' bs'' of Right (fs, lexWarnings) -> do when patched $ parseWarning zeroPos PWTQuirkyCabalFile "Legacy cabal file" -- UTF8 is validated in a prepass step, afterwards parsing is lenient.- parseGenericPackageDescription' ver lexWarnings (validateUTF8 bs') fs+ parseGenericPackageDescription' csv lexWarnings invalidUtf8 fs -- TODO: better marshalling of errors Left perr -> parseFatalFailure pos (show perr) where ppos = P.errorPos perr@@ -124,6 +116,14 @@ (patched, bs') = patchQuirks bs ver = scanSpecVersion bs' + invalidUtf8 = validateUTF8 bs'++ -- if there are invalid utf8 characters, we make the bytestring valid.+ bs'' = case invalidUtf8 of+ Nothing -> bs'+ Just _ -> toUTF8BS (fromUTF8BS bs')++ -- | 'Maybe' variant of 'parseGenericPackageDescription' parseGenericPackageDescriptionMaybe :: BS.ByteString -> Maybe GenericPackageDescription parseGenericPackageDescriptionMaybe =@@ -155,12 +155,12 @@ -- * first we parse fields of PackageDescription -- * then we parse sections (libraries, executables, etc) parseGenericPackageDescription'- :: Maybe Version+ :: Maybe CabalSpecVersion -> [LexWarning] -> Maybe Int -> [Field Position] -> ParseResult GenericPackageDescription-parseGenericPackageDescription' cabalVerM lexWarnings utf8WarnPos fs = do+parseGenericPackageDescription' scannedVer lexWarnings utf8WarnPos fs = do parseWarnings (toPWarnings lexWarnings) for_ utf8WarnPos $ \pos -> parseWarning zeroPos PWTUTF $ "UTF8 encoding problem at byte offset " ++ show pos@@ -168,45 +168,52 @@ let (fields, sectionFields) = takeFields fs' -- cabal-version- cabalVer <- case cabalVerM of+ specVer <- case scannedVer of Just v -> return v Nothing -> case Map.lookup "cabal-version" fields >>= safeLast of- Nothing -> return version0+ Nothing -> return CabalSpecV1_0 Just (MkNamelessField pos fls) -> do- v <- specVersion' . Newtype.unpack' SpecVersion <$> runFieldParser pos parsec cabalSpecLatest fls- when (v >= mkVersion [2,1]) $ parseFailure pos $+ -- version will be parsed twice, therefore we parse without warnings.+ v <- withoutWarnings $+ Newtype.unpack' SpecVersion <$>+ -- Use version with || and && but before addition of ^>= and removal of -any+ runFieldParser pos parsec CabalSpecV1_24 fls++ -- if it were at the beginning, scanner would found it+ when (v >= CabalSpecV2_2) $ parseFailure pos $ "cabal-version should be at the beginning of the file starting with spec version 2.2. " ++ "See https://github.com/haskell/cabal/issues/4899" return v - let specVer = cabalSpecFromVersionDigits (versionNumbers cabalVer)-- -- reset cabal version- setCabalSpecVersion (Just cabalVer)+ -- reset cabal version, it might not be set+ let specVer' = mkVersion (cabalSpecToVersionDigits specVer)+ setCabalSpecVersion (Just specVer') -- Package description pd <- parseFieldGrammar specVer fields packageDescriptionFieldGrammar -- Check that scanned and parsed versions match.- unless (cabalVer == specVersion pd) $ parseFailure zeroPos $+ unless (specVer == specVersion pd) $ parseFailure zeroPos $ "Scanned and parsed cabal-versions don't match " ++- prettyShow cabalVer ++ " /= " ++ prettyShow (specVersion pd)+ prettyShow (SpecVersion specVer) ++ " /= " ++ prettyShow (SpecVersion (specVersion pd)) maybeWarnCabalVersion syntax pd -- Sections- let gpd = emptyGenericPackageDescription & L.packageDescription .~ pd+ let gpd = emptyGenericPackageDescription+ & L.packageDescription .~ pd gpd1 <- view stateGpd <$> execStateT (goSections specVer sectionFields) (SectionS gpd Map.empty) - checkForUndefinedFlags gpd1- return gpd1+ let gpd2 = postProcessInternalDeps specVer gpd1+ checkForUndefinedFlags gpd2+ gpd2 `deepseq` return gpd2 where safeLast :: [a] -> Maybe a safeLast = listToMaybe . reverse - newSyntaxVersion :: Version- newSyntaxVersion = mkVersion [1, 2]+ newSyntaxVersion :: CabalSpecVersion+ newSyntaxVersion = CabalSpecV1_2 maybeWarnCabalVersion :: Syntax -> PackageDescription -> ParseResult () maybeWarnCabalVersion syntax pkg@@ -219,14 +226,8 @@ | syntax == OldSyntax && specVersion pkg >= newSyntaxVersion = parseWarning zeroPos PWTOldSyntax $ "A package using 'cabal-version: "- ++ displaySpecVersion (specVersionRaw pkg)+ ++ prettyShow (SpecVersion (specVersion pkg)) ++ "' must use section syntax. See the Cabal user guide for details."- where- displaySpecVersion (Left version) = prettyShow version- displaySpecVersion (Right versionRange) =- case asVersionIntervals versionRange of- [] {- impossible -} -> prettyShow versionRange- ((LowerBound version _, _):_) -> prettyShow (orLaterVersion version) maybeWarnCabalVersion _ _ = return () @@ -691,6 +692,92 @@ f ct = Const (Set.fromList (freeVars ct)) -------------------------------------------------------------------------------+-- Post processing of internal dependencies+-------------------------------------------------------------------------------++-- Note [Dependencies on sublibraries]+-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+--+-- This is solution to https://github.com/haskell/cabal/issues/6083+--+-- Before 'cabal-version: 3.0' we didn't have a syntax specially+-- for referring to internal libraries. Internal library names+-- shadowed the outside ones.+--+-- Since 'cabal-version: 3.0' we have ability to write+--+-- build-depends: some-package:its-sub-lib >=1.2.3+--+-- This allows us to refer also to local packages by `this-package:sublib`.+-- So since 'cabal-version: 3.4' to refer to *any*+-- sublibrary we must use the two part syntax. Here's small table:+--+-- | pre-3.4 | 3.4 and after |+-- ------------------|---------------------|-------------------------------|+-- pkg-name | may refer to sublib | always refers to external pkg |+-- pkg-name:sublib | refers to sublib | refers to sublib |+-- pkg-name:pkg-name | may refer to sublib | always refers to external pkg |+--+-- In pre-3.4 case, if a package 'this-pkg' has a sublibrary 'pkg-name',+-- all dependency definitions will refer to that sublirary.+--+-- In 3.4 and after case, 'pkg-name' will always refer to external package,+-- and to use internal library you have to say 'this-pkg:pkg-name'.+--+-- In summary, In 3.4 and after, the internal names don't shadow,+-- as there is an explicit syntax to refer to them,+-- i.e. what you write is what you get;+-- For pre-3.4 we post-process the file.+--+-- Similarly, we process mixins.+-- See https://github.com/haskell/cabal/issues/6281+--++postProcessInternalDeps :: CabalSpecVersion -> GenericPackageDescription -> GenericPackageDescription+postProcessInternalDeps specVer gpd+ | specVer >= CabalSpecV3_4 = gpd+ | otherwise = transformAllBuildInfos transformBI transformSBI gpd+ where+ transformBI :: BuildInfo -> BuildInfo+ transformBI+ = over L.targetBuildDepends (concatMap transformD)+ . over L.mixins (map transformM)++ transformSBI :: SetupBuildInfo -> SetupBuildInfo+ transformSBI = over L.setupDepends (concatMap transformD)++ transformD :: Dependency -> [Dependency]+ transformD (Dependency pn vr ln)+ | uqn `Set.member` internalLibs+ , LMainLibName `NES.member` ln+ = case NES.delete LMainLibName ln of+ Nothing -> [dep]+ Just ln' -> [dep, Dependency pn vr ln']+ where+ uqn = packageNameToUnqualComponentName pn+ dep = Dependency thisPn vr (NES.singleton (LSubLibName uqn))++ transformD d = [d]++ transformM :: Mixin -> Mixin+ transformM (Mixin pn LMainLibName incl)+ | uqn `Set.member` internalLibs+ = mkMixin thisPn (LSubLibName uqn) incl+ where+ uqn = packageNameToUnqualComponentName pn++ transformM m = m++ thisPn :: PackageName+ thisPn = pkgName (package (packageDescription gpd))++ internalLibs :: Set UnqualComponentName+ internalLibs = Set.fromList+ [ n+ | (n, _) <- condSubLibraries gpd+ ]++------------------------------------------------------------------------------- -- Old syntax ------------------------------------------------------------------------------- @@ -822,6 +909,10 @@ | otherwise = Nothing isExecutableField _ = Nothing +-------------------------------------------------------------------------------+-- Scan of spec version+-------------------------------------------------------------------------------+ -- | Quickly scan new-style spec-version -- -- A new-style spec-version declaration begins the .cabal file and@@ -852,7 +943,7 @@ -- -- This is currently more tolerant regarding leading 0 digits. --- ver <- simpleParsec (BS8.unpack vers)+ ver <- simpleParsecBS vers guard $ case versionNumbers ver of [_,_] -> True [_,_,_] -> True
cabal/Cabal/Distribution/PackageDescription/PrettyPrint.hs view
@@ -31,47 +31,41 @@ import Distribution.Compat.Prelude import Prelude () -import Distribution.Types.CondTree-import Distribution.Types.Dependency-import Distribution.Types.ForeignLib (ForeignLib (foreignLibName))-import Distribution.Types.LibraryName-import Distribution.Types.UnqualComponentName- import Distribution.CabalSpecVersion import Distribution.Fields.Pretty+import Distribution.Compat.Lens import Distribution.PackageDescription import Distribution.Pretty-import Distribution.Simple.Utils-import Distribution.Types.Version (versionNumbers)--import Distribution.FieldGrammar (PrettyFieldGrammar', prettyFieldGrammar)+import Distribution.Simple.Utils (writeFileAtomic, writeUTF8File)+import Distribution.Types.Mixin (Mixin (..), mkMixin)+import Distribution.FieldGrammar (PrettyFieldGrammar', prettyFieldGrammar)+import Distribution.PackageDescription.Configuration (transformAllBuildInfos) import Distribution.PackageDescription.FieldGrammar- (benchmarkFieldGrammar, buildInfoFieldGrammar, executableFieldGrammar, flagFieldGrammar,- foreignLibFieldGrammar, libraryFieldGrammar, packageDescriptionFieldGrammar,- setupBInfoFieldGrammar, sourceRepoFieldGrammar, testSuiteFieldGrammar)+ (benchmarkFieldGrammar, buildInfoFieldGrammar, executableFieldGrammar, flagFieldGrammar, foreignLibFieldGrammar, libraryFieldGrammar,+ packageDescriptionFieldGrammar, setupBInfoFieldGrammar, sourceRepoFieldGrammar, testSuiteFieldGrammar) import qualified Distribution.PackageDescription.FieldGrammar as FG+import qualified Distribution.Types.BuildInfo.Lens as L+import qualified Distribution.Types.SetupBuildInfo.Lens as L -import Text.PrettyPrint (Doc, char, hsep, parens, text, (<+>))+import Text.PrettyPrint (Doc, char, hsep, parens, text) -import qualified Data.ByteString.Lazy.Char8 as BS.Char8+import qualified Data.ByteString.Lazy.Char8 as BS.Char8+import qualified Distribution.Compat.NonEmptySet as NES -- | Writes a .cabal file from a generic package description-writeGenericPackageDescription :: FilePath -> GenericPackageDescription -> NoCallStackIO ()+writeGenericPackageDescription :: FilePath -> GenericPackageDescription -> IO () writeGenericPackageDescription fpath pkg = writeUTF8File fpath (showGenericPackageDescription pkg) -- | Writes a generic package description to a string showGenericPackageDescription :: GenericPackageDescription -> String showGenericPackageDescription gpd = showFields (const []) $ ppGenericPackageDescription v gpd where- v = cabalSpecFromVersionDigits- $ versionNumbers- $ specVersion- $ packageDescription gpd+ v = specVersion $ packageDescription gpd -- | Convert a generic package description to 'PrettyField's. ppGenericPackageDescription :: CabalSpecVersion -> GenericPackageDescription -> [PrettyField ()]-ppGenericPackageDescription v gpd = concat+ppGenericPackageDescription v gpd0 = concat [ ppPackageDescription v (packageDescription gpd) , ppSetupBInfo v (setupBuildInfo (packageDescription gpd)) , ppGenPackageFlags v (genPackageFlags gpd)@@ -82,7 +76,10 @@ , ppCondTestSuites v (condTestSuites gpd) , ppCondBenchmarks v (condBenchmarks gpd) ]+ where+ gpd = preProcessInternalDeps (specVersion (packageDescription gpd0)) gpd0 + ppPackageDescription :: CabalSpecVersion -> PackageDescription -> [PrettyField ()] ppPackageDescription v pd = prettyFieldGrammar v packageDescriptionFieldGrammar pd@@ -104,11 +101,11 @@ | otherwise = pure $ PrettySection () "custom-setup" [] $ prettyFieldGrammar v (setupBInfoFieldGrammar False) sbi -ppGenPackageFlags :: CabalSpecVersion -> [Flag] -> [PrettyField ()]+ppGenPackageFlags :: CabalSpecVersion -> [PackageFlag] -> [PrettyField ()] ppGenPackageFlags = map . ppFlag -ppFlag :: CabalSpecVersion -> Flag -> PrettyField ()-ppFlag v flag@(MkFlag name _ _ _) = PrettySection () "flag" [ppFlagName name] $+ppFlag :: CabalSpecVersion -> PackageFlag -> PrettyField ()+ppFlag v flag@(MkPackageFlag name _ _ _) = PrettySection () "flag" [ppFlagName name] $ prettyFieldGrammar v (flagFieldGrammar name) flag ppCondTree2 :: CabalSpecVersion -> PrettyFieldGrammar' s -> CondTree ConfVar [Dependency] s -> [PrettyField ()]@@ -180,10 +177,10 @@ ppCondition (CAnd c1 c2) = parens (hsep [ppCondition c1, text "&&" <+> ppCondition c2]) ppConfVar :: ConfVar -> Doc-ppConfVar (OS os) = text "os" <<>> parens (pretty os)-ppConfVar (Arch arch) = text "arch" <<>> parens (pretty arch)-ppConfVar (Flag name) = text "flag" <<>> parens (ppFlagName name)-ppConfVar (Impl c v) = text "impl" <<>> parens (pretty c <+> pretty v)+ppConfVar (OS os) = text "os" <<>> parens (pretty os)+ppConfVar (Arch arch) = text "arch" <<>> parens (pretty arch)+ppConfVar (PackageFlag name) = text "flag" <<>> parens (ppFlagName name)+ppConfVar (Impl c v) = text "impl" <<>> parens (pretty c <+> pretty v) ppFlagName :: FlagName -> Doc ppFlagName = text . unFlagName@@ -192,7 +189,7 @@ ppIfCondition c = PrettySection () "if" [ppCondition c] -- | @since 2.0.0.2-writePackageDescription :: FilePath -> PackageDescription -> NoCallStackIO ()+writePackageDescription :: FilePath -> PackageDescription -> IO () writePackageDescription fpath pkg = writeUTF8File fpath (showPackageDescription pkg) --TODO: make this use section syntax@@ -205,6 +202,7 @@ pdToGpd :: PackageDescription -> GenericPackageDescription pdToGpd pd = GenericPackageDescription { packageDescription = pd+ , gpdScannedVersion = Nothing , genPackageFlags = [] , condLibrary = mkCondTree <$> library pd , condSubLibraries = mkCondTreeL <$> subLibraries pd@@ -224,8 +222,54 @@ -> a -> (UnqualComponentName, CondTree ConfVar [Dependency] a) mkCondTree' f x = (f x, CondNode x [] []) +-------------------------------------------------------------------------------+-- Internal libs+-------------------------------------------------------------------------------++-- See Note [Dependencies on sublibraries] in Distribution.PackageDescription.Parsec+--+preProcessInternalDeps :: CabalSpecVersion -> GenericPackageDescription -> GenericPackageDescription+preProcessInternalDeps specVer gpd+ | specVer >= CabalSpecV3_4 = gpd+ | otherwise = transformAllBuildInfos transformBI transformSBI gpd+ where+ transformBI :: BuildInfo -> BuildInfo+ transformBI+ = over L.targetBuildDepends (concatMap transformD)+ . over L.mixins (map transformM)++ transformSBI :: SetupBuildInfo -> SetupBuildInfo+ transformSBI = over L.setupDepends (concatMap transformD)++ transformD :: Dependency -> [Dependency]+ transformD (Dependency pn vr ln)+ | pn == thisPn+ = if LMainLibName `NES.member` ln+ then Dependency thisPn vr mainLibSet : sublibs+ else sublibs+ where+ sublibs =+ [ Dependency (unqualComponentNameToPackageName uqn) vr mainLibSet+ | LSubLibName uqn <- NES.toList ln+ ]++ transformD d = [d]++ transformM :: Mixin -> Mixin+ transformM (Mixin pn (LSubLibName uqn) inc)+ | pn == thisPn+ = mkMixin (unqualComponentNameToPackageName uqn) LMainLibName inc+ transformM m = m++ thisPn :: PackageName+ thisPn = pkgName (package (packageDescription gpd))++-------------------------------------------------------------------------------+-- HookedBuildInfo+-------------------------------------------------------------------------------+ -- | @since 2.0.0.2-writeHookedBuildInfo :: FilePath -> HookedBuildInfo -> NoCallStackIO ()+writeHookedBuildInfo :: FilePath -> HookedBuildInfo -> IO () writeHookedBuildInfo fpath = writeFileAtomic fpath . BS.Char8.pack . showHookedBuildInfo
cabal/Cabal/Distribution/PackageDescription/Quirks.hs view
@@ -5,8 +5,8 @@ -- @since 2.2.0.0 module Distribution.PackageDescription.Quirks (patchQuirks) where -import Distribution.Compat.MD5 import Distribution.Compat.Prelude+import Distribution.Utils.MD5 import GHC.Fingerprint (Fingerprint (..)) import Prelude () @@ -250,13 +250,30 @@ (Fingerprint 12475837388692175691 18053834261188158945) (Fingerprint 16279938253437334942 15753349540193002309) (bsReplace "9223372036854775807" "999")-+ -- Not UTF8+ , mk "Name: nat\nVersion: 0.1\nDescription: Implementation of natural numbers and integers by a binary\n representation. The implementation is supposed to be lazy and\n "+ (Fingerprint 9222512268705577108 13085311382746579495)+ (Fingerprint 17468921266614378430 13221316288008291892)+ (bsReplace "\xf6" "\xc3\xb6")+ -- cabal-version: 2+ , mk "name: streaming-bracketed\nversion: 0.1.0.0\nsynopsis: A resource management decorator for \"streaming\". \ndescription: This package provides a decorator for the Stream type from\n the \"st"+ (Fingerprint 14670044663153191927 1427497586294143829)+ (Fingerprint 9233007756654759985 6571998449003682006)+ (bsReplace "cabal-version: 2" "cabal-version: 2.0")+ , mk "name: streaming-bracketed\nversion: 0.1.0.1\nsynopsis: A resource management decorator for \"streaming\". \ndescription: This package provides a decorator for the Stream type from\n \"stream"+ (Fingerprint 7298738862909203815 10141693276062967842)+ (Fingerprint 1349949738792220441 3593683359695349293)+ (bsReplace "cabal-version: 2" "cabal-version: 2.0")+ , mk "name: zsyntax\nversion: 0.2.0.0\ndescription: An automated theorem prover for Zsyntax, a\n logical calculus for molecular biology inspired by linear logic,\n that can be used to automatically verify biological\n"+ (Fingerprint 17812331267506881875 3005293725141563863)+ (Fingerprint 3445957263137759540 12472369104312474458)+ (bsReplace "cabal-version: 2" "cabal-version: 2.0") ] where mk a b c d = ((a, b), (c, d)) -- | Helper to create entries in patches-_makePatchKey :: FilePath -> (BS.ByteString -> BS.ByteString) -> NoCallStackIO ()+_makePatchKey :: FilePath -> (BS.ByteString -> BS.ByteString) -> IO () _makePatchKey fp transform = do contents <- BS.readFile fp let output = transform contents
cabal/Cabal/Distribution/Parsec.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE BangPatterns #-} {-# LANGUAGE CPP #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE GADTs #-}@@ -9,10 +10,14 @@ runParsecParser, runParsecParser', simpleParsec,+ simpleParsecBS,+ simpleParsec',+ simpleParsecW', lexemeParsec, eitherParsec, explicitEitherParsec,- -- * CabalParsing and and diagnostics+ explicitEitherParsec',+ -- * CabalParsing and diagnostics CabalParsing (..), -- ** Warnings PWarnType (..),@@ -34,25 +39,29 @@ parsecQuoted, parsecMaybeQuoted, parsecCommaList,+ parsecCommaNonEmpty, parsecLeadingCommaList,+ parsecLeadingCommaNonEmpty, parsecOptCommaList, parsecLeadingOptCommaList, parsecStandard, parsecUnqualComponentName, ) where +import Data.ByteString (ByteString) import Data.Char (digitToInt, intToDigit) import Data.List (transpose) import Distribution.CabalSpecVersion import Distribution.Compat.Prelude import Distribution.Parsec.Error (PError (..), showPError)-import Distribution.Parsec.FieldLineStream (FieldLineStream, fieldLineStreamFromString)+import Distribution.Parsec.FieldLineStream (FieldLineStream, fieldLineStreamFromBS, fieldLineStreamFromString) import Distribution.Parsec.Position (Position (..), incPos, retPos, showPos, zeroPos) import Distribution.Parsec.Warning (PWarnType (..), PWarning (..), showPWarning) import Numeric (showIntAtBase) import Prelude () import qualified Distribution.Compat.CharParsing as P+import qualified Distribution.Compat.DList as DList import qualified Distribution.Compat.MonadFail as Fail import qualified Text.Parsec as Parsec @@ -171,6 +180,32 @@ . runParsecParser lexemeParsec "<simpleParsec>" . fieldLineStreamFromString +-- | Like 'simpleParsec' but for 'ByteString'+simpleParsecBS :: Parsec a => ByteString -> Maybe a+simpleParsecBS+ = either (const Nothing) Just+ . runParsecParser lexemeParsec "<simpleParsec>"+ . fieldLineStreamFromBS++-- | Parse a 'String' with 'lexemeParsec' using specific 'CabalSpecVersion'.+--+-- @since 3.4.0.0+simpleParsec' :: Parsec a => CabalSpecVersion -> String -> Maybe a+simpleParsec' spec+ = either (const Nothing) Just+ . runParsecParser' spec lexemeParsec "<simpleParsec>"+ . fieldLineStreamFromString++-- | Parse a 'String' with 'lexemeParsec' using specific 'CabalSpecVersion'.+-- Fail if there are any warnings.+--+-- @since 3.4.0.0+simpleParsecW' :: Parsec a => CabalSpecVersion -> String -> Maybe a+simpleParsecW' spec+ = either (const Nothing) (\(x, ws) -> if null ws then Just x else Nothing)+ . runParsecParser' spec ((,) <$> lexemeParsec <*> liftParsec Parsec.getState) "<simpleParsec>"+ . fieldLineStreamFromString+ -- | Parse a 'String' with 'lexemeParsec'. eitherParsec :: Parsec a => String -> Either String a eitherParsec = explicitEitherParsec parsec@@ -182,6 +217,17 @@ . runParsecParser (parser <* P.spaces) "<eitherParsec>" . fieldLineStreamFromString +-- | Parse a 'String' with given 'ParsecParser' and 'CabalSpecVersion'. Trailing whitespace is accepted.+-- See 'explicitEitherParsec'.+--+-- @since 3.4.0.0+--+explicitEitherParsec' :: CabalSpecVersion -> ParsecParser a -> String -> Either String a+explicitEitherParsec' spec parser+ = either (Left . show) Right+ . runParsecParser' spec (parser <* P.spaces) "<eitherParsec>"+ . fieldLineStreamFromString+ -- | Run 'ParsecParser' with 'cabalSpecLatest'. runParsecParser :: ParsecParser a -> FilePath -> FieldLineStream -> Either Parsec.ParseError a runParsecParser = runParsecParser' cabalSpecLatest@@ -248,6 +294,9 @@ parsecCommaList :: CabalParsing m => m a -> m [a] parsecCommaList p = P.sepBy (p <* P.spaces) (P.char ',' *> P.spaces P.<?> "comma") +parsecCommaNonEmpty :: CabalParsing m => m a -> m (NonEmpty a)+parsecCommaNonEmpty p = P.sepByNonEmpty (p <* P.spaces) (P.char ',' *> P.spaces P.<?> "comma")+ -- | Like 'parsecCommaList' but accept leading or trailing comma. -- -- @@@ -265,6 +314,19 @@ lp = p <* P.spaces comma = P.char ',' *> P.spaces P.<?> "comma" +-- |+--+-- @since 3.4.0.0+parsecLeadingCommaNonEmpty :: CabalParsing m => m a -> m (NonEmpty a)+parsecLeadingCommaNonEmpty p = do+ c <- P.optional comma+ case c of+ Nothing -> P.sepEndByNonEmpty lp comma+ Just _ -> P.sepByNonEmpty lp comma+ where+ lp = p <* P.spaces+ comma = P.char ',' *> P.spaces P.<?> "comma"+ parsecOptCommaList :: CabalParsing m => m a -> m [a] parsecOptCommaList p = P.sepBy (p <* P.spaces) (P.optional comma) where@@ -309,16 +371,66 @@ parsecMaybeQuoted :: CabalParsing m => m a -> m a parsecMaybeQuoted p = parsecQuoted p <|> p -parsecUnqualComponentName :: CabalParsing m => m String-parsecUnqualComponentName = intercalate "-" <$> toList <$> P.sepByNonEmpty component (P.char '-')- where- component :: CabalParsing m => m String- component = do- cs <- P.munch1 isAlphaNum- if all isDigit cs- then fail "all digits in portion of unqualified component name"- else return cs+parsecUnqualComponentName :: forall m. CabalParsing m => m String+parsecUnqualComponentName = state0 DList.empty where+ --+ -- using @kleene@ package we can easily see that+ -- we need only two states to recognize+ -- unqual-component-name+ --+ -- Compare with declarative+ -- 'Distribution.FieldGrammar.Described.reUnqualComponent'.+ --+ -- @+ -- import Kleene+ -- import Kleene.Internal.Pretty+ -- import Algebra.Lattice+ -- import Data.Char+ --+ -- import qualified Data.RangeSet.Map as RSet+ --+ -- main = do+ -- -- this is an approximation, to get an idea.+ -- let component :: RE Char+ -- component = star alphaNum <> alpha <> star alphaNum+ --+ -- alphaNum = alpha \/ num+ -- alpha = unions $ map char ['a'..'z']+ -- num = unions $ map char ['0'..'9']+ --+ -- re :: RE Char+ -- re = component <> star (char '-' <> component)+ --+ -- putPretty re+ -- putPretty $ fromTM re+ -- @ + state0 :: DList.DList Char -> m String+ state0 acc = do+ c <- ch -- <|> fail ("Invalid component, after " ++ DList.toList acc)+ case () of+ _ | isDigit c -> state0 (DList.snoc acc c)+ | isAlphaNum c -> state1 (DList.snoc acc c)+ | c == '-' -> fail ("Empty component, after " ++ DList.toList acc)+ | otherwise -> fail ("Internal error, after " ++ DList.toList acc)++ state1 :: DList.DList Char -> m String+ state1 acc = state1' acc `alt` return (DList.toList acc)++ state1' :: DList.DList Char -> m String+ state1' acc = do+ c <- ch+ case () of+ _ | isAlphaNum c -> state1 (DList.snoc acc c)+ | c == '-' -> state0 (DList.snoc acc c)+ | otherwise -> fail ("Internal error, after " ++ DList.toList acc)++ ch :: m Char+ !ch = P.satisfy (\c -> isAlphaNum c || c == '-')++ alt :: m String -> m String -> m String+ !alt = (<|>)+ stringLiteral :: forall m. P.CharParsing m => m String stringLiteral = lit where lit :: m String@@ -379,7 +491,9 @@ nomore :: m () nomore = P.notFollowedBy anyd <|> toomuch - (low, ex : high) = splitAt bd dps+ (low, ex, high) = case splitAt bd dps of+ (low', ex' : high') -> (low', ex', high')+ (_, _) -> error "escapeCode: Logic error" in ((:) <$> P.choice low <*> atMost (length bds) anyd) <* nomore <|> ((:) <$> ex <*> ([] <$ nomore <|> bounded'' dps bds)) <|> if not (null bds)
− cabal/Cabal/Distribution/Parsec/Newtypes.hs
@@ -1,230 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE FunctionalDependencies #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeSynonymInstances #-}--- | This module provides @newtype@ wrappers to be used with "Distribution.FieldGrammar".-module Distribution.Parsec.Newtypes (- -- * List- alaList,- alaList',- -- ** Modifiers- CommaVCat (..),- CommaFSep (..),- VCat (..),- FSep (..),- NoCommaFSep (..),- Sep (..),- -- ** Type- List,- -- * Version & License- SpecVersion (..),- TestedWith (..),- SpecLicense (..),- -- * Identifiers- Token (..),- Token' (..),- MQuoted (..),- FilePathNT (..),- ) where--import Distribution.Compat.Newtype-import Distribution.Compat.Prelude-import Prelude ()--import Distribution.CabalSpecVersion-import Distribution.Compiler (CompilerFlavor)-import Distribution.License (License)-import Distribution.Parsec-import Distribution.Pretty-import Distribution.Version- (LowerBound (..), Version, VersionRange, anyVersion, asVersionIntervals, mkVersion)-import Text.PrettyPrint (Doc, comma, fsep, punctuate, vcat, (<+>))--import qualified Distribution.Compat.CharParsing as P-import qualified Distribution.SPDX as SPDX---- | Vertical list with commas. Displayed with 'vcat'-data CommaVCat = CommaVCat---- | Paragraph fill list with commas. Displayed with 'fsep'-data CommaFSep = CommaFSep---- | Vertical list with optional commas. Displayed with 'vcat'.-data VCat = VCat---- | Paragraph fill list with optional commas. Displayed with 'fsep'.-data FSep = FSep---- | Paragraph fill list without commas. Displayed with 'fsep'.-data NoCommaFSep = NoCommaFSep--class Sep sep where- prettySep :: Proxy sep -> [Doc] -> Doc-- parseSep :: CabalParsing m => Proxy sep -> m a -> m [a]--instance Sep CommaVCat where- prettySep _ = vcat . punctuate comma- parseSep _ p = do- v <- askCabalSpecVersion- if v >= CabalSpecV2_2 then parsecLeadingCommaList p else parsecCommaList p-instance Sep CommaFSep where- prettySep _ = fsep . punctuate comma- parseSep _ p = do- v <- askCabalSpecVersion- if v >= CabalSpecV2_2 then parsecLeadingCommaList p else parsecCommaList p-instance Sep VCat where- prettySep _ = vcat- parseSep _ p = do- v <- askCabalSpecVersion- if v >= CabalSpecV3_0 then parsecLeadingOptCommaList p else parsecOptCommaList p-instance Sep FSep where- prettySep _ = fsep- parseSep _ p = do- v <- askCabalSpecVersion- if v >= CabalSpecV3_0 then parsecLeadingOptCommaList p else parsecOptCommaList p-instance Sep NoCommaFSep where- prettySep _ = fsep- parseSep _ p = many (p <* P.spaces)---- | List separated with optional commas. Displayed with @sep@, arguments of--- type @a@ are parsed and pretty-printed as @b@.-newtype List sep b a = List { _getList :: [a] }---- | 'alaList' and 'alaList'' are simply 'List', with additional phantom--- arguments to constraint the resulting type------ >>> :t alaList VCat--- alaList VCat :: [a] -> List VCat (Identity a) a------ >>> :t alaList' FSep Token--- alaList' FSep Token :: [String] -> List FSep Token String----alaList :: sep -> [a] -> List sep (Identity a) a-alaList _ = List---- | More general version of 'alaList'.-alaList' :: sep -> (a -> b) -> [a] -> List sep b a-alaList' _ _ = List--instance Newtype [a] (List sep wrapper a)--instance (Newtype a b, Sep sep, Parsec b) => Parsec (List sep b a) where- parsec = pack . map (unpack :: b -> a) <$> parseSep (Proxy :: Proxy sep) parsec--instance (Newtype a b, Sep sep, Pretty b) => Pretty (List sep b a) where- pretty = prettySep (Proxy :: Proxy sep) . map (pretty . (pack :: a -> b)) . unpack---- | Haskell string or @[^ ,]+@-newtype Token = Token { getToken :: String }--instance Newtype String Token--instance Parsec Token where- parsec = pack <$> parsecToken--instance Pretty Token where- pretty = showToken . unpack---- | Haskell string or @[^ ]+@-newtype Token' = Token' { getToken' :: String }--instance Newtype String Token'--instance Parsec Token' where- parsec = pack <$> parsecToken'--instance Pretty Token' where- pretty = showToken . unpack---- | Either @"quoted"@ or @un-quoted@.-newtype MQuoted a = MQuoted { getMQuoted :: a }--instance Newtype a (MQuoted a)--instance Parsec a => Parsec (MQuoted a) where- parsec = pack <$> parsecMaybeQuoted parsec--instance Pretty a => Pretty (MQuoted a) where- pretty = pretty . unpack---- | Version range or just version, i.e. @cabal-version@ field.------ There are few things to consider:------ * Starting with 2.2 the cabal-version field should be the first field in the--- file and only exact version is accepted. Therefore if we get e.g.--- @>= 2.2@, we fail.--- See <https://github.com/haskell/cabal/issues/4899>----newtype SpecVersion = SpecVersion { getSpecVersion :: Either Version VersionRange }--instance Newtype (Either Version VersionRange) SpecVersion--instance Parsec SpecVersion where- parsec = pack <$> parsecSpecVersion- where- parsecSpecVersion = Left <$> parsec <|> Right <$> range- range = do- vr <- parsec- if specVersionFromRange vr >= mkVersion [2,1]- then fail "cabal-version higher than 2.2 cannot be specified as a range. See https://github.com/haskell/cabal/issues/4899"- else return vr--instance Pretty SpecVersion where- pretty = either pretty pretty . unpack--specVersionFromRange :: VersionRange -> Version-specVersionFromRange versionRange = case asVersionIntervals versionRange of- [] -> mkVersion [0]- ((LowerBound version _, _):_) -> version---- | SPDX License expression or legacy license-newtype SpecLicense = SpecLicense { getSpecLicense :: Either SPDX.License License }--instance Newtype (Either SPDX.License License) SpecLicense--instance Parsec SpecLicense where- parsec = do- v <- askCabalSpecVersion- if v >= CabalSpecV2_2- then SpecLicense . Left <$> parsec- else SpecLicense . Right <$> parsec--instance Pretty SpecLicense where- pretty = either pretty pretty . unpack---- | Version range or just version-newtype TestedWith = TestedWith { getTestedWith :: (CompilerFlavor, VersionRange) }--instance Newtype (CompilerFlavor, VersionRange) TestedWith--instance Parsec TestedWith where- parsec = pack <$> parsecTestedWith--instance Pretty TestedWith where- pretty x = case unpack x of- (compiler, vr) -> pretty compiler <+> pretty vr---- | Filepath are parsed as 'Token'.-newtype FilePathNT = FilePathNT { getFilePathNT :: String }--instance Newtype String FilePathNT--instance Parsec FilePathNT where- parsec = pack <$> parsecToken--instance Pretty FilePathNT where- pretty = showFilePath . unpack------------------------------------------------------------------------------------ Internal----------------------------------------------------------------------------------parsecTestedWith :: CabalParsing m => m (CompilerFlavor, VersionRange)-parsecTestedWith = do- name <- lexemeParsec- ver <- parsec <|> pure anyVersion- return (name, ver)
cabal/Cabal/Distribution/Parsec/Warning.hs view
@@ -35,6 +35,13 @@ | PWTDoubleDash -- ^ Double dash token, most likely it's a mistake - it's not a comment | PWTMultipleSingularField -- ^ e.g. name or version should be specified only once. | PWTBuildTypeDefault -- ^ Workaround for derive-package having build-type: Default. See <https://github.com/haskell/cabal/issues/5020>.++ | PWTVersionOperator -- ^ Version operators used (without cabal-version: 1.8)+ | PWTVersionWildcard -- ^ Version wildcard used (without cabal-version: 1.6)++ | PWTSpecVersion -- ^ Warnings about cabal-version format.++ | PWTExperimental -- ^ Experimental feature deriving (Eq, Ord, Show, Enum, Bounded, Generic) instance Binary PWarnType
cabal/Cabal/Distribution/Pretty.hs view
@@ -24,6 +24,10 @@ prettyVersioned :: CabalSpecVersion -> a -> PP.Doc prettyVersioned _ = pretty +-- | @since 3.4.0.0+instance Pretty PP.Doc where+ pretty = id+ instance Pretty Bool where pretty = PP.text . show
cabal/Cabal/Distribution/SPDX/License.hs view
@@ -44,6 +44,7 @@ deriving (Show, Read, Eq, Ord, Typeable, Data, Generic) instance Binary License+instance Structured License instance NFData License where rnf NONE = ()
cabal/Cabal/Distribution/SPDX/LicenseExceptionId.hs view
@@ -12,9 +12,11 @@ import Distribution.Compat.Prelude import Prelude () +import Distribution.Compat.Lens (set) import Distribution.Pretty import Distribution.Parsec import Distribution.Utils.Generic (isAsciiAlphaNum)+import Distribution.Utils.Structured (Structured (..), nominalStructure, typeVersion) import Distribution.SPDX.LicenseListVersion import qualified Data.Binary.Get as Binary@@ -45,25 +47,30 @@ | GCC_exception_2_0 -- ^ @GCC-exception-2.0@, GCC Runtime Library exception 2.0 | GCC_exception_3_1 -- ^ @GCC-exception-3.1@, GCC Runtime Library exception 3.1 | Gnu_javamail_exception -- ^ @gnu-javamail-exception@, GNU JavaMail exception- | GPL_CC_1_0 -- ^ @GPL-CC-1.0@, GPL Cooperation Commitment 1.0, SPDX License List 3.6+ | GPL_3_0_linking_exception -- ^ @GPL-3.0-linking-exception@, GPL-3.0 Linking Exception, SPDX License List 3.9+ | GPL_3_0_linking_source_exception -- ^ @GPL-3.0-linking-source-exception@, GPL-3.0 Linking Exception (with Corresponding Source), SPDX License List 3.9+ | GPL_CC_1_0 -- ^ @GPL-CC-1.0@, GPL Cooperation Commitment 1.0, SPDX License List 3.6, SPDX License List 3.9 | I2p_gpl_java_exception -- ^ @i2p-gpl-java-exception@, i2p GPL+Java Exception+ | LGPL_3_0_linking_exception -- ^ @LGPL-3.0-linking-exception@, LGPL-3.0 Linking Exception, SPDX License List 3.9 | Libtool_exception -- ^ @Libtool-exception@, Libtool Exception | Linux_syscall_note -- ^ @Linux-syscall-note@, Linux Syscall Note- | LLVM_exception -- ^ @LLVM-exception@, LLVM Exception, SPDX License List 3.2, SPDX License List 3.6+ | LLVM_exception -- ^ @LLVM-exception@, LLVM Exception, SPDX License List 3.2, SPDX License List 3.6, SPDX License List 3.9 | LZMA_exception -- ^ @LZMA-exception@, LZMA exception | Mif_exception -- ^ @mif-exception@, Macros and Inline Functions Exception | Nokia_Qt_exception_1_1 -- ^ @Nokia-Qt-exception-1.1@, Nokia Qt LGPL exception 1.1, SPDX License List 3.0, SPDX License List 3.2- | OCaml_LGPL_linking_exception -- ^ @OCaml-LGPL-linking-exception@, OCaml LGPL Linking Exception, SPDX License List 3.6+ | OCaml_LGPL_linking_exception -- ^ @OCaml-LGPL-linking-exception@, OCaml LGPL Linking Exception, SPDX License List 3.6, SPDX License List 3.9 | OCCT_exception_1_0 -- ^ @OCCT-exception-1.0@, Open CASCADE Exception 1.0- | OpenJDK_assembly_exception_1_0 -- ^ @OpenJDK-assembly-exception-1.0@, OpenJDK Assembly exception 1.0, SPDX License List 3.2, SPDX License List 3.6+ | OpenJDK_assembly_exception_1_0 -- ^ @OpenJDK-assembly-exception-1.0@, OpenJDK Assembly exception 1.0, SPDX License List 3.2, SPDX License List 3.6, SPDX License List 3.9 | Openvpn_openssl_exception -- ^ @openvpn-openssl-exception@, OpenVPN OpenSSL Exception- | PS_or_PDF_font_exception_20170817 -- ^ @PS-or-PDF-font-exception-20170817@, PS/PDF font exception (2017-08-17), SPDX License List 3.2, SPDX License List 3.6- | Qt_GPL_exception_1_0 -- ^ @Qt-GPL-exception-1.0@, Qt GPL exception 1.0, SPDX License List 3.2, SPDX License List 3.6- | Qt_LGPL_exception_1_1 -- ^ @Qt-LGPL-exception-1.1@, Qt LGPL exception 1.1, SPDX License List 3.2, SPDX License List 3.6+ | PS_or_PDF_font_exception_20170817 -- ^ @PS-or-PDF-font-exception-20170817@, PS/PDF font exception (2017-08-17), SPDX License List 3.2, SPDX License List 3.6, SPDX License List 3.9+ | Qt_GPL_exception_1_0 -- ^ @Qt-GPL-exception-1.0@, Qt GPL exception 1.0, SPDX License List 3.2, SPDX License List 3.6, SPDX License List 3.9+ | Qt_LGPL_exception_1_1 -- ^ @Qt-LGPL-exception-1.1@, Qt LGPL exception 1.1, SPDX License List 3.2, SPDX License List 3.6, SPDX License List 3.9 | Qwt_exception_1_0 -- ^ @Qwt-exception-1.0@, Qwt exception 1.0- | Swift_exception -- ^ @Swift-exception@, Swift Exception, SPDX License List 3.6+ | SHL_2_0 -- ^ @SHL-2.0@, Solderpad Hardware License v2.0, SPDX License List 3.9+ | SHL_2_1 -- ^ @SHL-2.1@, Solderpad Hardware License v2.1, SPDX License List 3.9+ | Swift_exception -- ^ @Swift-exception@, Swift Exception, SPDX License List 3.6, SPDX License List 3.9 | U_boot_exception_2_0 -- ^ @u-boot-exception-2.0@, U-Boot exception 2.0- | Universal_FOSS_exception_1_0 -- ^ @Universal-FOSS-exception-1.0@, Universal FOSS Exception, Version 1.0, SPDX License List 3.6+ | Universal_FOSS_exception_1_0 -- ^ @Universal-FOSS-exception-1.0@, Universal FOSS Exception, Version 1.0, SPDX License List 3.6, SPDX License List 3.9 | WxWindows_exception_3_1 -- ^ @WxWindows-exception-3.1@, WxWindows Library Exception 3.1 deriving (Eq, Ord, Enum, Bounded, Show, Read, Typeable, Data, Generic) @@ -75,6 +82,10 @@ then fail "Too large LicenseExceptionId tag" else return (toEnum (fromIntegral i)) +-- note: remember to bump version each time the definition changes+instance Structured LicenseExceptionId where+ structure p = set typeVersion 306 $ nominalStructure p+ instance Pretty LicenseExceptionId where pretty = Disp.text . licenseExceptionId @@ -110,8 +121,11 @@ licenseExceptionId GCC_exception_2_0 = "GCC-exception-2.0" licenseExceptionId GCC_exception_3_1 = "GCC-exception-3.1" licenseExceptionId Gnu_javamail_exception = "gnu-javamail-exception"+licenseExceptionId GPL_3_0_linking_exception = "GPL-3.0-linking-exception"+licenseExceptionId GPL_3_0_linking_source_exception = "GPL-3.0-linking-source-exception" licenseExceptionId GPL_CC_1_0 = "GPL-CC-1.0" licenseExceptionId I2p_gpl_java_exception = "i2p-gpl-java-exception"+licenseExceptionId LGPL_3_0_linking_exception = "LGPL-3.0-linking-exception" licenseExceptionId Libtool_exception = "Libtool-exception" licenseExceptionId Linux_syscall_note = "Linux-syscall-note" licenseExceptionId LLVM_exception = "LLVM-exception"@@ -126,6 +140,8 @@ licenseExceptionId Qt_GPL_exception_1_0 = "Qt-GPL-exception-1.0" licenseExceptionId Qt_LGPL_exception_1_1 = "Qt-LGPL-exception-1.1" licenseExceptionId Qwt_exception_1_0 = "Qwt-exception-1.0"+licenseExceptionId SHL_2_0 = "SHL-2.0"+licenseExceptionId SHL_2_1 = "SHL-2.1" licenseExceptionId Swift_exception = "Swift-exception" licenseExceptionId U_boot_exception_2_0 = "u-boot-exception-2.0" licenseExceptionId Universal_FOSS_exception_1_0 = "Universal-FOSS-exception-1.0"@@ -149,8 +165,11 @@ licenseExceptionName GCC_exception_2_0 = "GCC Runtime Library exception 2.0" licenseExceptionName GCC_exception_3_1 = "GCC Runtime Library exception 3.1" licenseExceptionName Gnu_javamail_exception = "GNU JavaMail exception"+licenseExceptionName GPL_3_0_linking_exception = "GPL-3.0 Linking Exception"+licenseExceptionName GPL_3_0_linking_source_exception = "GPL-3.0 Linking Exception (with Corresponding Source)" licenseExceptionName GPL_CC_1_0 = "GPL Cooperation Commitment 1.0" licenseExceptionName I2p_gpl_java_exception = "i2p GPL+Java Exception"+licenseExceptionName LGPL_3_0_linking_exception = "LGPL-3.0 Linking Exception" licenseExceptionName Libtool_exception = "Libtool Exception" licenseExceptionName Linux_syscall_note = "Linux Syscall Note" licenseExceptionName LLVM_exception = "LLVM Exception"@@ -165,6 +184,8 @@ licenseExceptionName Qt_GPL_exception_1_0 = "Qt GPL exception 1.0" licenseExceptionName Qt_LGPL_exception_1_1 = "Qt LGPL exception 1.1" licenseExceptionName Qwt_exception_1_0 = "Qwt exception 1.0"+licenseExceptionName SHL_2_0 = "Solderpad Hardware License v2.0"+licenseExceptionName SHL_2_1 = "Solderpad Hardware License v2.1" licenseExceptionName Swift_exception = "Swift Exception" licenseExceptionName U_boot_exception_2_0 = "U-Boot exception 2.0" licenseExceptionName Universal_FOSS_exception_1_0 = "Universal FOSS Exception, Version 1.0"@@ -200,12 +221,30 @@ , Universal_FOSS_exception_1_0 ] ++ bulkOfLicenses+licenseExceptionIdList LicenseListVersion_3_9 =+ [ GPL_3_0_linking_exception+ , GPL_3_0_linking_source_exception+ , GPL_CC_1_0+ , LGPL_3_0_linking_exception+ , LLVM_exception+ , OCaml_LGPL_linking_exception+ , OpenJDK_assembly_exception_1_0+ , PS_or_PDF_font_exception_20170817+ , Qt_GPL_exception_1_0+ , Qt_LGPL_exception_1_1+ , SHL_2_0+ , SHL_2_1+ , Swift_exception+ , Universal_FOSS_exception_1_0+ ]+ ++ bulkOfLicenses -- | Create a 'LicenseExceptionId' from a 'String'. mkLicenseExceptionId :: LicenseListVersion -> String -> Maybe LicenseExceptionId mkLicenseExceptionId LicenseListVersion_3_0 s = Map.lookup s stringLookup_3_0 mkLicenseExceptionId LicenseListVersion_3_2 s = Map.lookup s stringLookup_3_2 mkLicenseExceptionId LicenseListVersion_3_6 s = Map.lookup s stringLookup_3_6+mkLicenseExceptionId LicenseListVersion_3_9 s = Map.lookup s stringLookup_3_9 stringLookup_3_0 :: Map String LicenseExceptionId stringLookup_3_0 = Map.fromList $ map (\i -> (licenseExceptionId i, i)) $@@ -218,6 +257,10 @@ stringLookup_3_6 :: Map String LicenseExceptionId stringLookup_3_6 = Map.fromList $ map (\i -> (licenseExceptionId i, i)) $ licenseExceptionIdList LicenseListVersion_3_6++stringLookup_3_9 :: Map String LicenseExceptionId+stringLookup_3_9 = Map.fromList $ map (\i -> (licenseExceptionId i, i)) $+ licenseExceptionIdList LicenseListVersion_3_9 -- | License exceptions in all SPDX License lists bulkOfLicenses :: [LicenseExceptionId]
cabal/Cabal/Distribution/SPDX/LicenseExpression.hs view
@@ -16,7 +16,6 @@ import Distribution.SPDX.LicenseListVersion import Distribution.SPDX.LicenseReference import Distribution.Utils.Generic (isAsciiAlphaNum)-import Text.PrettyPrint ((<+>)) import qualified Distribution.Compat.CharParsing as P import qualified Text.PrettyPrint as Disp@@ -60,6 +59,8 @@ instance Binary LicenseExpression instance Binary SimpleLicenseExpression+instance Structured SimpleLicenseExpression+instance Structured LicenseExpression instance Pretty LicenseExpression where pretty = go 0
cabal/Cabal/Distribution/SPDX/LicenseId.hs view
@@ -6,6 +6,7 @@ licenseId, licenseName, licenseIsOsiApproved,+ licenseIsFsfLibre, mkLicenseId, licenseIdList, -- * Helpers@@ -15,9 +16,11 @@ import Distribution.Compat.Prelude import Prelude () +import Distribution.Compat.Lens (set) import Distribution.Pretty import Distribution.Parsec import Distribution.Utils.Generic (isAsciiAlphaNum)+import Distribution.Utils.Structured (Structured (..), nominalStructure, typeVersion) import Distribution.SPDX.LicenseListVersion import qualified Data.Binary.Get as Binary@@ -45,8 +48,8 @@ | AFL_3_0 -- ^ @AFL-3.0@, Academic Free License v3.0 | Afmparse -- ^ @Afmparse@, Afmparse License | AGPL_1_0 -- ^ @AGPL-1.0@, Affero General Public License v1.0, SPDX License List 3.0- | AGPL_1_0_only -- ^ @AGPL-1.0-only@, Affero General Public License v1.0 only, SPDX License List 3.2, SPDX License List 3.6- | AGPL_1_0_or_later -- ^ @AGPL-1.0-or-later@, Affero General Public License v1.0 or later, SPDX License List 3.2, SPDX License List 3.6+ | AGPL_1_0_only -- ^ @AGPL-1.0-only@, Affero General Public License v1.0 only, SPDX License List 3.2, SPDX License List 3.6, SPDX License List 3.9+ | AGPL_1_0_or_later -- ^ @AGPL-1.0-or-later@, Affero General Public License v1.0 or later, SPDX License List 3.2, SPDX License List 3.6, SPDX License List 3.9 | AGPL_3_0_only -- ^ @AGPL-3.0-only@, GNU Affero General Public License v3.0 only | AGPL_3_0_or_later -- ^ @AGPL-3.0-or-later@, GNU Affero General Public License v3.0 or later | Aladdin -- ^ @Aladdin@, Aladdin Free Public License@@ -72,12 +75,12 @@ | Beerware -- ^ @Beerware@, Beerware License | BitTorrent_1_0 -- ^ @BitTorrent-1.0@, BitTorrent Open Source License v1.0 | BitTorrent_1_1 -- ^ @BitTorrent-1.1@, BitTorrent Open Source License v1.1- | Blessing -- ^ @blessing@, SQLite Blessing, SPDX License List 3.6- | BlueOak_1_0_0 -- ^ @BlueOak-1.0.0@, Blue Oak Model License 1.0.0, SPDX License List 3.6+ | Blessing -- ^ @blessing@, SQLite Blessing, SPDX License List 3.6, SPDX License List 3.9+ | BlueOak_1_0_0 -- ^ @BlueOak-1.0.0@, Blue Oak Model License 1.0.0, SPDX License List 3.6, SPDX License List 3.9 | Borceux -- ^ @Borceux@, Borceux license | BSD_1_Clause -- ^ @BSD-1-Clause@, BSD 1-Clause License | BSD_2_Clause_FreeBSD -- ^ @BSD-2-Clause-FreeBSD@, BSD 2-Clause FreeBSD License- | BSD_2_Clause_NetBSD -- ^ @BSD-2-Clause-NetBSD@, BSD 2-Clause NetBSD License+ | BSD_2_Clause_NetBSD -- ^ @BSD-2-Clause-NetBSD@, BSD 2-Clause NetBSD License, SPDX License List 3.0, SPDX License List 3.2, SPDX License List 3.6 | BSD_2_Clause_Patent -- ^ @BSD-2-Clause-Patent@, BSD-2-Clause Plus Patent License | BSD_2_Clause -- ^ @BSD-2-Clause@, BSD 2-Clause "Simplified" License | BSD_3_Clause_Attribution -- ^ @BSD-3-Clause-Attribution@, BSD with attribution@@ -86,7 +89,7 @@ | BSD_3_Clause_No_Nuclear_License_2014 -- ^ @BSD-3-Clause-No-Nuclear-License-2014@, BSD 3-Clause No Nuclear License 2014 | BSD_3_Clause_No_Nuclear_License -- ^ @BSD-3-Clause-No-Nuclear-License@, BSD 3-Clause No Nuclear License | BSD_3_Clause_No_Nuclear_Warranty -- ^ @BSD-3-Clause-No-Nuclear-Warranty@, BSD 3-Clause No Nuclear Warranty- | BSD_3_Clause_Open_MPI -- ^ @BSD-3-Clause-Open-MPI@, BSD 3-Clause Open MPI variant, SPDX License List 3.6+ | BSD_3_Clause_Open_MPI -- ^ @BSD-3-Clause-Open-MPI@, BSD 3-Clause Open MPI variant, SPDX License List 3.6, SPDX License List 3.9 | BSD_3_Clause -- ^ @BSD-3-Clause@, BSD 3-Clause "New" or "Revised" License | BSD_4_Clause_UC -- ^ @BSD-4-Clause-UC@, BSD-4-Clause (University of California-Specific) | BSD_4_Clause -- ^ @BSD-4-Clause@, BSD 4-Clause "Original" or "Old" License@@ -95,6 +98,8 @@ | BSL_1_0 -- ^ @BSL-1.0@, Boost Software License 1.0 | Bzip2_1_0_5 -- ^ @bzip2-1.0.5@, bzip2 and libbzip2 License v1.0.5 | Bzip2_1_0_6 -- ^ @bzip2-1.0.6@, bzip2 and libbzip2 License v1.0.6+ | CAL_1_0_Combined_Work_Exception -- ^ @CAL-1.0-Combined-Work-Exception@, Cryptographic Autonomy License 1.0 (Combined Work Exception), SPDX License List 3.9+ | CAL_1_0 -- ^ @CAL-1.0@, Cryptographic Autonomy License 1.0, SPDX License List 3.9 | Caldera -- ^ @Caldera@, Caldera License | CATOSL_1_1 -- ^ @CATOSL-1.1@, Computer Associates Trusted Open Source License 1.1 | CC_BY_1_0 -- ^ @CC-BY-1.0@, Creative Commons Attribution 1.0 Generic@@ -127,7 +132,7 @@ | CC_BY_SA_2_5 -- ^ @CC-BY-SA-2.5@, Creative Commons Attribution Share Alike 2.5 Generic | CC_BY_SA_3_0 -- ^ @CC-BY-SA-3.0@, Creative Commons Attribution Share Alike 3.0 Unported | CC_BY_SA_4_0 -- ^ @CC-BY-SA-4.0@, Creative Commons Attribution Share Alike 4.0 International- | CC_PDDC -- ^ @CC-PDDC@, Creative Commons Public Domain Dedication and Certification, SPDX License List 3.6+ | CC_PDDC -- ^ @CC-PDDC@, Creative Commons Public Domain Dedication and Certification, SPDX License List 3.6, SPDX License List 3.9 | CC0_1_0 -- ^ @CC0-1.0@, Creative Commons Zero v1.0 Universal | CDDL_1_0 -- ^ @CDDL-1.0@, Common Development and Distribution License 1.0 | CDDL_1_1 -- ^ @CDDL-1.1@, Common Development and Distribution License 1.1@@ -139,15 +144,18 @@ | CECILL_2_1 -- ^ @CECILL-2.1@, CeCILL Free Software License Agreement v2.1 | CECILL_B -- ^ @CECILL-B@, CeCILL-B Free Software License Agreement | CECILL_C -- ^ @CECILL-C@, CeCILL-C Free Software License Agreement- | CERN_OHL_1_1 -- ^ @CERN-OHL-1.1@, CERN Open Hardware License v1.1, SPDX License List 3.6- | CERN_OHL_1_2 -- ^ @CERN-OHL-1.2@, CERN Open Hardware Licence v1.2, SPDX License List 3.6+ | CERN_OHL_1_1 -- ^ @CERN-OHL-1.1@, CERN Open Hardware Licence v1.1, SPDX License List 3.6, SPDX License List 3.9+ | CERN_OHL_1_2 -- ^ @CERN-OHL-1.2@, CERN Open Hardware Licence v1.2, SPDX License List 3.6, SPDX License List 3.9+ | CERN_OHL_P_2_0 -- ^ @CERN-OHL-P-2.0@, CERN Open Hardware Licence Version 2 - Permissive, SPDX License List 3.9+ | CERN_OHL_S_2_0 -- ^ @CERN-OHL-S-2.0@, CERN Open Hardware Licence Version 2 - Strongly Reciprocal, SPDX License List 3.9+ | CERN_OHL_W_2_0 -- ^ @CERN-OHL-W-2.0@, CERN Open Hardware Licence Version 2 - Weakly Reciprocal, SPDX License List 3.9 | ClArtistic -- ^ @ClArtistic@, Clarified Artistic License | CNRI_Jython -- ^ @CNRI-Jython@, CNRI Jython License | CNRI_Python_GPL_Compatible -- ^ @CNRI-Python-GPL-Compatible@, CNRI Python Open Source GPL Compatible License Agreement | CNRI_Python -- ^ @CNRI-Python@, CNRI Python License | Condor_1_1 -- ^ @Condor-1.1@, Condor Public License v1.1- | Copyleft_next_0_3_0 -- ^ @copyleft-next-0.3.0@, copyleft-next 0.3.0, SPDX License List 3.6- | Copyleft_next_0_3_1 -- ^ @copyleft-next-0.3.1@, copyleft-next 0.3.1, SPDX License List 3.6+ | Copyleft_next_0_3_0 -- ^ @copyleft-next-0.3.0@, copyleft-next 0.3.0, SPDX License List 3.6, SPDX License List 3.9+ | Copyleft_next_0_3_1 -- ^ @copyleft-next-0.3.1@, copyleft-next 0.3.1, SPDX License List 3.6, SPDX License List 3.9 | CPAL_1_0 -- ^ @CPAL-1.0@, Common Public Attribution License 1.0 | CPL_1_0 -- ^ @CPL-1.0@, Common Public License 1.0 | CPOL_1_02 -- ^ @CPOL-1.02@, Code Project Open License 1.02@@ -171,6 +179,7 @@ | EPL_1_0 -- ^ @EPL-1.0@, Eclipse Public License 1.0 | EPL_2_0 -- ^ @EPL-2.0@, Eclipse Public License 2.0 | ErlPL_1_1 -- ^ @ErlPL-1.1@, Erlang Public License v1.1+ | Etalab_2_0 -- ^ @etalab-2.0@, Etalab Open License 2.0, SPDX License List 3.9 | EUDatagrid -- ^ @EUDatagrid@, EU DataGrid Software License | EUPL_1_0 -- ^ @EUPL-1.0@, European Union Public License 1.0 | EUPL_1_1 -- ^ @EUPL-1.1@, European Union Public License 1.1@@ -202,7 +211,8 @@ | GPL_3_0_or_later -- ^ @GPL-3.0-or-later@, GNU General Public License v3.0 or later | GSOAP_1_3b -- ^ @gSOAP-1.3b@, gSOAP Public License v1.3b | HaskellReport -- ^ @HaskellReport@, Haskell Language Report License- | HPND_sell_variant -- ^ @HPND-sell-variant@, Historical Permission Notice and Disclaimer - sell variant, SPDX License List 3.6+ | Hippocratic_2_1 -- ^ @Hippocratic-2.1@, Hippocratic License 2.1, SPDX License List 3.9+ | HPND_sell_variant -- ^ @HPND-sell-variant@, Historical Permission Notice and Disclaimer - sell variant, SPDX License List 3.6, SPDX License List 3.9 | HPND -- ^ @HPND@, Historical Permission Notice and Disclaimer | IBM_pibs -- ^ @IBM-pibs@, IBM PowerPC Initialization and Boot Software | ICU -- ^ @ICU@, ICU License@@ -218,7 +228,7 @@ | IPL_1_0 -- ^ @IPL-1.0@, IBM Public License v1.0 | ISC -- ^ @ISC@, ISC License | JasPer_2_0 -- ^ @JasPer-2.0@, JasPer License- | JPNIC -- ^ @JPNIC@, Japan Network Information Center License, SPDX License List 3.6+ | JPNIC -- ^ @JPNIC@, Japan Network Information Center License, SPDX License List 3.6, SPDX License List 3.9 | JSON -- ^ @JSON@, JSON License | LAL_1_2 -- ^ @LAL-1.2@, Licence Art Libre 1.2 | LAL_1_3 -- ^ @LAL-1.3@, Licence Art Libre 1.3@@ -231,13 +241,14 @@ | LGPL_3_0_only -- ^ @LGPL-3.0-only@, GNU Lesser General Public License v3.0 only | LGPL_3_0_or_later -- ^ @LGPL-3.0-or-later@, GNU Lesser General Public License v3.0 or later | LGPLLR -- ^ @LGPLLR@, Lesser General Public License For Linguistic Resources- | Libpng_2_0 -- ^ @libpng-2.0@, PNG Reference Library version 2, SPDX License List 3.6+ | Libpng_2_0 -- ^ @libpng-2.0@, PNG Reference Library version 2, SPDX License List 3.6, SPDX License List 3.9 | Libpng -- ^ @Libpng@, libpng License+ | Libselinux_1_0 -- ^ @libselinux-1.0@, libselinux public domain notice, SPDX License List 3.9 | Libtiff -- ^ @libtiff@, libtiff License | LiLiQ_P_1_1 -- ^ @LiLiQ-P-1.1@, Licence Libre du Québec – Permissive version 1.1 | LiLiQ_R_1_1 -- ^ @LiLiQ-R-1.1@, Licence Libre du Québec – Réciprocité version 1.1 | LiLiQ_Rplus_1_1 -- ^ @LiLiQ-Rplus-1.1@, Licence Libre du Québec – Réciprocité forte version 1.1- | Linux_OpenIB -- ^ @Linux-OpenIB@, Linux Kernel Variant of OpenIB.org license, SPDX License List 3.2, SPDX License List 3.6+ | Linux_OpenIB -- ^ @Linux-OpenIB@, Linux Kernel Variant of OpenIB.org license, SPDX License List 3.2, SPDX License List 3.6, SPDX License List 3.9 | LPL_1_02 -- ^ @LPL-1.02@, Lucent Public License v1.02 | LPL_1_0 -- ^ @LPL-1.0@, Lucent Public License Version 1.0 | LPPL_1_0 -- ^ @LPPL-1.0@, LaTeX Project Public License v1.0@@ -246,8 +257,8 @@ | LPPL_1_3a -- ^ @LPPL-1.3a@, LaTeX Project Public License v1.3a | LPPL_1_3c -- ^ @LPPL-1.3c@, LaTeX Project Public License v1.3c | MakeIndex -- ^ @MakeIndex@, MakeIndex License- | MirOS -- ^ @MirOS@, MirOS License- | MIT_0 -- ^ @MIT-0@, MIT No Attribution, SPDX License List 3.2, SPDX License List 3.6+ | MirOS -- ^ @MirOS@, The MirOS Licence+ | MIT_0 -- ^ @MIT-0@, MIT No Attribution, SPDX License List 3.2, SPDX License List 3.6, SPDX License List 3.9 | MIT_advertising -- ^ @MIT-advertising@, Enlightenment License (e16) | MIT_CMU -- ^ @MIT-CMU@, CMU License | MIT_enna -- ^ @MIT-enna@, enna License@@ -263,11 +274,14 @@ | MS_PL -- ^ @MS-PL@, Microsoft Public License | MS_RL -- ^ @MS-RL@, Microsoft Reciprocal License | MTLL -- ^ @MTLL@, Matrix Template Library License+ | MulanPSL_1_0 -- ^ @MulanPSL-1.0@, Mulan Permissive Software License, Version 1, SPDX License List 3.9+ | MulanPSL_2_0 -- ^ @MulanPSL-2.0@, Mulan Permissive Software License, Version 2, SPDX License List 3.9 | Multics -- ^ @Multics@, Multics License | Mup -- ^ @Mup@, Mup License | NASA_1_3 -- ^ @NASA-1.3@, NASA Open Source Agreement 1.3 | Naumen -- ^ @Naumen@, Naumen Public License | NBPL_1_0 -- ^ @NBPL-1.0@, Net Boolean Public License v1+ | NCGL_UK_2_0 -- ^ @NCGL-UK-2.0@, Non-Commercial Government Licence, SPDX License List 3.9 | NCSA -- ^ @NCSA@, University of Illinois/NCSA Open Source License | Net_SNMP -- ^ @Net-SNMP@, Net-SNMP License | NetCDF -- ^ @NetCDF@, NetCDF license@@ -282,16 +296,24 @@ | NPL_1_1 -- ^ @NPL-1.1@, Netscape Public License v1.1 | NPOSL_3_0 -- ^ @NPOSL-3.0@, Non-Profit Open Software License 3.0 | NRL -- ^ @NRL@, NRL License+ | NTP_0 -- ^ @NTP-0@, NTP No Attribution, SPDX License List 3.9 | NTP -- ^ @NTP@, NTP License+ | O_UDA_1_0 -- ^ @O-UDA-1.0@, Open Use of Data Agreement v1.0, SPDX License List 3.9 | OCCT_PL -- ^ @OCCT-PL@, Open CASCADE Technology Public License | OCLC_2_0 -- ^ @OCLC-2.0@, OCLC Research Public License 2.0 | ODbL_1_0 -- ^ @ODbL-1.0@, ODC Open Database License v1.0- | ODC_By_1_0 -- ^ @ODC-By-1.0@, Open Data Commons Attribution License v1.0, SPDX License List 3.2, SPDX License List 3.6+ | ODC_By_1_0 -- ^ @ODC-By-1.0@, Open Data Commons Attribution License v1.0, SPDX License List 3.2, SPDX License List 3.6, SPDX License List 3.9+ | OFL_1_0_no_RFN -- ^ @OFL-1.0-no-RFN@, SIL Open Font License 1.0 with no Reserved Font Name, SPDX License List 3.9+ | OFL_1_0_RFN -- ^ @OFL-1.0-RFN@, SIL Open Font License 1.0 with Reserved Font Name, SPDX License List 3.9 | OFL_1_0 -- ^ @OFL-1.0@, SIL Open Font License 1.0+ | OFL_1_1_no_RFN -- ^ @OFL-1.1-no-RFN@, SIL Open Font License 1.1 with no Reserved Font Name, SPDX License List 3.9+ | OFL_1_1_RFN -- ^ @OFL-1.1-RFN@, SIL Open Font License 1.1 with Reserved Font Name, SPDX License List 3.9 | OFL_1_1 -- ^ @OFL-1.1@, SIL Open Font License 1.1- | OGL_UK_1_0 -- ^ @OGL-UK-1.0@, Open Government Licence v1.0, SPDX License List 3.6- | OGL_UK_2_0 -- ^ @OGL-UK-2.0@, Open Government Licence v2.0, SPDX License List 3.6- | OGL_UK_3_0 -- ^ @OGL-UK-3.0@, Open Government Licence v3.0, SPDX License List 3.6+ | OGC_1_0 -- ^ @OGC-1.0@, OGC Software License, Version 1.0, SPDX License List 3.9+ | OGL_Canada_2_0 -- ^ @OGL-Canada-2.0@, Open Government Licence - Canada, SPDX License List 3.9+ | OGL_UK_1_0 -- ^ @OGL-UK-1.0@, Open Government Licence v1.0, SPDX License List 3.6, SPDX License List 3.9+ | OGL_UK_2_0 -- ^ @OGL-UK-2.0@, Open Government Licence v2.0, SPDX License List 3.6, SPDX License List 3.9+ | OGL_UK_3_0 -- ^ @OGL-UK-3.0@, Open Government Licence v3.0, SPDX License List 3.6, SPDX License List 3.9 | OGTSL -- ^ @OGTSL@, Open Group Test Suite License | OLDAP_1_1 -- ^ @OLDAP-1.1@, Open LDAP Public License v1.1 | OLDAP_1_2 -- ^ @OLDAP-1.2@, Open LDAP Public License v1.2@@ -318,12 +340,16 @@ | OSL_2_0 -- ^ @OSL-2.0@, Open Software License 2.0 | OSL_2_1 -- ^ @OSL-2.1@, Open Software License 2.1 | OSL_3_0 -- ^ @OSL-3.0@, Open Software License 3.0- | Parity_6_0_0 -- ^ @Parity-6.0.0@, The Parity Public License 6.0.0, SPDX License List 3.6+ | Parity_6_0_0 -- ^ @Parity-6.0.0@, The Parity Public License 6.0.0, SPDX License List 3.6, SPDX License List 3.9+ | Parity_7_0_0 -- ^ @Parity-7.0.0@, The Parity Public License 7.0.0, SPDX License List 3.9 | PDDL_1_0 -- ^ @PDDL-1.0@, ODC Public Domain Dedication & License 1.0 | PHP_3_01 -- ^ @PHP-3.01@, PHP License v3.01 | PHP_3_0 -- ^ @PHP-3.0@, PHP License v3.0 | Plexus -- ^ @Plexus@, Plexus Classworlds License+ | PolyForm_Noncommercial_1_0_0 -- ^ @PolyForm-Noncommercial-1.0.0@, PolyForm Noncommercial License 1.0.0, SPDX License List 3.9+ | PolyForm_Small_Business_1_0_0 -- ^ @PolyForm-Small-Business-1.0.0@, PolyForm Small Business License 1.0.0, SPDX License List 3.9 | PostgreSQL -- ^ @PostgreSQL@, PostgreSQL License+ | PSF_2_0 -- ^ @PSF-2.0@, Python Software Foundation License 2.0, SPDX License List 3.9 | Psfrag -- ^ @psfrag@, psfrag License | Psutils -- ^ @psutils@, psutils License | Python_2_0 -- ^ @Python-2.0@, Python License 2.0@@ -340,13 +366,13 @@ | SAX_PD -- ^ @SAX-PD@, Sax Public Domain Notice | Saxpath -- ^ @Saxpath@, Saxpath License | SCEA -- ^ @SCEA@, SCEA Shared Source License- | Sendmail_8_23 -- ^ @Sendmail-8.23@, Sendmail License 8.23, SPDX License List 3.6+ | Sendmail_8_23 -- ^ @Sendmail-8.23@, Sendmail License 8.23, SPDX License List 3.6, SPDX License List 3.9 | Sendmail -- ^ @Sendmail@, Sendmail License | SGI_B_1_0 -- ^ @SGI-B-1.0@, SGI Free Software License B v1.0 | SGI_B_1_1 -- ^ @SGI-B-1.1@, SGI Free Software License B v1.1 | SGI_B_2_0 -- ^ @SGI-B-2.0@, SGI Free Software License B v2.0- | SHL_0_51 -- ^ @SHL-0.51@, Solderpad Hardware License, Version 0.51, SPDX License List 3.6- | SHL_0_5 -- ^ @SHL-0.5@, Solderpad Hardware License v0.5, SPDX License List 3.6+ | SHL_0_51 -- ^ @SHL-0.51@, Solderpad Hardware License, Version 0.51, SPDX License List 3.6, SPDX License List 3.9+ | SHL_0_5 -- ^ @SHL-0.5@, Solderpad Hardware License v0.5, SPDX License List 3.6, SPDX License List 3.9 | SimPL_2_0 -- ^ @SimPL-2.0@, Simple Public License 2.0 | SISSL_1_2 -- ^ @SISSL-1.2@, Sun Industry Standards Source License v1.2 | SISSL -- ^ @SISSL@, Sun Industry Standards Source License v1.1@@ -358,17 +384,20 @@ | Spencer_94 -- ^ @Spencer-94@, Spencer License 94 | Spencer_99 -- ^ @Spencer-99@, Spencer License 99 | SPL_1_0 -- ^ @SPL-1.0@, Sun Public License v1.0- | SSPL_1_0 -- ^ @SSPL-1.0@, Server Side Public License, v 1, SPDX License List 3.6+ | SSH_OpenSSH -- ^ @SSH-OpenSSH@, SSH OpenSSH license, SPDX License List 3.9+ | SSH_short -- ^ @SSH-short@, SSH short notice, SPDX License List 3.9+ | SSPL_1_0 -- ^ @SSPL-1.0@, Server Side Public License, v 1, SPDX License List 3.6, SPDX License List 3.9 | SugarCRM_1_1_3 -- ^ @SugarCRM-1.1.3@, SugarCRM Public License v1.1.3 | SWL -- ^ @SWL@, Scheme Widget Library (SWL) Software License Agreement- | TAPR_OHL_1_0 -- ^ @TAPR-OHL-1.0@, TAPR Open Hardware License v1.0, SPDX License List 3.6+ | TAPR_OHL_1_0 -- ^ @TAPR-OHL-1.0@, TAPR Open Hardware License v1.0, SPDX License List 3.6, SPDX License List 3.9 | TCL -- ^ @TCL@, TCL/TK License | TCP_wrappers -- ^ @TCP-wrappers@, TCP Wrappers License | TMate -- ^ @TMate@, TMate Open Source License | TORQUE_1_1 -- ^ @TORQUE-1.1@, TORQUE v2.5+ Software License v1.1 | TOSL -- ^ @TOSL@, Trusster Open Source License- | TU_Berlin_1_0 -- ^ @TU-Berlin-1.0@, Technische Universitaet Berlin License 1.0, SPDX License List 3.2, SPDX License List 3.6- | TU_Berlin_2_0 -- ^ @TU-Berlin-2.0@, Technische Universitaet Berlin License 2.0, SPDX License List 3.2, SPDX License List 3.6+ | TU_Berlin_1_0 -- ^ @TU-Berlin-1.0@, Technische Universitaet Berlin License 1.0, SPDX License List 3.2, SPDX License List 3.6, SPDX License List 3.9+ | TU_Berlin_2_0 -- ^ @TU-Berlin-2.0@, Technische Universitaet Berlin License 2.0, SPDX License List 3.2, SPDX License List 3.6, SPDX License List 3.9+ | UCL_1_0 -- ^ @UCL-1.0@, Upstream Compatibility License v1.0, SPDX License List 3.9 | Unicode_DFS_2015 -- ^ @Unicode-DFS-2015@, Unicode License Agreement - Data Files and Software (2015) | Unicode_DFS_2016 -- ^ @Unicode-DFS-2016@, Unicode License Agreement - Data Files and Software (2016) | Unicode_TOU -- ^ @Unicode-TOU@, Unicode Terms of Use@@ -413,6 +442,10 @@ then fail "Too large LicenseId tag" else return (toEnum (fromIntegral i)) +-- note: remember to bump version each time the definition changes+instance Structured LicenseId where+ structure p = set typeVersion 306 $ nominalStructure p+ instance Pretty LicenseId where pretty = Disp.text . licenseId @@ -542,6 +575,8 @@ licenseId BSL_1_0 = "BSL-1.0" licenseId Bzip2_1_0_5 = "bzip2-1.0.5" licenseId Bzip2_1_0_6 = "bzip2-1.0.6"+licenseId CAL_1_0_Combined_Work_Exception = "CAL-1.0-Combined-Work-Exception"+licenseId CAL_1_0 = "CAL-1.0" licenseId Caldera = "Caldera" licenseId CATOSL_1_1 = "CATOSL-1.1" licenseId CC_BY_1_0 = "CC-BY-1.0"@@ -588,6 +623,9 @@ licenseId CECILL_C = "CECILL-C" licenseId CERN_OHL_1_1 = "CERN-OHL-1.1" licenseId CERN_OHL_1_2 = "CERN-OHL-1.2"+licenseId CERN_OHL_P_2_0 = "CERN-OHL-P-2.0"+licenseId CERN_OHL_S_2_0 = "CERN-OHL-S-2.0"+licenseId CERN_OHL_W_2_0 = "CERN-OHL-W-2.0" licenseId ClArtistic = "ClArtistic" licenseId CNRI_Jython = "CNRI-Jython" licenseId CNRI_Python_GPL_Compatible = "CNRI-Python-GPL-Compatible"@@ -618,6 +656,7 @@ licenseId EPL_1_0 = "EPL-1.0" licenseId EPL_2_0 = "EPL-2.0" licenseId ErlPL_1_1 = "ErlPL-1.1"+licenseId Etalab_2_0 = "etalab-2.0" licenseId EUDatagrid = "EUDatagrid" licenseId EUPL_1_0 = "EUPL-1.0" licenseId EUPL_1_1 = "EUPL-1.1"@@ -649,6 +688,7 @@ licenseId GPL_3_0_or_later = "GPL-3.0-or-later" licenseId GSOAP_1_3b = "gSOAP-1.3b" licenseId HaskellReport = "HaskellReport"+licenseId Hippocratic_2_1 = "Hippocratic-2.1" licenseId HPND_sell_variant = "HPND-sell-variant" licenseId HPND = "HPND" licenseId IBM_pibs = "IBM-pibs"@@ -680,6 +720,7 @@ licenseId LGPLLR = "LGPLLR" licenseId Libpng_2_0 = "libpng-2.0" licenseId Libpng = "Libpng"+licenseId Libselinux_1_0 = "libselinux-1.0" licenseId Libtiff = "libtiff" licenseId LiLiQ_P_1_1 = "LiLiQ-P-1.1" licenseId LiLiQ_R_1_1 = "LiLiQ-R-1.1"@@ -710,11 +751,14 @@ licenseId MS_PL = "MS-PL" licenseId MS_RL = "MS-RL" licenseId MTLL = "MTLL"+licenseId MulanPSL_1_0 = "MulanPSL-1.0"+licenseId MulanPSL_2_0 = "MulanPSL-2.0" licenseId Multics = "Multics" licenseId Mup = "Mup" licenseId NASA_1_3 = "NASA-1.3" licenseId Naumen = "Naumen" licenseId NBPL_1_0 = "NBPL-1.0"+licenseId NCGL_UK_2_0 = "NCGL-UK-2.0" licenseId NCSA = "NCSA" licenseId Net_SNMP = "Net-SNMP" licenseId NetCDF = "NetCDF"@@ -729,13 +773,21 @@ licenseId NPL_1_1 = "NPL-1.1" licenseId NPOSL_3_0 = "NPOSL-3.0" licenseId NRL = "NRL"+licenseId NTP_0 = "NTP-0" licenseId NTP = "NTP"+licenseId O_UDA_1_0 = "O-UDA-1.0" licenseId OCCT_PL = "OCCT-PL" licenseId OCLC_2_0 = "OCLC-2.0" licenseId ODbL_1_0 = "ODbL-1.0" licenseId ODC_By_1_0 = "ODC-By-1.0"+licenseId OFL_1_0_no_RFN = "OFL-1.0-no-RFN"+licenseId OFL_1_0_RFN = "OFL-1.0-RFN" licenseId OFL_1_0 = "OFL-1.0"+licenseId OFL_1_1_no_RFN = "OFL-1.1-no-RFN"+licenseId OFL_1_1_RFN = "OFL-1.1-RFN" licenseId OFL_1_1 = "OFL-1.1"+licenseId OGC_1_0 = "OGC-1.0"+licenseId OGL_Canada_2_0 = "OGL-Canada-2.0" licenseId OGL_UK_1_0 = "OGL-UK-1.0" licenseId OGL_UK_2_0 = "OGL-UK-2.0" licenseId OGL_UK_3_0 = "OGL-UK-3.0"@@ -766,11 +818,15 @@ licenseId OSL_2_1 = "OSL-2.1" licenseId OSL_3_0 = "OSL-3.0" licenseId Parity_6_0_0 = "Parity-6.0.0"+licenseId Parity_7_0_0 = "Parity-7.0.0" licenseId PDDL_1_0 = "PDDL-1.0" licenseId PHP_3_01 = "PHP-3.01" licenseId PHP_3_0 = "PHP-3.0" licenseId Plexus = "Plexus"+licenseId PolyForm_Noncommercial_1_0_0 = "PolyForm-Noncommercial-1.0.0"+licenseId PolyForm_Small_Business_1_0_0 = "PolyForm-Small-Business-1.0.0" licenseId PostgreSQL = "PostgreSQL"+licenseId PSF_2_0 = "PSF-2.0" licenseId Psfrag = "psfrag" licenseId Psutils = "psutils" licenseId Python_2_0 = "Python-2.0"@@ -805,6 +861,8 @@ licenseId Spencer_94 = "Spencer-94" licenseId Spencer_99 = "Spencer-99" licenseId SPL_1_0 = "SPL-1.0"+licenseId SSH_OpenSSH = "SSH-OpenSSH"+licenseId SSH_short = "SSH-short" licenseId SSPL_1_0 = "SSPL-1.0" licenseId SugarCRM_1_1_3 = "SugarCRM-1.1.3" licenseId SWL = "SWL"@@ -816,6 +874,7 @@ licenseId TOSL = "TOSL" licenseId TU_Berlin_1_0 = "TU-Berlin-1.0" licenseId TU_Berlin_2_0 = "TU-Berlin-2.0"+licenseId UCL_1_0 = "UCL-1.0" licenseId Unicode_DFS_2015 = "Unicode-DFS-2015" licenseId Unicode_DFS_2016 = "Unicode-DFS-2016" licenseId Unicode_TOU = "Unicode-TOU"@@ -914,6 +973,8 @@ licenseName BSL_1_0 = "Boost Software License 1.0" licenseName Bzip2_1_0_5 = "bzip2 and libbzip2 License v1.0.5" licenseName Bzip2_1_0_6 = "bzip2 and libbzip2 License v1.0.6"+licenseName CAL_1_0_Combined_Work_Exception = "Cryptographic Autonomy License 1.0 (Combined Work Exception)"+licenseName CAL_1_0 = "Cryptographic Autonomy License 1.0" licenseName Caldera = "Caldera License" licenseName CATOSL_1_1 = "Computer Associates Trusted Open Source License 1.1" licenseName CC_BY_1_0 = "Creative Commons Attribution 1.0 Generic"@@ -958,8 +1019,11 @@ licenseName CECILL_2_1 = "CeCILL Free Software License Agreement v2.1" licenseName CECILL_B = "CeCILL-B Free Software License Agreement" licenseName CECILL_C = "CeCILL-C Free Software License Agreement"-licenseName CERN_OHL_1_1 = "CERN Open Hardware License v1.1"+licenseName CERN_OHL_1_1 = "CERN Open Hardware Licence v1.1" licenseName CERN_OHL_1_2 = "CERN Open Hardware Licence v1.2"+licenseName CERN_OHL_P_2_0 = "CERN Open Hardware Licence Version 2 - Permissive"+licenseName CERN_OHL_S_2_0 = "CERN Open Hardware Licence Version 2 - Strongly Reciprocal"+licenseName CERN_OHL_W_2_0 = "CERN Open Hardware Licence Version 2 - Weakly Reciprocal" licenseName ClArtistic = "Clarified Artistic License" licenseName CNRI_Jython = "CNRI Jython License" licenseName CNRI_Python_GPL_Compatible = "CNRI Python Open Source GPL Compatible License Agreement"@@ -990,6 +1054,7 @@ licenseName EPL_1_0 = "Eclipse Public License 1.0" licenseName EPL_2_0 = "Eclipse Public License 2.0" licenseName ErlPL_1_1 = "Erlang Public License v1.1"+licenseName Etalab_2_0 = "Etalab Open License 2.0" licenseName EUDatagrid = "EU DataGrid Software License" licenseName EUPL_1_0 = "European Union Public License 1.0" licenseName EUPL_1_1 = "European Union Public License 1.1"@@ -1021,6 +1086,7 @@ licenseName GPL_3_0_or_later = "GNU General Public License v3.0 or later" licenseName GSOAP_1_3b = "gSOAP Public License v1.3b" licenseName HaskellReport = "Haskell Language Report License"+licenseName Hippocratic_2_1 = "Hippocratic License 2.1" licenseName HPND_sell_variant = "Historical Permission Notice and Disclaimer - sell variant" licenseName HPND = "Historical Permission Notice and Disclaimer" licenseName IBM_pibs = "IBM PowerPC Initialization and Boot Software"@@ -1052,6 +1118,7 @@ licenseName LGPLLR = "Lesser General Public License For Linguistic Resources" licenseName Libpng_2_0 = "PNG Reference Library version 2" licenseName Libpng = "libpng License"+licenseName Libselinux_1_0 = "libselinux public domain notice" licenseName Libtiff = "libtiff License" licenseName LiLiQ_P_1_1 = "Licence Libre du Qu\233bec \8211 Permissive version 1.1" licenseName LiLiQ_R_1_1 = "Licence Libre du Qu\233bec \8211 R\233ciprocit\233 version 1.1"@@ -1065,7 +1132,7 @@ licenseName LPPL_1_3a = "LaTeX Project Public License v1.3a" licenseName LPPL_1_3c = "LaTeX Project Public License v1.3c" licenseName MakeIndex = "MakeIndex License"-licenseName MirOS = "MirOS License"+licenseName MirOS = "The MirOS Licence" licenseName MIT_0 = "MIT No Attribution" licenseName MIT_advertising = "Enlightenment License (e16)" licenseName MIT_CMU = "CMU License"@@ -1082,11 +1149,14 @@ licenseName MS_PL = "Microsoft Public License" licenseName MS_RL = "Microsoft Reciprocal License" licenseName MTLL = "Matrix Template Library License"+licenseName MulanPSL_1_0 = "Mulan Permissive Software License, Version 1"+licenseName MulanPSL_2_0 = "Mulan Permissive Software License, Version 2" licenseName Multics = "Multics License" licenseName Mup = "Mup License" licenseName NASA_1_3 = "NASA Open Source Agreement 1.3" licenseName Naumen = "Naumen Public License" licenseName NBPL_1_0 = "Net Boolean Public License v1"+licenseName NCGL_UK_2_0 = "Non-Commercial Government Licence" licenseName NCSA = "University of Illinois/NCSA Open Source License" licenseName Net_SNMP = "Net-SNMP License" licenseName NetCDF = "NetCDF license"@@ -1101,13 +1171,21 @@ licenseName NPL_1_1 = "Netscape Public License v1.1" licenseName NPOSL_3_0 = "Non-Profit Open Software License 3.0" licenseName NRL = "NRL License"+licenseName NTP_0 = "NTP No Attribution" licenseName NTP = "NTP License"+licenseName O_UDA_1_0 = "Open Use of Data Agreement v1.0" licenseName OCCT_PL = "Open CASCADE Technology Public License" licenseName OCLC_2_0 = "OCLC Research Public License 2.0" licenseName ODbL_1_0 = "ODC Open Database License v1.0" licenseName ODC_By_1_0 = "Open Data Commons Attribution License v1.0"+licenseName OFL_1_0_no_RFN = "SIL Open Font License 1.0 with no Reserved Font Name"+licenseName OFL_1_0_RFN = "SIL Open Font License 1.0 with Reserved Font Name" licenseName OFL_1_0 = "SIL Open Font License 1.0"+licenseName OFL_1_1_no_RFN = "SIL Open Font License 1.1 with no Reserved Font Name"+licenseName OFL_1_1_RFN = "SIL Open Font License 1.1 with Reserved Font Name" licenseName OFL_1_1 = "SIL Open Font License 1.1"+licenseName OGC_1_0 = "OGC Software License, Version 1.0"+licenseName OGL_Canada_2_0 = "Open Government Licence - Canada" licenseName OGL_UK_1_0 = "Open Government Licence v1.0" licenseName OGL_UK_2_0 = "Open Government Licence v2.0" licenseName OGL_UK_3_0 = "Open Government Licence v3.0"@@ -1138,11 +1216,15 @@ licenseName OSL_2_1 = "Open Software License 2.1" licenseName OSL_3_0 = "Open Software License 3.0" licenseName Parity_6_0_0 = "The Parity Public License 6.0.0"+licenseName Parity_7_0_0 = "The Parity Public License 7.0.0" licenseName PDDL_1_0 = "ODC Public Domain Dedication & License 1.0" licenseName PHP_3_01 = "PHP License v3.01" licenseName PHP_3_0 = "PHP License v3.0" licenseName Plexus = "Plexus Classworlds License"+licenseName PolyForm_Noncommercial_1_0_0 = "PolyForm Noncommercial License 1.0.0"+licenseName PolyForm_Small_Business_1_0_0 = "PolyForm Small Business License 1.0.0" licenseName PostgreSQL = "PostgreSQL License"+licenseName PSF_2_0 = "Python Software Foundation License 2.0" licenseName Psfrag = "psfrag License" licenseName Psutils = "psutils License" licenseName Python_2_0 = "Python License 2.0"@@ -1177,6 +1259,8 @@ licenseName Spencer_94 = "Spencer License 94" licenseName Spencer_99 = "Spencer License 99" licenseName SPL_1_0 = "Sun Public License v1.0"+licenseName SSH_OpenSSH = "SSH OpenSSH license"+licenseName SSH_short = "SSH short notice" licenseName SSPL_1_0 = "Server Side Public License, v 1" licenseName SugarCRM_1_1_3 = "SugarCRM Public License v1.1.3" licenseName SWL = "Scheme Widget Library (SWL) Software License Agreement"@@ -1188,6 +1272,7 @@ licenseName TOSL = "Trusster Open Source License" licenseName TU_Berlin_1_0 = "Technische Universitaet Berlin License 1.0" licenseName TU_Berlin_2_0 = "Technische Universitaet Berlin License 2.0"+licenseName UCL_1_0 = "Upstream Compatibility License v1.0" licenseName Unicode_DFS_2015 = "Unicode License Agreement - Data Files and Software (2015)" licenseName Unicode_DFS_2016 = "Unicode License Agreement - Data Files and Software (2016)" licenseName Unicode_TOU = "Unicode Terms of Use"@@ -1227,30 +1312,15 @@ licenseIsOsiApproved :: LicenseId -> Bool licenseIsOsiApproved NullBSD = True licenseIsOsiApproved AAL = True-licenseIsOsiApproved Abstyles = False-licenseIsOsiApproved Adobe_2006 = False-licenseIsOsiApproved Adobe_Glyph = False-licenseIsOsiApproved ADSL = False licenseIsOsiApproved AFL_1_1 = True licenseIsOsiApproved AFL_1_2 = True licenseIsOsiApproved AFL_2_0 = True licenseIsOsiApproved AFL_2_1 = True licenseIsOsiApproved AFL_3_0 = True-licenseIsOsiApproved Afmparse = False-licenseIsOsiApproved AGPL_1_0 = False-licenseIsOsiApproved AGPL_1_0_only = False-licenseIsOsiApproved AGPL_1_0_or_later = False licenseIsOsiApproved AGPL_3_0_only = True licenseIsOsiApproved AGPL_3_0_or_later = True-licenseIsOsiApproved Aladdin = False-licenseIsOsiApproved AMDPLPA = False-licenseIsOsiApproved AML = False-licenseIsOsiApproved AMPAS = False-licenseIsOsiApproved ANTLR_PD = False-licenseIsOsiApproved Apache_1_0 = False licenseIsOsiApproved Apache_1_1 = True licenseIsOsiApproved Apache_2_0 = True-licenseIsOsiApproved APAFML = False licenseIsOsiApproved APL_1_0 = True licenseIsOsiApproved APSL_1_0 = True licenseIsOsiApproved APSL_1_1 = True@@ -1260,341 +1330,223 @@ licenseIsOsiApproved Artistic_1_0_Perl = True licenseIsOsiApproved Artistic_1_0 = True licenseIsOsiApproved Artistic_2_0 = True-licenseIsOsiApproved Bahyph = False-licenseIsOsiApproved Barr = False-licenseIsOsiApproved Beerware = False-licenseIsOsiApproved BitTorrent_1_0 = False-licenseIsOsiApproved BitTorrent_1_1 = False-licenseIsOsiApproved Blessing = False-licenseIsOsiApproved BlueOak_1_0_0 = False-licenseIsOsiApproved Borceux = False-licenseIsOsiApproved BSD_1_Clause = False-licenseIsOsiApproved BSD_2_Clause_FreeBSD = False-licenseIsOsiApproved BSD_2_Clause_NetBSD = False+licenseIsOsiApproved BSD_1_Clause = True licenseIsOsiApproved BSD_2_Clause_Patent = True licenseIsOsiApproved BSD_2_Clause = True-licenseIsOsiApproved BSD_3_Clause_Attribution = False-licenseIsOsiApproved BSD_3_Clause_Clear = False licenseIsOsiApproved BSD_3_Clause_LBNL = True-licenseIsOsiApproved BSD_3_Clause_No_Nuclear_License_2014 = False-licenseIsOsiApproved BSD_3_Clause_No_Nuclear_License = False-licenseIsOsiApproved BSD_3_Clause_No_Nuclear_Warranty = False-licenseIsOsiApproved BSD_3_Clause_Open_MPI = False licenseIsOsiApproved BSD_3_Clause = True-licenseIsOsiApproved BSD_4_Clause_UC = False-licenseIsOsiApproved BSD_4_Clause = False-licenseIsOsiApproved BSD_Protection = False-licenseIsOsiApproved BSD_Source_Code = False licenseIsOsiApproved BSL_1_0 = True-licenseIsOsiApproved Bzip2_1_0_5 = False-licenseIsOsiApproved Bzip2_1_0_6 = False-licenseIsOsiApproved Caldera = False+licenseIsOsiApproved CAL_1_0_Combined_Work_Exception = True+licenseIsOsiApproved CAL_1_0 = True licenseIsOsiApproved CATOSL_1_1 = True-licenseIsOsiApproved CC_BY_1_0 = False-licenseIsOsiApproved CC_BY_2_0 = False-licenseIsOsiApproved CC_BY_2_5 = False-licenseIsOsiApproved CC_BY_3_0 = False-licenseIsOsiApproved CC_BY_4_0 = False-licenseIsOsiApproved CC_BY_NC_1_0 = False-licenseIsOsiApproved CC_BY_NC_2_0 = False-licenseIsOsiApproved CC_BY_NC_2_5 = False-licenseIsOsiApproved CC_BY_NC_3_0 = False-licenseIsOsiApproved CC_BY_NC_4_0 = False-licenseIsOsiApproved CC_BY_NC_ND_1_0 = False-licenseIsOsiApproved CC_BY_NC_ND_2_0 = False-licenseIsOsiApproved CC_BY_NC_ND_2_5 = False-licenseIsOsiApproved CC_BY_NC_ND_3_0 = False-licenseIsOsiApproved CC_BY_NC_ND_4_0 = False-licenseIsOsiApproved CC_BY_NC_SA_1_0 = False-licenseIsOsiApproved CC_BY_NC_SA_2_0 = False-licenseIsOsiApproved CC_BY_NC_SA_2_5 = False-licenseIsOsiApproved CC_BY_NC_SA_3_0 = False-licenseIsOsiApproved CC_BY_NC_SA_4_0 = False-licenseIsOsiApproved CC_BY_ND_1_0 = False-licenseIsOsiApproved CC_BY_ND_2_0 = False-licenseIsOsiApproved CC_BY_ND_2_5 = False-licenseIsOsiApproved CC_BY_ND_3_0 = False-licenseIsOsiApproved CC_BY_ND_4_0 = False-licenseIsOsiApproved CC_BY_SA_1_0 = False-licenseIsOsiApproved CC_BY_SA_2_0 = False-licenseIsOsiApproved CC_BY_SA_2_5 = False-licenseIsOsiApproved CC_BY_SA_3_0 = False-licenseIsOsiApproved CC_BY_SA_4_0 = False-licenseIsOsiApproved CC_PDDC = False-licenseIsOsiApproved CC0_1_0 = False licenseIsOsiApproved CDDL_1_0 = True-licenseIsOsiApproved CDDL_1_1 = False-licenseIsOsiApproved CDLA_Permissive_1_0 = False-licenseIsOsiApproved CDLA_Sharing_1_0 = False-licenseIsOsiApproved CECILL_1_0 = False-licenseIsOsiApproved CECILL_1_1 = False-licenseIsOsiApproved CECILL_2_0 = False licenseIsOsiApproved CECILL_2_1 = True-licenseIsOsiApproved CECILL_B = False-licenseIsOsiApproved CECILL_C = False-licenseIsOsiApproved CERN_OHL_1_1 = False-licenseIsOsiApproved CERN_OHL_1_2 = False-licenseIsOsiApproved ClArtistic = False-licenseIsOsiApproved CNRI_Jython = False-licenseIsOsiApproved CNRI_Python_GPL_Compatible = False licenseIsOsiApproved CNRI_Python = True-licenseIsOsiApproved Condor_1_1 = False-licenseIsOsiApproved Copyleft_next_0_3_0 = False-licenseIsOsiApproved Copyleft_next_0_3_1 = False licenseIsOsiApproved CPAL_1_0 = True licenseIsOsiApproved CPL_1_0 = True-licenseIsOsiApproved CPOL_1_02 = False-licenseIsOsiApproved Crossword = False-licenseIsOsiApproved CrystalStacker = False licenseIsOsiApproved CUA_OPL_1_0 = True-licenseIsOsiApproved Cube = False-licenseIsOsiApproved Curl = False-licenseIsOsiApproved D_FSL_1_0 = False-licenseIsOsiApproved Diffmark = False-licenseIsOsiApproved DOC = False-licenseIsOsiApproved Dotseqn = False-licenseIsOsiApproved DSDP = False-licenseIsOsiApproved Dvipdfm = False licenseIsOsiApproved ECL_1_0 = True licenseIsOsiApproved ECL_2_0 = True licenseIsOsiApproved EFL_1_0 = True licenseIsOsiApproved EFL_2_0 = True-licenseIsOsiApproved EGenix = False licenseIsOsiApproved Entessa = True licenseIsOsiApproved EPL_1_0 = True licenseIsOsiApproved EPL_2_0 = True-licenseIsOsiApproved ErlPL_1_1 = False licenseIsOsiApproved EUDatagrid = True-licenseIsOsiApproved EUPL_1_0 = False licenseIsOsiApproved EUPL_1_1 = True licenseIsOsiApproved EUPL_1_2 = True-licenseIsOsiApproved Eurosym = False licenseIsOsiApproved Fair = True licenseIsOsiApproved Frameworx_1_0 = True-licenseIsOsiApproved FreeImage = False-licenseIsOsiApproved FSFAP = False-licenseIsOsiApproved FSFULLR = False-licenseIsOsiApproved FSFUL = False-licenseIsOsiApproved FTL = False-licenseIsOsiApproved GFDL_1_1_only = False-licenseIsOsiApproved GFDL_1_1_or_later = False-licenseIsOsiApproved GFDL_1_2_only = False-licenseIsOsiApproved GFDL_1_2_or_later = False-licenseIsOsiApproved GFDL_1_3_only = False-licenseIsOsiApproved GFDL_1_3_or_later = False-licenseIsOsiApproved Giftware = False-licenseIsOsiApproved GL2PS = False-licenseIsOsiApproved Glide = False-licenseIsOsiApproved Glulxe = False-licenseIsOsiApproved Gnuplot = False-licenseIsOsiApproved GPL_1_0_only = False-licenseIsOsiApproved GPL_1_0_or_later = False licenseIsOsiApproved GPL_2_0_only = True licenseIsOsiApproved GPL_2_0_or_later = True licenseIsOsiApproved GPL_3_0_only = True licenseIsOsiApproved GPL_3_0_or_later = True-licenseIsOsiApproved GSOAP_1_3b = False-licenseIsOsiApproved HaskellReport = False-licenseIsOsiApproved HPND_sell_variant = False licenseIsOsiApproved HPND = True-licenseIsOsiApproved IBM_pibs = False-licenseIsOsiApproved ICU = False-licenseIsOsiApproved IJG = False-licenseIsOsiApproved ImageMagick = False-licenseIsOsiApproved IMatix = False-licenseIsOsiApproved Imlib2 = False-licenseIsOsiApproved Info_ZIP = False-licenseIsOsiApproved Intel_ACPI = False licenseIsOsiApproved Intel = True-licenseIsOsiApproved Interbase_1_0 = False licenseIsOsiApproved IPA = True licenseIsOsiApproved IPL_1_0 = True licenseIsOsiApproved ISC = True-licenseIsOsiApproved JasPer_2_0 = False-licenseIsOsiApproved JPNIC = False-licenseIsOsiApproved JSON = False-licenseIsOsiApproved LAL_1_2 = False-licenseIsOsiApproved LAL_1_3 = False-licenseIsOsiApproved Latex2e = False-licenseIsOsiApproved Leptonica = False licenseIsOsiApproved LGPL_2_0_only = True licenseIsOsiApproved LGPL_2_0_or_later = True licenseIsOsiApproved LGPL_2_1_only = True licenseIsOsiApproved LGPL_2_1_or_later = True licenseIsOsiApproved LGPL_3_0_only = True licenseIsOsiApproved LGPL_3_0_or_later = True-licenseIsOsiApproved LGPLLR = False-licenseIsOsiApproved Libpng_2_0 = False-licenseIsOsiApproved Libpng = False-licenseIsOsiApproved Libtiff = False licenseIsOsiApproved LiLiQ_P_1_1 = True licenseIsOsiApproved LiLiQ_R_1_1 = True licenseIsOsiApproved LiLiQ_Rplus_1_1 = True-licenseIsOsiApproved Linux_OpenIB = False licenseIsOsiApproved LPL_1_02 = True licenseIsOsiApproved LPL_1_0 = True-licenseIsOsiApproved LPPL_1_0 = False-licenseIsOsiApproved LPPL_1_1 = False-licenseIsOsiApproved LPPL_1_2 = False-licenseIsOsiApproved LPPL_1_3a = False licenseIsOsiApproved LPPL_1_3c = True-licenseIsOsiApproved MakeIndex = False licenseIsOsiApproved MirOS = True-licenseIsOsiApproved MIT_0 = True-licenseIsOsiApproved MIT_advertising = False-licenseIsOsiApproved MIT_CMU = False-licenseIsOsiApproved MIT_enna = False-licenseIsOsiApproved MIT_feh = False-licenseIsOsiApproved MITNFA = False licenseIsOsiApproved MIT = True licenseIsOsiApproved Motosoto = True-licenseIsOsiApproved Mpich2 = False licenseIsOsiApproved MPL_1_0 = True licenseIsOsiApproved MPL_1_1 = True licenseIsOsiApproved MPL_2_0_no_copyleft_exception = True licenseIsOsiApproved MPL_2_0 = True licenseIsOsiApproved MS_PL = True licenseIsOsiApproved MS_RL = True-licenseIsOsiApproved MTLL = False+licenseIsOsiApproved MulanPSL_2_0 = True licenseIsOsiApproved Multics = True-licenseIsOsiApproved Mup = False licenseIsOsiApproved NASA_1_3 = True licenseIsOsiApproved Naumen = True-licenseIsOsiApproved NBPL_1_0 = False licenseIsOsiApproved NCSA = True-licenseIsOsiApproved Net_SNMP = False-licenseIsOsiApproved NetCDF = False-licenseIsOsiApproved Newsletr = False licenseIsOsiApproved NGPL = True-licenseIsOsiApproved NLOD_1_0 = False-licenseIsOsiApproved NLPL = False licenseIsOsiApproved Nokia = True-licenseIsOsiApproved NOSL = False-licenseIsOsiApproved Noweb = False-licenseIsOsiApproved NPL_1_0 = False-licenseIsOsiApproved NPL_1_1 = False licenseIsOsiApproved NPOSL_3_0 = True-licenseIsOsiApproved NRL = False licenseIsOsiApproved NTP = True-licenseIsOsiApproved OCCT_PL = False licenseIsOsiApproved OCLC_2_0 = True-licenseIsOsiApproved ODbL_1_0 = False-licenseIsOsiApproved ODC_By_1_0 = False-licenseIsOsiApproved OFL_1_0 = False+licenseIsOsiApproved OFL_1_1_no_RFN = True+licenseIsOsiApproved OFL_1_1_RFN = True licenseIsOsiApproved OFL_1_1 = True-licenseIsOsiApproved OGL_UK_1_0 = False-licenseIsOsiApproved OGL_UK_2_0 = False-licenseIsOsiApproved OGL_UK_3_0 = False licenseIsOsiApproved OGTSL = True-licenseIsOsiApproved OLDAP_1_1 = False-licenseIsOsiApproved OLDAP_1_2 = False-licenseIsOsiApproved OLDAP_1_3 = False-licenseIsOsiApproved OLDAP_1_4 = False-licenseIsOsiApproved OLDAP_2_0_1 = False-licenseIsOsiApproved OLDAP_2_0 = False-licenseIsOsiApproved OLDAP_2_1 = False-licenseIsOsiApproved OLDAP_2_2_1 = False-licenseIsOsiApproved OLDAP_2_2_2 = False-licenseIsOsiApproved OLDAP_2_2 = False-licenseIsOsiApproved OLDAP_2_3 = False-licenseIsOsiApproved OLDAP_2_4 = False-licenseIsOsiApproved OLDAP_2_5 = False-licenseIsOsiApproved OLDAP_2_6 = False-licenseIsOsiApproved OLDAP_2_7 = False-licenseIsOsiApproved OLDAP_2_8 = False-licenseIsOsiApproved OML = False-licenseIsOsiApproved OpenSSL = False-licenseIsOsiApproved OPL_1_0 = False licenseIsOsiApproved OSET_PL_2_1 = True licenseIsOsiApproved OSL_1_0 = True-licenseIsOsiApproved OSL_1_1 = False licenseIsOsiApproved OSL_2_0 = True licenseIsOsiApproved OSL_2_1 = True licenseIsOsiApproved OSL_3_0 = True-licenseIsOsiApproved Parity_6_0_0 = False-licenseIsOsiApproved PDDL_1_0 = False-licenseIsOsiApproved PHP_3_01 = False licenseIsOsiApproved PHP_3_0 = True-licenseIsOsiApproved Plexus = False licenseIsOsiApproved PostgreSQL = True-licenseIsOsiApproved Psfrag = False-licenseIsOsiApproved Psutils = False licenseIsOsiApproved Python_2_0 = True-licenseIsOsiApproved Qhull = False licenseIsOsiApproved QPL_1_0 = True-licenseIsOsiApproved Rdisc = False-licenseIsOsiApproved RHeCos_1_1 = False licenseIsOsiApproved RPL_1_1 = True licenseIsOsiApproved RPL_1_5 = True licenseIsOsiApproved RPSL_1_0 = True-licenseIsOsiApproved RSA_MD = False licenseIsOsiApproved RSCPL = True-licenseIsOsiApproved Ruby = False-licenseIsOsiApproved SAX_PD = False-licenseIsOsiApproved Saxpath = False-licenseIsOsiApproved SCEA = False-licenseIsOsiApproved Sendmail_8_23 = False-licenseIsOsiApproved Sendmail = False-licenseIsOsiApproved SGI_B_1_0 = False-licenseIsOsiApproved SGI_B_1_1 = False-licenseIsOsiApproved SGI_B_2_0 = False-licenseIsOsiApproved SHL_0_51 = False-licenseIsOsiApproved SHL_0_5 = False licenseIsOsiApproved SimPL_2_0 = True-licenseIsOsiApproved SISSL_1_2 = False licenseIsOsiApproved SISSL = True licenseIsOsiApproved Sleepycat = True-licenseIsOsiApproved SMLNJ = False-licenseIsOsiApproved SMPPL = False-licenseIsOsiApproved SNIA = False-licenseIsOsiApproved Spencer_86 = False-licenseIsOsiApproved Spencer_94 = False-licenseIsOsiApproved Spencer_99 = False licenseIsOsiApproved SPL_1_0 = True-licenseIsOsiApproved SSPL_1_0 = False-licenseIsOsiApproved SugarCRM_1_1_3 = False-licenseIsOsiApproved SWL = False-licenseIsOsiApproved TAPR_OHL_1_0 = False-licenseIsOsiApproved TCL = False-licenseIsOsiApproved TCP_wrappers = False-licenseIsOsiApproved TMate = False-licenseIsOsiApproved TORQUE_1_1 = False-licenseIsOsiApproved TOSL = False-licenseIsOsiApproved TU_Berlin_1_0 = False-licenseIsOsiApproved TU_Berlin_2_0 = False-licenseIsOsiApproved Unicode_DFS_2015 = False-licenseIsOsiApproved Unicode_DFS_2016 = False-licenseIsOsiApproved Unicode_TOU = False-licenseIsOsiApproved Unlicense = False+licenseIsOsiApproved UCL_1_0 = True licenseIsOsiApproved UPL_1_0 = True-licenseIsOsiApproved Vim = False-licenseIsOsiApproved VOSTROM = False licenseIsOsiApproved VSL_1_0 = True-licenseIsOsiApproved W3C_19980720 = False-licenseIsOsiApproved W3C_20150513 = False licenseIsOsiApproved W3C = True licenseIsOsiApproved Watcom_1_0 = True-licenseIsOsiApproved Wsuipa = False-licenseIsOsiApproved WTFPL = False-licenseIsOsiApproved X11 = False-licenseIsOsiApproved Xerox = False-licenseIsOsiApproved XFree86_1_1 = False-licenseIsOsiApproved Xinetd = False licenseIsOsiApproved Xnet = True-licenseIsOsiApproved Xpp = False-licenseIsOsiApproved XSkat = False-licenseIsOsiApproved YPL_1_0 = False-licenseIsOsiApproved YPL_1_1 = False-licenseIsOsiApproved Zed = False-licenseIsOsiApproved Zend_2_0 = False-licenseIsOsiApproved Zimbra_1_3 = False-licenseIsOsiApproved Zimbra_1_4 = False-licenseIsOsiApproved Zlib_acknowledgement = False licenseIsOsiApproved Zlib = True-licenseIsOsiApproved ZPL_1_1 = False licenseIsOsiApproved ZPL_2_0 = True-licenseIsOsiApproved ZPL_2_1 = False+licenseIsOsiApproved _ = False +-- | Whether the license is considered libre by Free Software Foundation (FSF).+--+-- See <https://www.gnu.org/licenses/license-list.en.html>+--+-- @since 3.4.0.0+--+licenseIsFsfLibre :: LicenseId -> Bool+licenseIsFsfLibre AFL_1_1 = True+licenseIsFsfLibre AFL_1_2 = True+licenseIsFsfLibre AFL_2_0 = True+licenseIsFsfLibre AFL_2_1 = True+licenseIsFsfLibre AFL_3_0 = True+licenseIsFsfLibre AGPL_1_0 = True+licenseIsFsfLibre AGPL_3_0_only = True+licenseIsFsfLibre AGPL_3_0_or_later = True+licenseIsFsfLibre Apache_1_0 = True+licenseIsFsfLibre Apache_1_1 = True+licenseIsFsfLibre Apache_2_0 = True+licenseIsFsfLibre APSL_2_0 = True+licenseIsFsfLibre Artistic_2_0 = True+licenseIsFsfLibre BitTorrent_1_1 = True+licenseIsFsfLibre BSD_2_Clause_FreeBSD = True+licenseIsFsfLibre BSD_3_Clause_Clear = True+licenseIsFsfLibre BSD_3_Clause = True+licenseIsFsfLibre BSD_4_Clause = True+licenseIsFsfLibre BSL_1_0 = True+licenseIsFsfLibre CC_BY_4_0 = True+licenseIsFsfLibre CC_BY_SA_4_0 = True+licenseIsFsfLibre CC0_1_0 = True+licenseIsFsfLibre CDDL_1_0 = True+licenseIsFsfLibre CECILL_2_0 = True+licenseIsFsfLibre CECILL_B = True+licenseIsFsfLibre CECILL_C = True+licenseIsFsfLibre ClArtistic = True+licenseIsFsfLibre Condor_1_1 = True+licenseIsFsfLibre CPAL_1_0 = True+licenseIsFsfLibre CPL_1_0 = True+licenseIsFsfLibre ECL_2_0 = True+licenseIsFsfLibre EFL_2_0 = True+licenseIsFsfLibre EPL_1_0 = True+licenseIsFsfLibre EPL_2_0 = True+licenseIsFsfLibre EUDatagrid = True+licenseIsFsfLibre EUPL_1_1 = True+licenseIsFsfLibre EUPL_1_2 = True+licenseIsFsfLibre FSFAP = True+licenseIsFsfLibre FTL = True+licenseIsFsfLibre GFDL_1_1_only = True+licenseIsFsfLibre GFDL_1_1_or_later = True+licenseIsFsfLibre GFDL_1_2_only = True+licenseIsFsfLibre GFDL_1_2_or_later = True+licenseIsFsfLibre GFDL_1_3_only = True+licenseIsFsfLibre GFDL_1_3_or_later = True+licenseIsFsfLibre Gnuplot = True+licenseIsFsfLibre GPL_2_0_only = True+licenseIsFsfLibre GPL_2_0_or_later = True+licenseIsFsfLibre GPL_3_0_only = True+licenseIsFsfLibre GPL_3_0_or_later = True+licenseIsFsfLibre HPND = True+licenseIsFsfLibre IJG = True+licenseIsFsfLibre IMatix = True+licenseIsFsfLibre Imlib2 = True+licenseIsFsfLibre Intel = True+licenseIsFsfLibre IPA = True+licenseIsFsfLibre IPL_1_0 = True+licenseIsFsfLibre ISC = True+licenseIsFsfLibre LGPL_2_1_only = True+licenseIsFsfLibre LGPL_2_1_or_later = True+licenseIsFsfLibre LGPL_3_0_only = True+licenseIsFsfLibre LGPL_3_0_or_later = True+licenseIsFsfLibre LPL_1_02 = True+licenseIsFsfLibre LPPL_1_2 = True+licenseIsFsfLibre LPPL_1_3a = True+licenseIsFsfLibre MIT = True+licenseIsFsfLibre MPL_1_1 = True+licenseIsFsfLibre MPL_2_0 = True+licenseIsFsfLibre MS_PL = True+licenseIsFsfLibre MS_RL = True+licenseIsFsfLibre NCSA = True+licenseIsFsfLibre Nokia = True+licenseIsFsfLibre NOSL = True+licenseIsFsfLibre NPL_1_0 = True+licenseIsFsfLibre NPL_1_1 = True+licenseIsFsfLibre ODbL_1_0 = True+licenseIsFsfLibre OFL_1_0 = True+licenseIsFsfLibre OFL_1_1 = True+licenseIsFsfLibre OLDAP_2_3 = True+licenseIsFsfLibre OLDAP_2_7 = True+licenseIsFsfLibre OpenSSL = True+licenseIsFsfLibre OSL_1_0 = True+licenseIsFsfLibre OSL_1_1 = True+licenseIsFsfLibre OSL_2_0 = True+licenseIsFsfLibre OSL_2_1 = True+licenseIsFsfLibre OSL_3_0 = True+licenseIsFsfLibre PHP_3_01 = True+licenseIsFsfLibre Python_2_0 = True+licenseIsFsfLibre QPL_1_0 = True+licenseIsFsfLibre RPSL_1_0 = True+licenseIsFsfLibre Ruby = True+licenseIsFsfLibre SGI_B_2_0 = True+licenseIsFsfLibre SISSL = True+licenseIsFsfLibre Sleepycat = True+licenseIsFsfLibre SMLNJ = True+licenseIsFsfLibre SPL_1_0 = True+licenseIsFsfLibre Unlicense = True+licenseIsFsfLibre UPL_1_0 = True+licenseIsFsfLibre Vim = True+licenseIsFsfLibre W3C = True+licenseIsFsfLibre WTFPL = True+licenseIsFsfLibre X11 = True+licenseIsFsfLibre XFree86_1_1 = True+licenseIsFsfLibre Xinetd = True+licenseIsFsfLibre YPL_1_1 = True+licenseIsFsfLibre Zend_2_0 = True+licenseIsFsfLibre Zimbra_1_3 = True+licenseIsFsfLibre Zlib = True+licenseIsFsfLibre ZPL_2_0 = True+licenseIsFsfLibre ZPL_2_1 = True+licenseIsFsfLibre _ = False+ ------------------------------------------------------------------------------- -- Creation -------------------------------------------------------------------------------@@ -1602,11 +1554,13 @@ licenseIdList :: LicenseListVersion -> [LicenseId] licenseIdList LicenseListVersion_3_0 = [ AGPL_1_0+ , BSD_2_Clause_NetBSD ] ++ bulkOfLicenses licenseIdList LicenseListVersion_3_2 = [ AGPL_1_0_only , AGPL_1_0_or_later+ , BSD_2_Clause_NetBSD , Linux_OpenIB , MIT_0 , ODC_By_1_0@@ -1619,6 +1573,7 @@ , AGPL_1_0_or_later , Blessing , BlueOak_1_0_0+ , BSD_2_Clause_NetBSD , BSD_3_Clause_Open_MPI , CC_PDDC , CERN_OHL_1_1@@ -1644,12 +1599,69 @@ , TU_Berlin_2_0 ] ++ bulkOfLicenses+licenseIdList LicenseListVersion_3_9 =+ [ AGPL_1_0_only+ , AGPL_1_0_or_later+ , Blessing+ , BlueOak_1_0_0+ , BSD_3_Clause_Open_MPI+ , CAL_1_0_Combined_Work_Exception+ , CAL_1_0+ , CC_PDDC+ , CERN_OHL_1_1+ , CERN_OHL_1_2+ , CERN_OHL_P_2_0+ , CERN_OHL_S_2_0+ , CERN_OHL_W_2_0+ , Copyleft_next_0_3_0+ , Copyleft_next_0_3_1+ , Etalab_2_0+ , Hippocratic_2_1+ , HPND_sell_variant+ , JPNIC+ , Libpng_2_0+ , Libselinux_1_0+ , Linux_OpenIB+ , MIT_0+ , MulanPSL_1_0+ , MulanPSL_2_0+ , NCGL_UK_2_0+ , NTP_0+ , O_UDA_1_0+ , ODC_By_1_0+ , OFL_1_0_no_RFN+ , OFL_1_0_RFN+ , OFL_1_1_no_RFN+ , OFL_1_1_RFN+ , OGC_1_0+ , OGL_Canada_2_0+ , OGL_UK_1_0+ , OGL_UK_2_0+ , OGL_UK_3_0+ , Parity_6_0_0+ , Parity_7_0_0+ , PolyForm_Noncommercial_1_0_0+ , PolyForm_Small_Business_1_0_0+ , PSF_2_0+ , Sendmail_8_23+ , SHL_0_51+ , SHL_0_5+ , SSH_OpenSSH+ , SSH_short+ , SSPL_1_0+ , TAPR_OHL_1_0+ , TU_Berlin_1_0+ , TU_Berlin_2_0+ , UCL_1_0+ ]+ ++ bulkOfLicenses -- | Create a 'LicenseId' from a 'String'. mkLicenseId :: LicenseListVersion -> String -> Maybe LicenseId mkLicenseId LicenseListVersion_3_0 s = Map.lookup s stringLookup_3_0 mkLicenseId LicenseListVersion_3_2 s = Map.lookup s stringLookup_3_2 mkLicenseId LicenseListVersion_3_6 s = Map.lookup s stringLookup_3_6+mkLicenseId LicenseListVersion_3_9 s = Map.lookup s stringLookup_3_9 stringLookup_3_0 :: Map String LicenseId stringLookup_3_0 = Map.fromList $ map (\i -> (licenseId i, i)) $@@ -1663,6 +1675,10 @@ stringLookup_3_6 = Map.fromList $ map (\i -> (licenseId i, i)) $ licenseIdList LicenseListVersion_3_6 +stringLookup_3_9 :: Map String LicenseId+stringLookup_3_9 = Map.fromList $ map (\i -> (licenseId i, i)) $+ licenseIdList LicenseListVersion_3_9+ -- | Licenses in all SPDX License lists bulkOfLicenses :: [LicenseId] bulkOfLicenses =@@ -1706,7 +1722,6 @@ , Borceux , BSD_1_Clause , BSD_2_Clause_FreeBSD- , BSD_2_Clause_NetBSD , BSD_2_Clause_Patent , BSD_2_Clause , BSD_3_Clause_Attribution
cabal/Cabal/Distribution/SPDX/LicenseListVersion.hs view
@@ -10,10 +10,11 @@ = LicenseListVersion_3_0 | LicenseListVersion_3_2 | LicenseListVersion_3_6+ | LicenseListVersion_3_9 deriving (Eq, Ord, Show, Enum, Bounded) cabalSpecVersionToSPDXListVersion :: CabalSpecVersion -> LicenseListVersion-cabalSpecVersionToSPDXListVersion CabalSpecV3_2 = LicenseListVersion_3_6+cabalSpecVersionToSPDXListVersion CabalSpecV3_4 = LicenseListVersion_3_9 cabalSpecVersionToSPDXListVersion CabalSpecV3_0 = LicenseListVersion_3_6 cabalSpecVersionToSPDXListVersion CabalSpecV2_4 = LicenseListVersion_3_2 cabalSpecVersionToSPDXListVersion _ = LicenseListVersion_3_0
cabal/Cabal/Distribution/SPDX/LicenseReference.hs view
@@ -34,6 +34,7 @@ licenseDocumentRef = _lrDocument instance Binary LicenseRef+instance Structured LicenseRef instance NFData LicenseRef where rnf (LicenseRef d l) = rnf d `seq` rnf l
cabal/Cabal/Distribution/Simple.hs view
@@ -61,10 +61,10 @@ import Distribution.Compat.Prelude -- local-import Distribution.Simple.Compiler hiding (Flag)+import Distribution.Simple.Compiler import Distribution.Simple.UserHooks import Distribution.Package-import Distribution.PackageDescription hiding (Flag)+import Distribution.PackageDescription import Distribution.PackageDescription.Configuration import Distribution.Simple.Program import Distribution.Simple.Program.Db@@ -98,7 +98,6 @@ import System.Environment (getArgs, getProgName) import System.Directory (removeFile, doesFileExist ,doesDirectoryExist, removeDirectoryRecursive)-import System.Exit (exitWith,ExitCode(..)) import System.FilePath (searchPathSeparator, takeDirectory, (</>), splitDirectories, dropDrive) import Distribution.Compat.ResponseFile (expandResponse) import Distribution.Compat.Directory (makeAbsolute)@@ -413,31 +412,12 @@ (getBuildConfig hooks verbosity distPref) hooks flags' args +-- Since Cabal-3.4 UserHooks are completely ignored sdistAction :: UserHooks -> SDistFlags -> Args -> IO ()-sdistAction hooks flags _args = do- distPref <- findDistPrefOrDefault (sDistDistPref flags)- let pbi = emptyHookedBuildInfo-- mlbi <- maybeGetPersistBuildConfig distPref-- -- NB: It would be TOTALLY WRONG to use the 'PackageDescription'- -- store in the 'LocalBuildInfo' for the rest of @sdist@, because- -- that would result in only the files that would be built- -- according to the user's configure being packaged up.- -- In fact, it is not obvious why we need to read the- -- 'LocalBuildInfo' in the first place, except that we want- -- to do some architecture-independent preprocessing which- -- needs to be configured. This is totally awful, see- -- GH#130.-- (_, ppd) <- confPkgDescr hooks verbosity Nothing-- let pkg_descr0 = flattenPackageDescription ppd- sanityCheckHookedBuildInfo verbosity pkg_descr0 pbi- let pkg_descr = updatePackageDescription pbi pkg_descr0- mlbi' = fmap (\lbi -> lbi { localPkgDescr = pkg_descr }) mlbi-- sdist pkg_descr mlbi' flags srcPref (allSuffixHandlers hooks)+sdistAction _hooks flags _args = do+ (_, ppd) <- confPkgDescr emptyUserHooks verbosity Nothing+ let pkg_descr = flattenPackageDescription ppd+ sdist pkg_descr flags srcPref knownSuffixHandlers where verbosity = fromFlag (sDistVerbosity flags) @@ -606,7 +586,7 @@ traverse_ (writePersistBuildConfig distPref) maybeConfig where- removeFileOrDirectory :: FilePath -> NoCallStackIO ()+ removeFileOrDirectory :: FilePath -> IO () removeFileOrDirectory fname = do isDir <- doesDirectoryExist fname isFile <- doesFileExist fname@@ -740,11 +720,13 @@ let configureFile' = intercalate "/" $ splitDirectories configureFile for_ badAutoconfCharacters $ \(c, cname) -> when (c `elem` dropDrive configureFile') $- warn verbosity $- "The path to the './configure' script, '" ++ configureFile'- ++ "', contains the character '" ++ [c] ++ "' (" ++ cname ++ ")."- ++ " This may cause the script to fail with an obscure error, or for"- ++ " building the package to fail later."+ warn verbosity $ concat+ [ "The path to the './configure' script, '", configureFile'+ , "', contains the character '", [c], "' (", cname, ")."+ , " This may cause the script to fail with an obscure error, or for"+ , " building the package to fail later."+ ]+ let extraPath = fromNubList $ configProgramPathExtra flags let cflagsEnv = maybe (unwords ccFlags) (++ (" " ++ unwords ccFlags)) $ lookup "CFLAGS" env@@ -766,39 +748,39 @@ (programInvocation (sh {programOverrideEnv = overEnv}) args') { progInvokeCwd = Just (buildDir lbi) } Nothing -> die' verbosity notFoundMsg- where args = configureArgs backwardsCompatHack flags - badAutoconfCharacters =- [ (' ', "space")- , ('\t', "tab")- , ('\n', "newline")- , ('\0', "null")- , ('"', "double quote")- , ('#', "hash")- , ('$', "dollar sign")- , ('&', "ampersand")- , ('\'', "single quote")- , ('(', "left bracket")- , (')', "right bracket")- , ('*', "star")- , (';', "semicolon")- , ('<', "less-than sign")- , ('=', "equals sign")- , ('>', "greater-than sign")- , ('?', "question mark")- , ('[', "left square bracket")- , ('\\', "backslash")- , ('`', "backtick")- , ('|', "pipe")- ]- notFoundMsg = "The package has a './configure' script. " ++ "If you are on Windows, This requires a " ++ "Unix compatibility toolchain such as MinGW+MSYS or Cygwin. " ++ "If you are not on Windows, ensure that an 'sh' command " ++ "is discoverable in your path."++badAutoconfCharacters :: [(Char, String)]+badAutoconfCharacters =+ [ (' ', "space")+ , ('\t', "tab")+ , ('\n', "newline")+ , ('\0', "null")+ , ('"', "double quote")+ , ('#', "hash")+ , ('$', "dollar sign")+ , ('&', "ampersand")+ , ('\'', "single quote")+ , ('(', "left bracket")+ , (')', "right bracket")+ , ('*', "star")+ , (';', "semicolon")+ , ('<', "less-than sign")+ , ('=', "equals sign")+ , ('>', "greater-than sign")+ , ('?', "question mark")+ , ('[', "left square bracket")+ , ('\\', "backslash")+ , ('`', "backtick")+ , ('|', "pipe")+ ] getHookedBuildInfo :: Verbosity -> FilePath -> IO HookedBuildInfo getHookedBuildInfo verbosity build_dir = do
cabal/Cabal/Distribution/Simple/Bench.hs view
@@ -32,7 +32,6 @@ import Distribution.Simple.Utils import Distribution.Pretty -import System.Exit ( ExitCode(..), exitFailure, exitSuccess ) import System.Directory ( doesFileExist ) import System.FilePath ( (</>), (<.>) )
cabal/Cabal/Distribution/Simple/Build.hs view
@@ -41,8 +41,8 @@ import Distribution.Types.LocalBuildInfo import Distribution.Types.MungedPackageId import Distribution.Types.MungedPackageName+import Distribution.Types.ModuleRenaming import Distribution.Types.TargetInfo-import Distribution.Types.UnqualComponentName import Distribution.Package import Distribution.Backpack@@ -57,8 +57,8 @@ import Distribution.Simple.Build.PathsModule (generatePathsModule) import qualified Distribution.Simple.Program.HcPkg as HcPkg -import Distribution.Simple.Compiler hiding (Flag)-import Distribution.PackageDescription hiding (Flag)+import Distribution.Simple.Compiler+import Distribution.PackageDescription import qualified Distribution.InstalledPackageInfo as IPI import Distribution.InstalledPackageInfo (InstalledPackageInfo) import qualified Distribution.ModuleName as ModuleName@@ -81,6 +81,7 @@ import Distribution.System import Distribution.Pretty import Distribution.Verbosity+import Distribution.Version (thisVersion) import Distribution.Compat.Graph (IsNode(..)) @@ -535,8 +536,9 @@ , componentCompatPackageKey = compat_key , componentExposedModules = [IPI.ExposedModule m Nothing] }+ pkgName' = mkPackageName $ prettyShow compat_name pkg = pkg_descr {- package = (package pkg_descr) { pkgName = mkPackageName $ prettyShow compat_name }+ package = (package pkg_descr) { pkgName = pkgName' } , executables = [] , testSuites = [] , subLibraries = [lib]@@ -544,7 +546,10 @@ ipi = inplaceInstalledPackageInfo pwd distPref pkg (mkAbiHash "") lib lbi libClbi testDir = buildDir lbi </> stubName test </> stubName test ++ "-tmp"- testLibDep = thisPackageVersion $ package pkg+ testLibDep = Dependency+ pkgName'+ (thisVersion $ pkgVersion $ package pkg_descr)+ mainLibSet exe = Executable { exeName = mkUnqualComponentName $ stubName test, modulePath = stubFilePath test,
cabal/Cabal/Distribution/Simple/Build/Macros.hs view
@@ -34,122 +34,76 @@ import Distribution.Simple.Program.Types import Distribution.Types.MungedPackageId import Distribution.Types.MungedPackageName-import Distribution.Types.PackageId import Distribution.Pretty --- --------------------------------------------------------------- * Generate cabal_macros.h--- ---------------------------------------------------------------- Invariant: HeaderLines always has a trailing newline-type HeaderLines = String--line :: String -> HeaderLines-line str = str ++ "\n"--ifndef :: String -> HeaderLines -> HeaderLines-ifndef macro body =- line ("#ifndef " ++ macro) ++- body ++- line ("#endif /* " ++ macro ++ " */")--define :: String -> Maybe [String] -> String -> HeaderLines-define macro params val =- line ("#define " ++ macro ++ f params ++ " " ++ val)- where- f Nothing = ""- f (Just xs) = "(" ++ intercalate "," xs ++ ")"--defineStr :: String -> String -> HeaderLines-defineStr macro str = define macro Nothing (show str)--ifndefDefine :: String -> Maybe [String] -> String -> HeaderLines-ifndefDefine macro params str =- ifndef macro (define macro params str)--ifndefDefineStr :: String -> String -> HeaderLines-ifndefDefineStr macro str =- ifndef macro (defineStr macro str)+import qualified Distribution.Simple.Build.Macros.Z as Z -- | The contents of the @cabal_macros.h@ for the given configured package. -- generateCabalMacrosHeader :: PackageDescription -> LocalBuildInfo -> ComponentLocalBuildInfo -> String-generateCabalMacrosHeader pkg_descr lbi clbi =- "/* DO NOT EDIT: This file is automatically generated by Cabal */\n\n" ++- generatePackageVersionMacros- (package pkg_descr : map getPid (componentPackageDeps clbi)) ++- generateToolVersionMacros (configuredPrograms . withPrograms $ lbi) ++- generateComponentIdMacro lbi clbi ++- generateCurrentPackageVersion pkg_descr- where- getPid (_, MungedPackageId (MungedPackageName pn _) v) =- -- NB: Drop the library name! We're just reporting package versions.- -- This would have to be revisited if you are allowed to depend- -- on different versions of the same package- PackageIdentifier pn v+generateCabalMacrosHeader pkg_descr lbi clbi = Z.render Z.Z+ { Z.zPackages = map mkZPackage $ package pkg_descr : map getPid (componentPackageDeps clbi)+ , Z.zTools =+ [ Z.ZTool+ { Z.ztoolName = programId prog+ , Z.ztoolVersion = ver+ , Z.ztoolX = major1+ , Z.ztoolY = major2+ , Z.ztoolZ = minor+ }+ | prog <- configuredPrograms $ withPrograms lbi+ , ver <- maybeToList (programVersion prog)+ , let (major1,major2,minor) = majorMinor ver+ ]+ , Z.zPackageKey = case clbi of+ LibComponentLocalBuildInfo{} -> componentCompatPackageKey clbi+ _ -> ""+ , Z.zComponentId = prettyShow (componentComponentId clbi)+ , Z.zPackageVersion = pkgVersion (package pkg_descr)+ , Z.zNotNull = not . null+ , Z.zManglePkgName = map fixchar . unPackageName+ , Z.zMangleStr = map fixchar+ }+ where+ getPid (_, MungedPackageId (MungedPackageName pn _) v) =+ -- NB: Drop the library name! We're just reporting package versions.+ -- This would have to be revisited if you are allowed to depend+ -- on different versions of the same package+ PackageIdentifier pn v -- | Helper function that generates just the @VERSION_pkg@ and @MIN_VERSION_pkg@ -- macros for a list of package ids (usually used with the specific deps of -- a configured package). ---generatePackageVersionMacros :: [PackageId] -> String-generatePackageVersionMacros pkgids = concat- [ line ("/* package " ++ prettyShow pkgid ++ " */")- ++ generateMacros "" pkgname version- | pkgid@(PackageIdentifier name version) <- pkgids- , let pkgname = map fixchar (prettyShow name)- ]---- | Helper function that generates just the @TOOL_VERSION_pkg@ and--- @MIN_TOOL_VERSION_pkg@ macros for a list of configured programs.----generateToolVersionMacros :: [ConfiguredProgram] -> String-generateToolVersionMacros progs = concat- [ line ("/* tool " ++ progid ++ " */")- ++ generateMacros "TOOL_" progname version- | prog <- progs- , isJust . programVersion $ prog- , let progid = programId prog ++ "-" ++ prettyShow version- progname = map fixchar (programId prog)- Just version = programVersion prog- ]+generatePackageVersionMacros :: Version -> [PackageId] -> String+generatePackageVersionMacros ver pkgids = Z.render Z.Z+ { Z.zPackages = map mkZPackage pkgids+ , Z.zTools = []+ , Z.zPackageKey = ""+ , Z.zComponentId = ""+ , Z.zPackageVersion = ver+ , Z.zNotNull = not . null+ , Z.zManglePkgName = map fixchar . unPackageName+ , Z.zMangleStr = map fixchar+ } --- | Common implementation of 'generatePackageVersionMacros' and--- 'generateToolVersionMacros'.----generateMacros :: String -> String -> Version -> String-generateMacros macro_prefix name version =- concat- [ifndefDefineStr (macro_prefix ++ "VERSION_" ++ name) (prettyShow version)- ,ifndefDefine ("MIN_" ++ macro_prefix ++ "VERSION_" ++ name)- (Just ["major1","major2","minor"])- $ concat [- "(\\\n"- ," (major1) < ",major1," || \\\n"- ," (major1) == ",major1," && (major2) < ",major2," || \\\n"- ," (major1) == ",major1," && (major2) == ",major2," && (minor) <= ",minor,")"- ]- ,"\n"]+mkZPackage :: PackageId -> Z.ZPackage+mkZPackage (PackageIdentifier name ver) = Z.ZPackage+ { Z.zpkgName = name+ , Z.zpkgVersion = ver+ , Z.zpkgX = major1+ , Z.zpkgY = major2+ , Z.zpkgZ = minor+ } where- (major1:major2:minor:_) = map show (versionNumbers version ++ repeat 0)---- | Generate the @CURRENT_COMPONENT_ID@ definition for the component ID--- of the current package.-generateComponentIdMacro :: LocalBuildInfo -> ComponentLocalBuildInfo -> String-generateComponentIdMacro _lbi clbi =- concat $- [case clbi of- LibComponentLocalBuildInfo{} ->- ifndefDefineStr "CURRENT_PACKAGE_KEY" (componentCompatPackageKey clbi)- _ -> ""- ,ifndefDefineStr "CURRENT_COMPONENT_ID" (prettyShow (componentComponentId clbi))- ]+ (major1,major2,minor) = majorMinor ver --- | Generate the @CURRENT_PACKAGE_VERSION@ definition for the declared version--- of the current package.-generateCurrentPackageVersion :: PackageDescription -> String-generateCurrentPackageVersion pd =- ifndefDefineStr "CURRENT_PACKAGE_VERSION" (prettyShow (pkgVersion (package pd)))+majorMinor :: Version -> (String, String, String)+majorMinor ver = case map show (versionNumbers ver) of+ [] -> ("0", "0", "0")+ [x] -> (x, "0", "0")+ [x,y] -> (x, y, "0")+ (x:y:z:_) -> (x, y, z) fixchar :: Char -> Char fixchar '-' = '_'
+ cabal/Cabal/Distribution/Simple/Build/Macros/Z.hs view
@@ -0,0 +1,140 @@+{-# LANGUAGE DeriveGeneric #-}+module Distribution.Simple.Build.Macros.Z (render, Z(..), ZPackage (..), ZTool (..)) where+import Distribution.ZinzaPrelude+data Z+ = Z {zPackages :: ([ZPackage]),+ zTools :: ([ZTool]),+ zPackageKey :: String,+ zComponentId :: String,+ zPackageVersion :: Version,+ zNotNull :: (String -> Bool),+ zManglePkgName :: (PackageName -> String),+ zMangleStr :: (String -> String)}+ deriving Generic+data ZPackage+ = ZPackage {zpkgName :: PackageName,+ zpkgVersion :: Version,+ zpkgX :: String,+ zpkgY :: String,+ zpkgZ :: String}+ deriving Generic+data ZTool+ = ZTool {ztoolName :: String,+ ztoolVersion :: Version,+ ztoolX :: String,+ ztoolY :: String,+ ztoolZ :: String}+ deriving Generic+render :: Z -> String+render z_root = execWriter $ do+ tell "/* DO NOT EDIT: This file is automatically generated by Cabal */\n"+ tell "\n"+ forM_ (zPackages z_root) $ \z_var0_pkg -> do+ tell "/* package "+ tell (prettyShow (zpkgName z_var0_pkg))+ tell "-"+ tell (prettyShow (zpkgVersion z_var0_pkg))+ tell " */\n"+ tell "#ifndef VERSION_"+ tell (zManglePkgName z_root (zpkgName z_var0_pkg))+ tell "\n"+ tell "#define VERSION_"+ tell (zManglePkgName z_root (zpkgName z_var0_pkg))+ tell " \""+ tell (prettyShow (zpkgVersion z_var0_pkg))+ tell "\"\n"+ tell "#endif /* VERSION_"+ tell (zManglePkgName z_root (zpkgName z_var0_pkg))+ tell " */\n"+ tell "#ifndef MIN_VERSION_"+ tell (zManglePkgName z_root (zpkgName z_var0_pkg))+ tell "\n"+ tell "#define MIN_VERSION_"+ tell (zManglePkgName z_root (zpkgName z_var0_pkg))+ tell "(major1,major2,minor) (\\\n"+ tell " (major1) < "+ tell (zpkgX z_var0_pkg)+ tell " || \\\n"+ tell " (major1) == "+ tell (zpkgX z_var0_pkg)+ tell " && (major2) < "+ tell (zpkgY z_var0_pkg)+ tell " || \\\n"+ tell " (major1) == "+ tell (zpkgX z_var0_pkg)+ tell " && (major2) == "+ tell (zpkgY z_var0_pkg)+ tell " && (minor) <= "+ tell (zpkgZ z_var0_pkg)+ tell ")\n"+ tell "#endif /* MIN_VERSION_"+ tell (zManglePkgName z_root (zpkgName z_var0_pkg))+ tell " */\n"+ tell "\n"+ forM_ (zTools z_root) $ \z_var1_tool -> do+ tell "/* tool "+ tell (ztoolName z_var1_tool)+ tell "-"+ tell (prettyShow (ztoolVersion z_var1_tool))+ tell " */\n"+ tell "#ifndef TOOL_VERSION_"+ tell (zMangleStr z_root (ztoolName z_var1_tool))+ tell "\n"+ tell "#define TOOL_VERSION_"+ tell (zMangleStr z_root (ztoolName z_var1_tool))+ tell " \""+ tell (prettyShow (ztoolVersion z_var1_tool))+ tell "\"\n"+ tell "#endif /* TOOL_VERSION_"+ tell (zMangleStr z_root (ztoolName z_var1_tool))+ tell " */\n"+ tell "#ifndef MIN_TOOL_VERSION_"+ tell (zMangleStr z_root (ztoolName z_var1_tool))+ tell "\n"+ tell "#define MIN_TOOL_VERSION_"+ tell (zMangleStr z_root (ztoolName z_var1_tool))+ tell "(major1,major2,minor) (\\\n"+ tell " (major1) < "+ tell (ztoolX z_var1_tool)+ tell " || \\\n"+ tell " (major1) == "+ tell (ztoolX z_var1_tool)+ tell " && (major2) < "+ tell (ztoolY z_var1_tool)+ tell " || \\\n"+ tell " (major1) == "+ tell (ztoolX z_var1_tool)+ tell " && (major2) == "+ tell (ztoolY z_var1_tool)+ tell " && (minor) <= "+ tell (ztoolZ z_var1_tool)+ tell ")\n"+ tell "#endif /* MIN_TOOL_VERSION_"+ tell (zMangleStr z_root (ztoolName z_var1_tool))+ tell " */\n"+ tell "\n"+ if (zNotNull z_root (zPackageKey z_root))+ then do+ tell "#ifndef CURRENT_PACKAGE_KEY\n"+ tell "#define CURRENT_PACKAGE_KEY \""+ tell (zPackageKey z_root)+ tell "\"\n"+ tell "#endif /* CURRENT_packageKey */\n"+ return ()+ else do+ return ()+ if (zNotNull z_root (zComponentId z_root))+ then do+ tell "#ifndef CURRENT_COMPONENT_ID\n"+ tell "#define CURRENT_COMPONENT_ID \""+ tell (zComponentId z_root)+ tell "\"\n"+ tell "#endif /* CURRENT_COMPONENT_ID */\n"+ return ()+ else do+ return ()+ tell "#ifndef CURRENT_PACKAGE_VERSION\n"+ tell "#define CURRENT_PACKAGE_VERSION \""+ tell (prettyShow (zPackageVersion z_root))+ tell "\"\n"+ tell "#endif /* CURRENT_PACKAGE_VERSION */\n"
cabal/Cabal/Distribution/Simple/BuildPaths.hs view
@@ -43,8 +43,6 @@ import Prelude () import Distribution.Compat.Prelude -import Distribution.Types.ForeignLib-import Distribution.Types.UnqualComponentName (unUnqualComponentName) import Distribution.Package import Distribution.ModuleName as ModuleName import Distribution.Compiler
cabal/Cabal/Distribution/Simple/BuildTarget.hs view
@@ -57,8 +57,8 @@ import qualified Distribution.Compat.CharParsing as P import Control.Monad ( msum )-import Data.List ( stripPrefix, groupBy, partition )-import Data.Either ( partitionEithers )+import Data.List ( stripPrefix, groupBy )+import qualified Data.List.NonEmpty as NE import System.FilePath as FilePath ( dropExtension, normalise, splitDirectories, joinPath, splitPath , hasTrailingPathSeparator )@@ -153,7 +153,7 @@ return btargets -checkTargetExistsAsFile :: UserBuildTarget -> NoCallStackIO (UserBuildTarget, Bool)+checkTargetExistsAsFile :: UserBuildTarget -> IO (UserBuildTarget, Bool) checkTargetExistsAsFile t = do fexists <- existsAsFile (fileComponentOfTarget t) return (t, fexists)@@ -318,8 +318,9 @@ where classifyMatchErrors errs- | not (null expected) = let (things, got:_) = unzip expected in- BuildTargetExpected userTarget things got+ | Just expected' <- NE.nonEmpty expected+ = let (things, got:|_) = NE.unzip expected' in+ BuildTargetExpected userTarget (NE.toList things) got | not (null nosuch) = BuildTargetNoSuch userTarget nosuch | otherwise = error $ "resolveBuildTarget: internal error in matching" where@@ -552,7 +553,7 @@ -- data ComponentKind = LibKind | FLibKind | ExeKind | TestKind | BenchKind- deriving (Eq, Ord, Show)+ deriving (Eq, Ord, Show, Enum, Bounded) componentKind :: ComponentName -> ComponentKind componentKind (CLibName _) = LibKind
cabal/Cabal/Distribution/Simple/BuildToolDepends.hs view
@@ -12,9 +12,6 @@ import Distribution.Package import Distribution.PackageDescription-import Distribution.Types.ExeDependency-import Distribution.Types.LegacyExeDependency-import Distribution.Types.UnqualComponentName -- | Desugar a "build-tools" entry into proper a executable dependency if -- possible.
cabal/Cabal/Distribution/Simple/Command.hs view
@@ -56,7 +56,7 @@ option, multiOption, -- ** Liftings & Projections- liftOption,+ liftOption, liftOptionL, -- * Option Descriptions OptDescr(..), Description, SFlags, LFlags, OptFlags, ArgPlaceHolder,@@ -74,6 +74,7 @@ import qualified Distribution.GetOpt as GetOpt import Distribution.ReadE import Distribution.Simple.Utils+import Distribution.Compat.Lens (ALens', (^#), (#~)) data CommandUI flags = CommandUI {@@ -250,6 +251,10 @@ liftOption :: (b -> a) -> (a -> (b -> b)) -> OptionField a -> OptionField b liftOption get' set' opt = opt { optionDescr = liftOptDescr get' set' `map` optionDescr opt}++-- | @since 3.4.0.0+liftOptionL :: ALens' b a -> OptionField a -> OptionField b+liftOptionL l = liftOption (^# l) (l #~) liftOptDescr :: (b -> a) -> (a -> (b -> b)) -> OptDescr a -> OptDescr b
cabal/Cabal/Distribution/Simple/Compiler.hs view
@@ -47,7 +47,7 @@ flagToDebugInfoLevel, -- * Support for language extensions- Flag,+ CompilerFlag, languageToFlags, unsupportedLanguages, extensionsToFlags,@@ -63,6 +63,7 @@ backpackSupported, arResponseFilesSupported, libraryDynDirSupported,+ libraryVisibilitySupported, -- * Support for profiling detail levels ProfDetailLevel(..),@@ -73,7 +74,6 @@ import Prelude () import Distribution.Compat.Prelude-import Distribution.Utils.Generic(safeLast) import Distribution.Pretty import Distribution.Compiler@@ -81,7 +81,6 @@ import Language.Haskell.Extension import Distribution.Simple.Utils -import Control.Monad (join) import qualified Data.Map as Map (lookup) import System.Directory (canonicalizePath) @@ -94,9 +93,9 @@ compilerCompat :: [CompilerId], -- ^ Other implementations that this compiler claims to be -- compatible with.- compilerLanguages :: [(Language, Flag)],+ compilerLanguages :: [(Language, CompilerFlag)], -- ^ Supported language standards.- compilerExtensions :: [(Extension, Maybe Flag)],+ compilerExtensions :: [(Extension, Maybe CompilerFlag)], -- ^ Supported extensions. compilerProperties :: Map String String -- ^ A key-value map for properties not covered by the above fields.@@ -104,6 +103,7 @@ deriving (Eq, Generic, Typeable, Show, Read) instance Binary Compiler+instance Structured Compiler showCompilerId :: Compiler -> String showCompilerId = prettyShow . compilerId@@ -172,9 +172,10 @@ data PackageDB = GlobalPackageDB | UserPackageDB | SpecificPackageDB FilePath- deriving (Eq, Generic, Ord, Show, Read)+ deriving (Eq, Generic, Ord, Show, Read, Typeable) instance Binary PackageDB+instance Structured PackageDB -- | We typically get packages from several databases, and stack them -- together. This type lets us be explicit about that stacking. For example@@ -205,10 +206,10 @@ -- | Make package paths absolute -absolutePackageDBPaths :: PackageDBStack -> NoCallStackIO PackageDBStack+absolutePackageDBPaths :: PackageDBStack -> IO PackageDBStack absolutePackageDBPaths = traverse absolutePackageDBPath -absolutePackageDBPath :: PackageDB -> NoCallStackIO PackageDB+absolutePackageDBPath :: PackageDB -> IO PackageDB absolutePackageDBPath GlobalPackageDB = return GlobalPackageDB absolutePackageDBPath UserPackageDB = return UserPackageDB absolutePackageDBPath (SpecificPackageDB db) =@@ -225,9 +226,10 @@ data OptimisationLevel = NoOptimisation | NormalOptimisation | MaximumOptimisation- deriving (Bounded, Enum, Eq, Generic, Read, Show)+ deriving (Bounded, Enum, Eq, Generic, Read, Show, Typeable) instance Binary OptimisationLevel+instance Structured OptimisationLevel flagToOptimisationLevel :: Maybe String -> OptimisationLevel flagToOptimisationLevel Nothing = NormalOptimisation@@ -252,9 +254,10 @@ | MinimalDebugInfo | NormalDebugInfo | MaximalDebugInfo- deriving (Bounded, Enum, Eq, Generic, Read, Show)+ deriving (Bounded, Enum, Eq, Generic, Read, Show, Typeable) instance Binary DebugInfoLevel+instance Structured DebugInfoLevel flagToDebugInfoLevel :: Maybe String -> DebugInfoLevel flagToDebugInfoLevel Nothing = NormalDebugInfo@@ -276,12 +279,12 @@ [ lang | lang <- langs , isNothing (languageToFlag comp lang) ] -languageToFlags :: Compiler -> Maybe Language -> [Flag]+languageToFlags :: Compiler -> Maybe Language -> [CompilerFlag] languageToFlags comp = filter (not . null) . catMaybes . map (languageToFlag comp) . maybe [Haskell98] (\x->[x]) -languageToFlag :: Compiler -> Language -> Maybe Flag+languageToFlag :: Compiler -> Language -> Maybe CompilerFlag languageToFlag comp ext = lookup ext (compilerLanguages comp) @@ -291,16 +294,16 @@ [ ext | ext <- exts , isNothing (extensionToFlag' comp ext) ] -type Flag = String+type CompilerFlag = String -- |For the given compiler, return the flags for the supported extensions.-extensionsToFlags :: Compiler -> [Extension] -> [Flag]+extensionsToFlags :: Compiler -> [Extension] -> [CompilerFlag] extensionsToFlags comp = nub . filter (not . null) . catMaybes . map (extensionToFlag comp) -- | Looks up the flag for a given extension, for a given compiler. -- Ignores the subtlety of extensions which lack associated flags.-extensionToFlag :: Compiler -> Extension -> Maybe Flag+extensionToFlag :: Compiler -> Extension -> Maybe CompilerFlag extensionToFlag comp ext = join (extensionToFlag' comp ext) -- | Looks up the flag for a given extension, for a given compiler.@@ -312,7 +315,7 @@ -- the inner layer indicates whether it has a flag. -- When building strings, it is often more convenient to use 'extensionToFlag', -- which ignores the difference.-extensionToFlag' :: Compiler -> Extension -> Maybe (Maybe Flag)+extensionToFlag' :: Compiler -> Extension -> Maybe (Maybe CompilerFlag) extensionToFlag' comp ext = lookup ext (compilerExtensions comp) -- | Does this compiler support parallel --make mode?@@ -378,6 +381,15 @@ GHCJS -> True _ -> False +-- | Does this compiler support a package database entry with:+-- "visibility"?+libraryVisibilitySupported :: Compiler -> Bool+libraryVisibilitySupported comp = case compilerFlavor comp of+ GHC -> v >= mkVersion [8,8]+ _ -> False+ where+ v = compilerVersion comp+ -- | Utility function for GHC only features ghcSupported :: String -> Compiler -> Bool ghcSupported key comp =@@ -407,9 +419,10 @@ | ProfDetailToplevelFunctions | ProfDetailAllFunctions | ProfDetailOther String- deriving (Eq, Generic, Read, Show)+ deriving (Eq, Generic, Read, Show, Typeable) instance Binary ProfDetailLevel+instance Structured ProfDetailLevel flagToProfDetailLevel :: String -> ProfDetailLevel flagToProfDetailLevel "" = ProfDetailDefault
cabal/Cabal/Distribution/Simple/Configure.hs view
@@ -38,7 +38,7 @@ , tryGetPersistBuildConfig , maybeGetPersistBuildConfig , findDistPref, findDistPrefOrDefault- , getInternalPackages+ , getInternalLibraries , computeComponentId , computeCompatPackageKey , localBuildInfoFile@@ -55,21 +55,20 @@ , platformDefines, ) where -import qualified Prelude (tail)+import qualified Prelude as Unsafe (tail) import Distribution.Compat.Prelude import Distribution.Compiler import Distribution.Types.IncludeRenaming import Distribution.Utils.NubList-import Distribution.Simple.Compiler hiding (Flag)+import Distribution.Simple.Compiler import Distribution.Simple.PreProcess import Distribution.Package-import qualified Distribution.InstalledPackageInfo as Installed+import qualified Distribution.InstalledPackageInfo as IPI import Distribution.InstalledPackageInfo (InstalledPackageInfo) import qualified Distribution.Simple.PackageIndex as PackageIndex import Distribution.Simple.PackageIndex (InstalledPackageIndex)-import Distribution.PackageDescription as PD hiding (Flag)-import Distribution.Types.PackageDescription as PD+import Distribution.PackageDescription import Distribution.PackageDescription.PrettyPrint import Distribution.PackageDescription.Configuration import Distribution.PackageDescription.Check hiding (doesFileExist)@@ -78,20 +77,13 @@ import Distribution.Simple.Setup as Setup import Distribution.Simple.BuildTarget import Distribution.Simple.LocalBuildInfo-import Distribution.Types.ExeDependency-import Distribution.Types.LegacyExeDependency-import Distribution.Types.PkgconfigDependency+import Distribution.Types.PackageVersionConstraint+import Distribution.Types.PkgconfigVersion import Distribution.Types.PkgconfigVersionRange import Distribution.Types.LocalBuildInfo-import Distribution.Types.LibraryName-import Distribution.Types.LibraryVisibility import Distribution.Types.ComponentRequestedSpec-import Distribution.Types.ForeignLib-import Distribution.Types.ForeignLibType-import Distribution.Types.ForeignLibOption import Distribution.Types.GivenComponent import Distribution.Types.Mixin-import Distribution.Types.UnqualComponentName import Distribution.Simple.Utils import Distribution.System import Distribution.Version@@ -103,7 +95,6 @@ import Distribution.Backpack.PreExistingComponent import Distribution.Backpack.ConfiguredComponent (newPackageDepsBehaviour) import Distribution.Backpack.Id-import Distribution.Utils.Generic import Distribution.Utils.LogProgress import qualified Distribution.Simple.GHC as GHC@@ -112,18 +103,15 @@ import qualified Distribution.Simple.HaskellSuite as HaskellSuite import Control.Exception- ( ErrorCall, Exception, evaluate, throw, throwIO, try )-import Control.Monad ( forM, forM_ )+ ( try ) import Data.List.NonEmpty ( nonEmpty )-import Distribution.Compat.Binary ( decodeOrFailIO, encode )+import Distribution.Utils.Structured ( structuredDecodeOrFailIO, structuredEncode ) import Distribution.Compat.Directory ( listDirectory ) import Data.ByteString.Lazy ( ByteString ) import qualified Data.ByteString as BS import qualified Data.ByteString.Lazy.Char8 as BLC8 import Data.List- ( (\\), partition, inits, stripPrefix, intersect )-import Data.Either- ( partitionEithers )+ ( (\\), inits, stripPrefix, intersect, dropWhileEnd ) import qualified Data.Map as Map import System.Directory ( canonicalizePath, createDirectoryIfMissing, doesFileExist@@ -141,12 +129,12 @@ import Distribution.Parsec ( simpleParsec ) import Text.PrettyPrint- ( Doc, (<+>), ($+$), char, comma, hsep, nest+ ( Doc, ($+$), char, comma, hsep, nest , punctuate, quotes, render, renderStyle, sep, text ) import Distribution.Compat.Environment ( lookupEnv )-import Distribution.Compat.Exception ( catchExit, catchIO ) import qualified Data.Set as Set+import qualified Distribution.Compat.NonEmptySet as NES type UseExternalInternalDeps = Bool@@ -206,21 +194,17 @@ contents <- BS.readFile filename let (header, body) = BLC8.span (/='\n') (BLC8.fromChunks [contents]) - headerParseResult <- try $ evaluate $ parseHeader header- let (cabalId, compId) =- case headerParseResult of- Left (_ :: ErrorCall) -> throw ConfigStateFileBadHeader- Right x -> x+ (cabalId, compId) <- parseHeader header let getStoredValue = do- result <- decodeOrFailIO (BLC8.tail body)+ result <- structuredDecodeOrFailIO (BLC8.tail body) case result of- Left _ -> throw ConfigStateFileNoParse+ Left _ -> throwIO ConfigStateFileNoParse Right x -> return x deferErrorIfBadVersion act | cabalId /= currentCabalId = do eResult <- try act- throw $ ConfigStateFileBadVersion cabalId compId eResult+ throwIO $ ConfigStateFileBadVersion cabalId compId eResult | otherwise = act deferErrorIfBadVersion getStoredValue where@@ -254,11 +238,11 @@ -- 'localBuildInfoFile'. writePersistBuildConfig :: FilePath -- ^ The @dist@ directory path. -> LocalBuildInfo -- ^ The 'LocalBuildInfo' to write.- -> NoCallStackIO ()+ -> IO () writePersistBuildConfig distPref lbi = do createDirectoryIfMissing False distPref writeFileAtomic (localBuildInfoFile distPref) $- BLC8.unlines [showHeader pkgId, encode lbi]+ BLC8.unlines [showHeader pkgId, structuredEncode lbi] where pkgId = localPackage lbi @@ -274,16 +258,16 @@ -- | Parse the @setup-config@ file header, returning the package identifiers -- for Cabal and the compiler. parseHeader :: ByteString -- ^ The file contents.- -> (PackageIdentifier, PackageIdentifier)+ -> IO (PackageIdentifier, PackageIdentifier) parseHeader header = case BLC8.words header of ["Saved", "package", "config", "for", pkgId, "written", "by", cabalId, "using", compId] ->- fromMaybe (throw ConfigStateFileBadHeader) $ do+ maybe (throwIO ConfigStateFileBadHeader) return $ do _ <- simpleParsec (fromUTF8LBS pkgId) :: Maybe PackageIdentifier cabalId' <- simpleParsec (BLC8.unpack cabalId) compId' <- simpleParsec (BLC8.unpack compId) return (cabalId', compId')- _ -> throw ConfigStateFileNoHeader+ _ -> throwIO ConfigStateFileNoHeader -- | Generate the @setup-config@ file header. showHeader :: PackageIdentifier -- ^ The processed package.@@ -299,7 +283,7 @@ -- | Check that localBuildInfoFile is up-to-date with respect to the -- .cabal file.-checkPersistBuildConfigOutdated :: FilePath -> FilePath -> NoCallStackIO Bool+checkPersistBuildConfigOutdated :: FilePath -> FilePath -> IO Bool checkPersistBuildConfigOutdated distPref pkg_descr_file = pkg_descr_file `moreRecentFile` localBuildInfoFile distPref @@ -317,7 +301,7 @@ -- \"CABAL_BUILDDIR\" environment variable, or the default prefix. findDistPref :: FilePath -- ^ default \"dist\" prefix -> Setup.Flag FilePath -- ^ override \"dist\" prefix- -> NoCallStackIO FilePath+ -> IO FilePath findDistPref defDistPref overrideDistPref = do envDistPref <- liftM parseEnvDistPref (lookupEnv "CABAL_BUILDDIR") return $ fromFlagOrDefault defDistPref (mappend envDistPref overrideDistPref)@@ -334,7 +318,7 @@ -- set. (The @*DistPref@ flags are always set to a definite value before -- invoking 'UserHooks'.) findDistPrefOrDefault :: Setup.Flag FilePath -- ^ override \"dist\" prefix- -> NoCallStackIO FilePath+ -> IO FilePath findDistPrefOrDefault = findDistPref defaultDistPref -- |Perform the \"@.\/setup configure@\" action.@@ -407,8 +391,8 @@ -- The set of package names which are "shadowed" by internal -- packages, and which component they map to- let internalPackageSet :: Map PackageName (Maybe UnqualComponentName)- internalPackageSet = getInternalPackages pkg_descr0+ let internalPackageSet :: Set LibraryName+ internalPackageSet = getInternalLibraries pkg_descr0 -- Make a data structure describing what components are enabled. let enabled :: ComponentRequestedSpec@@ -451,7 +435,7 @@ -- NB: The fact that we bundle all the constraints together means -- that is not possible to configure a test-suite to use one -- version of a dependency, and the executable to use another.- (allConstraints :: [Dependency],+ (allConstraints :: [PackageVersionConstraint], requiredDepsMap :: Map (PackageName, ComponentName) InstalledPackageInfo) <- either (die' verbosity) return $ combinedConstraints (configConstraints cfg)@@ -459,7 +443,7 @@ installedPackageSet -- pkg_descr: The resolved package description, that does not contain any- -- conditionals, because we have have an assignment for+ -- conditionals, because we have an assignment for -- every flag, either picking them ourselves using a -- simple naive algorithm, or having them be passed to -- us by 'configConfigurationsFlags')@@ -891,26 +875,23 @@ -- file, and we haven't resolved them yet. finalizePD -- does the resolution of conditionals, and it takes internalPackageSet -- as part of its input.-getInternalPackages :: GenericPackageDescription- -> Map PackageName (Maybe UnqualComponentName)-getInternalPackages pkg_descr0 =+getInternalLibraries :: GenericPackageDescription+ -> Set LibraryName+getInternalLibraries pkg_descr0 = -- TODO: some day, executables will be fair game here too! let pkg_descr = flattenPackageDescription pkg_descr0- f lib = case libName lib of- LMainLibName -> (packageName pkg_descr, Nothing)- LSubLibName n' -> (unqualComponentNameToPackageName n', Just n')- in Map.fromList (map f (allLibraries pkg_descr))+ in Set.fromList (map libName (allLibraries pkg_descr)) -- | Returns true if a dependency is satisfiable. This function may -- report a dependency satisfiable even when it is not, but not vice--- versa. This is to be passed to finalizePD.+-- versa. This is to be passed to finalize dependencySatisfiable :: Bool -- ^ use external internal deps? -> Bool -- ^ exact configuration? -> Bool -- ^ allow depending on private libs? -> PackageName -> InstalledPackageIndex -- ^ installed set- -> Map PackageName (Maybe UnqualComponentName) -- ^ internal set+ -> Set LibraryName -- ^ library components -> Map (PackageName, ComponentName) InstalledPackageInfo -- ^ required dependencies -> (Dependency -> Bool)@@ -918,9 +899,8 @@ use_external_internal_deps exact_config allow_private_deps- pn installedPackageSet internalPackageSet requiredDepsMap+ pn installedPackageSet packageLibraries requiredDepsMap (Dependency depName vr sublibs)- | exact_config -- When we're given '--exact-configuration', we assume that all -- dependencies and flags are exactly specified on the command@@ -933,10 +913,10 @@ = if isInternalDep && not use_external_internal_deps -- Except for internal deps, when we're NOT per-component mode; -- those are just True.- then True+ then internalDepSatisfiable else -- Backward compatibility for the old sublibrary syntax- (sublibs == Set.singleton LMainLibName+ (sublibs == mainLibSet && Map.member (pn, CLibName $ LSubLibName $ packageNameToUnqualComponentName depName)@@ -949,36 +929,32 @@ -- When we are doing per-component configure, we now need to -- test if the internal dependency is in the index. This has -- DIFFERENT semantics from normal dependency satisfiability.- then internalDepSatisfiable+ then internalDepSatisfiableExternally -- If a 'PackageName' is defined by an internal component, the dep is -- satisfiable (we're going to build it ourselves)- else True+ else internalDepSatisfiable | otherwise = depSatisfiable where- isInternalDep = Map.member depName internalPackageSet+ -- Internal dependency is when dependency is the same as package.+ isInternalDep = pn == depName depSatisfiable = not . null $ PackageIndex.lookupDependency installedPackageSet depName vr internalDepSatisfiable =- not . null $ PackageIndex.lookupInternalDependency- installedPackageSet pn vr cn- where- cn | pn == depName- = LMainLibName - | otherwise- -- Reinterpret the "package name" as an unqualified component- -- name- = LSubLibName $ packageNameToUnqualComponentName depName- -- Check whether a libray exists and is visible.+ Set.isSubsetOf (NES.toSet sublibs) packageLibraries+ internalDepSatisfiableExternally =+ all (\ln -> not $ null $ PackageIndex.lookupInternalDependency installedPackageSet pn vr ln) sublibs++ -- Check whether a library exists and is visible. -- We don't disambiguate between dependency on non-existent or private -- library yet, so we just return a bool and later report a generic error. visible lib = maybe False -- Does not even exist (wasn't in the depsMap)- (\ipi -> Installed.libVisibility ipi == LibraryVisibilityPublic+ (\ipi -> IPI.libVisibility ipi == LibraryVisibilityPublic -- If the override is enabled, the visibility does -- not matter (it's handled externally) || allow_private_deps@@ -987,7 +963,7 @@ -- This is only triggered when passing a component -- of the same package as --dependency, such as in: -- cabal-testsuite/PackageTests/ConfigureComponent/SubLib/setup-explicit.test.hs- || pkgName (Installed.sourcePackageId ipi) == pn)+ || pkgName (IPI.sourcePackageId ipi) == pn) maybeIPI where maybeIPI = Map.lookup (depName, CLibName lib) requiredDepsMap @@ -1001,7 +977,7 @@ :: Verbosity -> ConfigFlags -> ComponentRequestedSpec- -> [Dependency]+ -> [PackageVersionConstraint] -> (Dependency -> Bool) -- ^ tests if a dependency is satisfiable. -- Might say it's satisfiable even when not. -> Compiler@@ -1041,7 +1017,7 @@ addExtraIncludeLibDirs pkg_descr = let extraBi = mempty { extraLibDirs = configExtraLibDirs cfg , extraFrameworkDirs = configExtraFrameworkDirs cfg- , PD.includeDirs = configExtraIncludeDirs cfg}+ , includeDirs = configExtraIncludeDirs cfg} modifyLib l = l{ libBuildInfo = libBuildInfo l `mappend` extraBi } modifyExecutable e = e{ buildInfo = buildInfo e@@ -1073,13 +1049,13 @@ ++ "package flags. To use this feature you must use " ++ "GHC 7.9 or later." - when (any (not.null.PD.reexportedModules) (PD.allLibraries pkg_descr)+ when (any (not.null.reexportedModules) (allLibraries pkg_descr) && not (reexportedModulesSupported comp)) $ die' verbosity $ "Your compiler does not support module re-exports. To use " ++ "this feature you must use GHC 7.9 or later." - when (any (not.null.PD.signatures) (PD.allLibraries pkg_descr)+ when (any (not.null.signatures) (allLibraries pkg_descr) && not (backpackSupported comp)) $ die' verbosity $ "Your compiler does not support Backpack. To use "@@ -1089,21 +1065,21 @@ configureDependencies :: Verbosity -> UseExternalInternalDeps- -> Map PackageName (Maybe UnqualComponentName) -- ^ internal packages+ -> Set LibraryName -> InstalledPackageIndex -- ^ installed packages -> Map (PackageName, ComponentName) InstalledPackageInfo -- ^ required deps -> PackageDescription -> ComponentRequestedSpec -> IO [PreExistingComponent] configureDependencies verbosity use_external_internal_deps- internalPackageSet installedPackageSet requiredDepsMap pkg_descr enableSpec = do+ packageLibraries installedPackageSet requiredDepsMap pkg_descr enableSpec = do let failedDeps :: [FailedDependency] allPkgDeps :: [ResolvedDependency] (failedDeps, allPkgDeps) = partitionEithers $ concat [ fmap (\s -> (dep, s)) <$> status | dep <- enabledBuildDepends pkg_descr enableSpec , let status = selectDependency (package pkg_descr)- internalPackageSet installedPackageSet+ packageLibraries installedPackageSet requiredDepsMap use_external_internal_deps dep ] internalPkgDeps = [ pkgid@@ -1258,12 +1234,12 @@ | InternalDependency PackageId data FailedDependency = DependencyNotExists PackageName- | DependencyMissingInternal PackageName PackageName+ | DependencyMissingInternal PackageName LibraryName | DependencyNoVersion Dependency -- | Test for a package dependency and record the version we have installed. selectDependency :: PackageId -- ^ Package id of current package- -> Map PackageName (Maybe UnqualComponentName)+ -> Set LibraryName -- ^ package libraries -> InstalledPackageIndex -- ^ Installed packages -> Map (PackageName, ComponentName) InstalledPackageInfo -- ^ Packages for which we have been given specific deps to@@ -1288,46 +1264,46 @@ -- -- We want "build-depends: MyLibrary" always to match the internal library -- even if there is a newer installed library "MyLibrary-0.2".- case Map.lookup dep_pkgname internalIndex of- Just cname ->+ if dep_pkgname == pn+ then if use_external_internal_deps- then do_external (Just $ maybeToLibraryName cname) <$> Set.toList libs- else do_internal- _ ->- do_external Nothing <$> Set.toList libs+ then do_external_internal <$> NES.toList libs+ else do_internal <$> NES.toList libs+ else+ do_external_external <$> NES.toList libs where+ pn = packageName pkgid -- It's an internal library, and we're not per-component build- do_internal = [Right $ InternalDependency- $ PackageIdentifier dep_pkgname $ packageVersion pkgid]+ do_internal lib+ | Set.member lib internalIndex+ = Right $ InternalDependency $ PackageIdentifier dep_pkgname $ packageVersion pkgid + | otherwise+ = Left $ DependencyMissingInternal dep_pkgname lib+ -- We have to look it up externally- do_external :: Maybe LibraryName -> LibraryName -> Either FailedDependency DependencyResolution- do_external is_internal lib = do+ do_external_external :: LibraryName -> Either FailedDependency DependencyResolution+ do_external_external lib = do ipi <- case Map.lookup (dep_pkgname, CLibName lib) requiredDepsMap of -- If we know the exact pkg to use, then use it. Just pkginstance -> Right pkginstance -- Otherwise we just pick an arbitrary instance of the latest version.- Nothing ->- case is_internal of- Nothing -> do_external_external- Just ln -> do_external_internal ln- return $ ExternalDependency $ ipiToPreExistingComponent ipi-- -- It's an external package, normal situation- do_external_external =- case pickLastIPI $ PackageIndex.lookupDependency installedIndex dep_pkgname vr of+ Nothing -> case pickLastIPI $ PackageIndex.lookupDependency installedIndex dep_pkgname vr of Nothing -> Left (DependencyNotExists dep_pkgname) Just pkg -> Right pkg+ return $ ExternalDependency $ ipiToPreExistingComponent ipi - -- It's an internal library, being looked up externally- do_external_internal- :: LibraryName -> Either FailedDependency InstalledPackageInfo- do_external_internal ln =- case pickLastIPI $ PackageIndex.lookupInternalDependency installedIndex- (packageName pkgid) vr ln of- Nothing -> Left (DependencyMissingInternal dep_pkgname (packageName pkgid))+ do_external_internal :: LibraryName -> Either FailedDependency DependencyResolution+ do_external_internal lib = do+ ipi <- case Map.lookup (dep_pkgname, CLibName lib) requiredDepsMap of+ -- If we know the exact pkg to use, then use it.+ Just pkginstance -> Right pkginstance+ Nothing -> case pickLastIPI $ PackageIndex.lookupInternalDependency installedIndex pn vr lib of+ -- It's an internal library, being looked up externally+ Nothing -> Left (DependencyMissingInternal dep_pkgname lib) Just pkg -> Right pkg+ return $ ExternalDependency $ ipiToPreExistingComponent ipi pickLastIPI :: [(Version, [InstalledPackageInfo])] -> Maybe InstalledPackageInfo pickLastIPI pkgs = safeHead . snd . last =<< nonEmpty pkgs@@ -1354,10 +1330,10 @@ ++ "Perhaps you need to download and install it from\n" ++ hackageUrl ++ prettyShow pkgname ++ "?" - reportFailedDependency (DependencyMissingInternal pkgname real_pkgname) =- "internal dependency " ++ prettyShow pkgname ++ " not installed.\n"+ reportFailedDependency (DependencyMissingInternal pkgname lib) =+ "internal dependency " ++ prettyShow (prettyLibraryNameComponent lib) ++ " not installed.\n" ++ "Perhaps you need to configure and install it first?\n"- ++ "(This library was defined by " ++ prettyShow real_pkgname ++ ")"+ ++ "(This library was defined by " ++ prettyShow pkgname ++ ")" reportFailedDependency (DependencyNoVersion dep) = "cannot satisfy dependency " ++ prettyShow (simplifyDependency dep) ++ "\n"@@ -1460,10 +1436,10 @@ -- deps in the end. So we still need to remember which installed packages to -- pick. combinedConstraints- :: [Dependency]+ :: [PackageVersionConstraint] -> [GivenComponent] -> InstalledPackageIndex- -> Either String ([Dependency],+ -> Either String ([PackageVersionConstraint], Map (PackageName, ComponentName) InstalledPackageInfo) combinedConstraints constraints dependencies installedPackages = do @@ -1477,9 +1453,9 @@ return (allConstraints, idConstraintMap) where- allConstraints :: [Dependency]+ allConstraints :: [PackageVersionConstraint] allConstraints = constraints- ++ [ thisPackageVersion (packageId pkg)+ ++ [ thisPackageVersionConstraint (packageId pkg) | (_, _, _, Just pkg) <- dependenciesPkgInfo ] idConstraintMap :: Map (PackageName, ComponentName) InstalledPackageInfo@@ -1618,13 +1594,11 @@ version <- pkgconfig ["--modversion", pkg] `catchIO` (\_ -> die' verbosity notFound) `catchExit` (\_ -> die' verbosity notFound)- case simpleParsec version of- Nothing -> die' verbosity- "parsing output of pkg-config --modversion failed"- Just v | not (withinPkgconfigVersionRange v range) ->- die' verbosity (badVersion v)- | otherwise ->- info verbosity (depSatisfied v)+ let trim = dropWhile isSpace . dropWhileEnd isSpace+ let v = PkgconfigVersion (toUTF8BS $ trim version)+ if not (withinPkgconfigVersionRange v range)+ then die' verbosity (badVersion v)+ else info verbosity (depSatisfied v) where notFound = "The pkg-config package '" ++ pkg ++ "'" ++ versionRequirement@@ -1663,7 +1637,7 @@ addPkgConfigBIBench = addPkgConfigBI benchmarkBuildInfo $ \bench bi -> bench { benchmarkBuildInfo = bi } - pkgconfigBuildInfo :: [PkgconfigDependency] -> NoCallStackIO BuildInfo+ pkgconfigBuildInfo :: [PkgconfigDependency] -> IO BuildInfo pkgconfigBuildInfo [] = return mempty pkgconfigBuildInfo pkgdeps = do let pkgs = nub [ prettyShow pkg | PkgconfigDependency pkg _ <- pkgdeps ]@@ -1687,11 +1661,11 @@ (extraLibs', ldflags') = partition ("-l" `isPrefixOf`) ldflags (extraLibDirs', ldflags'') = partition ("-L" `isPrefixOf`) ldflags' in mempty {- PD.includeDirs = map (drop 2) includeDirs',- PD.extraLibs = map (drop 2) extraLibs',- PD.extraLibDirs = map (drop 2) extraLibDirs',- PD.ccOptions = cflags',- PD.ldOptions = ldflags''+ includeDirs = map (drop 2) includeDirs',+ extraLibs = map (drop 2) extraLibs',+ extraLibDirs = map (drop 2) extraLibDirs',+ ccOptions = cflags',+ ldOptions = ldflags'' } -- -----------------------------------------------------------------------------@@ -1737,8 +1711,8 @@ missingHdr <- findOffendingHdr explainErrors missingHdr missingLibs) where- allHeaders = collectField PD.includes- allLibs = collectField PD.extraLibs+ allHeaders = collectField includes+ allLibs = collectField extraLibs ifBuildsWith headers args success failure = do checkDuplicateHeaders@@ -1758,16 +1732,16 @@ -- including file. As such we need to take drastic measures -- and delete the offending file in the source directory. checkDuplicateHeaders = do- let relIncDirs = filter (not . isAbsolute) (collectField PD.includeDirs)+ let relIncDirs = filter (not . isAbsolute) (collectField includeDirs) isHeader = isSuffixOf ".h"- genHeaders <- forM relIncDirs $ \dir ->+ genHeaders <- for relIncDirs $ \dir -> fmap (dir </>) . filter isHeader <$> listDirectory (buildDir lbi </> dir) `catchIO` (\_ -> return [])- srcHeaders <- forM relIncDirs $ \dir ->+ srcHeaders <- for relIncDirs $ \dir -> fmap (dir </>) . filter isHeader <$> listDirectory (baseDir lbi </> dir) `catchIO` (\_ -> return []) let commonHeaders = concat genHeaders `intersect` concat srcHeaders- forM_ commonHeaders $ \hdr -> do+ for_ commonHeaders $ \hdr -> do warn verbosity $ "Duplicate header found in " ++ (buildDir lbi </> hdr) ++ " and "@@ -1779,7 +1753,7 @@ findOffendingHdr = ifBuildsWith allHeaders ccArgs (return Nothing)- (go . Prelude.tail . inits $ allHeaders) -- inits always contains at least []+ (go . Unsafe.tail . inits $ allHeaders) -- inits always contains at least [] where go [] = return Nothing -- cannot happen go (hdrs:hdrsInits) =@@ -1811,42 +1785,42 @@ ++ [ "-I" ++ buildDir lbi </> "autogen" ] -- `configure' may generate headers in the build directory ++ [ "-I" ++ buildDir lbi </> dir- | dir <- ordNub (collectField PD.includeDirs)+ | dir <- ordNub (collectField includeDirs) , not (isAbsolute dir)] -- we might also reference headers from the -- packages directory. ++ [ "-I" ++ baseDir lbi </> dir- | dir <- ordNub (collectField PD.includeDirs)+ | dir <- ordNub (collectField includeDirs) , not (isAbsolute dir)]- ++ [ "-I" ++ dir | dir <- ordNub (collectField PD.includeDirs)+ ++ [ "-I" ++ dir | dir <- ordNub (collectField includeDirs) , isAbsolute dir] ++ ["-I" ++ baseDir lbi]- ++ collectField PD.cppOptions- ++ collectField PD.ccOptions+ ++ collectField cppOptions+ ++ collectField ccOptions ++ [ "-I" ++ dir | dir <- ordNub [ dir | dep <- deps- , dir <- Installed.includeDirs dep ]+ , dir <- IPI.includeDirs dep ] -- dedupe include dirs of dependencies -- to prevent quadratic blow-up ] ++ [ opt | dep <- deps- , opt <- Installed.ccOptions dep ]+ , opt <- IPI.ccOptions dep ] commonCcArgs = commonCppArgs- ++ collectField PD.ccOptions+ ++ collectField ccOptions ++ [ opt | dep <- deps- , opt <- Installed.ccOptions dep ]+ , opt <- IPI.ccOptions dep ] commonLdArgs = [ "-L" ++ dir- | dir <- ordNub (collectField PD.extraLibDirs) ]- ++ collectField PD.ldOptions+ | dir <- ordNub (collectField extraLibDirs) ]+ ++ collectField ldOptions ++ [ "-L" ++ dir | dir <- ordNub [ dir | dep <- deps- , dir <- Installed.libraryDirs dep ]+ , dir <- IPI.libraryDirs dep ] ] --TODO: do we also need dependent packages' ld options? makeLdArgs libs = [ "-l"++lib | lib <- libs ] ++ commonLdArgs@@ -2015,8 +1989,8 @@ traverse_ (doCheck pkgr) ipkgs where doCheck pkgr ipkg- | maybe False (== pkgr) (Installed.pkgRoot ipkg)- = forM_ (Installed.libraryDirs ipkg) $ \libdir -> do+ | maybe False (== pkgr) (IPI.pkgRoot ipkg)+ = for_ (IPI.libraryDirs ipkg) $ \libdir -> do -- When @prefix@ is not under @pkgroot@, -- @shortRelativePath prefix pkgroot@ will return a path with -- @..@s and following check will fail without @canonicalizePath@.
cabal/Cabal/Distribution/Simple/Doctest.hs view
@@ -25,8 +25,8 @@ import qualified Distribution.Simple.GHCJS as GHCJS -- local-import Distribution.PackageDescription as PD hiding (Flag)-import Distribution.Simple.Compiler hiding (Flag)+import Distribution.PackageDescription+import Distribution.Simple.Compiler import Distribution.Simple.Program.GHC import Distribution.Simple.Program import Distribution.Simple.PreProcess
cabal/Cabal/Distribution/Simple/Flag.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE FlexibleContexts #-} -----------------------------------------------------------------------------@@ -21,6 +22,7 @@ toFlag, fromFlag, fromFlagOrDefault,+ flagElim, flagToMaybe, flagToList, maybeToFlag,@@ -51,9 +53,10 @@ -- Its monoid instance gives us the behaviour where it starts out as -- 'NoFlag' and later flags override earlier ones. ---data Flag a = Flag a | NoFlag deriving (Eq, Generic, Show, Read)+data Flag a = Flag a | NoFlag deriving (Eq, Generic, Show, Read, Typeable) instance Binary a => Binary (Flag a)+instance Structured a => Structured (Flag a) instance Functor Flag where fmap f (Flag x) = Flag (f x)@@ -102,6 +105,11 @@ flagToMaybe :: Flag a -> Maybe a flagToMaybe (Flag x) = Just x flagToMaybe NoFlag = Nothing++-- | @since 3.4.0.0+flagElim :: b -> (a -> b) -> Flag a -> b+flagElim n _ NoFlag = n+flagElim _ f (Flag x) = f x flagToList :: Flag a -> [a] flagToList (Flag x) = [x]
cabal/Cabal/Distribution/Simple/GHC.hs view
@@ -51,6 +51,7 @@ registerPackage, componentGhcOptions, componentCcGhcOptions,+ getGhcAppDir, getLibDir, isDynamic, getGlobalPackageDB,@@ -73,6 +74,7 @@ import Distribution.Compat.Prelude import qualified Distribution.Simple.GHC.Internal as Internal+import Distribution.CabalSpecVersion import Distribution.Simple.GHC.ImplInfo import Distribution.Simple.GHC.EnvironmentParser import Distribution.PackageDescription.Utils (cabalBug)@@ -98,15 +100,11 @@ import Distribution.Simple.Program.GHC import Distribution.Simple.Setup import qualified Distribution.Simple.Setup as Cabal-import Distribution.Simple.Compiler hiding (Flag)+import Distribution.Simple.Compiler import Distribution.Version import Distribution.System import Distribution.Verbosity import Distribution.Pretty-import Distribution.Types.ForeignLib-import Distribution.Types.ForeignLibType-import Distribution.Types.ForeignLibOption-import Distribution.Types.UnqualComponentName import Distribution.Utils.NubList import Language.Haskell.Extension @@ -138,11 +136,11 @@ (userMaybeSpecifyPath "ghc" hcPath conf0) let implInfo = ghcVersionImplInfo ghcVersion - -- Cabal currently supports ghc >= 7.0.1 && < 8.10- unless (ghcVersion < mkVersion [8,10]) $+ -- Cabal currently supports ghc >= 7.0.1 && < 8.12+ unless (ghcVersion < mkVersion [8,14]) $ warn verbosity $ "Unknown/unsupported 'ghc' version detected "- ++ "(Cabal " ++ prettyShow cabalVersion ++ " supports 'ghc' version < 8.10): "+ ++ "(Cabal " ++ prettyShow cabalVersion ++ " supports 'ghc' version < 8.12): " ++ programPath ghcProg ++ " is version " ++ prettyShow ghcVersion -- This is slightly tricky, we have to configure ghc first, then we use the@@ -182,7 +180,7 @@ ghcInfo <- Internal.getGhcInfo verbosity implInfo ghcProg let ghcInfoMap = Map.fromList ghcInfo- extensions = -- workaround https://ghc.haskell.org/ticket/11214+ extensions = -- workaround https://gitlab.haskell.org/ghc/ghc/-/issues/11214 filterExt JavaScriptFFI $ -- see 'filterExtTH' comment below filterExtTH $ extensions0@@ -317,7 +315,7 @@ getGhcInfo :: Verbosity -> ConfiguredProgram -> IO [(String, String)] getGhcInfo verbosity ghcProg = Internal.getGhcInfo verbosity implInfo ghcProg where- Just version = programVersion ghcProg+ version = fromMaybe (error "GHC.getGhcInfo: no ghc version") $ programVersion ghcProg implInfo = ghcVersionImplInfo version -- | Given a single package DB, return all installed packages.@@ -363,8 +361,14 @@ return $! mconcat indices where- Just ghcProg = lookupProgram ghcProgram progdb+ ghcProg = fromMaybe (error "GHC.toPackageIndex: no ghc program") $ lookupProgram ghcProgram progdb +-- | Return the 'FilePath' to the GHC application data directory.+--+-- @since 3.4.0.0+getGhcAppDir :: IO FilePath+getGhcAppDir = getAppUserDataDirectory "ghc"+ getLibDir :: Verbosity -> LocalBuildInfo -> IO FilePath getLibDir verbosity lbi = dropWhileEndLE isSpace `fmap`@@ -385,18 +389,18 @@ -- | Return the 'FilePath' to the per-user GHC package database. getUserPackageDB- :: Verbosity -> ConfiguredProgram -> Platform -> NoCallStackIO FilePath+ :: Verbosity -> ConfiguredProgram -> Platform -> IO FilePath getUserPackageDB _verbosity ghcProg platform = do -- It's rather annoying that we have to reconstruct this, because ghc -- hides this information from us otherwise. But for certain use cases -- like change monitoring it really can't remain hidden.- appdir <- getAppUserDataDirectory "ghc"+ appdir <- getGhcAppDir return (appdir </> platformAndVersion </> packageConfFileName) where platformAndVersion = Internal.ghcPlatformAndVersionString platform ghcVersion packageConfFileName = "package.conf.d"- Just ghcVersion = programVersion ghcProg+ ghcVersion = fromMaybe (error "GHC.getUserPackageDB: no ghc version") $ programVersion ghcProg checkPackageDbEnvVar :: Verbosity -> IO () checkPackageDbEnvVar verbosity =@@ -426,7 +430,7 @@ die' verbosity $ "With current ghc versions the global package db is always used " ++ "and must be listed first. This ghc limitation is lifted in GHC 7.6,"- ++ "see http://ghc.haskell.org/trac/ghc/ticket/5977"+ ++ "see https://gitlab.haskell.org/ghc/ghc/-/issues/5977" checkPackageDbStackPre76 verbosity _ = die' verbosity $ "If the global package db is specified, it must be " ++ "specified first and cannot be specified multiple times"@@ -475,7 +479,7 @@ if isFileStyle then return path else return (path </> "package.cache") - Just ghcProg = lookupProgram ghcProgram progdb+ ghcProg = fromMaybe (error "GHC.toPackageIndex: no ghc program") $ lookupProgram ghcProgram progdb -- -----------------------------------------------------------------------------@@ -508,7 +512,7 @@ when (forceStatic || withStaticLib lbi) whenGHCiLib = when (withGHCiLib lbi) forRepl = maybe False (const True) mReplFlags- ifReplLib = when forRepl+ whenReplLib = when forRepl replFlags = fromMaybe mempty mReplFlags comp = compiler lbi ghcVersion = compilerVersion comp@@ -670,10 +674,6 @@ unless forRepl $ whenProfLib (runGhcProgIfNeeded profCxxOpts) | filename <- cxxSources libBi] - ifReplLib $ do- when (null (allLibModules lib clbi)) $ warn verbosity "No exposed modules"- ifReplLib (runGhcProg replOpts)- -- build any C sources unless (not has_code || null (cSources libBi)) $ do info verbosity "Building C Sources..."@@ -770,6 +770,9 @@ -- TODO: problem here is we need the .c files built first, so we can load them -- with ghci, but .c files can depend on .h files generated by ghc by ffi -- exports.+ whenReplLib $ do+ when (null (allLibModules lib clbi)) $ warn verbosity "No exposed modules"+ runGhcProg replOpts -- link: when has_code . unless forRepl $ do@@ -1175,7 +1178,7 @@ -- | Locate and return the 'BuildSources' required to build and link. gbuildSources :: Verbosity- -> Version -- ^ specVersion+ -> CabalSpecVersion -> FilePath -> GBuildMode -> IO BuildSources@@ -1194,7 +1197,7 @@ if isHaskell main then- if specVer < mkVersion [2] && (mainModName `elem` otherModNames)+ if specVer < CabalSpecV2_0 && (mainModName `elem` otherModNames) then do -- The cabal manual clearly states that `other-modules` is -- intended for non-main modules. However, there's at least one@@ -1684,7 +1687,7 @@ -- | Returns True if the modification date of the given source file is newer than -- the object file we last compiled for it, or if no object file exists yet.-checkNeedsRecompilation :: FilePath -> GhcOptions -> NoCallStackIO Bool+checkNeedsRecompilation :: FilePath -> GhcOptions -> IO Bool checkNeedsRecompilation filename opts = filename `moreRecentFile` oname where oname = getObjectFileName filename opts @@ -1700,7 +1703,7 @@ -- Calculates relative RPATHs when 'relocatable' is set. getRPaths :: LocalBuildInfo -> ComponentLocalBuildInfo -- ^ Component we are building- -> NoCallStackIO (NubListR FilePath)+ -> IO (NubListR FilePath) getRPaths lbi clbi | supportRPaths hostOS = do libraryPaths <- depLibraryPaths False (relocatable lbi) lbi clbi let hostPref = case hostOS of@@ -1941,7 +1944,7 @@ whenShared $ if -- The behavior for "extra-bundled-libraries" changed in version 2.5.0. -- See ghc issue #15837 and Cabal PR #5855.- | specVersion pkg < mkVersion [2,5] -> do+ | specVersion pkg < CabalSpecV3_0 -> do sequence_ [ installShared builtDir dynlibTargetDir (mkGenericSharedLibName platform compiler_id (l ++ f)) | l <- getHSLibraryName uid : extraBundledLibs (libBuildInfo lib)@@ -2032,9 +2035,9 @@ , HcPkg.suppressFilesCheck = v >= [6,6] } where- v = versionNumbers ver- Just ghcPkgProg = lookupProgram ghcPkgProgram progdb- Just ver = programVersion ghcPkgProg+ v = versionNumbers ver+ ghcPkgProg = fromMaybe (error "GHC.hcPkgInfo: no ghc program") $ lookupProgram ghcPkgProgram progdb+ ver = fromMaybe (error "GHC.hcPkgInfo: no ghc version") $ programVersion ghcPkgProg registerPackage :: Verbosity@@ -2051,10 +2054,10 @@ pkgRoot verbosity lbi = pkgRoot' where pkgRoot' GlobalPackageDB =- let Just ghcProg = lookupProgram ghcProgram (withPrograms lbi)+ let ghcProg = fromMaybe (error "GHC.pkgRoot: no ghc program") $ lookupProgram ghcProgram (withPrograms lbi) in fmap takeDirectory (getGlobalPackageDB verbosity ghcProg) pkgRoot' UserPackageDB = do- appDir <- getAppUserDataDirectory "ghc"+ appDir <- getGhcAppDir let ver = compilerVersion (compiler lbi) subdir = System.Info.arch ++ '-':System.Info.os ++ '-':prettyShow ver
cabal/Cabal/Distribution/Simple/GHC/EnvironmentParser.hs view
@@ -17,8 +17,6 @@ import Distribution.Types.UnitId ( mkUnitId ) -import Control.Exception- ( Exception, throwIO ) import qualified Text.Parsec as P import Text.Parsec.String ( Parser, parseFromFile )
cabal/Cabal/Distribution/Simple/GHC/Internal.hs view
@@ -51,12 +51,10 @@ import Distribution.Simple.GHC.ImplInfo import Distribution.Types.ComponentLocalBuildInfo import Distribution.Backpack-import Distribution.InstalledPackageInfo-import qualified Distribution.InstalledPackageInfo as InstalledPackageInfo-import Distribution.PackageDescription as PD hiding (Flag)-import Distribution.Compat.Exception+import qualified Distribution.InstalledPackageInfo as IPI+import Distribution.PackageDescription import Distribution.Lex-import Distribution.Simple.Compiler hiding (Flag)+import Distribution.Simple.Compiler import Distribution.Simple.Program.GHC import Distribution.Simple.Setup import qualified Distribution.ModuleName as ModuleName@@ -65,6 +63,7 @@ import Distribution.Types.UnitId import Distribution.Types.LocalBuildInfo import Distribution.Types.TargetInfo+import Distribution.Types.ModuleRenaming import Distribution.Simple.Utils import Distribution.Simple.BuildPaths import Distribution.System@@ -176,7 +175,7 @@ | (flags', ""):_ <- reads flags -> flags' | otherwise -> tokenizeQuotedWords flags - configureGcc :: Verbosity -> ConfiguredProgram -> NoCallStackIO ConfiguredProgram+ configureGcc :: Verbosity -> ConfiguredProgram -> IO ConfiguredProgram configureGcc _v gccProg = do return gccProg { programDefaultArgs = programDefaultArgs gccProg@@ -216,7 +215,7 @@ else return ldProg getLanguages :: Verbosity -> GhcImplInfo -> ConfiguredProgram- -> NoCallStackIO [(Language, String)]+ -> IO [(Language, String)] getLanguages _ implInfo _ -- TODO: should be using --supported-languages rather than hard coding | supportsHaskell2010 implInfo = return [(Haskell98, "-XHaskell98")@@ -281,10 +280,10 @@ ,autogenPackageModulesDir lbi ,odir] -- includes relative to the package- ++ PD.includeDirs bi+ ++ includeDirs bi -- potential includes generated by `configure' -- in the build directory- ++ [buildDir lbi </> dir | dir <- PD.includeDirs bi],+ ++ [buildDir lbi </> dir | dir <- includeDirs bi], ghcOptHideAllPackages= toFlag True, ghcOptPackageDBs = withPackageDB lbi, ghcOptPackages = toNubListR $ mkGhcOptPackages clbi,@@ -296,7 +295,7 @@ MinimalDebugInfo -> ["-g1"] NormalDebugInfo -> ["-g"] MaximalDebugInfo -> ["-g3"]) ++- PD.ccOptions bi,+ ccOptions bi, ghcOptObjDir = toFlag odir } @@ -317,10 +316,10 @@ ,autogenPackageModulesDir lbi ,odir] -- includes relative to the package- ++ PD.includeDirs bi+ ++ includeDirs bi -- potential includes generated by `configure' -- in the build directory- ++ [buildDir lbi </> dir | dir <- PD.includeDirs bi],+ ++ [buildDir lbi </> dir | dir <- includeDirs bi], ghcOptHideAllPackages= toFlag True, ghcOptPackageDBs = withPackageDB lbi, ghcOptPackages = toNubListR $ mkGhcOptPackages clbi,@@ -332,7 +331,7 @@ MinimalDebugInfo -> ["-g1"] NormalDebugInfo -> ["-g"] MaximalDebugInfo -> ["-g3"]) ++- PD.cxxOptions bi,+ cxxOptions bi, ghcOptObjDir = toFlag odir } @@ -353,10 +352,10 @@ ,autogenPackageModulesDir lbi ,odir] -- includes relative to the package- ++ PD.includeDirs bi+ ++ includeDirs bi -- potential includes generated by `configure' -- in the build directory- ++ [buildDir lbi </> dir | dir <- PD.includeDirs bi],+ ++ [buildDir lbi </> dir | dir <- includeDirs bi], ghcOptHideAllPackages= toFlag True, ghcOptPackageDBs = withPackageDB lbi, ghcOptPackages = toNubListR $ mkGhcOptPackages clbi,@@ -368,7 +367,7 @@ MinimalDebugInfo -> ["-g1"] NormalDebugInfo -> ["-g"] MaximalDebugInfo -> ["-g3"]) ++- PD.asmOptions bi,+ asmOptions bi, ghcOptObjDir = toFlag odir } @@ -412,14 +411,14 @@ ,autogenPackageModulesDir lbi ,odir] -- includes relative to the package- ++ PD.includeDirs bi+ ++ includeDirs bi -- potential includes generated by `configure' -- in the build directory- ++ [buildDir lbi </> dir | dir <- PD.includeDirs bi],+ ++ [buildDir lbi </> dir | dir <- includeDirs bi], ghcOptCppOptions = cppOptions bi, ghcOptCppIncludes = toNubListR $ [autogenComponentModulesDir lbi clbi </> cppHeaderName],- ghcOptFfiIncludes = toNubListR $ PD.includes bi,+ ghcOptFfiIncludes = toNubListR $ includes bi, ghcOptObjDir = toFlag odir, ghcOptHiDir = toFlag odir, ghcOptStubDir = toFlag odir,@@ -461,10 +460,10 @@ ,autogenPackageModulesDir lbi ,odir] -- includes relative to the package- ++ PD.includeDirs bi+ ++ includeDirs bi -- potential includes generated by `configure' -- in the build directory- ++ [buildDir lbi </> dir | dir <- PD.includeDirs bi],+ ++ [buildDir lbi </> dir | dir <- includeDirs bi], ghcOptCppOptions = cppOptions bi, ghcOptCppIncludes = toNubListR $ [autogenComponentModulesDir lbi clbi </> cppHeaderName],@@ -507,7 +506,7 @@ -- Module_split directory for each module. getHaskellObjects :: GhcImplInfo -> Library -> LocalBuildInfo -> ComponentLocalBuildInfo- -> FilePath -> String -> Bool -> NoCallStackIO [FilePath]+ -> FilePath -> String -> Bool -> IO [FilePath] getHaskellObjects _implInfo lib lbi clbi pref wanted_obj_ext allow_split_objs | splitObjs lbi && allow_split_objs = do let splitSuffix = "_" ++ wanted_obj_ext ++ "_split"@@ -527,21 +526,15 @@ -> [(OpenUnitId, ModuleRenaming)] mkGhcOptPackages = componentIncludes -substTopDir :: FilePath -> InstalledPackageInfo -> InstalledPackageInfo+substTopDir :: FilePath -> IPI.InstalledPackageInfo -> IPI.InstalledPackageInfo substTopDir topDir ipo = ipo {- InstalledPackageInfo.importDirs- = map f (InstalledPackageInfo.importDirs ipo),- InstalledPackageInfo.libraryDirs- = map f (InstalledPackageInfo.libraryDirs ipo),- InstalledPackageInfo.includeDirs- = map f (InstalledPackageInfo.includeDirs ipo),- InstalledPackageInfo.frameworkDirs- = map f (InstalledPackageInfo.frameworkDirs ipo),- InstalledPackageInfo.haddockInterfaces- = map f (InstalledPackageInfo.haddockInterfaces ipo),- InstalledPackageInfo.haddockHTMLs- = map f (InstalledPackageInfo.haddockHTMLs ipo)+ IPI.importDirs = map f (IPI.importDirs ipo),+ IPI.libraryDirs = map f (IPI.libraryDirs ipo),+ IPI.includeDirs = map f (IPI.includeDirs ipo),+ IPI.frameworkDirs = map f (IPI.frameworkDirs ipo),+ IPI.haddockInterfaces = map f (IPI.haddockInterfaces ipo),+ IPI.haddockHTMLs = map f (IPI.haddockHTMLs ipo) } where f ('$':'t':'o':'p':'d':'i':'r':rest) = topDir ++ rest f x = x@@ -563,7 +556,7 @@ mcsPP <- lookupEnv "CABAL_SANDBOX_PACKAGE_PATH" unless (mPP == mcsPP) abort where- lookupEnv :: String -> NoCallStackIO (Maybe String)+ lookupEnv :: String -> IO (Maybe String) lookupEnv name = (Just `fmap` getEnv name) `catchIO` const (return Nothing) abort =@@ -652,7 +645,7 @@ -> Platform -- ^ the GHC target platform -> Version -- ^ the GHC version -> [GhcEnvironmentFileEntry] -- ^ the content- -> NoCallStackIO FilePath+ -> IO FilePath writeGhcEnvironmentFile directory platform ghcversion entries = do writeFileAtomic envfile . BS.pack . renderGhcEnvironmentFile $ entries return envfile@@ -676,9 +669,9 @@ renderGhcEnvironmentFileEntry :: GhcEnvironmentFileEntry -> String renderGhcEnvironmentFileEntry entry = case entry of GhcEnvFileComment comment -> format comment- where format = intercalate "\n" . map ("--" <+>) . lines- pref <+> "" = pref- pref <+> str = pref ++ " " ++ str+ where format = intercalate "\n" . map ("--" <++>) . lines+ pref <++> "" = pref+ pref <++> str = pref ++ " " ++ str GhcEnvFilePackageId pkgid -> "package-id " ++ prettyShow pkgid GhcEnvFilePackageDb pkgdb -> case pkgdb of
cabal/Cabal/Distribution/Simple/GHCJS.hs view
@@ -63,15 +63,12 @@ import Distribution.Simple.Program.GHC import Distribution.Simple.Setup import qualified Distribution.Simple.Setup as Cabal-import Distribution.Simple.Compiler hiding (Flag)+import Distribution.Simple.Compiler+import Distribution.CabalSpecVersion import Distribution.Version import Distribution.System import Distribution.Verbosity import Distribution.Pretty-import Distribution.Types.ForeignLib-import Distribution.Types.ForeignLibType-import Distribution.Types.ForeignLibOption-import Distribution.Types.UnqualComponentName import Distribution.Utils.NubList import Control.Monad (msum)@@ -103,7 +100,7 @@ warn verbosity $ "Unknown/unsupported 'ghc' version detected " ++ "(Cabal " ++ prettyShow cabalVersion ++ " supports 'ghc' version < 8.8): "- ++ programPath ghcjsProg ++ " is is based on GHC version " +++ ++ programPath ghcjsProg ++ " is based on GHC version " ++ prettyShow ghcjsGhcVersion let implInfo = ghcjsVersionImplInfo ghcjsVersion ghcjsGhcVersion@@ -241,7 +238,7 @@ getGhcInfo :: Verbosity -> ConfiguredProgram -> IO [(String, String)] getGhcInfo verbosity ghcjsProg = Internal.getGhcInfo verbosity implInfo ghcjsProg where- Just version = programVersion ghcjsProg+ version = fromMaybe (error "GHCJS.getGhcInfo: no version") $ programVersion ghcjsProg implInfo = ghcVersionImplInfo version -- | Given a single package DB, return all installed packages.@@ -275,7 +272,7 @@ return $! (mconcat indices) where- Just ghcjsProg = lookupProgram ghcjsProgram progdb+ ghcjsProg = fromMaybe (error "GHCJS.toPackageIndex no ghcjs program") $ lookupProgram ghcjsProgram progdb getLibDir :: Verbosity -> LocalBuildInfo -> IO FilePath getLibDir verbosity lbi =@@ -296,7 +293,7 @@ getProgramOutput verbosity ghcProg ["--print-global-package-db"] -- | Return the 'FilePath' to the per-user GHC package database.-getUserPackageDB :: Verbosity -> ConfiguredProgram -> Platform -> NoCallStackIO FilePath+getUserPackageDB :: Verbosity -> ConfiguredProgram -> Platform -> IO FilePath getUserPackageDB _verbosity ghcjsProg platform = do -- It's rather annoying that we have to reconstruct this, because ghc -- hides this information from us otherwise. But for certain use cases@@ -307,7 +304,7 @@ platformAndVersion = Internal.ghcPlatformAndVersionString platform ghcjsVersion packageConfFileName = "package.conf.d"- Just ghcjsVersion = programVersion ghcjsProg+ ghcjsVersion = fromMaybe (error "GHCJS.getUserPackageDB: no version") $ programVersion ghcjsProg checkPackageDbEnvVar :: Verbosity -> IO () checkPackageDbEnvVar verbosity =@@ -320,7 +317,7 @@ | GlobalPackageDB `notElem` rest = die' verbosity $ "With current ghc versions the global package db is always used " ++ "and must be listed first. This ghc limitation may be lifted in "- ++ "future, see http://ghc.haskell.org/trac/ghc/ticket/5977"+ ++ "future, see https://gitlab.haskell.org/ghc/ghc/-/issues/5977" checkPackageDbStack verbosity _ = die' verbosity $ "If the global package db is specified, it must be " ++ "specified first and cannot be specified multiple times"@@ -360,7 +357,7 @@ if isFileStyle then return path else return (path </> "package.cache") - Just ghcjsProg = lookupProgram ghcjsProgram progdb+ ghcjsProg = fromMaybe (error "GHCJS.toPackageIndex no ghcjs program") $ lookupProgram ghcjsProgram progdb toJSLibName :: String -> String@@ -963,7 +960,7 @@ -- | Locate and return the 'BuildSources' required to build and link. gbuildSources :: Verbosity- -> Version -- ^ specVersion+ -> CabalSpecVersion -> FilePath -> GBuildMode -> IO BuildSources@@ -982,7 +979,7 @@ if isHaskell main then- if specVer < mkVersion [2] && (mainModName `elem` otherModNames)+ if specVer < CabalSpecV2_0 && (mainModName `elem` otherModNames) then do -- The cabal manual clearly states that `other-modules` is -- intended for non-main modules. However, there's at least one@@ -1464,7 +1461,7 @@ -- | Returns True if the modification date of the given source file is newer than -- the object file we last compiled for it, or if no object file exists yet.-checkNeedsRecompilation :: FilePath -> GhcOptions -> NoCallStackIO Bool+checkNeedsRecompilation :: FilePath -> GhcOptions -> IO Bool checkNeedsRecompilation filename opts = filename `moreRecentFile` oname where oname = getObjectFileName filename opts @@ -1480,7 +1477,7 @@ -- Calculates relative RPATHs when 'relocatable' is set. getRPaths :: LocalBuildInfo -> ComponentLocalBuildInfo -- ^ Component we are building- -> NoCallStackIO (NubListR FilePath)+ -> IO (NubListR FilePath) getRPaths lbi clbi | supportRPaths hostOS = do libraryPaths <- depLibraryPaths False (relocatable lbi) lbi clbi let hostPref = case hostOS of@@ -1782,8 +1779,8 @@ } where v7_10 = mkVersion [7,10]- Just ghcjsPkgProg = lookupProgram ghcjsPkgProgram progdb- Just ver = programVersion ghcjsPkgProg+ ghcjsPkgProg = fromMaybe (error "GHCJS.hcPkgInfo no ghcjs program") $ lookupProgram ghcjsPkgProgram progdb+ ver = fromMaybe (error "GHCJS.hcPkgInfo no ghcjs version") $ programVersion ghcjsPkgProg registerPackage :: Verbosity@@ -1800,7 +1797,7 @@ pkgRoot verbosity lbi = pkgRoot' where pkgRoot' GlobalPackageDB =- let Just ghcjsProg = lookupProgram ghcjsProgram (withPrograms lbi)+ let ghcjsProg = fromMaybe (error "GHCJS.pkgRoot: no ghcjs program") $ lookupProgram ghcjsProgram (withPrograms lbi) in fmap takeDirectory (getGlobalPackageDB verbosity ghcjsProg) pkgRoot' UserPackageDB = do appDir <- getAppUserDataDirectory "ghcjs"@@ -1830,4 +1827,4 @@ ) where script = exe <.> "jsexe" </> "all" <.> "js"- Just ghcjsProg = lookupProgram ghcjsProgram progdb+ ghcjsProg = fromMaybe (error "GHCJS.runCmd: no ghcjs program") $ lookupProgram ghcjsProgram progdb
cabal/Cabal/Distribution/Simple/Glob.hs view
@@ -28,11 +28,9 @@ import Prelude () import Distribution.Compat.Prelude -import Control.Monad (guard)-+import Distribution.CabalSpecVersion import Distribution.Simple.Utils import Distribution.Verbosity-import Distribution.Version import System.Directory (getDirectoryContents, doesDirectoryExist, doesFileExist) import System.FilePath (joinPath, splitExtensions, splitDirectories, takeFileName, (</>), (<.>))@@ -176,7 +174,7 @@ MultiDotEnabled -> Just (GlobMatch ()) | otherwise = Nothing -parseFileGlob :: Version -> FilePath -> Either GlobSyntaxError Glob+parseFileGlob :: CabalSpecVersion -> FilePath -> Either GlobSyntaxError Glob parseFileGlob version filepath = case reverse (splitDirectories filepath) of [] -> Left EmptyGlob@@ -200,14 +198,14 @@ | otherwise -> Right (FinalLit filename) foldM addStem (GlobFinal pat) segments where- allowGlob = version >= mkVersion [1,6]- allowGlobStar = version >= mkVersion [2,4]+ allowGlob = version >= CabalSpecV1_6+ allowGlobStar = version >= CabalSpecV2_4 addStem pat seg | '*' `elem` seg = Left StarInDirectory | otherwise = Right (GlobStem seg pat) multidot- | version >= mkVersion [2,4] = MultiDotEnabled- | otherwise = MultiDotDisabled+ | version >= CabalSpecV2_4 = MultiDotEnabled+ | otherwise = MultiDotDisabled -- | This will 'die'' when the glob matches no files, or if the glob -- refers to a missing directory, or if the glob fails to parse.@@ -222,7 +220,7 @@ -- prefix. -- -- The second 'FilePath' is the glob itself.-matchDirFileGlob :: Verbosity -> Version -> FilePath -> FilePath -> IO [FilePath]+matchDirFileGlob :: Verbosity -> CabalSpecVersion -> FilePath -> FilePath -> IO [FilePath] matchDirFileGlob verbosity version dir filepath = case parseFileGlob version filepath of Left err -> die' verbosity $ explainGlobSyntaxError filepath err Right glob -> do
cabal/Cabal/Distribution/Simple/Haddock.hs view
@@ -42,8 +42,8 @@ import Distribution.Types.ExposedModule import Distribution.Package import qualified Distribution.ModuleName as ModuleName-import Distribution.PackageDescription as PD hiding (Flag)-import Distribution.Simple.Compiler hiding (Flag)+import Distribution.PackageDescription+import Distribution.Simple.Compiler import Distribution.Simple.Glob import Distribution.Simple.Program.GHC import Distribution.Simple.Program.ResponseFile@@ -66,6 +66,7 @@ import Distribution.Parsec (simpleParsec) import Distribution.Utils.NubList import Distribution.Version+import qualified Distribution.Utils.ShortText as ShortText import Distribution.Verbosity import Language.Haskell.Extension@@ -352,20 +353,23 @@ ghcArgs = fromMaybe [] . lookup "ghc" . haddockProgramArgs $ flags fromPackageDescription :: HaddockTarget -> PackageDescription -> HaddockArgs-fromPackageDescription haddockTarget pkg_descr =- mempty { argInterfaceFile = Flag $ haddockName pkg_descr,- argPackageName = Flag $ packageId $ pkg_descr,- argOutputDir = Dir $- "doc" </> "html" </> haddockDirName haddockTarget pkg_descr,- argPrologue = Flag $ if null desc then synopsis pkg_descr- else desc,- argTitle = Flag $ showPkg ++ subtitle- }- where- desc = PD.description pkg_descr- showPkg = prettyShow (packageId pkg_descr)- subtitle | null (synopsis pkg_descr) = ""- | otherwise = ": " ++ synopsis pkg_descr+fromPackageDescription haddockTarget pkg_descr = mempty+ { argInterfaceFile = Flag $ haddockName pkg_descr+ , argPackageName = Flag $ packageId $ pkg_descr+ , argOutputDir = Dir $+ "doc" </> "html" </> haddockDirName haddockTarget pkg_descr+ , argPrologue = Flag $ ShortText.fromShortText $+ if ShortText.null desc+ then synopsis pkg_descr+ else desc+ , argTitle = Flag $ showPkg ++ subtitle+ }+ where+ desc = description pkg_descr+ showPkg = prettyShow (packageId pkg_descr)+ subtitle+ | ShortText.null (synopsis pkg_descr) = ""+ | otherwise = ": " ++ ShortText.fromShortText (synopsis pkg_descr) componentGhcOptions :: Verbosity -> LocalBuildInfo -> BuildInfo -> ComponentLocalBuildInfo -> FilePath@@ -521,7 +525,11 @@ haddockVersionMacro = "-D__HADDOCK_VERSION__=" ++ show (v1 * 1000 + v2 * 10 + v3) where- [v1, v2, v3] = take 3 $ versionNumbers haddockVersion ++ [0,0]+ (v1, v2, v3) = case versionNumbers haddockVersion of+ [] -> (0,0,0)+ [x] -> (x,0,0)+ [x,y] -> (x,y,0)+ (x:y:z:_) -> (x,y,z) getGhcLibDir :: Verbosity -> LocalBuildInfo -> IO HaddockArgs@@ -694,7 +702,7 @@ -- HTML paths, and an optional warning for packages with missing documentation. haddockPackagePaths :: [InstalledPackageInfo] -> Maybe (InstalledPackageInfo -> FilePath)- -> NoCallStackIO ([( FilePath -- path to interface+ -> IO ([( FilePath -- path to interface -- file , Maybe FilePath -- url to html
cabal/Cabal/Distribution/Simple/HaskellSuite.hs view
@@ -6,13 +6,10 @@ import Prelude () import Distribution.Compat.Prelude -import Data.Either (partitionEithers)--import qualified Data.Map as Map (empty) import qualified Data.List.NonEmpty as NE import Distribution.Simple.Program-import Distribution.Simple.Compiler as Compiler+import Distribution.Simple.Compiler import Distribution.Simple.Utils import Distribution.Simple.BuildPaths import Distribution.Verbosity@@ -25,8 +22,6 @@ import Distribution.PackageDescription import Distribution.Simple.LocalBuildInfo import Distribution.System (Platform)-import Distribution.Compat.Exception-import Distribution.Utils.Generic import Language.Haskell.Extension import Distribution.Simple.Program.Builtin @@ -80,11 +75,11 @@ let comp = Compiler { compilerId = CompilerId (HaskellSuite compName) compVersion,- compilerAbiTag = Compiler.NoAbiTag,+ compilerAbiTag = NoAbiTag, compilerCompat = [], compilerLanguages = languages, compilerExtensions = extensions,- compilerProperties = Map.empty+ compilerProperties = mempty } return (comp, confdCompiler, progdb2)@@ -107,7 +102,7 @@ simpleParsec versionStr return (name, version) -getExtensions :: Verbosity -> ConfiguredProgram -> IO [(Extension, Maybe Compiler.Flag)]+getExtensions :: Verbosity -> ConfiguredProgram -> IO [(Extension, Maybe CompilerFlag)] getExtensions verbosity prog = do extStrs <- lines `fmap`@@ -115,7 +110,7 @@ return [ (ext, Just $ "-X" ++ prettyShow ext) | Just ext <- map simpleParsec extStrs ] -getLanguages :: Verbosity -> ConfiguredProgram -> IO [(Language, Compiler.Flag)]+getLanguages :: Verbosity -> ConfiguredProgram -> IO [(Language, CompilerFlag)] getLanguages verbosity prog = do langStrs <- lines `fmap`@@ -139,7 +134,7 @@ where parsePackages str =- case partitionEithers $ map parseInstalledPackageInfo (splitPkgs str) of+ case partitionEithers $ map (parseInstalledPackageInfo . toUTF8BS) (splitPkgs str) of ([], ok) -> Right [ pkg | (_, pkg) <- ok ] (msgss, _) -> Left (foldMap NE.toList msgss) @@ -219,7 +214,7 @@ runProgramInvocation verbosity $ (programInvocation hspkg ["update", packageDbOpt $ registrationPackageDB packageDbs])- { progInvokeInput = Just $ showInstalledPackageInfo installedPkgInfo }+ { progInvokeInput = Just $ IODataText $ showInstalledPackageInfo installedPkgInfo } initPackageDB :: Verbosity -> ProgramDb -> FilePath -> IO () initPackageDB verbosity progdb dbPath =
cabal/Cabal/Distribution/Simple/InstallDirs.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE CPP #-}+{-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE FlexibleContexts #-}@@ -98,9 +99,10 @@ htmldir :: dir, haddockdir :: dir, sysconfdir :: dir- } deriving (Eq, Read, Show, Functor, Generic)+ } deriving (Eq, Read, Show, Functor, Generic, Typeable) instance Binary dir => Binary (InstallDirs dir)+instance Structured dir => Structured (InstallDirs dir) instance (Semigroup dir, Monoid dir) => Monoid (InstallDirs dir) where mempty = gmempty@@ -352,9 +354,10 @@ -- substituted for to get a real 'FilePath'. -- newtype PathTemplate = PathTemplate [PathComponent]- deriving (Eq, Ord, Generic)+ deriving (Eq, Ord, Generic, Typeable) instance Binary PathTemplate+instance Structured PathTemplate type PathTemplateEnv = [(PathTemplateVariable, PathTemplate)] @@ -462,7 +465,7 @@ -- --------------------------------------------------------------------------- -- Internal utilities -getWindowsProgramFilesDir :: NoCallStackIO FilePath+getWindowsProgramFilesDir :: IO FilePath getWindowsProgramFilesDir = do #ifdef mingw32_HOST_OS m <- shGetFolderPath csidl_PROGRAM_FILES@@ -472,7 +475,7 @@ return (fromMaybe "C:\\Program Files" m) #ifdef mingw32_HOST_OS-shGetFolderPath :: CInt -> NoCallStackIO (Maybe FilePath)+shGetFolderPath :: CInt -> IO (Maybe FilePath) shGetFolderPath n = allocaArray long_path_size $ \pPath -> do r <- c_SHGetFolderPath nullPtr n nullPtr 0 pPath
cabal/Cabal/Distribution/Simple/InstallDirs/Internal.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric #-} module Distribution.Simple.InstallDirs.Internal ( PathComponent(..)@@ -10,9 +11,10 @@ data PathComponent = Ordinary FilePath | Variable PathTemplateVariable- deriving (Eq, Ord, Generic)+ deriving (Eq, Ord, Generic, Typeable) instance Binary PathComponent+instance Structured PathComponent data PathTemplateVariable = PrefixVar -- ^ The @$prefix@ path variable@@ -39,9 +41,10 @@ | TestSuiteResultVar -- ^ The result of the test suite being run, eg -- @pass@, @fail@, or @error@. | BenchmarkNameVar -- ^ The name of the benchmark being run- deriving (Eq, Ord, Generic)+ deriving (Eq, Ord, Generic, Typeable) instance Binary PathTemplateVariable+instance Structured PathTemplateVariable instance Show PathTemplateVariable where show PrefixVar = "prefix"
cabal/Cabal/Distribution/Simple/LocalBuildInfo.hs view
@@ -190,7 +190,7 @@ -> Bool -- ^ Generate prefix-relative library paths -> LocalBuildInfo -> ComponentLocalBuildInfo -- ^ Component that is being built- -> NoCallStackIO [FilePath]+ -> IO [FilePath] depLibraryPaths inplace relative lbi clbi = do let pkgDescr = localPkgDescr lbi installDirs = absoluteComponentInstallDirs pkgDescr lbi (componentUnitId clbi) NoCopyDest
cabal/Cabal/Distribution/Simple/PackageIndex.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-}@@ -76,6 +77,7 @@ searchByName, SearchResult(..), searchByNameSubstring,+ searchWithPredicate, -- ** Bulk queries allPackages,@@ -144,9 +146,10 @@ -- preserved. See #1463 for discussion. packageIdIndex :: !(Map (PackageName, LibraryName) (Map Version [a])) - } deriving (Eq, Generic, Show, Read)+ } deriving (Eq, Generic, Show, Read, Typeable) instance Binary a => Binary (PackageIndex a)+instance Structured a => Structured (PackageIndex a) -- | The default package index which contains 'InstalledPackageInfo'. Normally -- use this.@@ -525,14 +528,18 @@ -- searchByNameSubstring :: PackageIndex a -> String -> [a] searchByNameSubstring index searchterm =+ searchWithPredicate index (\n -> lsearchterm `isInfixOf` lowercase n)+ where lsearchterm = lowercase searchterm++-- | @since 3.4.0.0+searchWithPredicate :: PackageIndex a -> (String -> Bool) -> [a]+searchWithPredicate index predicate = [ pkg -- Don't match internal packages | ((pname, LMainLibName), pvers) <- Map.toList (packageIdIndex index)- , lsearchterm `isInfixOf` lowercase (unPackageName pname)+ , predicate (unPackageName pname) , pkgs <- Map.elems pvers , pkg <- pkgs ]- where lsearchterm = lowercase searchterm- -- -- * Special queries
cabal/Cabal/Distribution/Simple/PreProcess.hs view
@@ -53,9 +53,6 @@ import Distribution.Pretty import Distribution.Version import Distribution.Verbosity-import Distribution.Types.ForeignLib-import Distribution.Types.LibraryName-import Distribution.Types.UnqualComponentName import System.Directory (doesFileExist) import System.Info (os, arch)@@ -123,12 +120,6 @@ -- preprocessor's output name format. type PreProcessorExtras = FilePath -> IO [FilePath] --- | A newtype around 'PreProcessorExtras', useful for storing--- 'PreProcessorExtras' inside of another type constructor (e.g., a list)--- without impredicativity (recall that the 'IO' type, which is contained in--- 'PreProcessorExtras', is a synonym for @'HasCallStack' => Prelude.IO@, which--- is a polymorphic type).-newtype WrappedPreProcessorExtras = WrapPPE { unWrapPPE :: PreProcessorExtras } mkSimplePreProcessor :: (FilePath -> FilePath -> Verbosity -> IO ()) -> (FilePath, FilePath)@@ -701,8 +692,8 @@ ] -- |Standard preprocessors with possible extra C sources: c2hs, hsc2hs.-knownExtrasHandlers :: [ WrappedPreProcessorExtras ]-knownExtrasHandlers = [ WrapPPE ppC2hsExtras, WrapPPE ppHsc2hsExtras ]+knownExtrasHandlers :: [ PreProcessorExtras ]+knownExtrasHandlers = [ ppC2hsExtras, ppHsc2hsExtras ] -- | Find any extra C sources generated by preprocessing that need to -- be added to the component (addresses issue #238).@@ -740,7 +731,7 @@ pp :: FilePath -> IO [FilePath] pp dir = (map (dir </>) . filter not_sub . concat) <$> for knownExtrasHandlers- (withLexicalCallStack (\f -> f dir) . unWrapPPE)+ (withLexicalCallStack (\f -> f dir)) -- TODO: This is a terrible hack to work around #3545 while we don't -- reorganize the directory layout. Basically, for the main -- library, we might accidentally pick up autogenerated sources for
cabal/Cabal/Distribution/Simple/Program.hs view
@@ -61,6 +61,7 @@ , programInvocation , runProgramInvocation , getProgramInvocationOutput+ , getProgramInvocationLBS -- * The collection of unconfigured and configured programs , builtinPrograms
cabal/Cabal/Distribution/Simple/Program/Builtin.hs view
@@ -54,7 +54,6 @@ import Distribution.Simple.Program.Run import Distribution.Simple.Program.Types import Distribution.Simple.Utils-import Distribution.Compat.Exception import Distribution.Verbosity import Distribution.Version @@ -105,7 +104,7 @@ ghcProgram = (simpleProgram "ghc") { programFindVersion = findProgramVersion "--numeric-version" id, - -- Workaround for https://ghc.haskell.org/trac/ghc/ticket/8825+ -- Workaround for https://gitlab.haskell.org/ghc/ghc/-/issues/8825 -- (spurious warning on non-english locales) programPostConf = \_verbosity ghcProg -> do let ghcProg' = ghcProg {
cabal/Cabal/Distribution/Simple/Program/Db.hs view
@@ -1,6 +1,6 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE RankNTypes #-} {-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-} ----------------------------------------------------------------------------- -- |@@ -61,19 +61,20 @@ ) where -import Prelude () import Distribution.Compat.Prelude+import Prelude () -import Distribution.Simple.Program.Types-import Distribution.Simple.Program.Find+import Distribution.Pretty import Distribution.Simple.Program.Builtin+import Distribution.Simple.Program.Find+import Distribution.Simple.Program.Types import Distribution.Simple.Utils-import Distribution.Version-import Distribution.Pretty+import Distribution.Utils.Structured (Structure (..), Structured (..)) import Distribution.Verbosity+import Distribution.Version -import Control.Monad (join) import Data.Tuple (swap)+ import qualified Data.Map as Map -- ------------------------------------------------------------@@ -151,7 +152,13 @@ configuredProgs = progs } +instance Structured ProgramDb where+ structure p = Nominal (typeRep p) 0 "ProgramDb"+ [ structure (Proxy :: Proxy ProgramSearchPath)+ , structure (Proxy :: Proxy ConfiguredProgs)+ ] + -- | The 'Read'\/'Show' and 'Binary' instances do not preserve all the -- unconfigured 'Programs' because 'Program' is not in 'Read'\/'Show' because -- it contains functions. So to fully restore a deserialised 'ProgramDb' use@@ -426,7 +433,7 @@ -- It returns 'Nothing' if the program couldn't be configured, -- or is not found. ----- @since 3.2.0.0+-- @since 3.0.1.0 needProgram :: Verbosity -> Program -> ProgramDb -> IO (Maybe (ConfiguredProgram, ProgramDb)) needProgram verbosity prog progdb = do
cabal/Cabal/Distribution/Simple/Program/Find.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE CPP #-}+{-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE RankNTypes #-}@@ -67,9 +68,10 @@ data ProgramSearchPathEntry = ProgramSearchPathDir FilePath -- ^ A specific dir | ProgramSearchPathDefault -- ^ The system default- deriving (Eq, Generic)+ deriving (Eq, Generic, Typeable) instance Binary ProgramSearchPathEntry+instance Structured ProgramSearchPathEntry defaultProgramSearchPath :: ProgramSearchPath defaultProgramSearchPath = [ProgramSearchPathDefault]@@ -95,7 +97,7 @@ where alltried = concat (reverse (notfoundat : tried)) - tryPathElem :: ProgramSearchPathEntry -> NoCallStackIO (Maybe FilePath, [FilePath])+ tryPathElem :: ProgramSearchPathEntry -> IO (Maybe FilePath, [FilePath]) tryPathElem (ProgramSearchPathDir dir) = findFirstExe [ dir </> prog <.> ext | ext <- exeExtensions ] @@ -120,7 +122,7 @@ dirs <- getSystemSearchPath findFirstExe [ dir </> prog <.> ext | dir <- dirs, ext <- exeExtensions ] - findFirstExe :: [FilePath] -> NoCallStackIO (Maybe FilePath, [FilePath])+ findFirstExe :: [FilePath] -> IO (Maybe FilePath, [FilePath]) findFirstExe = go [] where go fs' [] = return (Nothing, reverse fs')@@ -142,7 +144,7 @@ -- | Interpret a 'ProgramSearchPath' to construct a new @$PATH@ env var. -- Note that this is close but not perfect because on Windows the search -- algorithm looks at more than just the @%PATH%@.-programSearchPathAsPATHVar :: ProgramSearchPath -> NoCallStackIO String+programSearchPathAsPATHVar :: ProgramSearchPath -> IO String programSearchPathAsPATHVar searchpath = do ess <- traverse getEntries searchpath return (intercalate [searchPathSeparator] (concat ess))@@ -155,7 +157,7 @@ -- | Get the system search path. On Unix systems this is just the @$PATH@ env -- var, but on windows it's a bit more complicated. ---getSystemSearchPath :: NoCallStackIO [FilePath]+getSystemSearchPath :: IO [FilePath] getSystemSearchPath = fmap nub $ do #if defined(mingw32_HOST_OS) processdir <- takeDirectory `fmap` Win32.getModuleFileName Win32.nullHANDLE@@ -177,7 +179,7 @@ #endif #endif -findExecutable :: FilePath -> NoCallStackIO (Maybe FilePath)+findExecutable :: FilePath -> IO (Maybe FilePath) #ifdef HAVE_directory_121 findExecutable = Directory.findExecutable #else
cabal/Cabal/Distribution/Simple/Program/GHC.hs view
@@ -27,16 +27,16 @@ import Distribution.Backpack import Distribution.Compat.Semigroup (First'(..), Last'(..), Option'(..)) import Distribution.Simple.GHC.ImplInfo-import Distribution.PackageDescription hiding (Flag)+import Distribution.PackageDescription import Distribution.ModuleName-import Distribution.Simple.Compiler hiding (Flag)-import qualified Distribution.Simple.Compiler as Compiler (Flag)+import Distribution.Simple.Compiler import Distribution.Simple.Flag import Distribution.Simple.Program.Types import Distribution.Simple.Program.Run import Distribution.System import Distribution.Pretty import Distribution.Types.ComponentId+import Distribution.Types.ModuleRenaming import Distribution.Verbosity import Distribution.Version import Distribution.Utils.NubList@@ -55,7 +55,7 @@ supportedGHCVersions :: VersionRange supportedGHCVersions = intersectVersionRanges (orLaterVersion (mkVersion [8,0]))- (earlierVersion (mkVersion [8,9]))+ (earlierVersion (mkVersion [8,13])) from :: Monoid m => [Int] -> m -> m from version flags@@ -172,6 +172,19 @@ , "print-bind-contents", "print-evld-with-show" , "implicit-import-qualified", "error-spans" ]+ , from [7,8]+ [ "print-explicit-foralls" -- maybe also earlier, but GHC-7.6 doesn't have --show-options+ , "print-explicit-kinds"+ ]+ , from [8,0]+ [ "print-explicit-coercions"+ , "print-explicit-runtime-reps"+ , "print-equality-relations"+ , "print-unicode-syntax"+ , "print-expanded-synonyms"+ , "print-potential-instances"+ , "print-typechecker-elaboration"+ ] , from [8,2] [ "diagnostics-show-caret", "local-ghci-history" , "show-warning-groups", "hide-source-paths"@@ -179,6 +192,11 @@ ] , from [8,4] ["show-loaded-modules"] , from [8,6] [ "ghci-leak-check", "no-it" ]+ , from [8,10]+ [ "defer-diagnostics" -- affects printing of diagnostics+ , "keep-going" -- try harder, the build will still fail if it's erroneous+ , "print-axiom-incomps" -- print more debug info for closed type families+ ] ] , flagIn . invertibleFlagSet "-d" $ [ "ppr-case-as-let", "ppr-ticks" ] , isOptIntFlag@@ -201,7 +219,7 @@ simpleFlags :: Set String simpleFlags = Set.fromList . mconcat $- [ [ "-n", "-#include", "-Rghc-timing", "-dsuppress-all", "-dstg-stats"+ [ [ "-n", "-#include", "-Rghc-timing", "-dstg-stats" , "-dth-dec-file", "-dsource-stats", "-dverbose-core2core" , "-dverbose-stg2stg", "-dcore-lint", "-dstg-lint", "-dcmm-lint" , "-dasm-lint", "-dannot-lint", "-dshow-passes", "-dfaststring-stats"@@ -219,6 +237,7 @@ , from [8,4] $ to [8,6] [ "-fno-max-valid-substitutions" ] , from [8,6] [ "-dhex-word-literals" ] , from [8,8] [ "-fshow-docs-of-hole-fits", "-fno-show-docs-of-hole-fits" ]+ , from [8,12] [ "-dlinear-core-lint" ] ] isOptIntFlag :: String -> Any@@ -439,7 +458,7 @@ -- | A GHC version-dependent mapping of extensions to flags. This must be -- set to be able to make use of the 'ghcOptExtensions'.- ghcOptExtensionMap :: Map Extension (Maybe Compiler.Flag),+ ghcOptExtensionMap :: Map Extension (Maybe CompilerFlag), ---------------- -- Compilation@@ -794,7 +813,7 @@ ++ show dbstack -- | GHC >= 7.6 uses the '-package-db' flag. See--- https://ghc.haskell.org/trac/ghc/ticket/5977.+-- https://gitlab.haskell.org/ghc/ghc/-/issues/5977. packageDbArgsDb :: PackageDBStack -> [String] -- special cases to make arguments prettier in common scenarios packageDbArgsDb dbstack = case dbstack of
cabal/Cabal/Distribution/Simple/Program/HcPkg.hs view
@@ -1,5 +1,7 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE OverloadedStrings #-} ----------------------------------------------------------------------------- -- |@@ -42,30 +44,27 @@ listInvocation, ) where -import Prelude () import Distribution.Compat.Prelude hiding (init)--import Data.Either (partitionEithers)-import qualified Data.List.NonEmpty as NE+import Prelude () import Distribution.InstalledPackageInfo+import Distribution.Parsec+import Distribution.Pretty import Distribution.Simple.Compiler-import Distribution.Simple.Program.Types import Distribution.Simple.Program.Run+import Distribution.Simple.Program.Types import Distribution.Simple.Utils-import Distribution.Parsec-import Distribution.Pretty import Distribution.Types.ComponentId import Distribution.Types.PackageId import Distribution.Types.UnitId import Distribution.Verbosity-import Distribution.Compat.Exception -import Data.List- ( stripPrefix )-import System.FilePath as FilePath- ( (</>), (<.>)- , splitPath, splitDirectories, joinPath, isPathSeparator )+import Data.List (stripPrefix)+import System.FilePath as FilePath (isPathSeparator, joinPath, splitDirectories, splitPath, (<.>), (</>))++import qualified Data.ByteString as BS+import qualified Data.ByteString.Lazy as LBS+import qualified Data.List.NonEmpty as NE import qualified System.FilePath.Posix as FilePath.Posix -- | Information about the features and capabilities of an @hc-pkg@@@ -225,9 +224,9 @@ describe :: HcPkgInfo -> Verbosity -> PackageDBStack -> PackageId -> IO [InstalledPackageInfo] describe hpi verbosity packagedb pid = do - output <- getProgramInvocationOutput verbosity+ output <- getProgramInvocationLBS verbosity (describeInvocation hpi verbosity packagedb pid)- `catchIO` \_ -> return ""+ `catchIO` \_ -> return mempty case parsePackages output of Left ok -> return ok@@ -250,7 +249,7 @@ dump :: HcPkgInfo -> Verbosity -> PackageDB -> IO [InstalledPackageInfo] dump hpi verbosity packagedb = do - output <- getProgramInvocationOutput verbosity+ output <- getProgramInvocationLBS verbosity (dumpInvocation hpi verbosity packagedb) `catchIO` \e -> die' verbosity $ programId (hcPkgProgram hpi) ++ " dump failed: " ++ displayException e@@ -260,27 +259,51 @@ _ -> die' verbosity $ "failed to parse output of '" ++ programId (hcPkgProgram hpi) ++ " dump'" -parsePackages :: String -> Either [InstalledPackageInfo] [String]-parsePackages str =- case partitionEithers $ map parseInstalledPackageInfo (splitPkgs str) of- ([], ok) -> Left [ setUnitId . maybe id mungePackagePaths (pkgRoot pkg) $ pkg | (_, pkg) <- ok ]- (msgss, _) -> Right (foldMap NE.toList msgss) ---TODO: this could be a lot faster. We're doing normaliseLineEndings twice--- and converting back and forth with lines/unlines.-splitPkgs :: String -> [String]-splitPkgs = checkEmpty . map unlines . splitWith ("---" ==) . lines+parsePackages :: LBS.ByteString -> Either [InstalledPackageInfo] [String]+parsePackages lbs0 =+ case traverse parseInstalledPackageInfo $ splitPkgs lbs0 of+ Right ok -> Left [ setUnitId . maybe id mungePackagePaths (pkgRoot pkg) $ pkg | (_, pkg) <- ok ]+ Left msgs -> Right (NE.toList msgs) where- -- Handle the case of there being no packages at all.- checkEmpty [s] | all isSpace s = []- checkEmpty ss = ss+ splitPkgs :: LBS.ByteString -> [BS.ByteString]+ splitPkgs = checkEmpty . doSplit+ where+ -- Handle the case of there being no packages at all.+ checkEmpty [s] | BS.all isSpace8 s = []+ checkEmpty ss = ss - splitWith :: (a -> Bool) -> [a] -> [[a]]- splitWith p xs = ys : case zs of- [] -> []- _:ws -> splitWith p ws- where (ys,zs) = break p xs+ isSpace8 :: Word8 -> Bool+ isSpace8 9 = True -- '\t'+ isSpace8 10 = True -- '\n'+ isSpace8 13 = True -- '\r'+ isSpace8 32 = True -- ' '+ isSpace8 _ = False + doSplit :: LBS.ByteString -> [BS.ByteString]+ doSplit lbs = go (LBS.findIndices (\w -> w == 10 || w == 13) lbs)+ where+ go :: [Int64] -> [BS.ByteString]+ go [] = [ LBS.toStrict lbs ]+ go (idx:idxs) =+ let (pfx, sfx) = LBS.splitAt idx lbs+ in case foldr (<|>) Nothing $ map (`lbsStripPrefix` sfx) separators of+ Just sfx' -> LBS.toStrict pfx : doSplit sfx'+ Nothing -> go idxs++ separators :: [LBS.ByteString]+ separators = ["\n---\n", "\r\n---\r\n", "\r---\r"]++lbsStripPrefix :: LBS.ByteString -> LBS.ByteString -> Maybe LBS.ByteString+#if MIN_VERSION_bytestring(0,10,8)+lbsStripPrefix pfx lbs = LBS.stripPrefix pfx lbs+#else+lbsStripPrefix pfx lbs+ | LBS.isPrefixOf pfx lbs = Just (LBS.drop (LBS.length pfx) lbs)+ | otherwise = Nothing+#endif++ mungePackagePaths :: FilePath -> InstalledPackageInfo -> InstalledPackageInfo -- Perform path/URL variable substitution as per the Cabal ${pkgroot} spec -- (http://www.haskell.org/pipermail/libraries/2009-May/011772.html)@@ -376,7 +399,7 @@ -> ProgramInvocation registerInvocation hpi verbosity packagedbs pkgInfo registerOptions = (programInvocation (hcPkgProgram hpi) (args "-")) {- progInvokeInput = Just (showInstalledPackageInfo pkgInfo),+ progInvokeInput = Just $ IODataText $ showInstalledPackageInfo pkgInfo, progInvokeInputEncoding = IOEncodingUTF8 } where
cabal/Cabal/Distribution/Simple/Program/Hpc.hs view
@@ -19,7 +19,6 @@ import Prelude () import Distribution.Compat.Prelude -import Control.Monad (mapM) import System.Directory (makeRelativeToCurrentDirectory) import Distribution.ModuleName@@ -61,7 +60,7 @@ return passedDirs -- Prior to GHC 8.0, hpc assumes all .mix paths are relative.- hpcDirs'' <- mapM makeRelativeToCurrentDirectory hpcDirs'+ hpcDirs'' <- traverse makeRelativeToCurrentDirectory hpcDirs' runProgramInvocation verbosity (markupInvocation hpc tixFile hpcDirs'' destDir excluded)
cabal/Cabal/Distribution/Simple/Program/Run.hs view
@@ -1,5 +1,6 @@ {-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE RankNTypes #-} ----------------------------------------------------------------------------- -- |@@ -22,25 +23,26 @@ runProgramInvocation, getProgramInvocationOutput,+ getProgramInvocationLBS, getProgramInvocationOutputAndErrors, getEffectiveEnvironment, ) where -import Prelude () import Distribution.Compat.Prelude+import Prelude () +import Distribution.Compat.Environment import Distribution.Simple.Program.Types import Distribution.Simple.Utils-import Distribution.Verbosity-import Distribution.Compat.Environment import Distribution.Utils.Generic+import Distribution.Verbosity -import qualified Data.Map as Map-import System.FilePath-import System.Exit- ( ExitCode(..), exitWith )+import System.FilePath (searchPathSeparator) +import qualified Data.ByteString.Lazy as LBS+import qualified Data.Map as Map+ -- | Represents a specific invocation of a specific program. -- -- This is used as an intermediate type between deciding how to call a program@@ -55,17 +57,18 @@ -- Extra paths to add to PATH progInvokePathEnv :: [FilePath], progInvokeCwd :: Maybe FilePath,- progInvokeInput :: Maybe String,- progInvokeInputEncoding :: IOEncoding,+ progInvokeInput :: Maybe IOData,+ progInvokeInputEncoding :: IOEncoding, -- ^ TODO: remove this, make user decide when constructing 'progInvokeInput'. progInvokeOutputEncoding :: IOEncoding } data IOEncoding = IOEncodingText -- locale mode text | IOEncodingUTF8 -- always utf8 -encodeToIOData :: IOEncoding -> String -> IOData-encodeToIOData IOEncodingText = IODataText-encodeToIOData IOEncodingUTF8 = IODataBinary . toUTF8LBS+encodeToIOData :: IOEncoding -> IOData -> IOData+encodeToIOData _ iod@(IODataBinary _) = iod+encodeToIOData IOEncodingText iod@(IODataText _) = iod+encodeToIOData IOEncodingUTF8 (IODataText str) = IODataBinary (toUTF8LBS str) emptyProgramInvocation :: ProgramInvocation emptyProgramInvocation =@@ -156,36 +159,45 @@ die' verbosity $ "'" ++ progInvokePath inv ++ "' exited with an error:\n" ++ errors return output +getProgramInvocationLBS :: Verbosity -> ProgramInvocation -> IO LBS.ByteString+getProgramInvocationLBS verbosity inv = do+ (output, errors, exitCode) <- getProgramInvocationIODataAndErrors verbosity inv IODataModeBinary+ when (exitCode /= ExitSuccess) $+ die' verbosity $ "'" ++ progInvokePath inv ++ "' exited with an error:\n" ++ errors+ return output getProgramInvocationOutputAndErrors :: Verbosity -> ProgramInvocation -> IO (String, String, ExitCode)-getProgramInvocationOutputAndErrors verbosity- ProgramInvocation {- progInvokePath = path,- progInvokeArgs = args,- progInvokeEnv = envOverrides,- progInvokePathEnv = extraPath,- progInvokeCwd = mcwd,- progInvokeInput = minputStr,- progInvokeOutputEncoding = encoding- } = do- let mode = case encoding of IOEncodingUTF8 -> IODataModeBinary- IOEncodingText -> IODataModeText-- decode (IODataBinary b) = normaliseLineEndings (fromUTF8LBS b)- decode (IODataText s) = s+getProgramInvocationOutputAndErrors verbosity inv = case progInvokeOutputEncoding inv of+ IOEncodingText -> do+ (output, errors, exitCode) <- getProgramInvocationIODataAndErrors verbosity inv IODataModeText+ return (output, errors, exitCode)+ IOEncodingUTF8 -> do+ (output', errors, exitCode) <- getProgramInvocationIODataAndErrors verbosity inv IODataModeBinary+ return (normaliseLineEndings (fromUTF8LBS output'), errors, exitCode) +getProgramInvocationIODataAndErrors+ :: KnownIODataMode mode => Verbosity -> ProgramInvocation -> IODataMode mode+ -> IO (mode, String, ExitCode)+getProgramInvocationIODataAndErrors+ verbosity+ ProgramInvocation+ { progInvokePath = path+ , progInvokeArgs = args+ , progInvokeEnv = envOverrides+ , progInvokePathEnv = extraPath+ , progInvokeCwd = mcwd+ , progInvokeInput = minputStr+ , progInvokeInputEncoding = encoding+ }+ mode = do pathOverride <- getExtraPathEnv envOverrides extraPath menv <- getEffectiveEnvironment (envOverrides ++ pathOverride)- (output, errors, exitCode) <- rawSystemStdInOut verbosity- path args- mcwd menv- input mode- return (decode output, errors, exitCode)+ rawSystemStdInOut verbosity path args mcwd menv input mode where input = encodeToIOData encoding <$> minputStr -getExtraPathEnv :: [(String, Maybe String)] -> [FilePath] -> NoCallStackIO [(String, Maybe String)]+getExtraPathEnv :: [(String, Maybe String)] -> [FilePath] -> IO [(String, Maybe String)] getExtraPathEnv _ [] = return [] getExtraPathEnv env extras = do mb_path <- case lookup "PATH" env of@@ -202,7 +214,7 @@ -- precedence. -- getEffectiveEnvironment :: [(String, Maybe String)]- -> NoCallStackIO (Maybe [(String, String)])+ -> IO (Maybe [(String, String)]) getEffectiveEnvironment [] = return Nothing getEffectiveEnvironment overrides = fmap (Just . Map.toList . apply overrides . Map.fromList) getEnvironment
cabal/Cabal/Distribution/Simple/Program/Script.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE GADTs #-} ----------------------------------------------------------------------------- -- | -- Module : Distribution.Simple.Program.Script@@ -20,6 +21,7 @@ import Distribution.Compat.Prelude import Distribution.Simple.Program.Run+import Distribution.Simple.Utils import Distribution.System -- | Generate a system script, either POSIX shell script or Windows batch file@@ -45,8 +47,8 @@ ++ concatMap setEnv envExtra ++ [ "cd " ++ quote cwd | cwd <- maybeToList mcwd ] ++ [ (case minput of- Nothing -> ""- Just input -> "echo " ++ quote input ++ " | ")+ Nothing -> ""+ Just input -> "echo " ++ quote (iodataToText input) ++ " | ") ++ unwords (map quote $ path : args) ++ " \"$@\""] where@@ -60,7 +62,11 @@ escape ('\'':cs) = "'\\''" ++ escape cs escape (c :cs) = c : escape cs +iodataToText :: IOData -> String+iodataToText (IODataText str) = str+iodataToText (IODataBinary lbs) = fromUTF8LBS lbs + -- | Generate a Windows batch file that invokes a program. -- invocationAsBatchFile :: ProgramInvocation -> String@@ -81,7 +87,7 @@ Just input -> [ "(" ]- ++ [ "echo " ++ escape line | line <- lines input ]+ ++ [ "echo " ++ escape line | line <- lines $ iodataToText input ] ++ [ ") | " ++ "\"" ++ path ++ "\"" ++ concatMap (\arg -> ' ':quote arg) args ]
cabal/Cabal/Distribution/Simple/Program/Types.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE RankNTypes #-}@@ -133,6 +134,7 @@ deriving (Eq, Generic, Read, Show, Typeable) instance Binary ConfiguredProgram+instance Structured ConfiguredProgram -- | Where a program was found. Also tells us whether it's specified by user or -- not. This includes not just the path, but the program as well.@@ -142,9 +144,10 @@ -- eg. --ghc-path=\/usr\/bin\/ghc-6.6 | FoundOnSystem { locationPath :: FilePath } -- ^The program was found automatically.- deriving (Eq, Generic, Read, Show)+ deriving (Eq, Generic, Read, Show, Typeable) instance Binary ProgramLocation+instance Structured ProgramLocation -- | The full path of a configured program. programPath :: ConfiguredProgram -> FilePath
cabal/Cabal/Distribution/Simple/Register.hs view
@@ -23,7 +23,7 @@ -- build multi-package systems. -- -- This module does not delegate anything to the per-compiler modules but just--- mixes it all in in this module, which is rather unsatisfactory. The script+-- mixes it all in this module, which is rather unsatisfactory. The script -- generation and the unregister feature are not well used or tested. module Distribution.Simple.Register (@@ -87,7 +87,6 @@ import System.FilePath ((</>), (<.>), isAbsolute) import System.Directory -import Data.List (partition) import qualified Data.ByteString.Lazy.Char8 as BS.Char8 -- -----------------------------------------------------------------------------@@ -300,7 +299,7 @@ "Distribution.Simple.Register.createPackageDB: " ++ "not implemented for this compiler" -doesPackageDBExist :: FilePath -> NoCallStackIO Bool+doesPackageDBExist :: FilePath -> IO Bool doesPackageDBExist dbPath = do -- currently one impl for all compiler flavours, but could change if needed dir_exists <- doesDirectoryExist dbPath@@ -308,7 +307,7 @@ then return True else doesFileExist dbPath -deletePackageDB :: FilePath -> NoCallStackIO ()+deletePackageDB :: FilePath -> IO () deletePackageDB dbPath = do -- currently one impl for all compiler flavours, but could change if needed dir_exists <- doesDirectoryExist dbPath
cabal/Cabal/Distribution/Simple/Setup.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE CPP #-}+{-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE RankNTypes #-}@@ -88,28 +89,24 @@ import qualified Distribution.Compat.CharParsing as P import qualified Text.PrettyPrint as Disp import Distribution.ModuleName-import Distribution.PackageDescription hiding (Flag)+import Distribution.PackageDescription import Distribution.Simple.Command hiding (boolOpt, boolOpt') import qualified Distribution.Simple.Command as Command-import Distribution.Simple.Compiler hiding (Flag)+import Distribution.Simple.Compiler import Distribution.Simple.Flag import Distribution.Simple.Utils import Distribution.Simple.Program import Distribution.Simple.InstallDirs import Distribution.Verbosity import Distribution.Utils.NubList-import Distribution.Types.Dependency import Distribution.Types.ComponentId import Distribution.Types.GivenComponent import Distribution.Types.Module-import Distribution.Types.PackageName-import Distribution.Types.UnqualComponentName (unUnqualComponentName)+import Distribution.Types.PackageVersionConstraint import Distribution.Compat.Stack import Distribution.Compat.Semigroup (Last' (..), Option' (..)) -import Data.Function (on)- -- FIXME Not sure where this should live defaultDistPref :: FilePath defaultDistPref = "dist"@@ -128,7 +125,7 @@ data GlobalFlags = GlobalFlags { globalVersion :: Flag Bool, globalNumericVersion :: Flag Bool- } deriving (Generic)+ } deriving (Generic, Typeable) defaultGlobalFlags :: GlobalFlags defaultGlobalFlags = GlobalFlags {@@ -256,8 +253,8 @@ configSplitObjs :: Flag Bool, -- ^Enable -split-objs with GHC configStripExes :: Flag Bool, -- ^Enable executable stripping configStripLibs :: Flag Bool, -- ^Enable library stripping- configConstraints :: [Dependency], -- ^Additional constraints for- -- dependencies.+ configConstraints :: [PackageVersionConstraint], -- ^Additional constraints for+ -- dependencies. configDependencies :: [GivenComponent], -- ^The packages depended on. configInstantiateWith :: [(ModuleName, Module)],@@ -278,15 +275,16 @@ configDebugInfo :: Flag DebugInfoLevel, -- ^ Emit debug info. configUseResponseFiles :: Flag Bool, -- ^ Whether to use response files at all. They're used for such tools- -- as haddock, or or ld.+ -- as haddock, or ld. configAllowDependingOnPrivateLibs :: Flag Bool -- ^ Allow depending on private sublibraries. This is used by external -- tools (like cabal-install) so they can add multiple-public-libraries -- compatibility to older ghcs by checking visibility externally. }- deriving (Generic, Read, Show)+ deriving (Generic, Read, Show, Typeable) instance Binary ConfigFlags+instance Structured ConfigFlags -- | More convenient version of 'configPrograms'. Results in an -- 'error' if internal invariant is violated.@@ -347,7 +345,7 @@ where equal f = on (==) f a b -configAbsolutePaths :: ConfigFlags -> NoCallStackIO ConfigFlags+configAbsolutePaths :: ConfigFlags -> IO ConfigFlags configAbsolutePaths f = (\v -> f { configPackageDBs = v }) `liftM` traverse (maybe (return Nothing) (liftM Just . absolutePackageDBPath))@@ -610,8 +608,8 @@ "Force values for the given flags in Cabal conditionals in the .cabal file. E.g., --flags=\"debug -usebytestrings\" forces the flag \"debug\" to true and \"usebytestrings\" to false." configConfigurationsFlags (\v flags -> flags { configConfigurationsFlags = v }) (reqArg "FLAGS"- (parsecToReadE (\err -> "Invalid flag assignment: " ++ err) parsecFlagAssignment)- showFlagAssignment)+ (parsecToReadE (\err -> "Invalid flag assignment: " ++ err) legacyParsecFlagAssignment)+ legacyShowFlagAssignment') ,option "" ["extra-include-dirs"] "A list of directories to search for header files"@@ -726,16 +724,6 @@ reqArgFlag title _sf _lf d (fmap fromPathTemplate . get) (set . fmap toPathTemplate) -showFlagAssignment :: FlagAssignment -> [String]-showFlagAssignment = map showFlagValue' . unFlagAssignment- where- -- We can't use 'showFlagValue' because legacy custom-setups don't- -- support the '+' prefix in --flags; so we omit the (redundant) + prefix;- -- NB: we assume that we never have to set/enable '-'-prefixed flags here.- showFlagValue' :: (FlagName, Bool) -> String- showFlagValue' (f, True) = unFlagName f- showFlagValue' (f, False) = '-' : unFlagName f- readPackageDbList :: String -> [Maybe PackageDB] readPackageDbList "clear" = [Nothing] readPackageDbList "global" = [Just GlobalPackageDB]@@ -1036,7 +1024,7 @@ sDistListSources :: Flag FilePath, sDistVerbosity :: Flag Verbosity }- deriving (Show, Generic)+ deriving (Show, Generic, Typeable) defaultSDistFlags :: SDistFlags defaultSDistFlags = SDistFlags {@@ -1109,7 +1097,7 @@ regArgs :: [String], regCabalFilePath :: Flag FilePath }- deriving (Show, Generic)+ deriving (Show, Generic, Typeable) defaultRegisterFlags :: RegisterFlags defaultRegisterFlags = RegisterFlags {@@ -1223,7 +1211,7 @@ hscolourVerbosity :: Flag Verbosity, hscolourCabalFilePath :: Flag FilePath }- deriving (Show, Generic)+ deriving (Show, Generic, Typeable) emptyHscolourFlags :: HscolourFlags emptyHscolourFlags = mempty@@ -1316,7 +1304,7 @@ doctestDistPref :: Flag FilePath, doctestVerbosity :: Flag Verbosity }- deriving (Show, Generic)+ deriving (Show, Generic, Typeable) defaultDoctestFlags :: DoctestFlags defaultDoctestFlags = DoctestFlags {@@ -1384,9 +1372,10 @@ -- from documentation tarballs, and we might also want to use different -- flags than for development builds, so in this case we store the generated -- documentation in @<dist>/doc/html/<package id>-docs@.-data HaddockTarget = ForHackage | ForDevelopment deriving (Eq, Show, Generic)+data HaddockTarget = ForHackage | ForDevelopment deriving (Eq, Show, Generic, Typeable) instance Binary HaddockTarget+instance Structured HaddockTarget instance Pretty HaddockTarget where pretty ForHackage = Disp.text "for-hackage"@@ -1419,7 +1408,7 @@ haddockCabalFilePath :: Flag FilePath, haddockArgs :: [String] }- deriving (Show, Generic)+ deriving (Show, Generic, Typeable) defaultHaddockFlags :: HaddockFlags defaultHaddockFlags = HaddockFlags {@@ -1592,7 +1581,7 @@ cleanVerbosity :: Flag Verbosity, cleanCabalFilePath :: Flag FilePath }- deriving (Show, Generic)+ deriving (Show, Generic, Typeable) defaultCleanFlags :: CleanFlags defaultCleanFlags = CleanFlags {@@ -1650,7 +1639,7 @@ buildArgs :: [String], buildCabalFilePath :: Flag FilePath }- deriving (Read, Show, Generic)+ deriving (Read, Show, Generic, Typeable) defaultBuildFlags :: BuildFlags defaultBuildFlags = BuildFlags {@@ -1740,7 +1729,7 @@ replReload :: Flag Bool, replReplOptions :: [String] }- deriving (Show, Generic)+ deriving (Show, Generic, Typeable) defaultReplFlags :: ReplFlags defaultReplFlags = ReplFlags {@@ -1839,9 +1828,10 @@ -- ------------------------------------------------------------ data TestShowDetails = Never | Failures | Always | Streaming | Direct- deriving (Eq, Ord, Enum, Bounded, Generic, Show)+ deriving (Eq, Ord, Enum, Bounded, Generic, Show, Typeable) instance Binary TestShowDetails+instance Structured TestShowDetails knownTestShowDetails :: [TestShowDetails] knownTestShowDetails = [minBound..maxBound]@@ -1877,7 +1867,7 @@ testFailWhenNoTestSuites :: Flag Bool, -- TODO: think about if/how options are passed to test exes testOptions :: [PathTemplate]- } deriving (Generic)+ } deriving (Show, Generic, Typeable) defaultTestFlags :: TestFlags defaultTestFlags = TestFlags {@@ -1997,7 +1987,7 @@ benchmarkDistPref :: Flag FilePath, benchmarkVerbosity :: Flag Verbosity, benchmarkOptions :: [PathTemplate]- } deriving (Generic)+ } deriving (Show, Generic, Typeable) defaultBenchmarkFlags :: BenchmarkFlags defaultBenchmarkFlags = BenchmarkFlags {@@ -2230,7 +2220,7 @@ data ShowBuildInfoFlags = ShowBuildInfoFlags { buildInfoBuildFlags :: BuildFlags , buildInfoOutputFile :: Maybe FilePath- } deriving Show+ } deriving (Show, Typeable) defaultShowBuildFlags :: ShowBuildInfoFlags defaultShowBuildFlags =
cabal/Cabal/Distribution/Simple/ShowBuildInfo.hs view
@@ -56,6 +56,9 @@ module Distribution.Simple.ShowBuildInfo (mkBuildInfo) where +import Distribution.Compat.Prelude+import Prelude ()+ import qualified Distribution.Simple.GHC as GHC import qualified Distribution.Simple.Program.GHC as GHC @@ -122,7 +125,7 @@ ] where bi = componentBuildInfo comp- Just comp = lookupComponent pkg_descr name+ comp = fromMaybe (error $ "mkBuildInfo: no component " ++ prettyShow name) $ lookupComponent pkg_descr name compType = case comp of CLib _ -> "lib" CExe _ -> "exe"
cabal/Cabal/Distribution/Simple/SrcDist.hs view
@@ -39,14 +39,15 @@ dateToSnapshotNumber, -- * Extracting the source files- listPackageSources+ listPackageSources,+ listPackageSourcesWithDie, ) where import Prelude () import Distribution.Compat.Prelude -import Distribution.PackageDescription hiding (Flag)+import Distribution.PackageDescription import Distribution.PackageDescription.Check hiding (doesFileExist) import Distribution.Package import Distribution.ModuleName@@ -57,49 +58,40 @@ import Distribution.Simple.Utils import Distribution.Simple.Setup import Distribution.Simple.PreProcess-import Distribution.Simple.LocalBuildInfo import Distribution.Simple.BuildPaths import Distribution.Simple.Program import Distribution.Pretty-import Distribution.Types.ForeignLib import Distribution.Verbosity -import Data.List (partition) import qualified Data.Map as Map import Data.Time (UTCTime, getCurrentTime, toGregorian, utctDay) import System.Directory ( doesFileExist ) import System.IO (IOMode(WriteMode), hPutStrLn, withFile) import System.FilePath ((</>), (<.>), dropExtension, isRelative)-import Control.Monad -- |Create a source distribution.-sdist :: PackageDescription -- ^information from the tarball- -> Maybe LocalBuildInfo -- ^Information from configure- -> SDistFlags -- ^verbosity & snapshot- -> (FilePath -> FilePath) -- ^build prefix (temp dir)+sdist :: PackageDescription -- ^ information from the tarball+ -> SDistFlags -- ^ verbosity & snapshot+ -> (FilePath -> FilePath) -- ^ build prefix (temp dir) -> [PPSuffixHandler] -- ^ extra preprocessors (includes suffixes) -> IO ()-sdist pkg mb_lbi flags mkTmpDir pps = do+sdist pkg flags mkTmpDir pps = do distPref <- findDistPrefOrDefault $ sDistDistPref flags let targetPref = distPref tmpTargetDir = mkTmpDir distPref -- When given --list-sources, just output the list of sources to a file.- case (sDistListSources flags) of+ case sDistListSources flags of Flag path -> withFile path WriteMode $ \outHandle -> do- (ordinary, maybeExecutable) <- listPackageSources verbosity pkg pps+ ordinary <- listPackageSources verbosity "." pkg pps traverse_ (hPutStrLn outHandle) ordinary- traverse_ (hPutStrLn outHandle) maybeExecutable- notice verbosity $ "List of package sources written to file '"- ++ path ++ "'"+ notice verbosity $ "List of package sources written to file '" ++ path ++ "'"+ NoFlag -> do -- do some QA printPackageProblems verbosity pkg - when (isNothing mb_lbi) $- warn verbosity "Cannot run preprocessors. Run 'configure' command first."- date <- getCurrentTime let pkg' | snapshot = snapshotPackage date pkg | otherwise = pkg@@ -114,49 +106,64 @@ withTempDirectory verbosity tmpTargetDir "sdist." $ \tmpDir -> do let targetDir = tmpDir </> tarBallName pkg' generateSourceDir targetDir pkg'- targzFile <- createArchive verbosity pkg' mb_lbi tmpDir targetPref+ targzFile <- createArchive verbosity pkg' tmpDir targetPref notice verbosity $ "Source tarball created: " ++ targzFile where+ generateSourceDir :: FilePath -> PackageDescription -> IO () generateSourceDir targetDir pkg' = do- setupMessage verbosity "Building source dist for" (packageId pkg')- prepareTree verbosity pkg' mb_lbi targetDir pps+ prepareTree verbosity pkg' targetDir pps when snapshot $ overwriteSnapshotPackageDesc verbosity pkg' targetDir verbosity = fromFlag (sDistVerbosity flags) snapshot = fromFlag (sDistSnapshot flags) --- | List all source files of a package. Returns a tuple of lists: first--- component is a list of ordinary files, second one is a list of those files--- that may be executable.-listPackageSources :: Verbosity -- ^ verbosity- -> PackageDescription -- ^ info from the cabal file- -> [PPSuffixHandler] -- ^ extra preprocessors (include- -- suffixes)- -> IO ([FilePath], [FilePath])-listPackageSources verbosity pkg_descr0 pps = do- -- Call helpers that actually do all work.- ordinary <- listPackageSourcesOrdinary verbosity pkg_descr pps- maybeExecutable <- listPackageSourcesMaybeExecutable verbosity pkg_descr- return (ordinary, maybeExecutable)+-- | List all source files of a package.+--+-- Since @Cabal-3.4@ returns a single list. There shouldn't be any+-- executable files, they are hardly portable.+-- +listPackageSources+ :: Verbosity -- ^ verbosity+ -> FilePath -- ^ directory with cabal file+ -> PackageDescription -- ^ info from the cabal file+ -> [PPSuffixHandler] -- ^ extra preprocessors (include suffixes)+ -> IO [FilePath] -- ^ relative paths+listPackageSources verbosity cwd pkg_descr0 pps = do+ -- Call helpers that actually do all work.+ listPackageSources' verbosity die' cwd pkg_descr pps where pkg_descr = filterAutogenModules pkg_descr0 --- | List those source files that may be executable (e.g. the configure script).-listPackageSourcesMaybeExecutable :: Verbosity -> PackageDescription -> IO [FilePath]-listPackageSourcesMaybeExecutable verbosity pkg_descr =- -- Extra source files.- fmap concat . for (extraSrcFiles pkg_descr) $ \fpath ->- matchDirFileGlob verbosity (specVersion pkg_descr) "." fpath+-- | A variant of 'listPackageSources' with configurable 'die'.+--+-- /Note:/ may still 'die' directly. For example on missing include file.+--+-- Since @3.4.0.0+listPackageSourcesWithDie+ :: Verbosity -- ^ verbosity+ -> (Verbosity -> String -> IO [FilePath]) -- ^ 'die'' alternative+ -> FilePath -- ^ directory with cabal file+ -> PackageDescription -- ^ info from the cabal file+ -> [PPSuffixHandler] -- ^ extra preprocessors (include suffixes)+ -> IO [FilePath] -- ^ relative paths+listPackageSourcesWithDie verbosity rip cwd pkg_descr0 pps = do+ -- Call helpers that actually do all work.+ listPackageSources' verbosity rip cwd pkg_descr pps+ where+ pkg_descr = filterAutogenModules pkg_descr0 --- | List those source files that should be copied with ordinary permissions.-listPackageSourcesOrdinary :: Verbosity- -> PackageDescription- -> [PPSuffixHandler]- -> IO [FilePath]-listPackageSourcesOrdinary verbosity pkg_descr pps =++listPackageSources'+ :: Verbosity+ -> (Verbosity -> String -> IO [FilePath])+ -> FilePath+ -> PackageDescription+ -> [PPSuffixHandler]+ -> IO [FilePath]+listPackageSources' verbosity rip cwd pkg_descr pps = fmap concat . sequenceA $ [ -- Library sources.@@ -166,20 +173,20 @@ signatures = sigs, libBuildInfo = libBi } ->- allSourcesBuildInfo verbosity libBi pps (modules ++ sigs)+ allSourcesBuildInfo verbosity rip cwd libBi pps (modules ++ sigs) -- Executables sources. , fmap concat . withAllExe $ \Executable { modulePath = mainPath, buildInfo = exeBi } -> do- biSrcs <- allSourcesBuildInfo verbosity exeBi pps []- mainSrc <- findMainExeFile verbosity exeBi pps mainPath+ biSrcs <- allSourcesBuildInfo verbosity rip cwd exeBi pps []+ mainSrc <- findMainExeFile verbosity cwd exeBi pps mainPath return (mainSrc:biSrcs) -- Foreign library sources , fmap concat . withAllFLib $ \flib@(ForeignLib { foreignLibBuildInfo = flibBi }) -> do- biSrcs <- allSourcesBuildInfo verbosity flibBi pps []- defFiles <- mapM (findModDefFile verbosity flibBi pps)+ biSrcs <- allSourcesBuildInfo verbosity rip cwd flibBi pps []+ defFiles <- traverse (findModDefFile verbosity cwd flibBi pps) (foreignLibModDefFile flib) return (defFiles ++ biSrcs) @@ -189,13 +196,13 @@ let bi = testBuildInfo t case testInterface t of TestSuiteExeV10 _ mainPath -> do- biSrcs <- allSourcesBuildInfo verbosity bi pps []- srcMainFile <- findMainExeFile verbosity bi pps mainPath+ biSrcs <- allSourcesBuildInfo verbosity rip cwd bi pps []+ srcMainFile <- findMainExeFile verbosity cwd bi pps mainPath return (srcMainFile:biSrcs) TestSuiteLibV09 _ m ->- allSourcesBuildInfo verbosity bi pps [m]+ allSourcesBuildInfo verbosity rip cwd bi pps [m] TestSuiteUnsupported tp ->- die' verbosity $ "Unsupported test suite type: " ++ show tp+ rip verbosity $ "Unsupported test suite type: " ++ show tp -- Benchmarks sources. , fmap concat@@ -203,11 +210,11 @@ let bi = benchmarkBuildInfo bm case benchmarkInterface bm of BenchmarkExeV10 _ mainPath -> do- biSrcs <- allSourcesBuildInfo verbosity bi pps []- srcMainFile <- findMainExeFile verbosity bi pps mainPath+ biSrcs <- allSourcesBuildInfo verbosity rip cwd bi pps []+ srcMainFile <- findMainExeFile verbosity cwd bi pps mainPath return (srcMainFile:biSrcs)- BenchmarkUnsupported tp -> die' verbosity $ "Unsupported benchmark type: "- ++ show tp+ BenchmarkUnsupported tp ->+ rip verbosity $ "Unsupported benchmark type: " ++ show tp -- Data files. , fmap concat@@ -216,13 +223,17 @@ srcDataDir = if null srcDataDirRaw then "." else srcDataDirRaw- in fmap (fmap (srcDataDir </>)) $+ in fmap (fmap (\p -> srcDataDir </> p)) $ matchDirFileGlob verbosity (specVersion pkg_descr) srcDataDir filename + -- Extra source files.+ , fmap concat . for (extraSrcFiles pkg_descr) $ \fpath ->+ matchDirFileGlob verbosity (specVersion pkg_descr) cwd fpath+ -- Extra doc files. , fmap concat . for (extraDocFiles pkg_descr) $ \ filename ->- matchDirFileGlob verbosity (specVersion pkg_descr) "." filename+ matchDirFileGlob verbosity (specVersion pkg_descr) cwd filename -- License file(s). , return (licenseFiles pkg_descr)@@ -233,13 +244,13 @@ let lbi = libBuildInfo l incls = filter (`notElem` autogenIncludes lbi) (installIncludes lbi) relincdirs = "." : filter isRelative (includeDirs lbi)- traverse (fmap snd . findIncludeFile verbosity relincdirs) incls+ traverse (fmap snd . findIncludeFile verbosity cwd relincdirs) incls -- Setup script, if it exists.- , fmap (maybe [] (\f -> [f])) $ findSetupFile ""+ , fmap (maybe [] (\f -> [f])) $ findSetupFile cwd -- The .cabal file itself.- , fmap (\d -> [d]) (defaultPackageDesc verbosity)+ , fmap (\d -> [d]) (tryFindPackageDescCwd verbosity cwd ".") ] where@@ -255,44 +266,32 @@ -- |Prepare a directory tree of source files. prepareTree :: Verbosity -- ^verbosity -> PackageDescription -- ^info from the cabal file- -> Maybe LocalBuildInfo -> FilePath -- ^source tree to populate -> [PPSuffixHandler] -- ^extra preprocessors (includes suffixes) -> IO ()-prepareTree verbosity pkg_descr0 mb_lbi targetDir pps = do- -- If the package was configured then we can run platform-independent- -- pre-processors and include those generated files.- case mb_lbi of- Just lbi | not (null pps) -> do- let lbi' = lbi{ buildDir = targetDir </> buildDir lbi }- withAllComponentsInBuildOrder pkg_descr lbi' $ \c clbi ->- preprocessComponent pkg_descr c lbi' clbi True verbosity pps- _ -> return ()-- (ordinary, mExecutable) <- listPackageSources verbosity pkg_descr0 pps- installOrdinaryFiles verbosity targetDir (zip (repeat []) ordinary)- installMaybeExecutableFiles verbosity targetDir (zip (repeat []) mExecutable)- maybeCreateDefaultSetupScript targetDir-+prepareTree verbosity pkg_descr0 targetDir pps = do+ ordinary <- listPackageSources verbosity "." pkg_descr pps+ installOrdinaryFiles verbosity targetDir (zip (repeat []) ordinary)+ maybeCreateDefaultSetupScript targetDir where pkg_descr = filterAutogenModules pkg_descr0 -- | Find the setup script file, if it exists.-findSetupFile :: FilePath -> NoCallStackIO (Maybe FilePath)+findSetupFile :: FilePath -> IO (Maybe FilePath) findSetupFile targetDir = do- hsExists <- doesFileExist setupHs- lhsExists <- doesFileExist setupLhs+ hsExists <- doesFileExist (targetDir </> setupHs)+ lhsExists <- doesFileExist (targetDir </> setupLhs) if hsExists then return (Just setupHs) else if lhsExists then return (Just setupLhs) else return Nothing where- setupHs = targetDir </> "Setup.hs"- setupLhs = targetDir </> "Setup.lhs"+ setupHs = "Setup.hs"+ setupLhs = "Setup.lhs" -- | Create a default setup script in the target directory, if it doesn't exist.-maybeCreateDefaultSetupScript :: FilePath -> NoCallStackIO ()+maybeCreateDefaultSetupScript :: FilePath -> IO () maybeCreateDefaultSetupScript targetDir = do mSetupFile <- findSetupFile targetDir case mSetupFile of@@ -304,31 +303,36 @@ -- | Find the main executable file. findMainExeFile- :: Verbosity -> BuildInfo -> [PPSuffixHandler] -> FilePath -> IO FilePath-findMainExeFile verbosity exeBi pps mainPath = do- ppFile <- findFileWithExtension (ppSuffixes pps) (hsSourceDirs exeBi)+ :: Verbosity+ -> FilePath -- ^ cwd+ -> BuildInfo+ -> [PPSuffixHandler]+ -> FilePath -- ^ main-is+ -> IO FilePath+findMainExeFile verbosity cwd exeBi pps mainPath = do+ ppFile <- findFileCwdWithExtension cwd (ppSuffixes pps) (hsSourceDirs exeBi) (dropExtension mainPath) case ppFile of- Nothing -> findFileEx verbosity (hsSourceDirs exeBi) mainPath+ Nothing -> findFileCwd verbosity cwd (hsSourceDirs exeBi) mainPath Just pp -> return pp -- | Find a module definition file -- -- TODO: I don't know if this is right findModDefFile- :: Verbosity -> BuildInfo -> [PPSuffixHandler] -> FilePath -> IO FilePath-findModDefFile verbosity flibBi _pps modDefPath =- findFileEx verbosity (".":hsSourceDirs flibBi) modDefPath+ :: Verbosity -> FilePath -> BuildInfo -> [PPSuffixHandler] -> FilePath -> IO FilePath+findModDefFile verbosity cwd flibBi _pps modDefPath =+ findFileCwd verbosity cwd (".":hsSourceDirs flibBi) modDefPath -- | Given a list of include paths, try to find the include file named -- @f@. Return the name of the file and the full path, or exit with error if -- there's no such file.-findIncludeFile :: Verbosity -> [FilePath] -> String -> IO (String, FilePath)-findIncludeFile verbosity [] f = die' verbosity ("can't find include file " ++ f)-findIncludeFile verbosity (d:ds) f = do+findIncludeFile :: Verbosity -> FilePath -> [FilePath] -> String -> IO (String, FilePath)+findIncludeFile verbosity _ [] f = die' verbosity ("can't find include file " ++ f)+findIncludeFile verbosity cwd (d:ds) f = do let path = (d </> f)- b <- doesFileExist path- if b then return (f,path) else findIncludeFile verbosity ds f+ b <- doesFileExist (cwd </> path)+ if b then return (f,path) else findIncludeFile verbosity cwd ds f -- | Remove the auto-generated modules (like 'Paths_*') from 'exposed-modules' -- and 'other-modules'.@@ -353,15 +357,14 @@ -- It is expected that the appropriate snapshot version has already been set -- in the package description, eg using 'snapshotPackage' or 'snapshotVersion'. ---prepareSnapshotTree :: Verbosity -- ^verbosity- -> PackageDescription -- ^info from the cabal file- -> Maybe LocalBuildInfo- -> FilePath -- ^source tree to populate- -> [PPSuffixHandler] -- ^extra preprocessors (includes- -- suffixes)- -> IO ()-prepareSnapshotTree verbosity pkg mb_lbi targetDir pps = do- prepareTree verbosity pkg mb_lbi targetDir pps+prepareSnapshotTree+ :: Verbosity -- ^verbosity+ -> PackageDescription -- ^info from the cabal file+ -> FilePath -- ^source tree to populate+ -> [PPSuffixHandler] -- ^extra preprocessors (includes suffixes)+ -> IO ()+prepareSnapshotTree verbosity pkg targetDir pps = do+ prepareTree verbosity pkg targetDir pps overwriteSnapshotPackageDesc verbosity pkg targetDir overwriteSnapshotPackageDesc :: Verbosity -- ^verbosity@@ -409,21 +412,16 @@ + month * 100 + day --- | Callback type for use by sdistWith.-type CreateArchiveFun = Verbosity -- ^verbosity- -> PackageDescription -- ^info from cabal file- -> Maybe LocalBuildInfo -- ^info from configure- -> FilePath -- ^source tree to archive- -> FilePath -- ^name of archive to create- -> IO FilePath- -- | Create an archive from a tree of source files, and clean up the tree.-createArchive :: CreateArchiveFun-createArchive verbosity pkg_descr mb_lbi tmpDir targetPref = do+createArchive+ :: Verbosity -- ^ verbosity+ -> PackageDescription -- ^ info from cabal file+ -> FilePath -- ^ source tree to archive+ -> FilePath -- ^ name of archive to create+ -> IO FilePath+createArchive verbosity pkg_descr tmpDir targetPref = do let tarBallFilePath = targetPref </> tarBallName pkg_descr <.> "tar.gz"-- (tarProg, _) <- requireProgram verbosity tarProgram- (maybe defaultProgramDb withPrograms mb_lbi)+ (tarProg, _) <- requireProgram verbosity tarProgram defaultProgramDb let formatOptSupported = maybe False (== "YES") $ Map.lookup "Supports --format" (programProperties tarProg)@@ -438,25 +436,28 @@ return tarBallFilePath -- | Given a buildinfo, return the names of all source files.-allSourcesBuildInfo :: Verbosity- -> BuildInfo- -> [PPSuffixHandler] -- ^ Extra preprocessors- -> [ModuleName] -- ^ Exposed modules- -> IO [FilePath]-allSourcesBuildInfo verbosity bi pps modules = do+allSourcesBuildInfo+ :: Verbosity+ -> (Verbosity -> String -> IO [FilePath])+ -> FilePath -- ^ cwd+ -> BuildInfo+ -> [PPSuffixHandler] -- ^ Extra preprocessors+ -> [ModuleName] -- ^ Exposed modules+ -> IO [FilePath]+allSourcesBuildInfo verbosity rip cwd bi pps modules = do let searchDirs = hsSourceDirs bi sources <- fmap concat $ sequenceA $ [ let file = ModuleName.toFilePath module_ -- NB: *Not* findFileWithExtension, because the same source -- file may show up in multiple paths due to a conditional; -- we need to package all of them. See #367.- in findAllFilesWithExtension suffixes searchDirs file+ in findAllFilesCwdWithExtension cwd suffixes searchDirs file >>= nonEmpty (notFound module_) return | module_ <- modules ++ otherModules bi ] bootFiles <- sequenceA [ let file = ModuleName.toFilePath module_ fileExts = ["hs-boot", "lhs-boot"]- in findFileWithExtension fileExts (hsSourceDirs bi) file+ in findFileCwdWithExtension cwd fileExts (hsSourceDirs bi) file | module_ <- modules ++ otherModules bi ] return $ sources ++ catMaybes bootFiles ++ cSources bi ++ cxxSources bi ++@@ -466,7 +467,9 @@ nonEmpty x _ [] = x nonEmpty _ f xs = f xs suffixes = ppSuffixes pps ++ ["hs", "lhs", "hsig", "lhsig"]- notFound m = die' verbosity $ "Error: Could not find module: " ++ prettyShow m++ notFound :: ModuleName -> IO [FilePath]+ notFound m = rip verbosity $ "Error: Could not find module: " ++ prettyShow m ++ " with any suffix: " ++ show suffixes ++ ". If the module " ++ "is autogenerated it should be added to 'autogen-modules'."
cabal/Cabal/Distribution/Simple/Test.hs view
@@ -40,7 +40,6 @@ import System.Directory ( createDirectoryIfMissing, doesFileExist, getDirectoryContents , removeFile )-import System.Exit ( exitFailure, exitSuccess ) import System.FilePath ( (</>) ) -- |Perform the \"@.\/setup test@\" action.
cabal/Cabal/Distribution/Simple/Test/ExeV10.hs view
@@ -27,14 +27,14 @@ import Distribution.Pretty import Distribution.Verbosity -import Control.Concurrent (forkIO) import System.Directory ( createDirectoryIfMissing, doesDirectoryExist, doesFileExist , getCurrentDirectory, removeDirectoryRecursive )-import System.Exit ( ExitCode(..) ) import System.FilePath ( (</>), (<.>) )-import System.IO ( hGetContents, stdout, stderr )+import System.IO ( stdout, stderr ) +import qualified Data.ByteString.Lazy as LBS+ runTest :: PD.PackageDescription -> LBI.LocalBuildInfo -> LBI.ComponentLocalBuildInfo@@ -67,21 +67,7 @@ -- Write summary notices indicating start of test suite notice verbosity $ summarizeSuiteStart $ testName' - (wOut, wErr, logText) <- case details of- Direct -> return (stdout, stderr, "")- _ -> do- (rOut, wOut) <- createPipe - -- Read test executable's output lazily (returns immediately)- logText <- hGetContents rOut- -- Force the IO manager to drain the test output pipe- void $ forkIO $ length logText `seq` return ()-- -- '--show-details=streaming': print the log output in another thread- when (details == Streaming) $ void $ forkIO $ putStr logText-- return (wOut, wOut, logText)- -- Run the test executable let opts = map (testOption pkg_descr lbi suite) (testOptions flags)@@ -98,15 +84,35 @@ return (addLibraryPath os paths shellEnv) else return shellEnv - exit <- case testWrapper flags of- Flag path -> rawSystemIOWithEnv verbosity path (cmd:opts) Nothing (Just shellEnv')- -- these handles are automatically closed- Nothing (Just wOut) (Just wErr)+ -- Output logger+ (wOut, wErr, getLogText) <- case details of+ Direct -> return (stdout, stderr, return LBS.empty)+ _ -> do+ (rOut, wOut) <- createPipe - NoFlag -> rawSystemIOWithEnv verbosity cmd opts Nothing (Just shellEnv')- -- these handles are automatically closed- Nothing (Just wOut) (Just wErr)+ return $ (,,) wOut wOut $ do+ -- Read test executables' output+ logText <- LBS.hGetContents rOut + -- '--show-details=streaming': print the log output in another thread+ when (details == Streaming) $ LBS.putStr logText++ -- drain the output.+ evaluate (force logText)++ (exit, logText) <- case testWrapper flags of+ Flag path -> rawSystemIOWithEnvAndAction+ verbosity path (cmd:opts) Nothing (Just shellEnv')+ getLogText+ -- these handles are automatically closed+ Nothing (Just wOut) (Just wErr)++ NoFlag -> rawSystemIOWithEnvAndAction+ verbosity cmd opts Nothing (Just shellEnv')+ getLogText+ -- these handles are automatically closed+ Nothing (Just wOut) (Just wErr)+ -- Generate TestSuiteLog from executable exit code and a machine- -- readable test log. let suiteLog = buildLog exit@@ -116,7 +122,7 @@ -- Append contents of temporary log file to the final human- -- readable log file- appendFile (logFile suiteLog) logText+ LBS.appendFile (logFile suiteLog) logText -- Write end-of-suite summary notice to log file appendFile (logFile suiteLog) $ summarizeSuiteFinish suiteLog@@ -128,7 +134,9 @@ details == Failures && not (suitePassed $ testLogs suiteLog)) -- verbosity overrides show-details && verbosity >= normal- whenPrinting $ putStr $ unlines $ lines logText+ whenPrinting $ do+ LBS.putStr logText+ putChar '\n' -- Write summary notice to terminal indicating end of test suite notice verbosity $ summarizeSuiteFinish suiteLog
cabal/Cabal/Distribution/Simple/Test/LibV09.hs view
@@ -34,14 +34,14 @@ import Distribution.Verbosity import qualified Control.Exception as CE+import qualified Data.ByteString.Lazy as LBS import System.Directory ( createDirectoryIfMissing, canonicalizePath , doesDirectoryExist, doesFileExist , getCurrentDirectory, removeDirectoryRecursive, removeFile , setCurrentDirectory )-import System.Exit ( exitSuccess, exitWith, ExitCode(..) ) import System.FilePath ( (</>), (<.>) )-import System.IO ( hClose, hGetContents, hPutStr )+import System.IO ( hClose, hPutStr ) import System.Process (StdStream(..), waitForProcess) runTest :: PD.PackageDescription@@ -79,6 +79,8 @@ suiteLog <- CE.bracket openCabalTemp deleteIfExists $ \tempLog -> do + -- TODO: this setup is broken,+ -- if the test output is too big, we will deadlock. (rOut, wOut) <- createPipe -- Run test executable@@ -113,9 +115,9 @@ -- Append contents of temporary log file to the final human- -- readable log file- logText <- hGetContents rOut+ logText <- LBS.hGetContents rOut -- Force the IO manager to drain the test output pipe- length logText `seq` return ()+ _ <- evaluate (force logText) exitcode <- waitForProcess process unless (exitcode == ExitSuccess) $ do@@ -135,7 +137,7 @@ -- Write summary notice to log file indicating start of test suite appendFile (logFile suiteLog) $ summarizeSuiteStart testName' - appendFile (logFile suiteLog) logText+ LBS.appendFile (logFile suiteLog) logText -- Write end-of-suite summary notice to log file appendFile (logFile suiteLog) $ summarizeSuiteFinish suiteLog@@ -146,7 +148,9 @@ whenPrinting = when $ (details > Never) && (not (suitePassed $ testLogs suiteLog) || details == Always) && verbosity >= normal- whenPrinting $ putStr $ unlines $ lines logText+ whenPrinting $ do+ LBS.putStr logText+ putChar '\n' return suiteLog @@ -159,7 +163,7 @@ return suiteLog where testName' = unUnqualComponentName $ PD.testName suite- + deleteIfExists file = do exists <- doesFileExist file when exists $ removeFile file@@ -203,11 +207,13 @@ -- is being created -> FilePath -- ^ path to directory where stub source -- should be located- -> NoCallStackIO ()+ -> IO () writeSimpleTestStub t dir = do createDirectoryIfMissing True dir let filename = dir </> stubFilePath t- PD.TestSuiteLibV09 _ m = PD.testInterface t+ m = case PD.testInterface t of+ PD.TestSuiteLibV09 _ m' -> m'+ _ -> error "writeSimpleTestStub: invalid TestSuite passed" writeFile filename $ simpleTestStub m -- | Source code for library test suite stub executable@@ -231,7 +237,7 @@ setCurrentDirectory dir stubWriteLog f n results where- errHandler :: CE.SomeException -> NoCallStackIO TestLogs+ errHandler :: CE.SomeException -> IO TestLogs errHandler e = case CE.fromException e of Just CE.UserInterrupt -> CE.throwIO e _ -> return $ TestLog { testName = "Cabal test suite exception",@@ -272,7 +278,7 @@ -- | From a test stub, write the 'TestSuiteLog' to temporary file for the calling -- Cabal process to read.-stubWriteLog :: FilePath -> UnqualComponentName -> TestLogs -> NoCallStackIO ()+stubWriteLog :: FilePath -> UnqualComponentName -> TestLogs -> IO () stubWriteLog f n logs = do let testLog = TestSuiteLog { testSuiteName = n, testLogs = logs, logFile = f } writeFile (logFile testLog) $ show testLog
cabal/Cabal/Distribution/Simple/Test/Log.hs view
@@ -143,7 +143,7 @@ where addTriple (p1, f1, e1) (p2, f2, e2) = (p1 + p2, f1 + f2, e1 + e2) --- | Print a summary of a single test case's result to the console, supressing+-- | Print a summary of a single test case's result to the console, suppressing -- output for certain verbosity or test filter levels. summarizeTest :: Verbosity -> TestShowDetails -> TestLogs -> IO () summarizeTest _ _ (GroupLogs {}) = return ()
cabal/Cabal/Distribution/Simple/UHC.hs view
@@ -29,7 +29,7 @@ import Distribution.Package hiding (installedUnitId) import Distribution.PackageDescription import Distribution.Simple.BuildPaths-import Distribution.Simple.Compiler as C+import Distribution.Simple.Compiler import Distribution.Simple.LocalBuildInfo import Distribution.Simple.PackageIndex import Distribution.Simple.Program@@ -60,7 +60,7 @@ let comp = Compiler { compilerId = CompilerId UHC uhcVersion,- compilerAbiTag = C.NoAbiTag,+ compilerAbiTag = NoAbiTag, compilerCompat = [], compilerLanguages = uhcLanguages, compilerExtensions = uhcLanguageExtensions,@@ -69,11 +69,11 @@ compPlatform = Nothing return (comp, compPlatform, progdb') -uhcLanguages :: [(Language, C.Flag)]+uhcLanguages :: [(Language, CompilerFlag)] uhcLanguages = [(Haskell98, "")] -- | The flags for the supported extensions.-uhcLanguageExtensions :: [(Extension, Maybe C.Flag)]+uhcLanguageExtensions :: [(Extension, Maybe CompilerFlag)] uhcLanguageExtensions = let doFlag (f, (enable, disable)) = [(EnableExtension f, enable), (DisableExtension f, disable)]@@ -116,11 +116,13 @@ getGlobalPackageDir verbosity progdb = do output <- getDbProgramOutput verbosity uhcProgram progdb ["--meta-pkgdir-system"]- -- call to "lines" necessary, because pkgdir contains an extra newline at the end- let [pkgdir] = lines output+ -- we need to trim because pkgdir contains an extra newline at the end+ let pkgdir = trimEnd output return pkgdir+ where+ trimEnd = reverse . dropWhile isSpace . reverse -getUserPackageDir :: NoCallStackIO FilePath+getUserPackageDir :: IO FilePath getUserPackageDir = do homeDir <- getHomeDirectory return $ homeDir </> ".cabal" </> "lib" -- TODO: determine in some other way@@ -149,7 +151,7 @@ -- | Check if a certain dir contains a valid package. Currently, we are -- looking only for the presence of an installed package configuration. -- TODO: Actually make use of the information provided in the file.-isPkgDir :: String -> String -> String -> NoCallStackIO Bool+isPkgDir :: String -> String -> String -> IO Bool isPkgDir _ _ ('.' : _) = return False -- ignore files starting with a . isPkgDir c dir xs = do let candidate = dir </> uhcPackageDir xs c
cabal/Cabal/Distribution/Simple/Utils.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE CPP #-}+{-# LANGUAGE GADTs #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE RankNTypes #-}@@ -50,6 +51,7 @@ rawSystemStdout, rawSystemStdInOut, rawSystemIOWithEnv,+ rawSystemIOWithEnvAndAction, createProcessWithEnv, maybeExit, xargs,@@ -61,7 +63,8 @@ -- "Distribution.Utils.IOData" for convience as they're -- exposed in the API of 'rawSystemStdInOut' IOData(..),- IODataMode(..),+ KnownIODataMode (..),+ IODataMode (..), -- * copying files createDirectoryIfMissingVerbose,@@ -92,10 +95,13 @@ -- * finding files findFileEx,+ findFileCwd, findFirstFile, findFileWithExtension,+ findFileCwdWithExtension, findFileWithExtension', findAllFilesWithExtension,+ findAllFilesCwdWithExtension, findModuleFileEx, findModuleFilesEx, getDirectoryContentsRecursive,@@ -117,13 +123,16 @@ -- * .cabal and .buildinfo files defaultPackageDesc, findPackageDesc,+ findPackageDescCwd, tryFindPackageDesc,+ tryFindPackageDescCwd, findHookedPackageDesc, -- * reading and writing files safely withFileContents, writeFileAtomic, rewriteFileEx,+ rewriteFileLBS, -- * Unicode fromUTF8BS,@@ -153,6 +162,8 @@ ordNubRight, safeHead, safeTail,+ safeLast,+ safeInit, unintersperse, wrapText, wrapLine,@@ -169,10 +180,9 @@ import Prelude () import Distribution.Compat.Prelude-import Control.Exception (SomeException) import Distribution.Utils.Generic-import Distribution.Utils.IOData (IOData(..), IODataMode(..))+import Distribution.Utils.IOData (IOData(..), IODataMode (..), KnownIODataMode (..)) import qualified Distribution.Utils.IOData as IOData import Distribution.ModuleName as ModuleName import Distribution.System@@ -180,7 +190,6 @@ import Distribution.Compat.Async import Distribution.Compat.CopyFile import Distribution.Compat.Internal.TempFile-import Distribution.Compat.Exception import Distribution.Compat.FilePath as FilePath import Distribution.Compat.Stack import Distribution.Verbosity@@ -213,28 +222,27 @@ , getModificationTime, createDirectory, removeDirectoryRecursive ) import System.Environment ( getProgName )-import System.Exit- ( exitWith, ExitCode(..) ) import System.FilePath as FilePath ( normalise, (</>), (<.>) , getSearchPath, joinPath, takeDirectory, splitExtension , splitDirectories, searchPathSeparator ) import System.IO ( Handle, hSetBinaryMode, hGetContents, stderr, stdout, hPutStr, hFlush- , hClose, hSetBuffering, BufferMode(..) )+ , hClose, hSetBuffering, BufferMode(..), hPutStrLn ) import System.IO.Error import System.IO.Unsafe ( unsafeInterleaveIO ) import qualified Control.Exception as Exception +import Foreign.C.Error (Errno (..), ePIPE) import Data.Time.Clock.POSIX (getPOSIXTime, POSIXTime)-import Control.Exception (IOException, evaluate, throwIO, fromException) import Numeric (showFFloat)-import qualified System.Process as Process- ( CreateProcess(..), StdStream(..), proc)+import Distribution.Compat.Process (createProcess, rawSystem, runInteractiveProcess) import System.Process- ( ProcessHandle, createProcess, rawSystem, runInteractiveProcess+ ( ProcessHandle , showCommandForUser, waitForProcess)+import qualified System.Process as Process+import qualified GHC.IO.Exception as GHC import qualified Text.PrettyPrint as Disp @@ -245,7 +253,7 @@ #elif defined(CABAL_VERSION) cabalVersion = mkVersion [CABAL_VERSION] #else-cabalVersion = mkVersion [1,9999] --used when bootstrapping+cabalVersion = mkVersion [3,0] --used when bootstrapping #endif -- ----------------------------------------------------------------------------@@ -378,15 +386,15 @@ ] where -- Let async exceptions rise to the top for the default top-handler- rethrowAsyncExceptions :: Exception.AsyncException -> NoCallStackIO a+ rethrowAsyncExceptions :: Exception.AsyncException -> IO a rethrowAsyncExceptions a = throwIO a -- ExitCode gets thrown asynchronously too, and we don't want to print it- rethrowExitStatus :: ExitCode -> NoCallStackIO a+ rethrowExitStatus :: ExitCode -> IO a rethrowExitStatus = throwIO -- Print all other exceptions- handle :: Exception.SomeException -> NoCallStackIO a+ handle :: Exception.SomeException -> IO a handle se = do hFlush stdout pname <- getProgName@@ -424,6 +432,11 @@ topHandler :: IO a -> IO a topHandler prog = topHandlerWith (const $ exitWith (ExitFailure 1)) prog +verbosityHandle :: Verbosity -> Handle+verbosityHandle verbosity+ | isVerboseStderr verbosity = stderr+ | otherwise = stdout+ -- | Non fatal conditions that may be indicative of an error or problem. -- -- We display these at the 'normal' verbosity level.@@ -447,10 +460,12 @@ notice :: Verbosity -> String -> IO () notice verbosity msg = withFrozenCallStack $ do when (verbosity >= normal) $ do+ let h = verbosityHandle verbosity ts <- getPOSIXTime- hPutStr stdout . withMetadata ts NormalMark FlagTrace verbosity- . wrapTextVerbosity verbosity- $ msg+ hPutStr h+ $ withMetadata ts NormalMark FlagTrace verbosity+ $ wrapTextVerbosity verbosity+ $ msg -- | Display a message at 'normal' verbosity level, but without -- wrapping.@@ -458,8 +473,9 @@ noticeNoWrap :: Verbosity -> String -> IO () noticeNoWrap verbosity msg = withFrozenCallStack $ do when (verbosity >= normal) $ do+ let h = verbosityHandle verbosity ts <- getPOSIXTime- hPutStr stdout . withMetadata ts NormalMark FlagTrace verbosity $ msg+ hPutStr h . withMetadata ts NormalMark FlagTrace verbosity $ msg -- | Pretty-print a 'Disp.Doc' status message at 'normal' verbosity -- level. Use this if you need fancy formatting.@@ -467,9 +483,12 @@ noticeDoc :: Verbosity -> Disp.Doc -> IO () noticeDoc verbosity msg = withFrozenCallStack $ do when (verbosity >= normal) $ do+ let h = verbosityHandle verbosity ts <- getPOSIXTime- hPutStr stdout . withMetadata ts NormalMark FlagTrace verbosity- . Disp.renderStyle defaultStyle $ msg+ hPutStr h+ $ withMetadata ts NormalMark FlagTrace verbosity+ $ Disp.renderStyle defaultStyle+ $ msg -- | Display a "setup status message". Prefer using setupMessage' -- if possible.@@ -485,17 +504,21 @@ info :: Verbosity -> String -> IO () info verbosity msg = withFrozenCallStack $ when (verbosity >= verbose) $ do+ let h = verbosityHandle verbosity ts <- getPOSIXTime- hPutStr stdout . withMetadata ts NeverMark FlagTrace verbosity- . wrapTextVerbosity verbosity- $ msg+ hPutStr h+ $ withMetadata ts NeverMark FlagTrace verbosity+ $ wrapTextVerbosity verbosity+ $ msg infoNoWrap :: Verbosity -> String -> IO () infoNoWrap verbosity msg = withFrozenCallStack $ when (verbosity >= verbose) $ do+ let h = verbosityHandle verbosity ts <- getPOSIXTime- hPutStr stdout . withMetadata ts NeverMark FlagTrace verbosity- $ msg+ hPutStr h+ $ withMetadata ts NeverMark FlagTrace verbosity+ $ msg -- | Detailed internal debugging information --@@ -504,10 +527,11 @@ debug :: Verbosity -> String -> IO () debug verbosity msg = withFrozenCallStack $ when (verbosity >= deafening) $ do+ let h = verbosityHandle verbosity ts <- getPOSIXTime- hPutStr stdout . withMetadata ts NeverMark FlagTrace verbosity- . wrapTextVerbosity verbosity- $ msg+ hPutStr h $ withMetadata ts NeverMark FlagTrace verbosity+ $ wrapTextVerbosity verbosity+ $ msg -- ensure that we don't lose output if we segfault/infinite loop hFlush stdout @@ -516,9 +540,11 @@ debugNoWrap :: Verbosity -> String -> IO () debugNoWrap verbosity msg = withFrozenCallStack $ when (verbosity >= deafening) $ do+ let h = verbosityHandle verbosity ts <- getPOSIXTime- hPutStr stdout . withMetadata ts NeverMark FlagTrace verbosity- $ msg+ hPutStr h+ $ withMetadata ts NeverMark FlagTrace verbosity+ $ msg -- ensure that we don't lose output if we segfault/infinite loop hFlush stdout @@ -529,11 +555,11 @@ -> IO () chattyTry desc action = catchIO action $ \exception ->- putStrLn $ "Error while " ++ desc ++ ": " ++ show exception+ hPutStrLn stderr $ "Error while " ++ desc ++ ": " ++ show exception -- | Run an IO computation, returning @e@ if it raises a "file -- does not exist" error.-handleDoesNotExist :: a -> NoCallStackIO a -> NoCallStackIO a+handleDoesNotExist :: a -> IO a -> IO a handleDoesNotExist e = Exception.handleJust (\ioe -> if isDoesNotExistError ioe then Just ioe else Nothing)@@ -675,6 +701,8 @@ res <- cmd unless (res == ExitSuccess) $ exitWith res ++ printRawCommandAndArgs :: Verbosity -> FilePath -> [String] -> IO () printRawCommandAndArgs verbosity path args = withFrozenCallStack $ printRawCommandAndArgsAndEnv verbosity path args Nothing Nothing@@ -757,6 +785,29 @@ mbToStd :: Maybe Handle -> Process.StdStream mbToStd = maybe Process.Inherit Process.UseHandle +rawSystemIOWithEnvAndAction+ :: Verbosity+ -> FilePath+ -> [String]+ -> Maybe FilePath -- ^ New working dir or inherit+ -> Maybe [(String, String)] -- ^ New environment or inherit+ -> IO a -- ^ action to perform after process is created, but before 'waitForProcess'.+ -> Maybe Handle -- ^ stdin+ -> Maybe Handle -- ^ stdout+ -> Maybe Handle -- ^ stderr+ -> IO (ExitCode, a)+rawSystemIOWithEnvAndAction verbosity path args mcwd menv action inp out err = withFrozenCallStack $ do+ (_,_,_,ph) <- createProcessWithEnv verbosity path args mcwd menv+ (mbToStd inp) (mbToStd out) (mbToStd err)+ a <- action+ exitcode <- waitForProcess ph+ unless (exitcode == ExitSuccess) $ do+ debug verbosity $ path ++ " returned " ++ show exitcode+ return (exitcode, a)+ where+ mbToStd :: Maybe Handle -> Process.StdStream+ mbToStd = maybe Process.Inherit Process.UseHandle+ createProcessWithEnv :: Verbosity -> FilePath@@ -793,11 +844,10 @@ -- -- The output is assumed to be text in the locale encoding. ---rawSystemStdout :: Verbosity -> FilePath -> [String] -> IO String+rawSystemStdout :: forall mode. KnownIODataMode mode => Verbosity -> FilePath -> [String] -> IO mode rawSystemStdout verbosity path args = withFrozenCallStack $ do- (IODataText output, errors, exitCode) <- rawSystemStdInOut verbosity path args- Nothing Nothing- Nothing IODataModeText+ (output, errors, exitCode) <- rawSystemStdInOut verbosity path args+ Nothing Nothing Nothing (IOData.iodataMode :: IODataMode mode) when (exitCode /= ExitSuccess) $ die' verbosity errors return output@@ -806,15 +856,16 @@ -- also supply some input. Also provides control over whether the binary/text -- mode of the input and output. ---rawSystemStdInOut :: Verbosity+rawSystemStdInOut :: KnownIODataMode mode+ => Verbosity -> FilePath -- ^ Program location -> [String] -- ^ Arguments -> Maybe FilePath -- ^ New working dir or inherit -> Maybe [(String, String)] -- ^ New environment or inherit -> Maybe IOData -- ^ input text and binary mode- -> IODataMode -- ^ output in binary mode- -> IO (IOData, String, ExitCode) -- ^ output, errors, exit-rawSystemStdInOut verbosity path args mcwd menv input outputMode = withFrozenCallStack $ do+ -> IODataMode mode -- ^ iodata mode, acts as proxy+ -> IO (mode, String, ExitCode) -- ^ output, errors, exit+rawSystemStdInOut verbosity path args mcwd menv input _ = withFrozenCallStack $ do printRawCommandAndArgs verbosity path args Exception.bracket@@ -829,16 +880,11 @@ -- fork off a couple threads to pull on the stderr and stdout -- so if the process writes to stderr we do not block. - withAsyncNF (hGetContents errh) $ \errA -> withAsyncNF (IOData.hGetContents outh outputMode) $ \outA -> do+ withAsyncNF (hGetContents errh) $ \errA -> withAsyncNF (IOData.hGetIODataContents outh) $ \outA -> do -- push all the input, if any- case input of- Nothing -> return ()- Just inputData -> do- -- input mode depends on what the caller wants- -- todo: ignoreSigPipe- IOData.hPutContents inh inputData- --TODO: this probably fails if the process refuses to consume- -- or if it closes stdin (eg if it exits)+ ignoreSigPipe $ case input of+ Nothing -> hClose inh+ Just inputData -> IOData.hPutContents inh inputData -- wait for both to finish mberr1 <- waitCatch outA@@ -856,22 +902,28 @@ " with error message:\n" ++ err ++ case input of Nothing -> ""- Just d | IOData.null d -> ""- Just (IODataText inp) -> "\nstdin input:\n" ++ inp+ Just d | IOData.null d -> ""+ Just (IODataText inp) -> "\nstdin input:\n" ++ inp Just (IODataBinary inp) -> "\nstdin input (binary):\n" ++ show inp - -- Check if we we hit an exception while consuming the output+ -- Check if we hit an exception while consuming the output -- (e.g. a text decoding error) out <- reportOutputIOError mberr1 return (out, err, exitcode) where- reportOutputIOError :: Either SomeException a -> NoCallStackIO a+ reportOutputIOError :: Either Exception.SomeException a -> IO a reportOutputIOError (Right x) = return x reportOutputIOError (Left exc) = case fromException exc of Just ioe -> throwIO (ioeSetFileName ioe ("output of " ++ path)) Nothing -> throwIO exc + ignoreSigPipe :: IO () -> IO ()+ ignoreSigPipe = Exception.handle $ \e -> case e of+ GHC.IOError { GHC.ioe_type = GHC.ResourceVanished, GHC.ioe_errno = Just ioe }+ | Errno ioe == ePIPE -> return ()+ _ -> throwIO e+ -- | Look for a program and try to find it's version number. It can accept -- either an absolute path or the name of a program binary, in which case we -- will look for the program on the path.@@ -936,6 +988,21 @@ -- | Find a file by looking in a search path. The file path must match exactly. --+-- @since 3.4.0.0+findFileCwd+ :: Verbosity+ -> FilePath -- ^ cwd+ -> [FilePath] -- ^ relative search location+ -> FilePath -- ^ File Name+ -> IO FilePath+findFileCwd verbosity cwd searchPath fileName =+ findFirstFile (cwd </>)+ [ path </> fileName+ | path <- nub searchPath]+ >>= maybe (die' verbosity $ fileName ++ " doesn't exist") return++-- | Find a file by looking in a search path. The file path must match exactly.+-- findFileEx :: Verbosity -> [FilePath] -- ^search locations -> FilePath -- ^File Name@@ -953,17 +1020,43 @@ findFileWithExtension :: [String] -> [FilePath] -> FilePath- -> NoCallStackIO (Maybe FilePath)+ -> IO (Maybe FilePath) findFileWithExtension extensions searchPath baseName = findFirstFile id [ path </> baseName <.> ext | path <- nub searchPath , ext <- nub extensions ] +-- | @since 3.4.0.0+findFileCwdWithExtension+ :: FilePath+ -> [String]+ -> [FilePath]+ -> FilePath+ -> IO (Maybe FilePath)+findFileCwdWithExtension cwd extensions searchPath baseName =+ findFirstFile (cwd </>)+ [ path </> baseName <.> ext+ | path <- nub searchPath+ , ext <- nub extensions ]++-- | @since 3.4.0.0+findAllFilesCwdWithExtension+ :: FilePath -- ^ cwd+ -> [String] -- ^ extensions+ -> [FilePath] -- ^ relative search locations+ -> FilePath -- ^ basename+ -> IO [FilePath]+findAllFilesCwdWithExtension cwd extensions searchPath basename =+ findAllFiles (cwd </>)+ [ path </> basename <.> ext+ | path <- nub searchPath+ , ext <- nub extensions ]+ findAllFilesWithExtension :: [String] -> [FilePath] -> FilePath- -> NoCallStackIO [FilePath]+ -> IO [FilePath] findAllFilesWithExtension extensions searchPath basename = findAllFiles id [ path </> basename <.> ext@@ -976,14 +1069,14 @@ findFileWithExtension' :: [String] -> [FilePath] -> FilePath- -> NoCallStackIO (Maybe (FilePath, FilePath))+ -> IO (Maybe (FilePath, FilePath)) findFileWithExtension' extensions searchPath baseName = findFirstFile (uncurry (</>)) [ (path, baseName <.> ext) | path <- nub searchPath , ext <- nub extensions ] -findFirstFile :: (a -> FilePath) -> [a] -> NoCallStackIO (Maybe a)+findFirstFile :: (a -> FilePath) -> [a] -> IO (Maybe a) findFirstFile file = findFirst where findFirst [] = return Nothing findFirst (x:xs) = do exists <- doesFileExist (file x)@@ -991,7 +1084,7 @@ then return (Just x) else findFirst xs -findAllFiles :: (a -> FilePath) -> [a] -> NoCallStackIO [a]+findAllFiles :: (a -> FilePath) -> [a] -> IO [a] findAllFiles file = filterM (doesFileExist . file) @@ -1077,7 +1170,7 @@ -- Environment variables -- | Is this directory in the system search path?-isInSearchPath :: FilePath -> NoCallStackIO Bool+isInSearchPath :: FilePath -> IO Bool isInSearchPath path = fmap (elem path) getSearchPath addLibraryPath :: OS@@ -1107,7 +1200,7 @@ -- The expected use case is when the second file is generated using the first. -- In this use case, if the result is True then the second file is out of date. ---moreRecentFile :: FilePath -> FilePath -> NoCallStackIO Bool+moreRecentFile :: FilePath -> FilePath -> IO Bool moreRecentFile a b = do exists <- doesFileExist b if not exists@@ -1117,7 +1210,7 @@ return (ta > tb) -- | Like 'moreRecentFile', but also checks that the first file exists.-existsAndIsMoreRecentThan :: FilePath -> FilePath -> NoCallStackIO Bool+existsAndIsMoreRecentThan :: FilePath -> FilePath -> IO Bool existsAndIsMoreRecentThan a b = do exists <- doesFileExist a if not exists@@ -1295,7 +1388,7 @@ -- File permissions -- | Like 'doesFileExist', but also checks that the file is executable.-doesExecutableExist :: FilePath -> NoCallStackIO Bool+doesExecutableExist :: FilePath -> IO Bool doesExecutableExist f = do exists <- doesFileExist f if exists@@ -1334,7 +1427,7 @@ (\(name, handle) -> do hClose handle unless (optKeepTempFiles opts) $ handleDoesNotExist () . removeFile $ name)- (withLexicalCallStack (uncurry action))+ (withLexicalCallStack (\x -> uncurry action x)) -- | Create and use a temporary directory. --@@ -1349,7 +1442,7 @@ withTempDirectory :: Verbosity -> FilePath -> String -> (FilePath -> IO a) -> IO a withTempDirectory verbosity targetDir template f = withFrozenCallStack $ withTempDirectoryEx verbosity defaultTempFileOptions targetDir template- (withLexicalCallStack f)+ (withLexicalCallStack (\x -> f x)) -- | A version of 'withTempDirectory' that additionally takes a -- 'TempFileOptions' argument.@@ -1360,7 +1453,7 @@ (createTempDirectory targetDir template) (unless (optKeepTempFiles opts) . handleDoesNotExist () . removeDirectoryRecursive)- (withLexicalCallStack f)+ (withLexicalCallStack (\x -> f x)) ----------------------------------- -- Safely reading and writing files@@ -1373,21 +1466,25 @@ -- ASCII-representable. Since Cabal-3.0 the file is assumed to be -- UTF-8 encoded. rewriteFileEx :: Verbosity -> FilePath -> String -> IO ()-rewriteFileEx verbosity path newContent =+rewriteFileEx verbosity path =+ rewriteFileLBS verbosity path . toUTF8LBS++-- | Same as `rewriteFileEx` but for 'ByteString's.+rewriteFileLBS :: Verbosity -> FilePath -> BS.ByteString -> IO ()+rewriteFileLBS verbosity path newContent = flip catchIO mightNotExist $ do existingContent <- annotateIO verbosity $ BS.readFile path _ <- evaluate (BS.length existingContent)- unless (existingContent == newContent') $+ unless (existingContent == newContent) $ annotateIO verbosity $- writeFileAtomic path newContent'+ writeFileAtomic path newContent where- newContent' = toUTF8LBS newContent- mightNotExist e | isDoesNotExistError e- = annotateIO verbosity $ writeFileAtomic path newContent'+ = annotateIO verbosity $ writeFileAtomic path newContent | otherwise = ioError e + -- | The path name that represents the current directory. -- In Unix, it's @\".\"@, but this is system-specific. -- (E.g. AmigaOS uses the empty string @\"\"@ for the current directory.)@@ -1447,17 +1544,24 @@ -- |Find a package description file in the given directory. Looks for -- @.cabal@ files. findPackageDesc :: FilePath -- ^Where to look- -> NoCallStackIO (Either String FilePath) -- ^<pkgname>.cabal-findPackageDesc dir- = do files <- getDirectoryContents dir+ -> IO (Either String FilePath) -- ^<pkgname>.cabal+findPackageDesc = findPackageDescCwd "."++-- | @since 3.4.0.0+findPackageDescCwd+ :: FilePath -- ^ project root+ -> FilePath -- ^ relative directory+ -> IO (Either String FilePath) -- ^ <pkgname>.cabal relative to the project root+findPackageDescCwd cwd dir+ = do files <- getDirectoryContents (cwd </> dir) -- to make sure we do not mistake a ~/.cabal/ dir for a <pkgname>.cabal -- file we filter to exclude dirs and null base file names:- cabalFiles <- filterM doesFileExist- [ dir </> file+ cabalFiles <- filterM (doesFileExist . snd)+ [ (dir </> file, cwd </> dir </> file) | file <- files , let (name, ext) = splitExtension file , not (null name) && ext == ".cabal" ]- case cabalFiles of+ case map fst cabalFiles of [] -> return (Left noDesc) [cabalFile] -> return (Right cabalFile) multiple -> return (Left $ multiDesc multiple)@@ -1476,6 +1580,13 @@ tryFindPackageDesc :: Verbosity -> FilePath -> IO FilePath tryFindPackageDesc verbosity dir = either (die' verbosity) return =<< findPackageDesc dir++-- | Like 'findPackageDescCwd', but calls 'die' in case of error.+--+-- @since 3.4.0.0+tryFindPackageDescCwd :: Verbosity -> FilePath -> FilePath -> IO FilePath+tryFindPackageDescCwd verbosity cwd dir =+ either (die' verbosity) return =<< findPackageDescCwd cwd dir -- |Find auxiliary package information in the given directory. -- Looks for @.buildinfo@ files.
cabal/Cabal/Distribution/System.hs view
@@ -60,7 +60,7 @@ -- are two situations where we need to do it. -- -- For parsing OS and arch names in .cabal files we really want everyone to be--- referring to the same or or arch by the same name. Variety is not a virtue+-- referring to the same or arch by the same name. Variety is not a virtue -- in this case. We don't mind about case though. -- -- For the System.Info.os\/arch different Haskell implementations use different@@ -101,7 +101,7 @@ deriving (Eq, Generic, Ord, Show, Read, Typeable, Data) instance Binary OS-+instance Structured OS instance NFData OS where rnf = genericRnf knownOSs :: [OS]@@ -122,7 +122,8 @@ osAliases Compat FreeBSD = ["kfreebsdgnu"] osAliases Permissive Solaris = ["solaris2"] osAliases Compat Solaris = ["solaris2"]-osAliases _ Android = ["linux-android"]+osAliases Permissive Android = ["linux-android", "linux-androideabi", "linux-androideabihf"]+osAliases Compat Android = ["linux-android"] osAliases _ _ = [] instance Pretty OS where@@ -132,6 +133,8 @@ instance Parsec OS where parsec = classifyOS Compat <$> parsecIdent ++ classifyOS :: ClassificationStrictness -> String -> OS classifyOS strictness s = fromMaybe (OtherOS s) $ lookup (lowercase s) osMap@@ -169,7 +172,7 @@ deriving (Eq, Generic, Ord, Show, Read, Typeable, Data) instance Binary Arch-+instance Structured Arch instance NFData Arch where rnf = genericRnf knownArches :: [Arch]@@ -217,7 +220,7 @@ deriving (Eq, Generic, Ord, Show, Read, Typeable, Data) instance Binary Platform-+instance Structured Platform instance NFData Platform where rnf = genericRnf instance Pretty Platform where
cabal/Cabal/Distribution/Types/AbiDependency.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric #-} module Distribution.Types.AbiDependency where @@ -25,7 +26,7 @@ depUnitId :: Package.UnitId, depAbiHash :: Package.AbiHash }- deriving (Eq, Generic, Read, Show)+ deriving (Eq, Generic, Read, Show, Typeable) instance Pretty AbiDependency where pretty (AbiDependency uid abi) =@@ -39,4 +40,5 @@ return (AbiDependency uid abi) instance Binary AbiDependency+instance Structured AbiDependency instance NFData AbiDependency where rnf = genericRnf
cabal/Cabal/Distribution/Types/AbiHash.hs view
@@ -25,7 +25,7 @@ -- -- @since 2.0.0.2 newtype AbiHash = AbiHash ShortText- deriving (Eq, Show, Read, Generic)+ deriving (Eq, Show, Read, Generic, Typeable) -- | Construct a 'AbiHash' from a 'String' --@@ -51,7 +51,7 @@ fromString = mkAbiHash instance Binary AbiHash-+instance Structured AbiHash instance NFData AbiHash where rnf = genericRnf instance Pretty AbiHash where
cabal/Cabal/Distribution/Types/Benchmark.hs view
@@ -32,7 +32,7 @@ deriving (Generic, Show, Read, Eq, Typeable, Data) instance Binary Benchmark-+instance Structured Benchmark instance NFData Benchmark where rnf = genericRnf instance L.HasBuildInfo Benchmark where
cabal/Cabal/Distribution/Types/BenchmarkInterface.hs view
@@ -34,7 +34,7 @@ deriving (Eq, Generic, Read, Show, Typeable, Data) instance Binary BenchmarkInterface-+instance Structured BenchmarkInterface instance NFData BenchmarkInterface where rnf = genericRnf instance Monoid BenchmarkInterface where
cabal/Cabal/Distribution/Types/BenchmarkType.hs view
@@ -1,5 +1,6 @@ {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE OverloadedStrings #-} module Distribution.Types.BenchmarkType ( BenchmarkType(..),@@ -12,7 +13,7 @@ import Distribution.Parsec import Distribution.Pretty import Distribution.Version-import Text.PrettyPrint (char, text)+import Text.PrettyPrint (char, text) -- | The \"benchmark-type\" field in the benchmark stanza. --@@ -23,7 +24,7 @@ deriving (Generic, Show, Read, Eq, Typeable, Data) instance Binary BenchmarkType-+instance Structured BenchmarkType instance NFData BenchmarkType where rnf = genericRnf knownBenchmarkTypes :: [BenchmarkType]
cabal/Cabal/Distribution/Types/BuildInfo.hs view
@@ -83,13 +83,13 @@ -- Example 2: a library that is being built by a foreing tool (e.g. rust) -- and copied and registered together with this library. The -- logic on how this library is built will have to be encoded in a- -- custom Setup for now. Oherwise cabal would need to lear how to+ -- custom Setup for now. Otherwise cabal would need to lear how to -- call arbitrary library builders. extraLibFlavours :: [String], -- ^ Hidden Flag. This set of strings, will be appended to all libraries when -- copying. E.g. [libHS<name>_<flavour> | flavour <- extraLibFlavours]. This -- should only be needed in very specific cases, e.g. the `rts` package, where -- there are multiple copies of slightly differently built libs.- extraDynLibFlavours :: [String], -- ^ Hidden Flag. This set of strings will be be appended to all /dynamic/+ extraDynLibFlavours :: [String], -- ^ Hidden Flag. This set of strings will be appended to all /dynamic/ -- libraries when copying. This is particularly useful with the `rts` package, -- where we want different dynamic flavours of the RTS library to be installed. extraLibDirs :: [String],@@ -110,7 +110,7 @@ deriving (Generic, Show, Read, Eq, Typeable, Data) instance Binary BuildInfo-+instance Structured BuildInfo instance NFData BuildInfo where rnf = genericRnf instance Monoid BuildInfo where
cabal/Cabal/Distribution/Types/BuildType.hs view
@@ -1,5 +1,6 @@ {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE OverloadedStrings #-} module Distribution.Types.BuildType ( BuildType(..),@@ -27,7 +28,7 @@ deriving (Generic, Show, Read, Eq, Typeable, Data) instance Binary BuildType-+instance Structured BuildType instance NFData BuildType where rnf = genericRnf knownBuildTypes :: [BuildType]
cabal/Cabal/Distribution/Types/ComponentId.hs view
@@ -56,6 +56,7 @@ fromString = mkComponentId instance Binary ComponentId+instance Structured ComponentId instance Pretty ComponentId where pretty = text . unComponentId
cabal/Cabal/Distribution/Types/ComponentLocalBuildInfo.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE TypeFamilies #-} @@ -18,8 +19,8 @@ import Distribution.Types.UnitId import Distribution.Types.ComponentName import Distribution.Types.MungedPackageName+import Distribution.Types.ModuleRenaming -import Distribution.PackageDescription import qualified Distribution.InstalledPackageInfo as Installed -- | The first five fields are common across all algebraic variants.@@ -108,9 +109,10 @@ componentExeDeps :: [UnitId], componentInternalDeps :: [UnitId] }- deriving (Generic, Read, Show)+ deriving (Generic, Read, Show, Typeable) instance Binary ComponentLocalBuildInfo+instance Structured ComponentLocalBuildInfo instance IsNode ComponentLocalBuildInfo where type Key ComponentLocalBuildInfo = UnitId
cabal/Cabal/Distribution/Types/ComponentName.hs view
@@ -28,6 +28,7 @@ deriving (Eq, Generic, Ord, Read, Show, Typeable) instance Binary ComponentName+instance Structured ComponentName -- Build-target-ish syntax instance Pretty ComponentName where
cabal/Cabal/Distribution/Types/ComponentRequestedSpec.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric #-} module Distribution.Types.ComponentRequestedSpec ( -- $buildable_vs_enabled_components@@ -66,8 +67,10 @@ = ComponentRequestedSpec { testsRequested :: Bool , benchmarksRequested :: Bool } | OneComponentRequestedSpec ComponentName- deriving (Generic, Read, Show, Eq)+ deriving (Generic, Read, Show, Eq, Typeable)+ instance Binary ComponentRequestedSpec+instance Structured ComponentRequestedSpec -- | The default set of enabled components. Historically tests and -- benchmarks are NOT enabled by default.
cabal/Cabal/Distribution/Types/CondTree.hs view
@@ -3,6 +3,7 @@ {-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE DeriveFoldable #-} {-# LANGUAGE DeriveTraversable #-}+{-# LANGUAGE ScopedTypeVariables #-} module Distribution.Types.CondTree ( CondTree(..),@@ -63,7 +64,7 @@ deriving (Show, Eq, Typeable, Data, Generic, Functor, Foldable, Traversable) instance (Binary v, Binary c, Binary a) => Binary (CondTree v c a)-+instance (Structured v, Structured c, Structured a) => Structured (CondTree v c a) instance (NFData v, NFData c, NFData a) => NFData (CondTree v c a) where rnf = genericRnf -- | A 'CondBranch' represents a conditional branch, e.g., @if@@ -79,13 +80,13 @@ -- This instance is written by hand because GHC 8.0.1/8.0.2 infinite -- loops when trying to derive it with optimizations. See--- https://ghc.haskell.org/trac/ghc/ticket/13056+-- https://gitlab.haskell.org/ghc/ghc/-/issues/13056 instance Foldable (CondBranch v c) where foldMap f (CondBranch _ c Nothing) = foldMap f c foldMap f (CondBranch _ c (Just a)) = foldMap f c `mappend` foldMap f a instance (Binary v, Binary c, Binary a) => Binary (CondBranch v c a)-+instance (Structured v, Structured c, Structured a) => Structured (CondBranch v c a) instance (NFData v, NFData c, NFData a) => NFData (CondBranch v c a) where rnf = genericRnf condIfThen :: Condition v -> CondTree v c a -> CondBranch v c a@@ -139,8 +140,9 @@ -- | Extract the condition matched by the given predicate from a cond tree. ----- We use this mainly for extracting buildable conditions (see the Note above),--- but the function is in fact more general.+-- We use this mainly for extracting buildable conditions (see the Note in+-- Distribution.PackageDescription.Configuration), but the function is in fact+-- more general. extractCondition :: Eq v => (a -> Bool) -> CondTree v c a -> Condition v extractCondition p = go where
cabal/Cabal/Distribution/Types/Condition.hs view
@@ -97,7 +97,7 @@ mplus = mappend instance Binary c => Binary (Condition c)-+instance Structured c => Structured (Condition c) instance NFData c => NFData (Condition c) where rnf = genericRnf -- | Simplify the condition and return its free variables.
cabal/Cabal/Distribution/Types/ConfVar.hs view
@@ -15,10 +15,11 @@ -- | A @ConfVar@ represents the variable type used. data ConfVar = OS OS | Arch Arch- | Flag FlagName+ | PackageFlag FlagName | Impl CompilerFlavor VersionRange deriving (Eq, Show, Typeable, Data, Generic) instance Binary ConfVar+instance Structured ConfVar instance NFData ConfVar where rnf = genericRnf
cabal/Cabal/Distribution/Types/Dependency.hs view
@@ -1,42 +1,42 @@ {-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveGeneric #-} module Distribution.Types.Dependency ( Dependency(..)+ , mkDependency , depPkgName , depVerRange , depLibraries- , thisPackageVersion- , notThisPackageVersion , simplifyDependency+ , mainLibSet ) where -import Prelude () import Distribution.Compat.Prelude+import Prelude () -import Distribution.Version ( VersionRange, thisVersion- , notThisVersion, anyVersion- , simplifyVersionRange )+import Distribution.Types.VersionRange (isAnyVersionLight)+import Distribution.Version (VersionRange, anyVersion, simplifyVersionRange) import Distribution.CabalSpecVersion-import Distribution.Pretty-import qualified Text.PrettyPrint as PP+import Distribution.Compat.CharParsing (char, spaces)+import Distribution.Compat.Parsing (between, option) import Distribution.Parsec-import Distribution.Compat.CharParsing (char, spaces)-import Distribution.Compat.Parsing (between, option)-import Distribution.Types.PackageId-import Distribution.Types.PackageName+import Distribution.Pretty import Distribution.Types.LibraryName+import Distribution.Types.PackageName import Distribution.Types.UnqualComponentName -import Text.PrettyPrint ((<+>))-import qualified Data.Set as Set+import qualified Distribution.Compat.NonEmptySet as NES+import qualified Text.PrettyPrint as PP -- | Describes a dependency on a source package (API) --+-- /Invariant:/ package name does not appear as 'LSubLibName' in+-- set of library names.+-- data Dependency = Dependency PackageName VersionRange- (Set LibraryName)+ (NonEmptySet LibraryName) -- ^ The set of libraries required from the package. -- Only the selected libraries will be built. -- It does not affect the cabal-install solver yet.@@ -48,68 +48,128 @@ depVerRange :: Dependency -> VersionRange depVerRange (Dependency _ vr _) = vr -depLibraries :: Dependency -> Set LibraryName+depLibraries :: Dependency -> NonEmptySet LibraryName depLibraries (Dependency _ _ cs) = cs +-- | Smart constructor of 'Dependency'.+--+-- If 'PackageName' is appears as 'LSubLibName' in a set of sublibraries,+-- it is automatically converted to 'LMainLibName'.+--+-- @since 3.4.0.0+--+mkDependency :: PackageName -> VersionRange -> NonEmptySet LibraryName -> Dependency+mkDependency pn vr lb = Dependency pn vr (NES.map conv lb)+ where+ pn' = packageNameToUnqualComponentName pn++ conv l@LMainLibName = l+ conv l@(LSubLibName ln) | ln == pn' = LMainLibName+ | otherwise = l+ instance Binary Dependency+instance Structured Dependency instance NFData Dependency where rnf = genericRnf +-- |+--+-- >>> prettyShow $ Dependency "pkg" anyVersion mainLibSet+-- "pkg"+--+-- >>> prettyShow $ Dependency "pkg" anyVersion $ NES.insert (LSubLibName "sublib") mainLibSet+-- "pkg:{pkg, sublib}"+--+-- >>> prettyShow $ Dependency "pkg" anyVersion $ NES.singleton (LSubLibName "sublib")+-- "pkg:sublib"+--+-- >>> prettyShow $ Dependency "pkg" anyVersion $ NES.insert (LSubLibName "sublib-b") $ NES.singleton (LSubLibName "sublib-a")+-- "pkg:{sublib-a, sublib-b}"+-- instance Pretty Dependency where- pretty (Dependency name ver sublibs) = pretty name- <+> optionalMonoid- (sublibs /= Set.singleton LMainLibName)- (PP.colon <+> PP.braces prettySublibs)- <+> pretty ver+ pretty (Dependency name ver sublibs) = withSubLibs (pretty name) <+> pver where- optionalMonoid True x = x- optionalMonoid False _ = mempty- prettySublibs = PP.hsep $ PP.punctuate PP.comma $ prettySublib <$> Set.toList sublibs- prettySublib LMainLibName = PP.text $ unPackageName name- prettySublib (LSubLibName un) = PP.text $ unUnqualComponentName un+ -- TODO: change to isAnyVersion after #6736+ pver | isAnyVersionLight ver = PP.empty+ | otherwise = pretty ver -versionGuardMultilibs :: (Monad m, CabalParsing m) => m a -> m a-versionGuardMultilibs expr = do- csv <- askCabalSpecVersion- if csv < CabalSpecV3_0- then fail $ unwords- [ "Sublibrary dependency syntax used."- , "To use this syntax the package needs to specify at least 'cabal-version: 3.0'."- , "Alternatively, if you are depending on an internal library, you can write"- , "directly the library name as it were a package."- ]- else- expr+ withSubLibs doc = case NES.toList sublibs of+ [LMainLibName] -> doc+ [LSubLibName uq] -> doc <<>> PP.colon <<>> pretty uq+ _ -> doc <<>> PP.colon <<>> PP.braces prettySublibs + prettySublibs = PP.hsep $ PP.punctuate PP.comma $ prettySublib <$> NES.toList sublibs++ prettySublib LMainLibName = PP.text $ unPackageName name+ prettySublib (LSubLibName un) = PP.text $ unUnqualComponentName un++-- |+--+-- >>> simpleParsec "mylib:sub" :: Maybe Dependency+-- Just (Dependency (PackageName "mylib") (OrLaterVersion (mkVersion [0])) (fromNonEmpty (LSubLibName (UnqualComponentName "sub") :| [])))+--+-- >>> simpleParsec "mylib:{sub1,sub2}" :: Maybe Dependency+-- Just (Dependency (PackageName "mylib") (OrLaterVersion (mkVersion [0])) (fromNonEmpty (LSubLibName (UnqualComponentName "sub1") :| [LSubLibName (UnqualComponentName "sub2")])))+--+-- >>> simpleParsec "mylib:{ sub1 , sub2 }" :: Maybe Dependency+-- Just (Dependency (PackageName "mylib") (OrLaterVersion (mkVersion [0])) (fromNonEmpty (LSubLibName (UnqualComponentName "sub1") :| [LSubLibName (UnqualComponentName "sub2")])))+--+-- >>> simpleParsec "mylib:{ sub1 , sub2 } ^>= 42" :: Maybe Dependency+-- Just (Dependency (PackageName "mylib") (MajorBoundVersion (mkVersion [42])) (fromNonEmpty (LSubLibName (UnqualComponentName "sub1") :| [LSubLibName (UnqualComponentName "sub2")])))+--+-- >>> simpleParsec "mylib:{ } ^>= 42" :: Maybe Dependency+-- Nothing+--+-- >>> traverse_ print (map simpleParsec ["mylib:mylib", "mylib:{mylib}", "mylib:{mylib,sublib}" ] :: [Maybe Dependency])+-- Just (Dependency (PackageName "mylib") (OrLaterVersion (mkVersion [0])) (fromNonEmpty (LMainLibName :| [])))+-- Just (Dependency (PackageName "mylib") (OrLaterVersion (mkVersion [0])) (fromNonEmpty (LMainLibName :| [])))+-- Just (Dependency (PackageName "mylib") (OrLaterVersion (mkVersion [0])) (fromNonEmpty (LMainLibName :| [LSubLibName (UnqualComponentName "sublib")])))+--+-- Spaces around colon are not allowed:+--+-- >>> map simpleParsec ["mylib: sub", "mylib :sub", "mylib: {sub1,sub2}", "mylib :{sub1,sub2}"] :: [Maybe Dependency]+-- [Nothing,Nothing,Nothing,Nothing]+--+-- Sublibrary syntax is accepted since @cabal-version: 3.0@+--+-- >>> map (`simpleParsec'` "mylib:sub") [CabalSpecV2_4, CabalSpecV3_0] :: [Maybe Dependency]+-- [Nothing,Just (Dependency (PackageName "mylib") (OrLaterVersion (mkVersion [0])) (fromNonEmpty (LSubLibName (UnqualComponentName "sub") :| [])))]+-- instance Parsec Dependency where parsec = do- name <- lexemeParsec+ name <- parsec - libs <- option [LMainLibName]- $ (char ':' *> spaces *>)- $ versionGuardMultilibs- $ pure <$> parseLib name <|> parseMultipleLibs name+ libs <- option mainLibSet $ do+ _ <- char ':'+ versionGuardMultilibs+ parsecWarning PWTExperimental "colon specifier is experimental feature (issue #5660)"+ NES.singleton <$> parseLib <|> parseMultipleLibs spaces -- https://github.com/haskell/cabal/issues/5846 ver <- parsec <|> pure anyVersion- return $ Dependency name ver $ Set.fromList libs- where makeLib pn ln | unPackageName pn == ln = LMainLibName- | otherwise = LSubLibName $ mkUnqualComponentName ln- parseLib pn = makeLib pn <$> parsecUnqualComponentName- parseMultipleLibs pn = between (char '{' *> spaces)- (spaces <* char '}')- $ parsecCommaList $ parseLib pn+ return $ mkDependency name ver libs+ where+ parseLib = LSubLibName <$> parsec+ parseMultipleLibs = between+ (char '{' *> spaces)+ (spaces *> char '}')+ (NES.fromNonEmpty <$> parsecCommaNonEmpty parseLib) --- mempty should never be in a Dependency-as-dependency.--- This is only here until the Dependency-as-constraint problem is solved #5570.--- Same for below.-thisPackageVersion :: PackageIdentifier -> Dependency-thisPackageVersion (PackageIdentifier n v) =- Dependency n (thisVersion v) Set.empty+versionGuardMultilibs :: CabalParsing m => m ()+versionGuardMultilibs = do+ csv <- askCabalSpecVersion+ when (csv < CabalSpecV3_0) $ fail $ unwords+ [ "Sublibrary dependency syntax used."+ , "To use this syntax the package needs to specify at least 'cabal-version: 3.0'."+ , "Alternatively, if you are depending on an internal library, you can write"+ , "directly the library name as it were a package."+ ] -notThisPackageVersion :: PackageIdentifier -> Dependency-notThisPackageVersion (PackageIdentifier n v) =- Dependency n (notThisVersion v) Set.empty+-- | Library set with main library.+--+-- @since 3.4.0.0+mainLibSet :: NonEmptySet LibraryName+mainLibSet = NES.singleton LMainLibName -- | Simplify the 'VersionRange' expression in a 'Dependency'. -- See 'simplifyVersionRange'.
cabal/Cabal/Distribution/Types/DependencyMap.hs view
@@ -5,19 +5,20 @@ constrainBy, ) where -import Prelude () import Distribution.Compat.Prelude+import Prelude () import Distribution.Types.Dependency-import Distribution.Types.PackageName import Distribution.Types.LibraryName+import Distribution.Types.PackageName+import Distribution.Types.PackageVersionConstraint import Distribution.Version import qualified Data.Map.Lazy as Map -- | A map of dependencies. Newtyped since the default monoid instance is not -- appropriate. The monoid instance uses 'intersectVersionRanges'.-newtype DependencyMap = DependencyMap { unDependencyMap :: Map PackageName (VersionRange, Set LibraryName) }+newtype DependencyMap = DependencyMap { unDependencyMap :: Map PackageName (VersionRange, NonEmptySet LibraryName) } deriving (Show, Read) instance Monoid DependencyMap where@@ -28,9 +29,9 @@ (DependencyMap a) <> (DependencyMap b) = DependencyMap (Map.unionWith intersectVersionRangesAndJoinComponents a b) -intersectVersionRangesAndJoinComponents :: (VersionRange, Set LibraryName)- -> (VersionRange, Set LibraryName)- -> (VersionRange, Set LibraryName)+intersectVersionRangesAndJoinComponents :: (VersionRange, NonEmptySet LibraryName)+ -> (VersionRange, NonEmptySet LibraryName)+ -> (VersionRange, NonEmptySet LibraryName) intersectVersionRangesAndJoinComponents (va, ca) (vb, cb) = (intersectVersionRanges va vb, ca <> cb) @@ -45,14 +46,12 @@ -- Combines dependencies where the result will only contain keys from the left -- (first) map. If a key also exists in the right map, both constraints will -- be intersected.-constrainBy :: DependencyMap -- ^ Input map- -> DependencyMap -- ^ Extra constraints- -> DependencyMap-constrainBy left extra =- DependencyMap $- Map.foldrWithKey tightenConstraint (unDependencyMap left)- (unDependencyMap extra)- where tightenConstraint n c l =- case Map.lookup n l of- Nothing -> l- Just vrcs -> Map.insert n (intersectVersionRangesAndJoinComponents vrcs c) l+constrainBy+ :: DependencyMap+ -> [PackageVersionConstraint]+ -> DependencyMap+constrainBy = foldl' tightenConstraint where+ tightenConstraint (DependencyMap l) (PackageVersionConstraint pn vr) = DependencyMap $+ case Map.lookup pn l of+ Nothing -> l+ Just (vr', cs) -> Map.insert pn (intersectVersionRanges vr' vr, cs) l
cabal/Cabal/Distribution/Types/ExeDependency.hs view
@@ -13,10 +13,10 @@ import Distribution.Types.ComponentName import Distribution.Types.PackageName import Distribution.Types.UnqualComponentName-import Distribution.Version (VersionRange, anyVersion)+import Distribution.Version (VersionRange, anyVersion, isAnyVersion) import qualified Distribution.Compat.CharParsing as P-import Text.PrettyPrint (text, (<+>))+import qualified Text.PrettyPrint as PP -- | Describes a dependency on an executable from a package --@@ -27,18 +27,22 @@ deriving (Generic, Read, Show, Eq, Typeable, Data) instance Binary ExeDependency+instance Structured ExeDependency instance NFData ExeDependency where rnf = genericRnf instance Pretty ExeDependency where pretty (ExeDependency name exe ver) =- (pretty name <<>> text ":" <<>> pretty exe) <+> pretty ver+ pretty name <<>> PP.colon <<>> pretty exe PP.<+> pver+ where+ pver | isAnyVersion ver = PP.empty+ | otherwise = pretty ver -- | -- -- Examples -- -- >>> simpleParsec "happy:happy" :: Maybe ExeDependency--- Just (ExeDependency (PackageName "happy") (UnqualComponentName "happy") AnyVersion)+-- Just (ExeDependency (PackageName "happy") (UnqualComponentName "happy") (OrLaterVersion (mkVersion [0]))) -- -- >>> simpleParsec "happy:happy >= 1.19.12" :: Maybe ExeDependency -- Just (ExeDependency (PackageName "happy") (UnqualComponentName "happy") (OrLaterVersion (mkVersion [1,19,12])))
cabal/Cabal/Distribution/Types/Executable.hs view
@@ -31,7 +31,7 @@ buildInfo f l = (\x -> l { buildInfo = x }) <$> f (buildInfo l) instance Binary Executable-+instance Structured Executable instance NFData Executable where rnf = genericRnf instance Monoid Executable where
cabal/Cabal/Distribution/Types/ExecutableScope.hs view
@@ -1,5 +1,6 @@ {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE OverloadedStrings #-} module Distribution.Types.ExecutableScope ( ExecutableScope(..),@@ -28,7 +29,7 @@ pri = ExecutablePrivate <$ P.string "private" instance Binary ExecutableScope-+instance Structured ExecutableScope instance NFData ExecutableScope where rnf = genericRnf -- | 'Any' like semigroup, where 'ExecutablePrivate' is 'Any True'
cabal/Cabal/Distribution/Types/ExposedModule.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric #-} module Distribution.Types.ExposedModule where @@ -17,7 +18,7 @@ exposedName :: ModuleName, exposedReexport :: Maybe OpenModule }- deriving (Eq, Generic, Read, Show)+ deriving (Eq, Generic, Read, Show, Typeable) instance Pretty ExposedModule where pretty (ExposedModule m reexport) =@@ -40,5 +41,5 @@ return (ExposedModule m reexport) instance Binary ExposedModule-+instance Structured ExposedModule instance NFData ExposedModule where rnf = genericRnf
cabal/Cabal/Distribution/Types/Flag.hs view
@@ -2,11 +2,14 @@ {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} module Distribution.Types.Flag (- Flag(..),+ -- * Package flag+ PackageFlag(..), emptyFlag,+ -- * Flag name FlagName, mkFlagName, unFlagName,+ -- * Flag assignment FlagAssignment, mkFlagAssignment, unFlagAssignment,@@ -17,7 +20,13 @@ nullFlagAssignment, showFlagValue, dispFlagAssignment,+ showFlagAssignment, parsecFlagAssignment,+ parsecFlagAssignmentNonEmpty,+ -- ** Legacy formats+ legacyShowFlagAssignment,+ legacyShowFlagAssignment',+ legacyParsecFlagAssignment, ) where import Prelude ()@@ -37,7 +46,7 @@ -- | A flag can represent a feature to be included, or a way of linking -- a target against its dependencies, or in fact whatever you can think of.-data Flag = MkFlag+data PackageFlag = MkPackageFlag { flagName :: FlagName , flagDescription :: String , flagDefault :: Bool@@ -45,13 +54,13 @@ } deriving (Show, Eq, Typeable, Data, Generic) -instance Binary Flag--instance NFData Flag where rnf = genericRnf+instance Binary PackageFlag+instance Structured PackageFlag+instance NFData PackageFlag where rnf = genericRnf --- | A 'Flag' initialized with default parameters.-emptyFlag :: FlagName -> Flag-emptyFlag name = MkFlag+-- | A 'PackageFlag' initialized with default parameters.+emptyFlag :: FlagName -> PackageFlag+emptyFlag name = MkPackageFlag { flagName = name , flagDescription = "" , flagDefault = True@@ -92,6 +101,7 @@ unFlagName (FlagName s) = fromShortText s instance Binary FlagName+instance Structured FlagName instance Pretty FlagName where pretty = Disp.text . unFlagName@@ -110,10 +120,14 @@ -- discovered during configuration. For example @--flags=foo --flags=-bar@ -- becomes @[("foo", True), ("bar", False)]@ --+-- TODO: Why we record the multiplicity of the flag?+-- newtype FlagAssignment = FlagAssignment { getFlagAssignment :: Map.Map FlagName (Int, Bool) }- deriving (Binary, Generic, NFData)+ deriving (Binary, Generic, NFData, Typeable) +instance Structured FlagAssignment+ instance Eq FlagAssignment where (==) (FlagAssignment m1) (FlagAssignment m2) = fmap snd m1 == fmap snd m2@@ -226,6 +240,32 @@ showFlagValue (f, True) = '+' : unFlagName f showFlagValue (f, False) = '-' : unFlagName f +-- | @since 3.4.0.0+instance Pretty FlagAssignment where+ pretty = dispFlagAssignment++-- |+--+-- >>> simpleParsec "" :: Maybe FlagAssignment+-- Just (fromList [])+--+-- >>> simpleParsec "+foo -bar" :: Maybe FlagAssignment+-- Just (fromList [(FlagName "bar",(1,False)),(FlagName "foo",(1,True))])+--+-- >>> simpleParsec "-none -any" :: Maybe FlagAssignment+-- Just (fromList [(FlagName "any",(1,False)),(FlagName "none",(1,False))])+--+-- >>> simpleParsec "+foo -foo +foo +foo" :: Maybe FlagAssignment+-- Just (fromList [(FlagName "foo",(4,True))])+--+-- >>> simpleParsec "+foo -bar baz" :: Maybe FlagAssignment+-- Nothing+--+-- @since 3.4.0.0+--+instance Parsec FlagAssignment where+ parsec = parsecFlagAssignment+ -- | Pretty-prints a flag assignment. dispFlagAssignment :: FlagAssignment -> Disp.Doc dispFlagAssignment = Disp.hsep . map (Disp.text . showFlagValue) . unFlagAssignment@@ -233,6 +273,67 @@ -- | Parses a flag assignment. parsecFlagAssignment :: CabalParsing m => m FlagAssignment parsecFlagAssignment = mkFlagAssignment <$>+ P.sepBy (onFlag <|> offFlag) P.skipSpaces1+ where+ onFlag = do+ _ <- P.char '+'+ f <- parsec+ return (f, True)+ offFlag = do+ _ <- P.char '-'+ f <- parsec+ return (f, False)++-- | Parse a non-empty flag assignment+--+-- The flags have to explicitly start with minus or plus.+--+-- @since 3.4.0.0+parsecFlagAssignmentNonEmpty :: CabalParsing m => m FlagAssignment+parsecFlagAssignmentNonEmpty = mkFlagAssignment . toList <$>+ P.sepByNonEmpty (onFlag <|> offFlag) P.skipSpaces1+ where+ onFlag = do+ _ <- P.char '+'+ f <- parsec+ return (f, True)+ offFlag = do+ _ <- P.char '-'+ f <- parsec+ return (f, False)++-- | Show flag assignment.+--+-- @since 3.4.0.0+showFlagAssignment :: FlagAssignment -> String+showFlagAssignment = prettyShow . dispFlagAssignment++-------------------------------------------------------------------------------+-- Legacy: without requiring ++-------------------------------------------------------------------------------++-- | We need this as far as we support custom setups older than 2.2.0.0+--+-- @since 3.4.0.0+legacyShowFlagAssignment :: FlagAssignment -> String+legacyShowFlagAssignment =+ prettyShow . Disp.hsep . map Disp.text . legacyShowFlagAssignment'++-- | @since 3.4.0.0+legacyShowFlagAssignment' :: FlagAssignment -> [String]+legacyShowFlagAssignment' = map legacyShowFlagValue . unFlagAssignment++-- | @since 3.4.0.0+legacyShowFlagValue :: (FlagName, Bool) -> String+legacyShowFlagValue (f, True) = unFlagName f+legacyShowFlagValue (f, False) = '-' : unFlagName f++-- |+-- We need this as far as we support custom setups older than 2.2.0.0+--+-- @since 3.4.0.0+legacyParsecFlagAssignment :: CabalParsing m => m FlagAssignment+legacyParsecFlagAssignment = mkFlagAssignment <$> P.sepBy (onFlag <|> offFlag) P.skipSpaces1 where onFlag = do
cabal/Cabal/Distribution/Types/ForeignLib.hs view
@@ -31,8 +31,8 @@ import Distribution.Version import qualified Distribution.Compat.CharParsing as P-import qualified Text.PrettyPrint as Disp-import qualified Text.Read as Read+import qualified Text.PrettyPrint as Disp+import qualified Text.Read as Read import qualified Distribution.Types.BuildInfo.Lens as L @@ -83,7 +83,7 @@ return (mkLibVersionInfo t) instance Binary LibVersionInfo-+instance Structured LibVersionInfo instance NFData LibVersionInfo where rnf = genericRnf instance Pretty LibVersionInfo where@@ -136,7 +136,7 @@ buildInfo f l = (\x -> l { foreignLibBuildInfo = x }) <$> f (foreignLibBuildInfo l) instance Binary ForeignLib-+instance Structured ForeignLib instance NFData ForeignLib where rnf = genericRnf instance Semigroup ForeignLib where
cabal/Cabal/Distribution/Types/ForeignLibOption.hs view
@@ -1,5 +1,6 @@ {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE OverloadedStrings #-} module Distribution.Types.ForeignLibOption( ForeignLibOption(..)@@ -34,5 +35,5 @@ _ -> fail "unrecognized foreign-library option" instance Binary ForeignLibOption-+instance Structured ForeignLibOption instance NFData ForeignLibOption where rnf = genericRnf
cabal/Cabal/Distribution/Types/ForeignLibType.hs view
@@ -1,5 +1,6 @@ {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE OverloadedStrings #-} module Distribution.Types.ForeignLibType( ForeignLibType(..),@@ -42,7 +43,7 @@ _ -> ForeignLibTypeUnknown instance Binary ForeignLibType-+instance Structured ForeignLibType instance NFData ForeignLibType where rnf = genericRnf instance Semigroup ForeignLibType where
cabal/Cabal/Distribution/Types/GenericPackageDescription.hs view
@@ -2,6 +2,7 @@ {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE ScopedTypeVariables #-} module Distribution.Types.GenericPackageDescription ( GenericPackageDescription(..),@@ -28,6 +29,7 @@ import Distribution.Types.TestSuite import Distribution.Types.UnqualComponentName import Distribution.Package+import Distribution.Version -- --------------------------------------------------------------------------- -- The 'GenericPackageDescription' type@@ -35,7 +37,16 @@ data GenericPackageDescription = GenericPackageDescription { packageDescription :: PackageDescription- , genPackageFlags :: [Flag]+ , gpdScannedVersion :: Maybe Version+ -- ^ This is a version as specified in source.+ -- We populate this field in index reading for dummy GPDs,+ -- only when GPD reading failed, but scanning haven't.+ --+ -- Cabal-the-library never produces GPDs with Just as gpdScannedVersion.+ --+ -- Perfectly, PackageIndex should have sum type, so we don't need to+ -- have dummy GPDs.+ , genPackageFlags :: [PackageFlag] , condLibrary :: Maybe (CondTree ConfVar [Dependency] Library) , condSubLibraries :: [( UnqualComponentName , CondTree ConfVar [Dependency] Library )]@@ -54,25 +65,41 @@ packageId = packageId . packageDescription instance Binary GenericPackageDescription-+instance Structured GenericPackageDescription instance NFData GenericPackageDescription where rnf = genericRnf emptyGenericPackageDescription :: GenericPackageDescription-emptyGenericPackageDescription = GenericPackageDescription emptyPackageDescription [] Nothing [] [] [] [] []+emptyGenericPackageDescription = GenericPackageDescription emptyPackageDescription Nothing [] Nothing [] [] [] [] [] -- ----------------------------------------------------------------------------- -- Traversal Instances instance L.HasBuildInfos GenericPackageDescription where- traverseBuildInfos f (GenericPackageDescription p a1 x1 x2 x3 x4 x5 x6) =- GenericPackageDescription- <$> L.traverseBuildInfos f p- <*> pure a1- <*> (traverse . traverse . L.buildInfo) f x1- <*> (traverse . L._2 . traverse . L.buildInfo) f x2- <*> (traverse . L._2 . traverse . L.buildInfo) f x3- <*> (traverse . L._2 . traverse . L.buildInfo) f x4- <*> (traverse . L._2 . traverse . L.buildInfo) f x5- <*> (traverse . L._2 . traverse . L.buildInfo) f x6+ traverseBuildInfos f (GenericPackageDescription p v a1 x1 x2 x3 x4 x5 x6) =+ GenericPackageDescription+ <$> L.traverseBuildInfos f p+ <*> pure v+ <*> pure a1+ <*> (traverse . traverseCondTreeBuildInfo) f x1+ <*> (traverse . L._2 . traverseCondTreeBuildInfo) f x2+ <*> (traverse . L._2 . traverseCondTreeBuildInfo) f x3+ <*> (traverse . L._2 . traverseCondTreeBuildInfo) f x4+ <*> (traverse . L._2 . traverseCondTreeBuildInfo) f x5+ <*> (traverse . L._2 . traverseCondTreeBuildInfo) f x6+ where +-- We use this traversal to keep [Dependency] field in CondTree up to date.+traverseCondTreeBuildInfo+ :: forall f comp v. (Applicative f, L.HasBuildInfo comp)+ => LensLike' f (CondTree v [Dependency] comp) L.BuildInfo+traverseCondTreeBuildInfo g = node where+ mkCondNode :: comp -> [CondBranch v [Dependency] comp] -> CondTree v [Dependency] comp+ mkCondNode comp branches = CondNode comp (view L.targetBuildDepends comp) branches + node (CondNode comp _ branches) = mkCondNode+ <$> L.buildInfo g comp+ <*> traverse branch branches++ branch (CondBranch v x y) = CondBranch v+ <$> node x+ <*> traverse node y
cabal/Cabal/Distribution/Types/GenericPackageDescription/Lens.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE Rank2Types #-} module Distribution.Types.GenericPackageDescription.Lens ( GenericPackageDescription,- Flag,+ PackageFlag, FlagName, ConfVar (..), module Distribution.Types.GenericPackageDescription.Lens,@@ -22,14 +22,14 @@ import Distribution.Types.Benchmark (Benchmark) import Distribution.Types.ForeignLib (ForeignLib) import Distribution.Types.GenericPackageDescription (GenericPackageDescription(GenericPackageDescription) )-import Distribution.Types.Flag (Flag(MkFlag), FlagName)+import Distribution.Types.Flag (PackageFlag(MkPackageFlag), FlagName) import Distribution.Types.ConfVar (ConfVar (..)) import Distribution.Types.Library (Library) import Distribution.Types.TestSuite (TestSuite) import Distribution.Types.UnqualComponentName (UnqualComponentName) import Distribution.System (Arch, OS) import Distribution.Compiler (CompilerFlavor)-import Distribution.Version (VersionRange)+import Distribution.Version (Version, VersionRange) ------------------------------------------------------------------------------- -- GenericPackageDescription@@ -39,7 +39,11 @@ packageDescription f s = fmap (\x -> s { T.packageDescription = x }) (f (T.packageDescription s)) {-# INLINE packageDescription #-} -genPackageFlags :: Lens' GenericPackageDescription [Flag]+gpdScannedVersion :: Lens' GenericPackageDescription (Maybe Version)+gpdScannedVersion f s = fmap (\x -> s { T.gpdScannedVersion = x }) (f (T.gpdScannedVersion s))+{-# INLINE gpdScannedVersion #-}++genPackageFlags :: Lens' GenericPackageDescription [PackageFlag] genPackageFlags f s = fmap (\x -> s { T.genPackageFlags = x }) (f (T.genPackageFlags s)) {-# INLINE genPackageFlags #-} @@ -73,9 +77,10 @@ -> f (CondTree ConfVar [Dependency] a)) -> GenericPackageDescription -> f GenericPackageDescription-allCondTrees f (GenericPackageDescription p a1 x1 x2 x3 x4 x5 x6) =+allCondTrees f (GenericPackageDescription p v a1 x1 x2 x3 x4 x5 x6) = GenericPackageDescription <$> pure p+ <*> pure v <*> pure a1 <*> traverse f x1 <*> (traverse . _2) f x2@@ -89,20 +94,20 @@ -- Flag ------------------------------------------------------------------------------- -flagName :: Lens' Flag FlagName-flagName f (MkFlag x1 x2 x3 x4) = fmap (\y1 -> MkFlag y1 x2 x3 x4) (f x1)+flagName :: Lens' PackageFlag FlagName+flagName f (MkPackageFlag x1 x2 x3 x4) = fmap (\y1 -> MkPackageFlag y1 x2 x3 x4) (f x1) {-# INLINE flagName #-} -flagDescription :: Lens' Flag String-flagDescription f (MkFlag x1 x2 x3 x4) = fmap (\y1 -> MkFlag x1 y1 x3 x4) (f x2)+flagDescription :: Lens' PackageFlag String+flagDescription f (MkPackageFlag x1 x2 x3 x4) = fmap (\y1 -> MkPackageFlag x1 y1 x3 x4) (f x2) {-# INLINE flagDescription #-} -flagDefault :: Lens' Flag Bool-flagDefault f (MkFlag x1 x2 x3 x4) = fmap (\y1 -> MkFlag x1 x2 y1 x4) (f x3)+flagDefault :: Lens' PackageFlag Bool+flagDefault f (MkPackageFlag x1 x2 x3 x4) = fmap (\y1 -> MkPackageFlag x1 x2 y1 x4) (f x3) {-# INLINE flagDefault #-} -flagManual :: Lens' Flag Bool-flagManual f (MkFlag x1 x2 x3 x4) = fmap (\y1 -> MkFlag x1 x2 x3 y1) (f x4)+flagManual :: Lens' PackageFlag Bool+flagManual f (MkPackageFlag x1 x2 x3 x4) = fmap (\y1 -> MkPackageFlag x1 x2 x3 y1) (f x4) {-# INLINE flagManual #-} -------------------------------------------------------------------------------@@ -117,9 +122,9 @@ _Arch f (Arch arch) = Arch <$> f arch _Arch _ x = pure x -_Flag :: Traversal' ConfVar FlagName-_Flag f (Flag flag) = Flag <$> f flag-_Flag _ x = pure x+_PackageFlag :: Traversal' ConfVar FlagName+_PackageFlag f (PackageFlag flag) = PackageFlag <$> f flag+_PackageFlag _ x = pure x _Impl :: Traversal' ConfVar (CompilerFlavor, VersionRange) _Impl f (Impl cf vr) = uncurry Impl <$> f (cf, vr)
cabal/Cabal/Distribution/Types/GivenComponent.hs view
@@ -25,4 +25,4 @@ deriving (Generic, Read, Show, Eq, Typeable) instance Binary GivenComponent-+instance Structured GivenComponent
cabal/Cabal/Distribution/Types/IncludeRenaming.hs view
@@ -15,7 +15,7 @@ import qualified Distribution.Compat.CharParsing as P import Distribution.Parsec import Distribution.Pretty-import Text.PrettyPrint (text, (<+>))+import Text.PrettyPrint (text) import qualified Text.PrettyPrint as Disp -- ---------------------------------------------------------------------------@@ -30,6 +30,7 @@ deriving (Show, Read, Eq, Ord, Typeable, Data, Generic) instance Binary IncludeRenaming+instance Structured IncludeRenaming instance NFData IncludeRenaming where rnf = genericRnf @@ -53,7 +54,7 @@ parsec = do prov_rn <- parsec req_rn <- P.option defaultRenaming $ P.try $ do- P.spaces+ P.spaces -- no need to be space _ <- P.string "requires" P.spaces parsec
cabal/Cabal/Distribution/Types/InstalledPackageInfo.hs view
@@ -1,6 +1,7 @@ {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE OverloadedStrings #-} module Distribution.Types.InstalledPackageInfo ( InstalledPackageInfo (..), emptyInstalledPackageInfo,@@ -25,6 +26,7 @@ import Distribution.Types.MungedPackageId import Distribution.Types.MungedPackageName import Distribution.Version (nullVersion)+import Distribution.Utils.ShortText (ShortText) import qualified Distribution.Package as Package import qualified Distribution.SPDX as SPDX@@ -50,15 +52,15 @@ instantiatedWith :: [(ModuleName, OpenModule)], compatPackageKey :: String, license :: Either SPDX.License License,- copyright :: String,- maintainer :: String,- author :: String,- stability :: String,- homepage :: String,- pkgUrl :: String,- synopsis :: String,- description :: String,- category :: String,+ copyright :: !ShortText,+ maintainer :: !ShortText,+ author :: !ShortText,+ stability :: !ShortText,+ homepage :: !ShortText,+ pkgUrl :: !ShortText,+ synopsis :: !ShortText,+ description :: !ShortText,+ category :: !ShortText, -- these parts are required by an installed package only: abiHash :: AbiHash, indefinite :: Bool,@@ -93,6 +95,7 @@ deriving (Eq, Generic, Typeable, Read, Show) instance Binary InstalledPackageInfo+instance Structured InstalledPackageInfo instance NFData InstalledPackageInfo where rnf = genericRnf
cabal/Cabal/Distribution/Types/InstalledPackageInfo/FieldGrammar.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE ConstraintKinds #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE OverloadedStrings #-}@@ -19,11 +20,10 @@ import Distribution.ModuleName import Distribution.Package import Distribution.Parsec-import Distribution.Parsec.Newtypes import Distribution.Pretty+import Distribution.Types.LibraryName import Distribution.Types.LibraryVisibility import Distribution.Types.MungedPackageName-import Distribution.Types.LibraryName import Distribution.Types.UnqualComponentName import Distribution.Version @@ -44,16 +44,33 @@ -- 34886 KnownBranch -- 8197 wild1_ixF0 ----- https://ghc.haskell.org/trac/ghc/ticket/13253 might be the cause.+-- https://gitlab.haskell.org/ghc/ghc/-/issues/13253 might be the cause. -- -- The workaround is to prevent GHC optimising the code:-infixl 4 <+>-(<+>) :: Applicative f => f (a -> b) -> f a -> f b-f <+> x = f <*> x-{-# NOINLINE (<+>) #-}+infixl 4 <@>+(<@>) :: Applicative f => f (a -> b) -> f a -> f b+f <@> x = f <*> x+{-# NOINLINE (<@>) #-} ipiFieldGrammar- :: (FieldGrammar g, Applicative (g InstalledPackageInfo), Applicative (g Basic))+ :: ( FieldGrammar c g, Applicative (g InstalledPackageInfo), Applicative (g Basic)+ , c (Identity AbiHash)+ , c (Identity LibraryVisibility)+ , c (Identity PackageName)+ , c (Identity UnitId)+ , c (Identity UnqualComponentName)+ , c (List FSep (Identity AbiDependency) AbiDependency)+ , c (List FSep (Identity UnitId) UnitId)+ , c (List FSep (MQuoted ModuleName) ModuleName)+ , c (List FSep FilePathNT String)+ , c (List FSep Token String)+ , c (MQuoted MungedPackageName)+ , c (MQuoted Version)+ , c CompatPackageKey+ , c ExposedModules+ , c InstWith+ , c SpecLicenseLenient+ ) => g InstalledPackageInfo InstalledPackageInfo ipiFieldGrammar = mkInstalledPackageInfo -- Deprecated fields@@ -61,47 +78,47 @@ --- https://github.com/haskell/cabal/commit/40f3601e17024f07e0da8e64d3dd390177ce908b ^^^ deprecatedSince CabalSpecV1_22 "hugs isn't supported anymore" -- Very basic fields: name, version, package-name, lib-name and visibility- <+> blurFieldGrammar basic basicFieldGrammar+ <@> blurFieldGrammar basic basicFieldGrammar -- Basic fields- <+> optionalFieldDef "id" L.installedUnitId (mkUnitId "")- <+> optionalFieldDefAla "instantiated-with" InstWith L.instantiatedWith []- <+> optionalFieldDefAla "key" CompatPackageKey L.compatPackageKey ""- <+> optionalFieldDefAla "license" SpecLicenseLenient L.license (Left SPDX.NONE)- <+> freeTextFieldDef "copyright" L.copyright- <+> freeTextFieldDef "maintainer" L.maintainer- <+> freeTextFieldDef "author" L.author- <+> freeTextFieldDef "stability" L.stability- <+> freeTextFieldDef "homepage" L.homepage- <+> freeTextFieldDef "package-url" L.pkgUrl- <+> freeTextFieldDef "synopsis" L.synopsis- <+> freeTextFieldDef "description" L.description- <+> freeTextFieldDef "category" L.category+ <@> optionalFieldDef "id" L.installedUnitId (mkUnitId "")+ <@> optionalFieldDefAla "instantiated-with" InstWith L.instantiatedWith []+ <@> optionalFieldDefAla "key" CompatPackageKey L.compatPackageKey ""+ <@> optionalFieldDefAla "license" SpecLicenseLenient L.license (Left SPDX.NONE)+ <@> freeTextFieldDefST "copyright" L.copyright+ <@> freeTextFieldDefST "maintainer" L.maintainer+ <@> freeTextFieldDefST "author" L.author+ <@> freeTextFieldDefST "stability" L.stability+ <@> freeTextFieldDefST "homepage" L.homepage+ <@> freeTextFieldDefST "package-url" L.pkgUrl+ <@> freeTextFieldDefST "synopsis" L.synopsis+ <@> freeTextFieldDefST "description" L.description+ <@> freeTextFieldDefST "category" L.category -- Installed fields- <+> optionalFieldDef "abi" L.abiHash (mkAbiHash "")- <+> booleanFieldDef "indefinite" L.indefinite False- <+> booleanFieldDef "exposed" L.exposed False- <+> monoidalFieldAla "exposed-modules" ExposedModules L.exposedModules- <+> monoidalFieldAla "hidden-modules" (alaList' FSep MQuoted) L.hiddenModules- <+> booleanFieldDef "trusted" L.trusted False- <+> monoidalFieldAla "import-dirs" (alaList' FSep FilePathNT) L.importDirs- <+> monoidalFieldAla "library-dirs" (alaList' FSep FilePathNT) L.libraryDirs- <+> monoidalFieldAla "dynamic-library-dirs" (alaList' FSep FilePathNT) L.libraryDynDirs- <+> optionalFieldDefAla "data-dir" FilePathNT L.dataDir ""- <+> monoidalFieldAla "hs-libraries" (alaList' FSep Token) L.hsLibraries- <+> monoidalFieldAla "extra-libraries" (alaList' FSep Token) L.extraLibraries- <+> monoidalFieldAla "extra-ghci-libraries" (alaList' FSep Token) L.extraGHCiLibraries- <+> monoidalFieldAla "include-dirs" (alaList' FSep FilePathNT) L.includeDirs- <+> monoidalFieldAla "includes" (alaList' FSep FilePathNT) L.includes- <+> monoidalFieldAla "depends" (alaList FSep) L.depends- <+> monoidalFieldAla "abi-depends" (alaList FSep) L.abiDepends- <+> monoidalFieldAla "cc-options" (alaList' FSep Token) L.ccOptions- <+> monoidalFieldAla "cxx-options" (alaList' FSep Token) L.cxxOptions- <+> monoidalFieldAla "ld-options" (alaList' FSep Token) L.ldOptions- <+> monoidalFieldAla "framework-dirs" (alaList' FSep FilePathNT) L.frameworkDirs- <+> monoidalFieldAla "frameworks" (alaList' FSep Token) L.frameworks- <+> monoidalFieldAla "haddock-interfaces" (alaList' FSep FilePathNT) L.haddockInterfaces- <+> monoidalFieldAla "haddock-html" (alaList' FSep FilePathNT) L.haddockHTMLs- <+> optionalFieldAla "pkgroot" FilePathNT L.pkgRoot+ <@> optionalFieldDef "abi" L.abiHash (mkAbiHash "")+ <@> booleanFieldDef "indefinite" L.indefinite False+ <@> booleanFieldDef "exposed" L.exposed False+ <@> monoidalFieldAla "exposed-modules" ExposedModules L.exposedModules+ <@> monoidalFieldAla "hidden-modules" (alaList' FSep MQuoted) L.hiddenModules+ <@> booleanFieldDef "trusted" L.trusted False+ <@> monoidalFieldAla "import-dirs" (alaList' FSep FilePathNT) L.importDirs+ <@> monoidalFieldAla "library-dirs" (alaList' FSep FilePathNT) L.libraryDirs+ <@> monoidalFieldAla "dynamic-library-dirs" (alaList' FSep FilePathNT) L.libraryDynDirs+ <@> optionalFieldDefAla "data-dir" FilePathNT L.dataDir ""+ <@> monoidalFieldAla "hs-libraries" (alaList' FSep Token) L.hsLibraries+ <@> monoidalFieldAla "extra-libraries" (alaList' FSep Token) L.extraLibraries+ <@> monoidalFieldAla "extra-ghci-libraries" (alaList' FSep Token) L.extraGHCiLibraries+ <@> monoidalFieldAla "include-dirs" (alaList' FSep FilePathNT) L.includeDirs+ <@> monoidalFieldAla "includes" (alaList' FSep FilePathNT) L.includes+ <@> monoidalFieldAla "depends" (alaList FSep) L.depends+ <@> monoidalFieldAla "abi-depends" (alaList FSep) L.abiDepends+ <@> monoidalFieldAla "cc-options" (alaList' FSep Token) L.ccOptions+ <@> monoidalFieldAla "cxx-options" (alaList' FSep Token) L.cxxOptions+ <@> monoidalFieldAla "ld-options" (alaList' FSep Token) L.ldOptions+ <@> monoidalFieldAla "framework-dirs" (alaList' FSep FilePathNT) L.frameworkDirs+ <@> monoidalFieldAla "frameworks" (alaList' FSep Token) L.frameworks+ <@> monoidalFieldAla "haddock-interfaces" (alaList' FSep FilePathNT) L.haddockInterfaces+ <@> monoidalFieldAla "haddock-html" (alaList' FSep FilePathNT) L.haddockHTMLs+ <@> optionalFieldAla "pkgroot" FilePathNT L.pkgRoot where mkInstalledPackageInfo _ Basic {..} = InstalledPackageInfo -- _basicPkgName is not used@@ -180,7 +197,6 @@ instance Pretty ExposedModules where pretty = showExposedModules . getExposedModules - newtype CompatPackageKey = CompatPackageKey { getCompatPackageKey :: String } instance Newtype String CompatPackageKey@@ -192,7 +208,6 @@ parsec = CompatPackageKey <$> P.munch1 uid_char where uid_char c = Char.isAlphaNum c || c `elem` ("-_.=[],:<>+" :: String) - newtype InstWith = InstWith { getInstWith :: [(ModuleName,OpenModule)] } instance Newtype [(ModuleName, OpenModule)] InstWith@@ -203,7 +218,6 @@ instance Parsec InstWith where parsec = InstWith . Map.toList <$> parsecOpenModuleSubst - -- | SPDX License expression or legacy license. Lenient parser, accepts either. newtype SpecLicenseLenient = SpecLicenseLenient { getSpecLicenseLenient :: Either SPDX.License License } @@ -270,14 +284,20 @@ {-# INLINE basicLibVisibility #-} basicFieldGrammar- :: (FieldGrammar g, Applicative (g Basic))+ :: ( FieldGrammar c g, Applicative (g Basic)+ , c (Identity LibraryVisibility)+ , c (Identity PackageName)+ , c (Identity UnqualComponentName)+ , c (MQuoted MungedPackageName)+ , c (MQuoted Version)+ ) => g Basic Basic basicFieldGrammar = mkBasic <$> optionalFieldDefAla "name" MQuoted basicName (mungedPackageName emptyInstalledPackageInfo) <*> optionalFieldDefAla "version" MQuoted basicVersion nullVersion <*> optionalField "package-name" basicPkgName <*> optionalField "lib-name" basicLibName- <+> optionalFieldDef "visibility" basicLibVisibility LibraryVisibilityPrivate+ <*> optionalFieldDef "visibility" basicLibVisibility LibraryVisibilityPrivate where mkBasic n v pn ln lv = Basic n v pn ln' lv' where
cabal/Cabal/Distribution/Types/InstalledPackageInfo/Lens.hs view
@@ -14,7 +14,9 @@ import Distribution.Types.InstalledPackageInfo (AbiDependency, ExposedModule, InstalledPackageInfo) import Distribution.Types.LibraryName (LibraryName) import Distribution.Types.LibraryVisibility (LibraryVisibility)+import Distribution.Utils.ShortText (ShortText) + import qualified Distribution.SPDX as SPDX import qualified Distribution.Types.InstalledPackageInfo as T @@ -46,39 +48,39 @@ license f s = fmap (\x -> s { T.license = x }) (f (T.license s)) {-# INLINE license #-} -copyright :: Lens' InstalledPackageInfo String+copyright :: Lens' InstalledPackageInfo ShortText copyright f s = fmap (\x -> s { T.copyright = x }) (f (T.copyright s)) {-# INLINE copyright #-} -maintainer :: Lens' InstalledPackageInfo String+maintainer :: Lens' InstalledPackageInfo ShortText maintainer f s = fmap (\x -> s { T.maintainer = x }) (f (T.maintainer s)) {-# INLINE maintainer #-} -author :: Lens' InstalledPackageInfo String+author :: Lens' InstalledPackageInfo ShortText author f s = fmap (\x -> s { T.author = x }) (f (T.author s)) {-# INLINE author #-} -stability :: Lens' InstalledPackageInfo String+stability :: Lens' InstalledPackageInfo ShortText stability f s = fmap (\x -> s { T.stability = x }) (f (T.stability s)) {-# INLINE stability #-} -homepage :: Lens' InstalledPackageInfo String+homepage :: Lens' InstalledPackageInfo ShortText homepage f s = fmap (\x -> s { T.homepage = x }) (f (T.homepage s)) {-# INLINE homepage #-} -pkgUrl :: Lens' InstalledPackageInfo String+pkgUrl :: Lens' InstalledPackageInfo ShortText pkgUrl f s = fmap (\x -> s { T.pkgUrl = x }) (f (T.pkgUrl s)) {-# INLINE pkgUrl #-} -synopsis :: Lens' InstalledPackageInfo String+synopsis :: Lens' InstalledPackageInfo ShortText synopsis f s = fmap (\x -> s { T.synopsis = x }) (f (T.synopsis s)) {-# INLINE synopsis #-} -description :: Lens' InstalledPackageInfo String+description :: Lens' InstalledPackageInfo ShortText description f s = fmap (\x -> s { T.description = x }) (f (T.description s)) {-# INLINE description #-} -category :: Lens' InstalledPackageInfo String+category :: Lens' InstalledPackageInfo ShortText category f s = fmap (\x -> s { T.category = x }) (f (T.category s)) {-# INLINE category #-}
cabal/Cabal/Distribution/Types/LegacyExeDependency.hs view
@@ -9,10 +9,10 @@ import Distribution.Parsec import Distribution.Pretty-import Distribution.Version (VersionRange, anyVersion)+import Distribution.Version (VersionRange, anyVersion) import qualified Distribution.Compat.CharParsing as P-import Text.PrettyPrint (text, (<+>))+import qualified Text.PrettyPrint as Disp -- | Describes a legacy `build-tools`-style dependency on an executable --@@ -27,11 +27,12 @@ deriving (Generic, Read, Show, Eq, Typeable, Data) instance Binary LegacyExeDependency+instance Structured LegacyExeDependency instance NFData LegacyExeDependency where rnf = genericRnf instance Pretty LegacyExeDependency where- pretty (LegacyExeDependency name ver) =- text name <+> pretty ver+ pretty (LegacyExeDependency name ver) =+ Disp.text name <+> pretty ver instance Parsec LegacyExeDependency where parsec = do
cabal/Cabal/Distribution/Types/Library.hs view
@@ -35,7 +35,7 @@ buildInfo f l = (\x -> l { libBuildInfo = x }) <$> f (libBuildInfo l) instance Binary Library-+instance Structured Library instance NFData Library where rnf = genericRnf emptyLibrary :: Library
cabal/Cabal/Distribution/Types/LibraryName.hs view
@@ -28,6 +28,7 @@ deriving (Eq, Generic, Ord, Read, Show, Typeable, Data) instance Binary LibraryName+instance Structured LibraryName instance NFData LibraryName where rnf = genericRnf -- | Pretty print 'LibraryName' in build-target-ish syntax.
cabal/Cabal/Distribution/Types/LibraryVisibility.hs view
@@ -1,5 +1,6 @@ {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE OverloadedStrings #-} module Distribution.Types.LibraryVisibility( LibraryVisibility(..),@@ -32,12 +33,14 @@ instance Parsec LibraryVisibility where parsec = do name <- P.munch1 isAlpha+ parsecWarning PWTExperimental "visibility is experimental feature (issue #5660)" case name of "public" -> return LibraryVisibilityPublic "private" -> return LibraryVisibilityPrivate _ -> fail $ "Unknown visibility: " ++ name instance Binary LibraryVisibility+instance Structured LibraryVisibility instance NFData LibraryVisibility where rnf = genericRnf instance Semigroup LibraryVisibility where
cabal/Cabal/Distribution/Types/LocalBuildInfo.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE RankNTypes #-}@@ -156,9 +157,10 @@ progPrefix :: PathTemplate, -- ^Prefix to be prepended to installed executables progSuffix :: PathTemplate, -- ^Suffix to be appended to installed executables relocatable :: Bool -- ^Whether to build a relocatable package- } deriving (Generic, Read, Show)+ } deriving (Generic, Read, Show, Typeable) instance Binary LocalBuildInfo+instance Structured LocalBuildInfo ------------------------------------------------------------------------------- -- Accessor functions
cabal/Cabal/Distribution/Types/Mixin.hs view
@@ -3,34 +3,91 @@ module Distribution.Types.Mixin ( Mixin(..),+ mkMixin,+ normaliseMixin, ) where import Distribution.Compat.Prelude import Prelude () -import Text.PrettyPrint ((<+>))-+import Distribution.CabalSpecVersion import Distribution.Parsec import Distribution.Pretty import Distribution.Types.IncludeRenaming+import Distribution.Types.LibraryName import Distribution.Types.PackageName+import Distribution.Types.UnqualComponentName import qualified Distribution.Compat.CharParsing as P+import qualified Text.PrettyPrint as PP +-- |+--+-- /Invariant:/ if 'mixinLibraryName' is 'LSubLibName', it's not+-- the same as 'mixinPackageName'. In other words,+-- the same invariant as 'Dependency' has.+-- data Mixin = Mixin { mixinPackageName :: PackageName+ , mixinLibraryName :: LibraryName , mixinIncludeRenaming :: IncludeRenaming } deriving (Show, Read, Eq, Ord, Typeable, Data, Generic) instance Binary Mixin+instance Structured Mixin instance NFData Mixin where rnf = genericRnf instance Pretty Mixin where- pretty (Mixin pkg_name incl) = pretty pkg_name <+> pretty incl+ pretty (Mixin pn LMainLibName incl) = pretty pn <+> pretty incl+ pretty (Mixin pn (LSubLibName ln) incl) = pretty pn <<>> PP.colon <<>> pretty ln <+> pretty incl +-- |+--+-- >>> simpleParsec "mylib" :: Maybe Mixin+-- Just (Mixin {mixinPackageName = PackageName "mylib", mixinLibraryName = LMainLibName, mixinIncludeRenaming = IncludeRenaming {includeProvidesRn = DefaultRenaming, includeRequiresRn = DefaultRenaming}})+--+-- >>> simpleParsec "thatlib:sublib" :: Maybe Mixin+-- Just (Mixin {mixinPackageName = PackageName "thatlib", mixinLibraryName = LSubLibName (UnqualComponentName "sublib"), mixinIncludeRenaming = IncludeRenaming {includeProvidesRn = DefaultRenaming, includeRequiresRn = DefaultRenaming}})+--+-- >>> simpleParsec "thatlib:thatlib" :: Maybe Mixin+-- Just (Mixin {mixinPackageName = PackageName "thatlib", mixinLibraryName = LMainLibName, mixinIncludeRenaming = IncludeRenaming {includeProvidesRn = DefaultRenaming, includeRequiresRn = DefaultRenaming}})+--+-- Sublibrary syntax is accepted since @cabal-version: 3.4@.+--+-- >>> map (`simpleParsec'` "mylib:sub") [CabalSpecV3_0, CabalSpecV3_4] :: [Maybe Mixin]+-- [Nothing,Just (Mixin {mixinPackageName = PackageName "mylib", mixinLibraryName = LSubLibName (UnqualComponentName "sub"), mixinIncludeRenaming = IncludeRenaming {includeProvidesRn = DefaultRenaming, includeRequiresRn = DefaultRenaming}})]+-- instance Parsec Mixin where parsec = do- mod_name <- parsec+ pn <- parsec+ ln <- P.option LMainLibName $ do+ _ <- P.char ':'+ versionGuardMultilibs+ parsecWarning PWTExperimental "colon specifier is experimental feature (issue #5660)"+ LSubLibName <$> parsec P.spaces incl <- parsec- return (Mixin mod_name incl)+ return (mkMixin pn ln incl)+ where++versionGuardMultilibs :: CabalParsing m => m ()+versionGuardMultilibs = do+ csv <- askCabalSpecVersion+ when (csv < CabalSpecV3_4) $ fail $ unwords+ [ "Sublibrary mixin syntax used."+ , "To use this syntax the package needs to specify at least 'cabal-version: 3.4'."+ ]++-- | Smart constructor of 'Mixin', enforces invariant.+-- +-- @since 3.4.0.0+mkMixin :: PackageName -> LibraryName -> IncludeRenaming -> Mixin+mkMixin pn (LSubLibName uqn) incl+ | packageNameToUnqualComponentName pn == uqn+ = Mixin pn LMainLibName incl+mkMixin pn ln incl+ = Mixin pn ln incl++-- | Restore invariant+normaliseMixin :: Mixin -> Mixin+normaliseMixin (Mixin pn ln incl) = mkMixin pn ln incl
cabal/Cabal/Distribution/Types/Module.hs view
@@ -29,6 +29,7 @@ deriving (Generic, Read, Show, Eq, Ord, Typeable, Data) instance Binary Module+instance Structured Module instance Pretty Module where pretty (Module uid mod_name) =
cabal/Cabal/Distribution/Types/ModuleReexport.hs view
@@ -14,8 +14,7 @@ import Distribution.Types.PackageName import qualified Distribution.Compat.CharParsing as P-import Text.PrettyPrint ((<+>))-import qualified Text.PrettyPrint as Disp+import qualified Text.PrettyPrint as Disp -- ----------------------------------------------------------------------------- -- Module re-exports@@ -28,7 +27,7 @@ deriving (Eq, Generic, Read, Show, Typeable, Data) instance Binary ModuleReexport-+instance Structured ModuleReexport instance NFData ModuleReexport where rnf = genericRnf instance Pretty ModuleReexport where
cabal/Cabal/Distribution/Types/ModuleRenaming.hs view
@@ -21,7 +21,7 @@ import qualified Data.Map as Map import qualified Data.Set as Set import qualified Distribution.Compat.CharParsing as P-import Text.PrettyPrint (hsep, parens, punctuate, text, (<+>), comma)+import Text.PrettyPrint (hsep, parens, punctuate, text, comma) -- | Renaming applied to the modules provided by a package. -- The boolean indicates whether or not to also include all of the@@ -70,6 +70,7 @@ instance Binary ModuleRenaming where+instance Structured ModuleRenaming where instance NFData ModuleRenaming where rnf = genericRnf
cabal/Cabal/Distribution/Types/MungedPackageId.hs view
@@ -31,6 +31,7 @@ deriving (Generic, Read, Show, Eq, Ord, Typeable, Data) instance Binary MungedPackageId+instance Structured MungedPackageId -- | --
cabal/Cabal/Distribution/Types/MungedPackageName.hs view
@@ -34,6 +34,7 @@ deriving (Generic, Read, Show, Eq, Ord, Typeable, Data) instance Binary MungedPackageName+instance Structured MungedPackageName instance NFData MungedPackageName where rnf = genericRnf -- | Computes the package name for a library. If this is the public
cabal/Cabal/Distribution/Types/PackageDescription.hs view
@@ -28,8 +28,6 @@ module Distribution.Types.PackageDescription ( PackageDescription(..),- specVersion,- specVersion', license, license', buildType,@@ -84,10 +82,12 @@ import Distribution.Types.SourceRepo import Distribution.Types.HookedBuildInfo +import Distribution.CabalSpecVersion import Distribution.Compiler import Distribution.License import Distribution.Package import Distribution.Version+import Distribution.Utils.ShortText import qualified Distribution.SPDX as SPDX @@ -105,26 +105,22 @@ -- the following are required by all packages: -- | The version of the Cabal spec that this package description uses.- -- For historical reasons this is specified with a version range but- -- only ranges of the form @>= v@ make sense. We are in the process of- -- transitioning to specifying just a single version, not a range.- -- See also 'specVersion'.- specVersionRaw :: Either Version VersionRange,+ specVersion :: CabalSpecVersion, package :: PackageIdentifier, licenseRaw :: Either SPDX.License License, licenseFiles :: [FilePath],- copyright :: String,- maintainer :: String,- author :: String,- stability :: String,+ copyright :: !ShortText,+ maintainer :: !ShortText,+ author :: !ShortText,+ stability :: !ShortText, testedWith :: [(CompilerFlavor,VersionRange)],- homepage :: String,- pkgUrl :: String,- bugReports :: String,+ homepage :: !ShortText,+ pkgUrl :: !ShortText,+ bugReports :: !ShortText, sourceRepos :: [SourceRepo],- synopsis :: String, -- ^A one-line summary of this package- description :: String, -- ^A more verbose description of this package- category :: String,+ synopsis :: !ShortText, -- ^A one-line summary of this package+ description :: !ShortText, -- ^A more verbose description of this package+ category :: !ShortText, customFieldsPD :: [(String,String)], -- ^Custom fields starting -- with x-, stored in a -- simple assoc-list.@@ -152,31 +148,13 @@ deriving (Generic, Show, Read, Eq, Typeable, Data) instance Binary PackageDescription+instance Structured PackageDescription instance NFData PackageDescription where rnf = genericRnf instance Package PackageDescription where packageId = package --- | The version of the Cabal spec that this package should be interpreted--- against.------ Historically we used a version range but we are switching to using a single--- version. Currently we accept either. This function converts into a single--- version by ignoring upper bounds in the version range.----specVersion :: PackageDescription -> Version-specVersion = specVersion' . specVersionRaw---- |------ @since 2.2.0.0-specVersion' :: Either Version VersionRange -> Version-specVersion' (Left version) = version-specVersion' (Right versionRange) = case asVersionIntervals versionRange of- [] -> mkVersion [0]- ((LowerBound version _, _):_) -> version- -- | The SPDX 'LicenseExpression' of the package. -- -- @since 2.2.0.0@@ -206,7 +184,7 @@ -- @since 2.2 buildType :: PackageDescription -> BuildType buildType pkg- | specVersion pkg >= mkVersion [2,1]+ | specVersion pkg >= CabalSpecV2_2 = fromMaybe newDefault (buildTypeRaw pkg) | otherwise -- cabal-version < 2.1 = fromMaybe Custom (buildTypeRaw pkg)@@ -221,20 +199,20 @@ nullVersion, licenseRaw = Right UnspecifiedLicense, -- TODO: licenseFiles = [],- specVersionRaw = Right anyVersion,+ specVersion = CabalSpecV1_0, buildTypeRaw = Nothing,- copyright = "",- maintainer = "",- author = "",- stability = "",+ copyright = mempty,+ maintainer = mempty,+ author = mempty,+ stability = mempty, testedWith = [],- homepage = "",- pkgUrl = "",- bugReports = "",+ homepage = mempty,+ pkgUrl = mempty,+ bugReports = mempty, sourceRepos = [],- synopsis = "",- description = "",- category = "",+ synopsis = mempty,+ description = mempty,+ category = mempty, customFieldsPD = [], setupBuildInfo = Nothing, library = Nothing,@@ -473,6 +451,6 @@ <*> (traverse . L.buildInfo) f x6 -- benchmarks <*> pure a20 -- data files <*> pure a21 -- data dir- <*> pure a22 -- exta src files+ <*> pure a22 -- extra src files <*> pure a23 -- extra temp files <*> pure a24 -- extra doc files
cabal/Cabal/Distribution/Types/PackageDescription/Lens.hs view
@@ -1,5 +1,5 @@ {-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE RankNTypes #-} module Distribution.Types.PackageDescription.Lens ( PackageDescription, module Distribution.Types.PackageDescription.Lens,@@ -9,27 +9,29 @@ import Distribution.Compat.Prelude import Prelude () -import Distribution.Compiler (CompilerFlavor)-import Distribution.License (License)-import Distribution.ModuleName (ModuleName)-import Distribution.Types.Benchmark (Benchmark, benchmarkModules)-import Distribution.Types.Benchmark.Lens (benchmarkName, benchmarkBuildInfo)-import Distribution.Types.BuildInfo (BuildInfo)-import Distribution.Types.BuildType (BuildType)-import Distribution.Types.ComponentName (ComponentName(..))-import Distribution.Types.Executable (Executable, exeModules)-import Distribution.Types.Executable.Lens (exeName, exeBuildInfo)-import Distribution.Types.ForeignLib (ForeignLib, foreignLibModules)-import Distribution.Types.ForeignLib.Lens (foreignLibName, foreignLibBuildInfo)-import Distribution.Types.Library (Library, explicitLibModules)-import Distribution.Types.Library.Lens (libName, libBuildInfo)-import Distribution.Types.PackageDescription (PackageDescription)-import Distribution.Types.PackageId (PackageIdentifier)-import Distribution.Types.SetupBuildInfo (SetupBuildInfo)-import Distribution.Types.SourceRepo (SourceRepo)-import Distribution.Types.TestSuite (TestSuite, testModules)-import Distribution.Types.TestSuite.Lens (testName, testBuildInfo)-import Distribution.Version (Version, VersionRange)+import Distribution.CabalSpecVersion (CabalSpecVersion)+import Distribution.Compiler (CompilerFlavor)+import Distribution.License (License)+import Distribution.ModuleName (ModuleName)+import Distribution.Types.Benchmark (Benchmark, benchmarkModules)+import Distribution.Types.Benchmark.Lens (benchmarkBuildInfo, benchmarkName)+import Distribution.Types.BuildInfo (BuildInfo)+import Distribution.Types.BuildType (BuildType)+import Distribution.Types.ComponentName (ComponentName (..))+import Distribution.Types.Executable (Executable, exeModules)+import Distribution.Types.Executable.Lens (exeBuildInfo, exeName)+import Distribution.Types.ForeignLib (ForeignLib, foreignLibModules)+import Distribution.Types.ForeignLib.Lens (foreignLibBuildInfo, foreignLibName)+import Distribution.Types.Library (Library, explicitLibModules)+import Distribution.Types.Library.Lens (libBuildInfo, libName)+import Distribution.Types.PackageDescription (PackageDescription)+import Distribution.Types.PackageId (PackageIdentifier)+import Distribution.Types.SetupBuildInfo (SetupBuildInfo)+import Distribution.Types.SourceRepo (SourceRepo)+import Distribution.Types.TestSuite (TestSuite, testModules)+import Distribution.Types.TestSuite.Lens (testBuildInfo, testName)+import Distribution.Utils.ShortText (ShortText)+import Distribution.Version (VersionRange) import qualified Distribution.SPDX as SPDX import qualified Distribution.Types.PackageDescription as T@@ -42,23 +44,23 @@ licenseRaw f s = fmap (\x -> s { T.licenseRaw = x }) (f (T.licenseRaw s)) {-# INLINE licenseRaw #-} -licenseFiles :: Lens' PackageDescription [String]+licenseFiles :: Lens' PackageDescription [FilePath] licenseFiles f s = fmap (\x -> s { T.licenseFiles = x }) (f (T.licenseFiles s)) {-# INLINE licenseFiles #-} -copyright :: Lens' PackageDescription String+copyright :: Lens' PackageDescription ShortText copyright f s = fmap (\x -> s { T.copyright = x }) (f (T.copyright s)) {-# INLINE copyright #-} -maintainer :: Lens' PackageDescription String+maintainer :: Lens' PackageDescription ShortText maintainer f s = fmap (\x -> s { T.maintainer = x }) (f (T.maintainer s)) {-# INLINE maintainer #-} -author :: Lens' PackageDescription String+author :: Lens' PackageDescription ShortText author f s = fmap (\x -> s { T.author = x }) (f (T.author s)) {-# INLINE author #-} -stability :: Lens' PackageDescription String+stability :: Lens' PackageDescription ShortText stability f s = fmap (\x -> s { T.stability = x }) (f (T.stability s)) {-# INLINE stability #-} @@ -66,15 +68,15 @@ testedWith f s = fmap (\x -> s { T.testedWith = x }) (f (T.testedWith s)) {-# INLINE testedWith #-} -homepage :: Lens' PackageDescription String+homepage :: Lens' PackageDescription ShortText homepage f s = fmap (\x -> s { T.homepage = x }) (f (T.homepage s)) {-# INLINE homepage #-} -pkgUrl :: Lens' PackageDescription String+pkgUrl :: Lens' PackageDescription ShortText pkgUrl f s = fmap (\x -> s { T.pkgUrl = x }) (f (T.pkgUrl s)) {-# INLINE pkgUrl #-} -bugReports :: Lens' PackageDescription String+bugReports :: Lens' PackageDescription ShortText bugReports f s = fmap (\x -> s { T.bugReports = x }) (f (T.bugReports s)) {-# INLINE bugReports #-} @@ -82,15 +84,15 @@ sourceRepos f s = fmap (\x -> s { T.sourceRepos = x }) (f (T.sourceRepos s)) {-# INLINE sourceRepos #-} -synopsis :: Lens' PackageDescription String+synopsis :: Lens' PackageDescription ShortText synopsis f s = fmap (\x -> s { T.synopsis = x }) (f (T.synopsis s)) {-# INLINE synopsis #-} -description :: Lens' PackageDescription String+description :: Lens' PackageDescription ShortText description f s = fmap (\x -> s { T.description = x }) (f (T.description s)) {-# INLINE description #-} -category :: Lens' PackageDescription String+category :: Lens' PackageDescription ShortText category f s = fmap (\x -> s { T.category = x }) (f (T.category s)) {-# INLINE category #-} @@ -98,9 +100,9 @@ customFieldsPD f s = fmap (\x -> s { T.customFieldsPD = x }) (f (T.customFieldsPD s)) {-# INLINE customFieldsPD #-} -specVersionRaw :: Lens' PackageDescription (Either Version VersionRange)-specVersionRaw f s = fmap (\x -> s { T.specVersionRaw = x }) (f (T.specVersionRaw s))-{-# INLINE specVersionRaw #-}+specVersion :: Lens' PackageDescription CabalSpecVersion+specVersion f s = fmap (\x -> s { T.specVersion = x }) (f (T.specVersion s))+{-# INLINE specVersion #-} buildTypeRaw :: Lens' PackageDescription (Maybe BuildType) buildTypeRaw f s = fmap (\x -> s { T.buildTypeRaw = x }) (f (T.buildTypeRaw s))@@ -165,18 +167,18 @@ componentModules cname = case cname of CLibName name -> componentModules' name allLibraries libName explicitLibModules- CFLibName name -> + CFLibName name -> componentModules' name (foreignLibs . traverse) foreignLibName foreignLibModules- CExeName name -> + CExeName name -> componentModules' name (executables . traverse) exeName exeModules- CTestName name -> + CTestName name -> componentModules' name (testSuites . traverse) testName testModules CBenchName name -> componentModules' name (benchmarks . traverse) benchmarkName benchmarkModules where componentModules' :: (Eq name, Monoid r)- => name + => name -> Traversal' PackageDescription a -> Lens' a name -> (a -> [ModuleName])@@ -192,21 +194,21 @@ -- | @since 2.4 componentBuildInfo :: ComponentName -> Traversal' PackageDescription BuildInfo componentBuildInfo cname = case cname of- CLibName name -> + CLibName name -> componentBuildInfo' name allLibraries libName libBuildInfo- CFLibName name -> + CFLibName name -> componentBuildInfo' name (foreignLibs . traverse) foreignLibName foreignLibBuildInfo- CExeName name -> + CExeName name -> componentBuildInfo' name (executables . traverse) exeName exeBuildInfo- CTestName name -> + CTestName name -> componentBuildInfo' name (testSuites . traverse) testName testBuildInfo CBenchName name -> componentBuildInfo' name (benchmarks . traverse) benchmarkName benchmarkBuildInfo where componentBuildInfo' :: Eq name- => name + => name -> Traversal' PackageDescription a- -> Lens' a name + -> Lens' a name -> Traversal' a BuildInfo -> Traversal' PackageDescription BuildInfo componentBuildInfo' name pdL nameL biL =
cabal/Cabal/Distribution/Types/PackageId.hs view
@@ -1,5 +1,5 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-} module Distribution.Types.PackageId ( PackageIdentifier(..) , PackageId@@ -8,7 +8,7 @@ import Distribution.Compat.Prelude import Prelude () -import Distribution.Parsec (Parsec (..), simpleParsec)+import Distribution.Parsec (Parsec (..), simpleParsec) import Distribution.Pretty import Distribution.Types.PackageName import Distribution.Version (Version, nullVersion)@@ -29,6 +29,7 @@ deriving (Generic, Read, Show, Eq, Ord, Typeable, Data) instance Binary PackageIdentifier+instance Structured PackageIdentifier instance Pretty PackageIdentifier where pretty (PackageIdentifier n v)
cabal/Cabal/Distribution/Types/PackageName.hs view
@@ -2,7 +2,9 @@ {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric #-} module Distribution.Types.PackageName- ( PackageName, unPackageName, mkPackageName+ ( PackageName+ , unPackageName, mkPackageName+ , unPackageNameST, mkPackageNameST ) where import Prelude ()@@ -28,6 +30,10 @@ unPackageName :: PackageName -> String unPackageName (PackageName s) = fromShortText s +-- | @since 3.4.0.0+unPackageNameST :: PackageName -> ShortText+unPackageNameST (PackageName s) = s+ -- | Construct a 'PackageName' from a 'String' -- -- 'mkPackageName' is the inverse to 'unPackageName'@@ -39,6 +45,15 @@ mkPackageName :: String -> PackageName mkPackageName = PackageName . toShortText +-- | Construct a 'PackageName' from a 'ShortText'+--+-- Note: No validations are performed to ensure that the resulting+-- 'PackageName' is valid+--+-- @since 3.4.0.0+mkPackageNameST :: ShortText -> PackageName+mkPackageNameST = PackageName+ -- | 'mkPackageName' -- -- @since 2.0.0.2@@ -46,6 +61,7 @@ fromString = mkPackageName instance Binary PackageName+instance Structured PackageName instance Pretty PackageName where pretty = Disp.text . unPackageName
cabal/Cabal/Distribution/Types/PackageVersionConstraint.hs view
@@ -1,39 +1,74 @@ {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric #-}-module Distribution.Types.PackageVersionConstraint- ( PackageVersionConstraint(..)- ) where+module Distribution.Types.PackageVersionConstraint (+ PackageVersionConstraint(..),+ thisPackageVersionConstraint,+ simplifyPackageVersionConstraint,+) where import Distribution.Compat.Prelude import Prelude () import Distribution.Parsec import Distribution.Pretty+import Distribution.Types.PackageId import Distribution.Types.PackageName-import Distribution.Types.VersionRange+import Distribution.Types.Version+import Distribution.Types.VersionRange.Internal+import Distribution.Version (simplifyVersionRange) import qualified Distribution.Compat.CharParsing as P-import Text.PrettyPrint ((<+>)) -- | A version constraint on a package. Different from 'ExeDependency' and -- 'Dependency' since it does not specify the need for a component, not even -- the main library.--- There are a few places in the codebase where 'Dependency' is used where--- 'PackageVersionConstraint' should be used instead (#5570).+-- There are a few places in the codebase where 'Dependency' was used where+-- 'PackageVersionConstraint' is not used instead (#5570). data PackageVersionConstraint = PackageVersionConstraint PackageName VersionRange deriving (Generic, Read, Show, Eq, Typeable, Data) instance Binary PackageVersionConstraint+instance Structured PackageVersionConstraint instance NFData PackageVersionConstraint where rnf = genericRnf instance Pretty PackageVersionConstraint where- pretty (PackageVersionConstraint name ver) = pretty name <+> pretty ver+ -- Cannot do: PackageVersionConstraint have to be parseable+ -- as Dependency, due roundtrip problems. (e.g. talking to old ./Setup).+ --+ -- pretty (PackageVersionConstraint name (ThisVersion ver)) =+ -- pretty (PackageIdentifier name ver)+ pretty (PackageVersionConstraint name ver) =+ pretty name <+> pretty ver +-- |+--+-- >>> simpleParsec "foo" :: Maybe PackageVersionConstraint+-- Just (PackageVersionConstraint (PackageName "foo") (OrLaterVersion (mkVersion [0])))+--+-- >>> simpleParsec "foo >=2.0" :: Maybe PackageVersionConstraint+-- Just (PackageVersionConstraint (PackageName "foo") (OrLaterVersion (mkVersion [2,0])))+--+-- >>> simpleParsec "foo-2.0" :: Maybe PackageVersionConstraint+-- Just (PackageVersionConstraint (PackageName "foo") (ThisVersion (mkVersion [2,0])))+-- instance Parsec PackageVersionConstraint where parsec = do- name <- parsec- P.spaces- ver <- parsec <|> return anyVersion- P.spaces- return (PackageVersionConstraint name ver)+ PackageIdentifier name ver <- parsec+ if ver == nullVersion+ then do+ P.spaces+ vr <- parsec <|> return anyVersion+ P.spaces+ return (PackageVersionConstraint name vr)+ else+ pure (PackageVersionConstraint name (thisVersion ver)) +-- | @since 3.4.0.0+thisPackageVersionConstraint :: PackageIdentifier -> PackageVersionConstraint+thisPackageVersionConstraint (PackageIdentifier pn vr) =+ PackageVersionConstraint pn (thisVersion vr)++-- | @since 3.4.0.0+simplifyPackageVersionConstraint :: PackageVersionConstraint -> PackageVersionConstraint+simplifyPackageVersionConstraint (PackageVersionConstraint pn vr) =+ PackageVersionConstraint pn (simplifyVersionRange vr)
cabal/Cabal/Distribution/Types/PkgconfigDependency.hs view
@@ -14,7 +14,6 @@ import Distribution.Pretty import qualified Distribution.Compat.CharParsing as P-import Text.PrettyPrint ((<+>)) -- | Describes a dependency on a pkg-config library --@@ -25,11 +24,12 @@ deriving (Generic, Read, Show, Eq, Typeable, Data) instance Binary PkgconfigDependency+instance Structured PkgconfigDependency instance NFData PkgconfigDependency where rnf = genericRnf instance Pretty PkgconfigDependency where- pretty (PkgconfigDependency name ver) =- pretty name <+> pretty ver+ pretty (PkgconfigDependency name PcAnyVersion) = pretty name+ pretty (PkgconfigDependency name ver) = pretty name <+> pretty ver instance Parsec PkgconfigDependency where parsec = do
cabal/Cabal/Distribution/Types/PkgconfigName.hs view
@@ -47,6 +47,7 @@ fromString = mkPkgconfigName instance Binary PkgconfigName+instance Structured PkgconfigName -- pkg-config allows versions and other letters in package names, eg -- "gtk+-2.0" is a valid pkg-config package _name_. It then has a package@@ -55,7 +56,13 @@ pretty = Disp.text . unPkgconfigName instance Parsec PkgconfigName where- parsec = mkPkgconfigName <$> P.munch1 (\c -> isAlphaNum c || c `elem` "+-._")+ parsec = mkPkgconfigName <$> P.munch1 isNameChar where+ -- https://gitlab.haskell.org/ghc/ghc/issues/17752+ isNameChar '-' = True+ isNameChar '_' = True+ isNameChar '.' = True+ isNameChar '+' = True+ isNameChar c = isAlphaNum c instance NFData PkgconfigName where rnf (PkgconfigName pkg) = rnf pkg
cabal/Cabal/Distribution/Types/PkgconfigVersion.hs view
@@ -34,11 +34,20 @@ PkgconfigVersion a `compare` PkgconfigVersion b = rpmvercmp a b instance Binary PkgconfigVersion+instance Structured PkgconfigVersion instance NFData PkgconfigVersion where rnf = genericRnf instance Pretty PkgconfigVersion where pretty (PkgconfigVersion bs) = PP.text (BS8.unpack bs) +-- |+--+-- >>> simpleParsec "1.0.2n" :: Maybe PkgconfigVersion+-- Just (PkgconfigVersion "1.0.2n")+--+-- >>> simpleParsec "0.3.5+ds" :: Maybe PkgconfigVersion+-- Nothing+-- instance Parsec PkgconfigVersion where parsec = PkgconfigVersion . BS8.pack <$> P.munch1 predicate where predicate c = isAsciiAlphaNum c || c == '.' || c == '-'@@ -54,6 +63,11 @@ rpmvercmp a b = go0 (BS.unpack a) (BS.unpack b) where go0 :: [Word8] -> [Word8] -> Ordering+ -- if there is _any_ trailing "garbage", it seems to affect result+ -- https://github.com/haskell/cabal/issues/6805+ go0 [] [] = EQ+ go0 [] _ = LT+ go0 _ [] = GT go0 xs ys = go1 (dropNonAlnum8 xs) (dropNonAlnum8 ys) go1 :: [Word8] -> [Word8] -> Ordering
cabal/Cabal/Distribution/Types/PkgconfigVersionRange.hs view
@@ -18,6 +18,7 @@ import Distribution.Pretty import Distribution.Types.PkgconfigVersion import Distribution.Types.Version+import Distribution.Types.VersionInterval import Distribution.Types.VersionRange import qualified Data.ByteString.Char8 as BS8@@ -37,6 +38,7 @@ deriving (Generic, Read, Show, Eq, Typeable, Data) instance Binary PkgconfigVersionRange+instance Structured PkgconfigVersionRange instance NFData PkgconfigVersionRange where rnf = genericRnf instance Pretty PkgconfigVersionRange where@@ -68,7 +70,7 @@ csv <- askCabalSpecVersion if csv >= CabalSpecV3_0 then pkgconfigParser- else versionRangeToPkgconfigVersionRange <$> versionRangeParser P.integral+ else versionRangeToPkgconfigVersionRange <$> versionRangeParser P.integral csv -- "modern" parser of @pkg-config@ package versions. pkgconfigParser :: CabalParsing m => m PkgconfigVersionRange@@ -85,7 +87,7 @@ factor = parens expr <|> prim prim = do- op <- P.munch1 (`elem` "<>=^-") P.<?> "operator"+ op <- P.munch1 isOpChar P.<?> "operator" case op of "-" -> anyPkgconfigVersion <$ (P.string "any" *> P.spaces) @@ -97,6 +99,14 @@ _ -> P.unexpected $ "Unknown version operator " ++ show op + -- https://gitlab.haskell.org/ghc/ghc/issues/17752+ isOpChar '<' = True+ isOpChar '=' = True+ isOpChar '>' = True+ isOpChar '^' = True+ isOpChar '-' = True+ isOpChar _ = False+ afterOp f = do P.spaces v <- parsec@@ -133,10 +143,19 @@ versionToPkgconfigVersion = PkgconfigVersion . BS8.pack . prettyShow versionRangeToPkgconfigVersionRange :: VersionRange -> PkgconfigVersionRange-versionRangeToPkgconfigVersionRange = foldVersionRange- anyPkgconfigVersion- (PcThisVersion . versionToPkgconfigVersion)- (PcLaterVersion . versionToPkgconfigVersion)- (PcEarlierVersion . versionToPkgconfigVersion)- PcUnionVersionRanges- PcIntersectVersionRanges+versionRangeToPkgconfigVersionRange vr+ | isAnyVersion vr+ = PcAnyVersion+ | otherwise+ = case asVersionIntervals vr of+ [] -> PcEarlierVersion (PkgconfigVersion (BS8.pack "0"))+ (i:is) -> foldl (\r j -> PcUnionVersionRanges r (conv j)) (conv i) is+ where+ conv (LowerBound v b, NoUpperBound) = convL v b+ conv (LowerBound v b, UpperBound u c) = PcIntersectVersionRanges (convL v b) (convU u c)++ convL v ExclusiveBound = PcLaterVersion (versionToPkgconfigVersion v)+ convL v InclusiveBound = PcOrLaterVersion (versionToPkgconfigVersion v)++ convU v ExclusiveBound = PcEarlierVersion (versionToPkgconfigVersion v)+ convU v InclusiveBound = PcOrEarlierVersion (versionToPkgconfigVersion v)
cabal/Cabal/Distribution/Types/SetupBuildInfo.hs view
@@ -28,7 +28,7 @@ deriving (Generic, Show, Eq, Read, Typeable, Data) instance Binary SetupBuildInfo-+instance Structured SetupBuildInfo instance NFData SetupBuildInfo where rnf = genericRnf instance Monoid SetupBuildInfo where
cabal/Cabal/Distribution/Types/SourceRepo.hs view
@@ -5,6 +5,7 @@ SourceRepo(..), RepoKind(..), RepoType(..),+ KnownRepoType (..), knownRepoTypes, emptySourceRepo, classifyRepoType,@@ -21,6 +22,7 @@ import qualified Distribution.Compat.CharParsing as P import qualified Text.PrettyPrint as Disp+import qualified Data.Map.Strict as M -- ------------------------------------------------------------ -- * Source repos@@ -95,7 +97,7 @@ } instance Binary SourceRepo-+instance Structured SourceRepo instance NFData SourceRepo where rnf = genericRnf -- | What this repo info is for, what it represents.@@ -115,27 +117,45 @@ deriving (Eq, Generic, Ord, Read, Show, Typeable, Data) instance Binary RepoKind-+instance Structured RepoKind instance NFData RepoKind where rnf = genericRnf -- | An enumeration of common source control systems. The fields used in the -- 'SourceRepo' depend on the type of repo. The tools and methods used to -- obtain and track the repo depend on the repo type. ---data RepoType = Darcs | Git | SVN | CVS- | Mercurial | GnuArch | Bazaar | Monotone+data KnownRepoType = Darcs | Git | SVN | CVS+ | Mercurial | GnuArch | Bazaar | Monotone+ | Pijul -- ^ @since 3.4.0.0+ deriving (Eq, Generic, Ord, Read, Show, Typeable, Data, Enum, Bounded)++instance Binary KnownRepoType+instance Structured KnownRepoType+instance NFData KnownRepoType where rnf = genericRnf++instance Parsec KnownRepoType where+ parsec = do+ str <- P.munch1 isIdent+ maybe+ (P.unexpected $ "Could not parse KnownRepoType from " ++ str)+ return+ (M.lookup str knownRepoTypeMap)++instance Pretty KnownRepoType where+ pretty = Disp.text . lowercase . show++data RepoType = KnownRepoType KnownRepoType | OtherRepoType String deriving (Eq, Generic, Ord, Read, Show, Typeable, Data) instance Binary RepoType-+instance Structured RepoType instance NFData RepoType where rnf = genericRnf -knownRepoTypes :: [RepoType]-knownRepoTypes = [Darcs, Git, SVN, CVS- ,Mercurial, GnuArch, Bazaar, Monotone]+knownRepoTypes :: [KnownRepoType]+knownRepoTypes = [minBound .. maxBound] -repoTypeAliases :: RepoType -> [String]+repoTypeAliases :: KnownRepoType -> [String] repoTypeAliases Bazaar = ["bzr"] repoTypeAliases Mercurial = ["hg"] repoTypeAliases GnuArch = ["arch"]@@ -155,20 +175,27 @@ "this" -> RepoThis _ -> RepoKindUnknown name -instance Pretty RepoType where- pretty (OtherRepoType other) = Disp.text other- pretty other = Disp.text (lowercase (show other))- instance Parsec RepoType where parsec = classifyRepoType <$> P.munch1 isIdent +instance Pretty RepoType where+ pretty (OtherRepoType other) = Disp.text other+ pretty (KnownRepoType t) = pretty t+ classifyRepoType :: String -> RepoType classifyRepoType s =- fromMaybe (OtherRepoType s) $ lookup (lowercase s) repoTypeMap- where- repoTypeMap = [ (name, repoType')- | repoType' <- knownRepoTypes- , name <- prettyShow repoType' : repoTypeAliases repoType' ]+ maybe+ (OtherRepoType s)+ KnownRepoType+ (M.lookup (lowercase s) knownRepoTypeMap)++knownRepoTypeMap :: Map String KnownRepoType+knownRepoTypeMap =+ M.fromList+ [ (name, repoType')+ | repoType' <- knownRepoTypes+ , name <- prettyShow repoType' : repoTypeAliases repoType'+ ] isIdent :: Char -> Bool isIdent c = isAlphaNum c || c == '_' || c == '-'
cabal/Cabal/Distribution/Types/TestSuite.hs view
@@ -35,6 +35,7 @@ buildInfo f l = (\x -> l { testBuildInfo = x }) <$> f (testBuildInfo l) instance Binary TestSuite+instance Structured TestSuite instance NFData TestSuite where rnf = genericRnf
cabal/Cabal/Distribution/Types/TestSuiteInterface.hs view
@@ -39,6 +39,7 @@ deriving (Eq, Generic, Read, Show, Typeable, Data) instance Binary TestSuiteInterface+instance Structured TestSuiteInterface instance NFData TestSuiteInterface where rnf = genericRnf
cabal/Cabal/Distribution/Types/TestType.hs view
@@ -1,5 +1,6 @@ {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE OverloadedStrings #-} module Distribution.Types.TestType ( TestType(..),@@ -12,7 +13,7 @@ import Distribution.Parsec import Distribution.Pretty-import Text.PrettyPrint (char, text)+import Text.PrettyPrint (char, text) -- | The \"test-type\" field in the test suite stanza. --@@ -22,6 +23,7 @@ deriving (Generic, Show, Read, Eq, Typeable, Data) instance Binary TestType+instance Structured TestType instance NFData TestType where rnf = genericRnf
cabal/Cabal/Distribution/Types/UnitId.hs view
@@ -66,6 +66,7 @@ deriving (Generic, Read, Show, Eq, Ord, Typeable, Data, NFData) instance Binary UnitId+instance Structured UnitId -- | The textual format for 'UnitId' coincides with the format -- GHC accepts for @-package-id@.@@ -77,7 +78,13 @@ -- GHC accepts for @-package-id@. -- instance Parsec UnitId where- parsec = mkUnitId <$> P.munch1 (\c -> isAlphaNum c || c `elem` "-_.+")+ parsec = mkUnitId <$> P.munch1 isUnitChar where+ -- https://gitlab.haskell.org/ghc/ghc/issues/17752+ isUnitChar '-' = True+ isUnitChar '_' = True+ isUnitChar '.' = True+ isUnitChar '+' = True+ isUnitChar c = isAlphaNum c -- | If you need backwards compatibility, consider using 'display' -- instead, which is supported by all versions of Cabal.@@ -113,6 +120,8 @@ -- unfilled holes. newtype DefUnitId = DefUnitId { unDefUnitId :: UnitId } deriving (Generic, Read, Show, Eq, Ord, Typeable, Data, Binary, NFData, Pretty)++instance Structured DefUnitId -- Workaround for a GHC 8.0.1 bug, see -- https://github.com/haskell/cabal/issues/4793#issuecomment-334258288
cabal/Cabal/Distribution/Types/UnqualComponentName.hs view
@@ -2,7 +2,7 @@ {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} module Distribution.Types.UnqualComponentName- ( UnqualComponentName, unUnqualComponentName, mkUnqualComponentName+ ( UnqualComponentName, unUnqualComponentName, unUnqualComponentNameST, mkUnqualComponentName , packageNameToUnqualComponentName, unqualComponentNameToPackageName ) where @@ -31,6 +31,10 @@ unUnqualComponentName :: UnqualComponentName -> String unUnqualComponentName (UnqualComponentName s) = fromShortText s +-- | @since 3.4.0.0+unUnqualComponentNameST :: UnqualComponentName -> ShortText+unUnqualComponentNameST (UnqualComponentName s) = s+ -- | Construct a 'UnqualComponentName' from a 'String' -- -- 'mkUnqualComponentName' is the inverse to 'unUnqualComponentName'@@ -49,6 +53,7 @@ fromString = mkUnqualComponentName instance Binary UnqualComponentName+instance Structured UnqualComponentName instance Pretty UnqualComponentName where pretty = showToken . unUnqualComponentName@@ -73,7 +78,7 @@ -- -- @since 2.0.0.2 packageNameToUnqualComponentName :: PackageName -> UnqualComponentName-packageNameToUnqualComponentName = mkUnqualComponentName . unPackageName+packageNameToUnqualComponentName = UnqualComponentName . unPackageNameST -- | Converts an unqualified component name to a package name --@@ -85,4 +90,4 @@ -- -- @since 2.0.0.2 unqualComponentNameToPackageName :: UnqualComponentName -> PackageName-unqualComponentNameToPackageName = mkPackageName . unUnqualComponentName+unqualComponentNameToPackageName = mkPackageNameST . unUnqualComponentNameST
cabal/Cabal/Distribution/Types/Version.hs view
@@ -81,6 +81,7 @@ return (mkVersion v) instance Binary Version+instance Structured Version instance NFData Version where rnf (PV0 _) = ()
cabal/Cabal/Distribution/Types/VersionInterval.hs view
@@ -26,7 +26,7 @@ import Control.Exception (assert) import Distribution.Types.Version-import Distribution.Types.VersionRange+import Distribution.Types.VersionRange.Internal -- NonEmpty import qualified Prelude (foldr1)@@ -200,15 +200,18 @@ -- | Convert a 'VersionRange' to a sequence of version intervals. -- toVersionIntervals :: VersionRange -> VersionIntervals-toVersionIntervals = foldVersionRange- ( chkIvl (minLowerBound, NoUpperBound))- (\v -> chkIvl (LowerBound v InclusiveBound, UpperBound v InclusiveBound))- (\v -> chkIvl (LowerBound v ExclusiveBound, NoUpperBound))- (\v -> if isVersion0 v then VersionIntervals [] else- chkIvl (minLowerBound, UpperBound v ExclusiveBound))- unionVersionIntervals- intersectVersionIntervals- where+toVersionIntervals = cataVersionRange alg where+ alg (ThisVersionF v) = chkIvl (LowerBound v InclusiveBound, UpperBound v InclusiveBound)+ alg (LaterVersionF v) = chkIvl (LowerBound v ExclusiveBound, NoUpperBound)+ alg (OrLaterVersionF v) = chkIvl (LowerBound v InclusiveBound, NoUpperBound)+ alg (EarlierVersionF v)+ | isVersion0 v = VersionIntervals []+ | otherwise = chkIvl (minLowerBound, UpperBound v ExclusiveBound)+ alg (OrEarlierVersionF v) = chkIvl (minLowerBound, UpperBound v InclusiveBound)+ alg (MajorBoundVersionF v) = chkIvl (LowerBound v InclusiveBound, UpperBound (majorUpperBound v) ExclusiveBound)+ alg (UnionVersionRangesF v1 v2) = unionVersionIntervals v1 v2+ alg (IntersectVersionRangesF v1 v2) = intersectVersionIntervals v1 v2+ chkIvl interval = checkInvariant (VersionIntervals [interval]) -- | Convert a 'VersionIntervals' value back into a 'VersionRange' expression@@ -223,9 +226,6 @@ interval (LowerBound v InclusiveBound) (UpperBound v' InclusiveBound) | v == v' = thisVersion v- interval (LowerBound v InclusiveBound)- (UpperBound v' ExclusiveBound) | isWildcardRange v v'- = withinVersion v interval l u = lowerBound l `intersectVersionRanges'` upperBound u lowerBound (LowerBound v InclusiveBound)
cabal/Cabal/Distribution/Types/VersionRange.hs view
@@ -30,6 +30,8 @@ embedVersionRange, -- ** Utilities+ isAnyVersion,+ isAnyVersionLight, wildcardUpperBound, majorUpperBound, isWildcardRange,@@ -38,8 +40,8 @@ import Distribution.Compat.Prelude import Distribution.Types.Version+import Distribution.Types.VersionInterval import Distribution.Types.VersionRange.Internal-import Distribution.Utils.Generic import Prelude () -- | Fold over the basic syntactic structure of a 'VersionRange'.@@ -57,26 +59,19 @@ -> (a -> a -> a) -- ^ @\"_ || _\"@ union -> (a -> a -> a) -- ^ @\"_ && _\"@ intersection -> VersionRange -> a-foldVersionRange anyv this later earlier union intersect = fold+foldVersionRange _any this later earlier union intersect = fold where fold = cataVersionRange alg - alg AnyVersionF = anyv alg (ThisVersionF v) = this v alg (LaterVersionF v) = later v alg (OrLaterVersionF v) = union (this v) (later v) alg (EarlierVersionF v) = earlier v alg (OrEarlierVersionF v) = union (this v) (earlier v)- alg (WildcardVersionF v) = fold (wildcard v) alg (MajorBoundVersionF v) = fold (majorBound v) alg (UnionVersionRangesF v1 v2) = union v1 v2 alg (IntersectVersionRangesF v1 v2) = intersect v1 v2- alg (VersionRangeParensF v) = v - wildcard v = intersectVersionRanges- (orLaterVersion v)- (earlierVersion (wildcardUpperBound v))- majorBound v = intersectVersionRanges (orLaterVersion v) (earlierVersion (majorUpperBound v))@@ -104,12 +99,11 @@ -- | Remove 'VersionRangeParens' constructors. --+-- Since version 3.4 this function is 'id', there aren't 'VersionRangeParens' constructor in 'VersionRange' anymore.+-- -- @since 2.2 stripParensVersionRange :: VersionRange -> VersionRange-stripParensVersionRange = hyloVersionRange embed projectVersionRange- where- embed (VersionRangeParensF vr) = vr- embed vr = embedVersionRange vr+stripParensVersionRange = id -- | Does this version fall within the given range? --@@ -124,16 +118,35 @@ (||) (&&) +-- | Does this 'VersionRange' place any restriction on the 'Version' or is it+-- in fact equivalent to 'AnyVersion'.+--+-- Note this is a semantic check, not simply a syntactic check. So for example+-- the following is @True@ (for all @v@).+--+-- > isAnyVersion (EarlierVersion v `UnionVersionRanges` orLaterVersion v)+--+isAnyVersion :: VersionRange -> Bool+isAnyVersion vr = case asVersionIntervals vr of+ [(LowerBound v InclusiveBound, NoUpperBound)] -> v == version0+ _ -> False++-- A fast and non-precise version of 'isAnyVersion',+-- returns 'True' only for @>= 0@ 'VersionRange's.+--+-- /Do not use/. The "VersionIntervals don't destroy MajorBoundVersion"+-- https://github.com/haskell/cabal/pull/6736 pull-request+-- will change 'simplifyVersionRange' to properly preserve semantics.+-- Then we can use it to normalise 'VersionRange's in tests.+--+isAnyVersionLight :: VersionRange -> Bool+isAnyVersionLight (OrLaterVersion v) = v == version0+isAnyVersionLight _vr = False+ ---------------------------- -- Wildcard range utilities -- --- | @since 2.2-wildcardUpperBound :: Version -> Version-wildcardUpperBound = alterVersion $- \lowerBound -> case unsnoc lowerBound of- Nothing -> []- Just (xs, x) -> xs ++ [x + 1] isWildcardRange :: Version -> Version -> Bool isWildcardRange ver1 ver2 = check (versionNumbers ver1) (versionNumbers ver2)
cabal/Cabal/Distribution/Types/VersionRange/Internal.hs view
@@ -4,6 +4,7 @@ {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE DeriveTraversable #-} {-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-} -- | The only purpose of this module is to prevent the export of@@ -30,6 +31,7 @@ , versionRangeParser , majorUpperBound+ , wildcardUpperBound ) where import Distribution.Compat.Prelude@@ -39,28 +41,25 @@ import Distribution.CabalSpecVersion import Distribution.Parsec import Distribution.Pretty-import Text.PrettyPrint ((<+>))+import Distribution.Utils.Generic (unsnoc) import qualified Distribution.Compat.CharParsing as P import qualified Distribution.Compat.DList as DList import qualified Text.PrettyPrint as Disp data VersionRange- = AnyVersion- | ThisVersion Version -- = version+ = ThisVersion Version -- = version | LaterVersion Version -- > version (NB. not >=) | OrLaterVersion Version -- >= version | EarlierVersion Version -- < version | OrEarlierVersion Version -- <= version- | WildcardVersion Version -- == ver.* (same as >= ver && < ver+1) | MajorBoundVersion Version -- @^>= ver@ (same as >= ver && < MAJ(ver)+1) | UnionVersionRanges VersionRange VersionRange | IntersectVersionRanges VersionRange VersionRange- | VersionRangeParens VersionRange -- just '(exp)' parentheses syntax deriving ( Data, Eq, Generic, Read, Show, Typeable ) instance Binary VersionRange-+instance Structured VersionRange instance NFData VersionRange where rnf = genericRnf -- | The version range @-any@. That is, a version range containing all@@ -69,18 +68,17 @@ -- > withinRange v anyVersion = True -- anyVersion :: VersionRange-anyVersion = AnyVersion+anyVersion = OrLaterVersion (mkVersion [0]) -- | The empty version range, that is a version range containing no versions. -- -- This can be constructed using any unsatisfiable version range expression,--- for example @> 1 && < 1@.+-- for example @< 0@. -- -- > withinRange v noVersion = False -- noVersion :: VersionRange-noVersion = IntersectVersionRanges (LaterVersion v) (EarlierVersion v)- where v = mkVersion [1]+noVersion = EarlierVersion (mkVersion [0]) -- | The version range @== v@ --@@ -150,7 +148,9 @@ -- > upper (Version lower t) = Version (init lower ++ [last lower + 1]) t -- withinVersion :: Version -> VersionRange-withinVersion = WildcardVersion+withinVersion v = intersectVersionRanges+ (orLaterVersion v)+ (earlierVersion (wildcardUpperBound v)) -- | The version range @^>= v@. --@@ -168,33 +168,27 @@ -- -- @since 2.2 data VersionRangeF a- = AnyVersionF- | ThisVersionF Version -- = version+ = ThisVersionF Version -- = version | LaterVersionF Version -- > version (NB. not >=) | OrLaterVersionF Version -- >= version | EarlierVersionF Version -- < version | OrEarlierVersionF Version -- <= version- | WildcardVersionF Version -- == ver.* (same as >= ver && < ver+1) | MajorBoundVersionF Version -- @^>= ver@ (same as >= ver && < MAJ(ver)+1) | UnionVersionRangesF a a | IntersectVersionRangesF a a- | VersionRangeParensF a deriving ( Data, Eq, Generic, Read, Show, Typeable , Functor, Foldable, Traversable ) -- | @since 2.2 projectVersionRange :: VersionRange -> VersionRangeF VersionRange-projectVersionRange AnyVersion = AnyVersionF projectVersionRange (ThisVersion v) = ThisVersionF v projectVersionRange (LaterVersion v) = LaterVersionF v projectVersionRange (OrLaterVersion v) = OrLaterVersionF v projectVersionRange (EarlierVersion v) = EarlierVersionF v projectVersionRange (OrEarlierVersion v) = OrEarlierVersionF v-projectVersionRange (WildcardVersion v) = WildcardVersionF v projectVersionRange (MajorBoundVersion v) = MajorBoundVersionF v projectVersionRange (UnionVersionRanges a b) = UnionVersionRangesF a b projectVersionRange (IntersectVersionRanges a b) = IntersectVersionRangesF a b-projectVersionRange (VersionRangeParens a) = VersionRangeParensF a -- | Fold 'VersionRange'. --@@ -204,17 +198,14 @@ -- | @since 2.2 embedVersionRange :: VersionRangeF VersionRange -> VersionRange-embedVersionRange AnyVersionF = AnyVersion embedVersionRange (ThisVersionF v) = ThisVersion v embedVersionRange (LaterVersionF v) = LaterVersion v embedVersionRange (OrLaterVersionF v) = OrLaterVersion v embedVersionRange (EarlierVersionF v) = EarlierVersion v embedVersionRange (OrEarlierVersionF v) = OrEarlierVersion v-embedVersionRange (WildcardVersionF v) = WildcardVersion v embedVersionRange (MajorBoundVersionF v) = MajorBoundVersion v embedVersionRange (UnionVersionRangesF a b) = UnionVersionRanges a b embedVersionRange (IntersectVersionRangesF a b) = IntersectVersionRanges a b-embedVersionRange (VersionRangeParensF a) = VersionRangeParens a -- | Unfold 'VersionRange'. --@@ -234,34 +225,98 @@ -- Parsec & Pretty ------------------------------------------------------------------------------- +-- |+--+-- >>> fmap pretty (simpleParsec' CabalSpecV1_6 "== 3.2.*" :: Maybe VersionRange)+-- Just >=3.2 && <3.3+--+-- >>> fmap (prettyVersioned CabalSpecV1_6) (simpleParsec' CabalSpecV1_6 "== 3.2.*" :: Maybe VersionRange)+-- Just ==3.2.*+--+-- >>> fmap pretty (simpleParsec' CabalSpecV1_6 "-any" :: Maybe VersionRange)+-- Just >=0+--+-- >>> fmap (prettyVersioned CabalSpecV1_6) (simpleParsec' CabalSpecV1_6 "-any" :: Maybe VersionRange)+-- Just >=0+-- instance Pretty VersionRange where- pretty = fst . cataVersionRange alg- where- alg AnyVersionF = (Disp.text "-any", 0 :: Int)- alg (ThisVersionF v) = (Disp.text "==" <<>> pretty v, 0)- alg (LaterVersionF v) = (Disp.char '>' <<>> pretty v, 0)- alg (OrLaterVersionF v) = (Disp.text ">=" <<>> pretty v, 0)- alg (EarlierVersionF v) = (Disp.char '<' <<>> pretty v, 0)- alg (OrEarlierVersionF v) = (Disp.text "<=" <<>> pretty v, 0)- alg (WildcardVersionF v) = (Disp.text "==" <<>> dispWild v, 0)- alg (MajorBoundVersionF v) = (Disp.text "^>=" <<>> pretty v, 0)- alg (UnionVersionRangesF (r1, p1) (r2, p2)) =- (punct 1 p1 r1 <+> Disp.text "||" <+> punct 2 p2 r2 , 2)- alg (IntersectVersionRangesF (r1, p1) (r2, p2)) =- (punct 0 p1 r1 <+> Disp.text "&&" <+> punct 1 p2 r2 , 1)- alg (VersionRangeParensF (r, _)) =- (Disp.parens r, 0)+ pretty = prettyVersioned cabalSpecLatest - dispWild ver =- Disp.hcat (Disp.punctuate (Disp.char '.')- (map Disp.int $ versionNumbers ver))- <<>> Disp.text ".*"+ prettyVersioned csv+ | csv > CabalSpecV1_6 = prettyVersionRange+ | otherwise = prettyVersionRange16 - punct p p' | p < p' = Disp.parens- | otherwise = id+prettyVersionRange :: VersionRange -> Disp.Doc+prettyVersionRange = fst . cataVersionRange alg+ where+ alg :: VersionRangeF (Disp.Doc, Int) -> (Disp.Doc, Int)+ alg (ThisVersionF v) = (Disp.text "==" <<>> pretty v, 0)+ alg (LaterVersionF v) = (Disp.char '>' <<>> pretty v, 0)+ alg (OrLaterVersionF v) = (Disp.text ">=" <<>> pretty v, 0)+ alg (EarlierVersionF v) = (Disp.char '<' <<>> pretty v, 0)+ alg (OrEarlierVersionF v) = (Disp.text "<=" <<>> pretty v, 0)+ alg (MajorBoundVersionF v) = (Disp.text "^>=" <<>> pretty v, 0)+ alg (UnionVersionRangesF (r1, p1) (r2, p2)) =+ (punct 1 p1 r1 <+> Disp.text "||" <+> punct 2 p2 r2 , 2)+ alg (IntersectVersionRangesF (r1, p1) (r2, p2)) =+ (punct 0 p1 r1 <+> Disp.text "&&" <+> punct 1 p2 r2 , 1) + punct p p' | p < p' = Disp.parens+ | otherwise = id++-- | Don't use && and || operators. If possible.+prettyVersionRange16 :: VersionRange -> Disp.Doc+prettyVersionRange16 (IntersectVersionRanges (OrLaterVersion v) (EarlierVersion u))+ | u == wildcardUpperBound v+ = Disp.text "==" <<>> dispWild v+ where+ dispWild ver =+ Disp.hcat (Disp.punctuate (Disp.char '.')+ (map Disp.int $ versionNumbers ver))+ <<>> Disp.text ".*"++prettyVersionRange16 vr = prettyVersionRange vr++-- |+--+-- >>> simpleParsec "^>= 3.4" :: Maybe VersionRange+-- Just (MajorBoundVersion (mkVersion [3,4]))+--+-- Small history:+--+-- @-any@ and @-none@ removed in 3.4+-- Use @>=0@ and @<0@ instead.+--+-- >>> map (`simpleParsec'` "-none") [CabalSpecV3_0, CabalSpecV3_4] :: [Maybe VersionRange]+-- [Just (EarlierVersion (mkVersion [0])),Nothing]+--+-- Set operations are introduced in 3.0+--+-- >>> map (`simpleParsec'` "^>= { 1.2 , 1.3 }") [CabalSpecV2_4, CabalSpecV3_0] :: [Maybe VersionRange]+-- [Nothing,Just (UnionVersionRanges (MajorBoundVersion (mkVersion [1,2])) (MajorBoundVersion (mkVersion [1,3])))]+--+-- @^>=@ is introduced in 2.0+--+-- >>> map (`simpleParsec'` "^>=1.2") [CabalSpecV1_24, CabalSpecV2_0] :: [Maybe VersionRange]+-- [Nothing,Just (MajorBoundVersion (mkVersion [1,2]))]+--+-- @-none@ is introduced in 1.22+--+-- >>> map (`simpleParsec'` "-none") [CabalSpecV1_20, CabalSpecV1_22] :: [Maybe VersionRange]+-- [Nothing,Just (EarlierVersion (mkVersion [0]))]+--+-- Operators are introduced in 1.8. Issues only a warning.+--+-- >>> map (`simpleParsecW'` "== 1 || ==2") [CabalSpecV1_6, CabalSpecV1_8] :: [Maybe VersionRange]+-- [Nothing,Just (UnionVersionRanges (ThisVersion (mkVersion [1])) (ThisVersion (mkVersion [2])))]+--+-- Wild-version ranges are introduced in 1.6. Issues only a warning.+--+-- >>> map (`simpleParsecW'` "== 1.2.*") [CabalSpecV1_4, CabalSpecV1_6] :: [Maybe VersionRange]+-- [Nothing,Just (IntersectVersionRanges (OrLaterVersion (mkVersion [1,2])) (EarlierVersion (mkVersion [1,3])))]+-- instance Parsec VersionRange where- parsec = versionRangeParser versionDigitParser+ parsec = askCabalSpecVersion >>= versionRangeParser versionDigitParser -- | 'VersionRange' parser parametrised by version digit parser --@@ -270,13 +325,14 @@ -- versions, 'PkgConfigVersionRange'. -- -- @since 3.0-versionRangeParser :: forall m. CabalParsing m => m Int -> m VersionRange-versionRangeParser digitParser = expr+versionRangeParser :: forall m. CabalParsing m => m Int -> CabalSpecVersion -> m VersionRange+versionRangeParser digitParser csv = expr where expr = do P.spaces t <- term P.spaces (do _ <- P.string "||"+ checkOp P.spaces e <- expr return (unionVersionRanges t e)@@ -285,6 +341,7 @@ term = do f <- factor P.spaces (do _ <- P.string "&&"+ checkOp P.spaces t <- term return (intersectVersionRanges f t)@@ -293,13 +350,14 @@ factor = parens expr <|> prim prim = do- op <- P.munch1 (`elem` "<>=^-") P.<?> "operator"+ op <- P.munch1 isOpChar P.<?> "operator" case op of "-" -> anyVersion <$ P.string "any" <|> P.string "none" *> noVersion' "==" -> do P.spaces (do (wild, v) <- verOrWild+ checkWild wild pure $ (if wild then withinVersion else thisVersion) v <|> (verSet' thisVersion =<< verSet))@@ -325,13 +383,42 @@ ">" -> pure $ laterVersion v _ -> fail $ "Unknown version operator " ++ show op - -- Note: There are other features:- -- && and || since 1.8- -- x.y.* (wildcard) since 1.6+ -- Cannot be warning+ -- On 2020-03-16 there was around 27400 files on Hackage failing to parse due this+ -- For example https://hackage.haskell.org/package/haxr-3000.0.0/haxr.cabal+ --+ checkOp = when (csv < CabalSpecV1_8) $+ parsecWarning PWTVersionOperator $ unwords+ [ "version operators used."+ , "To use version operators the package needs to specify at least 'cabal-version: >= 1.8'."+ ] + -- Cannot be warning+ -- On 2020-03-16 there was 46 files on Hackage failing to parse due this+ -- For example https://hackage.haskell.org/package/derive-0.1.2/derive.cabal+ --+ checkWild False = pure ()+ checkWild True = when (csv < CabalSpecV1_6) $+ parsecWarning PWTVersionWildcard $ unwords+ [ "Wildcard syntax used."+ , "To use version wildcards the package needs to specify at least 'cabal-version: >= 1.6'."+ ]++ -- https://gitlab.haskell.org/ghc/ghc/issues/17752+ isOpChar '<' = True+ isOpChar '=' = True+ isOpChar '>' = True+ isOpChar '^' = True+ isOpChar '-' = csv < CabalSpecV3_4+ -- https://github.com/haskell/cabal/issues/6589+ -- Unfortunately we have must not consume the dash,+ -- as otherwise following parts may not be parsed.+ --+ -- i.e. we cannot fail here with good error.+ isOpChar _ = False+ -- -none version range is available since 1.22- noVersion' = do- csv <- askCabalSpecVersion+ noVersion' = if csv >= CabalSpecV1_22 then pure noVersion else fail $ unwords@@ -342,8 +429,7 @@ ] -- ^>= is available since 2.0- majorBoundVersion' v = do- csv <- askCabalSpecVersion+ majorBoundVersion' v = if csv >= CabalSpecV2_0 then pure $ majorBoundVersion v else fail $ unwords@@ -359,8 +445,7 @@ embed vr = embedVersionRange vr -- version set notation (e.g. "== { 0.0.1.0, 0.0.2.0, 0.1.0.0 }")- verSet' op vs = do- csv <- askCabalSpecVersion+ verSet' op vs = if csv >= CabalSpecV3_0 then pure $ foldr1 unionVersionRanges (fmap op vs) else fail $ unwords@@ -404,9 +489,10 @@ parens p = P.between ((P.char '(' P.<?> "opening paren") >> P.spaces) (P.char ')' >> P.spaces)- (do a <- p+ $ do+ a <- p P.spaces- return (VersionRangeParens a))+ return a tags :: CabalParsing m => m () tags = do@@ -431,3 +517,10 @@ [] -> [0,1] -- should not happen [m1] -> [m1,1] -- e.g. version '1' (m1:m2:_) -> [m1,m2+1]++-- | @since 2.2+wildcardUpperBound :: Version -> Version+wildcardUpperBound = alterVersion $+ \lowerBound -> case unsnoc lowerBound of+ Nothing -> []+ Just (xs, x) -> xs ++ [x + 1]
cabal/Cabal/Distribution/Utils/Generic.hs view
@@ -77,6 +77,11 @@ unsnoc, unsnocNE, + -- * Triples+ fstOf3,+ sndOf3,+ trdOf3,+ -- * FilePath stuff isAbsoluteOnAnyPlatform, isRelativeOnAnyPlatform,@@ -90,12 +95,9 @@ import Data.Bits ((.&.), (.|.), shiftL) import Data.List ( isInfixOf )-import Data.Ord- ( comparing )-import qualified Data.ByteString.Lazy as BS import qualified Data.Set as Set- import qualified Data.ByteString as SBS+import qualified Data.ByteString.Lazy as LBS import System.Directory ( removeFile, renameFile )@@ -143,7 +145,7 @@ -- The file is read lazily but if it is not fully consumed by the action then -- the remaining input is truncated and the file is closed. ---withFileContents :: FilePath -> (String -> NoCallStackIO a) -> NoCallStackIO a+withFileContents :: FilePath -> (String -> IO a) -> IO a withFileContents name action = withFile name ReadMode (\hnd -> hGetContents hnd >>= action)@@ -156,14 +158,14 @@ -- On windows it is not possible to delete a file that is open by a process. -- This case will give an IO exception but the atomic property is not affected. ---writeFileAtomic :: FilePath -> BS.ByteString -> NoCallStackIO ()+writeFileAtomic :: FilePath -> LBS.ByteString -> IO () writeFileAtomic targetPath content = do let (targetDir, targetFile) = splitFileName targetPath Exception.bracketOnError (openBinaryTempFileWithDefaultPermissions targetDir $ targetFile <.> "tmp") (\(tmpPath, handle) -> hClose handle >> removeFile tmpPath) (\(tmpPath, handle) -> do- BS.hPut handle content+ LBS.hPut handle content hClose handle renameFile tmpPath targetPath) @@ -181,10 +183,10 @@ -- | Variant of 'fromUTF8BS' for lazy 'BS.ByteString's ---fromUTF8LBS :: BS.ByteString -> String-fromUTF8LBS = decodeStringUtf8 . BS.unpack+fromUTF8LBS :: LBS.ByteString -> String+fromUTF8LBS = decodeStringUtf8 . LBS.unpack --- | Encode 'String' to to UTF8-encoded 'SBS.ByteString'+-- | Encode 'String' to UTF8-encoded 'SBS.ByteString' -- -- Code-points in the @U+D800@-@U+DFFF@ range will be encoded -- as the replacement character (i.e. @U+FFFD@).@@ -194,8 +196,8 @@ -- | Variant of 'toUTF8BS' for lazy 'BS.ByteString's ---toUTF8LBS :: String -> BS.ByteString-toUTF8LBS = BS.pack . encodeStringUtf8+toUTF8LBS :: String -> LBS.ByteString+toUTF8LBS = LBS.pack . encodeStringUtf8 -- | Check that strict 'ByteString' is valid UTF8. Returns 'Just offset' if it's not. validateUTF8 :: SBS.ByteString -> Maybe Int@@ -247,8 +249,8 @@ -- -- Reads lazily using ordinary 'readFile'. ---readUTF8File :: FilePath -> NoCallStackIO String-readUTF8File f = (ignoreBOM . fromUTF8LBS) <$> BS.readFile f+readUTF8File :: FilePath -> IO String+readUTF8File f = (ignoreBOM . fromUTF8LBS) <$> LBS.readFile f -- | Reads a UTF8 encoded text file as a Unicode String --@@ -257,14 +259,14 @@ withUTF8FileContents :: FilePath -> (String -> IO a) -> IO a withUTF8FileContents name action = withBinaryFile name ReadMode- (\hnd -> BS.hGetContents hnd >>= action . ignoreBOM . fromUTF8LBS)+ (\hnd -> LBS.hGetContents hnd >>= action . ignoreBOM . fromUTF8LBS) -- | Writes a Unicode String as a UTF8 encoded text file. -- -- Uses 'writeFileAtomic', so provides the same guarantees. ---writeUTF8File :: FilePath -> String -> NoCallStackIO ()-writeUTF8File path = writeFileAtomic path . BS.pack . encodeStringUtf8+writeUTF8File :: FilePath -> String -> IO ()+writeUTF8File path = writeFileAtomic path . toUTF8LBS -- | Fix different systems silly line ending conventions normaliseLineEndings :: String -> String@@ -369,21 +371,29 @@ bSet = Set.fromList b -- | A total variant of 'head'.+--+-- @since 3.2.0.0 safeHead :: [a] -> Maybe a safeHead [] = Nothing safeHead (x:_) = Just x -- | A total variant of 'tail'.+--+-- @since 3.2.0.0 safeTail :: [a] -> [a] safeTail [] = [] safeTail (_:xs) = xs -- | A total variant of 'last'.+--+-- @since 3.2.0.0 safeLast :: [a] -> Maybe a safeLast [] = Nothing safeLast (x:xs) = Just (foldl (\_ a -> a) x xs) -- | A total variant of 'init'.+--+-- @since 3.2.0.0 safeInit :: [a] -> [a] safeInit [] = [] safeInit [_] = []@@ -485,6 +495,8 @@ -- >>> unsnoc [] -- Nothing --+-- @since 3.2.0.0+-- unsnoc :: [a] -> Maybe ([a], a) unsnoc [] = Nothing unsnoc (x:xs) = Just (unsnocNE (x :| xs))@@ -499,10 +511,28 @@ -- >>> unsnocNE (1 :| []) -- ([],1) --+-- @since 3.2.0.0+-- unsnocNE :: NonEmpty a -> ([a], a) unsnocNE (x:|xs) = go x xs where go y [] = ([], y) go y (z:zs) = let ~(ws, w) = go z zs in (y : ws, w)++-------------------------------------------------------------------------------+-- Triples+-------------------------------------------------------------------------------++-- | @since 3.4.0.0+fstOf3 :: (a,b,c) -> a+fstOf3 (a,_,_) = a++-- | @since 3.4.0.0+sndOf3 :: (a,b,c) -> b+sndOf3 (_,b,_) = b++-- | @since 3.4.0.0+trdOf3 :: (a,b,c) -> c+trdOf3 (_,_,c) = c -- ------------------------------------------------------------ -- * FilePath stuff
cabal/Cabal/Distribution/Utils/IOData.hs view
@@ -1,14 +1,17 @@+{-# LANGUAGE GADTs #-}+{-# LANGUAGE RankNTypes #-} -- | @since 2.2.0 module Distribution.Utils.IOData ( -- * 'IOData' & 'IODataMode' type- IOData(..)- , IODataMode(..)+ IOData (..)+ , IODataMode (..)+ , KnownIODataMode (..)+ , withIOData , null- , hGetContents , hPutContents ) where -import qualified Data.ByteString.Lazy as BS+import qualified Data.ByteString.Lazy as LBS import Distribution.Compat.Prelude hiding (null) import qualified Prelude import qualified System.IO@@ -16,46 +19,68 @@ -- | Represents either textual or binary data passed via I/O functions -- which support binary/text mode ----- @since 2.2.0-data IOData = IODataText String- -- ^ How Text gets encoded is usually locale-dependent.- | IODataBinary BS.ByteString- -- ^ Raw binary which gets read/written in binary mode.+-- @since 2.2+data IOData+ = IODataText String+ -- ^ How Text gets encoded is usually locale-dependent.+ | IODataBinary LBS.ByteString+ -- ^ Raw binary which gets read/written in binary mode. +withIOData :: IOData -> (forall mode. IODataMode mode -> mode -> r) -> r+withIOData (IODataText str) k = k IODataModeText str+withIOData (IODataBinary lbs) k = k IODataModeBinary lbs+ -- | Test whether 'IOData' is empty------ @since 2.2.0 null :: IOData -> Bool-null (IODataText s) = Prelude.null s-null (IODataBinary b) = BS.null b+null (IODataText s) = Prelude.null s+null (IODataBinary b) = LBS.null b instance NFData IOData where- rnf (IODataText s) = rnf s- rnf (IODataBinary bs) = rnf bs+ rnf (IODataText s) = rnf s+ rnf (IODataBinary lbs) = rnf lbs -data IODataMode = IODataModeText | IODataModeBinary+-- | @since 2.2+class NFData mode => KnownIODataMode mode where+ -- | 'IOData' Wrapper for 'System.IO.hGetContents'+ --+ -- __Note__: This operation uses lazy I/O. Use 'NFData' to force all+ -- data to be read and consequently the internal file handle to be+ -- closed.+ --+ hGetIODataContents :: System.IO.Handle -> Prelude.IO mode --- | 'IOData' Wrapper for 'System.IO.hGetContents'------ __Note__: This operation uses lazy I/O. Use 'NFData' to force all--- data to be read and consequently the internal file handle to be--- closed.------ @since 2.2.0-hGetContents :: System.IO.Handle -> IODataMode -> Prelude.IO IOData-hGetContents h IODataModeText = do- System.IO.hSetBinaryMode h False- IODataText <$> System.IO.hGetContents h-hGetContents h IODataModeBinary = do- System.IO.hSetBinaryMode h True- IODataBinary <$> BS.hGetContents h+ toIOData :: mode -> IOData+ iodataMode :: IODataMode mode +-- | @since 3.2+data IODataMode mode where+ IODataModeText :: IODataMode String+ IODataModeBinary :: IODataMode LBS.ByteString++instance a ~ Char => KnownIODataMode [a] where+ hGetIODataContents h = do+ System.IO.hSetBinaryMode h False+ System.IO.hGetContents h++ toIOData = IODataText+ iodataMode = IODataModeText++instance KnownIODataMode LBS.ByteString where+ hGetIODataContents h = do+ System.IO.hSetBinaryMode h True+ LBS.hGetContents h++ toIOData = IODataBinary+ iodataMode = IODataModeBinary+ -- | 'IOData' Wrapper for 'System.IO.hPutStr' and 'System.IO.hClose' ----- This is the dual operation ot 'ioDataHGetContents',+-- This is the dual operation ot 'hGetIODataContents', -- and consequently the handle is closed with `hClose`. ----- @since 2.2.0+-- /Note:/ this performs lazy-IO.+--+-- @since 2.2 hPutContents :: System.IO.Handle -> IOData -> Prelude.IO () hPutContents h (IODataText c) = do System.IO.hSetBinaryMode h False@@ -63,5 +88,5 @@ System.IO.hClose h hPutContents h (IODataBinary c) = do System.IO.hSetBinaryMode h True- BS.hPutStr h c+ LBS.hPutStr h c System.IO.hClose h
cabal/Cabal/Distribution/Utils/LogProgress.hs view
@@ -44,7 +44,7 @@ -- | Run 'LogProgress', outputting traces according to 'Verbosity', -- 'die' if there is an error.-runLogProgress :: Verbosity -> LogProgress a -> NoCallStackIO a+runLogProgress :: Verbosity -> LogProgress a -> IO a runLogProgress verbosity (LogProgress m) = foldProgress step_fn fail_fn return (m env) where@@ -52,11 +52,11 @@ le_verbosity = verbosity, le_context = [] }- step_fn :: LogMsg -> NoCallStackIO a -> NoCallStackIO a+ step_fn :: LogMsg -> IO a -> IO a step_fn doc go = do putStrLn (render doc) go- fail_fn :: Doc -> NoCallStackIO a+ fail_fn :: Doc -> IO a fail_fn doc = do dieNoWrap verbosity (render doc)
+ cabal/Cabal/Distribution/Utils/MD5.hs view
@@ -0,0 +1,79 @@+module Distribution.Utils.MD5 (+ MD5,+ showMD5,+ md5,+ -- * Helpers+ md5FromInteger,+ -- * Binary+ binaryPutMD5,+ binaryGetMD5,+ ) where++import Data.Binary (Get, Put)+import Data.Binary.Get (getWord64le)+import Data.Binary.Put (putWord64le)+import Data.Bits (complement, shiftR, (.&.))+import Foreign.Ptr (castPtr)+import GHC.Fingerprint (Fingerprint (..), fingerprintData)+import Numeric (showHex)+import System.IO.Unsafe (unsafeDupablePerformIO)++import qualified Data.ByteString as BS+import qualified Data.ByteString.Unsafe as BS++type MD5 = Fingerprint++-- | Show 'MD5' in human readable form+--+-- >>> showMD5 (Fingerprint 123 456)+-- "000000000000007b00000000000001c8"+--+-- >>> showMD5 $ md5 $ BS.pack [0..127]+-- "37eff01866ba3f538421b30b7cbefcac"+--+-- @since 3.2.0.0+showMD5 :: MD5 -> String+showMD5 (Fingerprint a b) = pad a' ++ pad b' where+ a' = showHex a ""+ b' = showHex b ""+ pad s = replicate (16 - length s) '0' ++ s++-- | @since 3.2.0.0+md5 :: BS.ByteString -> MD5+md5 bs = unsafeDupablePerformIO $ BS.unsafeUseAsCStringLen bs $ \(ptr, len) ->+ fingerprintData (castPtr ptr) len++-- | @since 3.2.0.0+binaryPutMD5 :: MD5 -> Put+binaryPutMD5 (Fingerprint a b) = do+ putWord64le a+ putWord64le b++-- | @since 3.2.0.0+binaryGetMD5 :: Get MD5+binaryGetMD5 = do+ a <- getWord64le+ b <- getWord64le+ return (Fingerprint a b)++-- |+--+-- >>> showMD5 $ md5FromInteger 0x37eff01866ba3f538421b30b7cbefcac+-- "37eff01866ba3f538421b30b7cbefcac"+--+-- Note: the input is truncated:+--+-- >>> showMD5 $ md5FromInteger 0x1230000037eff01866ba3f538421b30b7cbefcac+-- "37eff01866ba3f538421b30b7cbefcac"+--+-- Yet, negative numbers are not a problem...+--+-- >>> showMD5 $ md5FromInteger (-1)+-- "ffffffffffffffffffffffffffffffff"+--+-- @since 3.4.0.0+md5FromInteger :: Integer -> MD5+md5FromInteger i = Fingerprint hi lo where+ mask = complement 0+ lo = mask .&. fromInteger i+ hi = mask .&. fromInteger (i `shiftR` 64)
cabal/Cabal/Distribution/Utils/NubList.hs view
@@ -1,5 +1,6 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE ScopedTypeVariables #-} module Distribution.Utils.NubList ( NubList -- opaque , toNubList -- smart construtor@@ -12,8 +13,8 @@ , overNubListR ) where -import Prelude () import Distribution.Compat.Prelude+import Prelude () import Distribution.Simple.Utils @@ -74,6 +75,8 @@ instance (Ord a, Binary a) => Binary (NubList a) where put (NubList l) = put l get = fmap toNubList get++instance Structured a => Structured (NubList a) -- | NubListR : A right-biased version of 'NubList'. That is @toNubListR -- ["-XNoFoo", "-XFoo", "-XNoFoo"]@ will result in @["-XFoo", "-XNoFoo"]@,
cabal/Cabal/Distribution/Utils/ShortText.hs view
@@ -1,22 +1,37 @@-{-# LANGUAGE CPP #-}+{-# LANGUAGE CPP #-} {-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveGeneric #-} +-- | Compact representation of short 'Strings'+--+-- This module is designed to be import qualifeid+--+-- @+-- import Distribution.Utils.ShortText (ShortText)+-- import qualified Distribution.Utils.ShortText as ShortText+-- @ module Distribution.Utils.ShortText ( -- * 'ShortText' type ShortText , toShortText , fromShortText+ , unsafeFromUTF8BS + -- * Operations+ , null+ , length+ -- * internal utilities , decodeStringUtf8 , encodeStringUtf8 ) where +import Distribution.Compat.Prelude hiding (length, null) import Prelude ()-import Distribution.Compat.Prelude-import Distribution.Utils.String +import Distribution.Utils.String (decodeStringUtf8, encodeStringUtf8)+import Distribution.Utils.Structured (Structured (..), nominalStructure)+ #if defined(MIN_VERSION_bytestring) # if MIN_VERSION_bytestring(0,10,4) # define HAVE_SHORTBYTESTRING 1@@ -40,8 +55,13 @@ #define MIN_VERSION_binary(x, y, z) 0 #endif +import qualified Data.ByteString as BS+import qualified Data.List as List+ #if HAVE_SHORTBYTESTRING import qualified Data.ByteString.Short as BS.Short+#else+import Distribution.Utils.Generic (fromUTF8BS) #endif -- | Construct 'ShortText' from 'String'@@ -50,6 +70,16 @@ -- | Convert 'ShortText' to 'String' fromShortText :: ShortText -> String +-- | Convert from UTF-8 encoded strict 'ByteString'.+--+-- @since 3.2.0.0+unsafeFromUTF8BS :: BS.ByteString -> ShortText++-- | Text whether 'ShortText' is empty.+--+-- @since 3.2.0.0+null :: ShortText -> Bool+ -- | Compact representation of short 'Strings' -- -- The data is stored internally as UTF8 in an@@ -75,9 +105,14 @@ get = fmap (ST . BS.Short.toShort) get # endif + toShortText = ST . BS.Short.pack . encodeStringUtf8 fromShortText = decodeStringUtf8 . BS.Short.unpack . unST++unsafeFromUTF8BS = ST . BS.Short.toShort++null = BS.Short.null . unST #else newtype ShortText = ST { unST :: String } deriving (Eq,Ord,Generic,Data,Typeable)@@ -89,8 +124,14 @@ toShortText = ST fromShortText = unST++unsafeFromUTF8BS = ST . fromUTF8BS++null = List.null . unST #endif +instance Structured ShortText where structure = nominalStructure+ instance NFData ShortText where rnf = rnf . unST @@ -109,3 +150,10 @@ instance IsString ShortText where fromString = toShortText++-- | /O(n)/. Length in characters. /Slow/ as converts to string.+--+-- @since 3.2.0.0+length :: ShortText -> Int+length = List.length . fromShortText+-- Note: avoid using it, we use it @cabal check@ implementation, where it's ok.
+ cabal/Cabal/Distribution/Utils/Structured.hs view
@@ -0,0 +1,472 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE DefaultSignatures #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+#if __GLASGOW_HASKELL__ >= 711+{-# LANGUAGE PatternSynonyms #-}+#endif+#if __GLASGOW_HASKELL__ >= 800+{-# LANGUAGE TypeInType #-}+#endif+-- |+--+-- Copyright: (c) 2019 Oleg Grenrus+--+-- Structurally tag binary serialisaton stream.+-- Useful when most 'Binary' instances are 'Generic' derived.+--+-- Say you have a data type+--+-- @+-- data Record = Record+-- { _recordFields :: HM.HashMap Text (Integer, ByteString)+-- , _recordEnabled :: Bool+-- }+-- deriving (Eq, Show, Generic)+--+-- instance 'Binary' Record+-- instance 'Structured' Record+-- @+--+-- then you can serialise and deserialise @Record@ values with a structure tag by simply+--+-- @+-- 'structuredEncode' record :: 'LBS.ByteString'+-- 'structuredDecode' lbs :: IO Record+-- @+--+-- If structure of @Record@ changes in between, deserialisation will fail early.+--+-- Technically, 'Structured' is not related to 'Binary', and may+-- be useful in other uses.+--+module Distribution.Utils.Structured (+ -- * Encoding and decoding+ -- | These functions operate like @binary@'s counterparts,+ -- but the serialised version has a structure hash in front.+ structuredEncode,+ structuredEncodeFile,+ structuredDecode,+ structuredDecodeOrFailIO,+ structuredDecodeFileOrFail,+ -- * Structured class+ Structured (structure),+ MD5,+ structureHash,+ structureBuilder,+ genericStructure,+ GStructured,+ nominalStructure,+ containerStructure,+ -- * Structure type+ Structure (..),+ TypeName,+ ConstructorName,+ TypeVersion,+ SopStructure,+ hashStructure,+ typeVersion,+ typeName,+ ) where++import Data.Int (Int16, Int32, Int64, Int8)+import Data.List.NonEmpty (NonEmpty)+import Data.Proxy (Proxy (..))+import Data.Ratio (Ratio)+import Data.Word (Word, Word16, Word32, Word64, Word8)++import qualified Control.Monad.Trans.State.Strict as State++import Control.Exception (ErrorCall (..), catch, evaluate)++import GHC.Generics++import qualified Data.ByteString as BS+import qualified Data.ByteString.Lazy as LBS+import qualified Data.ByteString.Lazy.Builder as Builder+import qualified Data.IntMap as IM+import qualified Data.IntSet as IS+import qualified Data.Map as Map+import qualified Data.Sequence as Seq+import qualified Data.Set as Set+import qualified Data.Text as T+import qualified Data.Text.Lazy as LT+import qualified Data.Time as Time+import qualified Distribution.Compat.Binary as Binary++#ifdef MIN_VERSION_aeson+import qualified Data.Aeson as Aeson+#endif++#if __GLASGOW_HASKELL__ >= 800+import Data.Kind (Type)+#else+#define Type *+#endif++import Distribution.Compat.Typeable (Typeable, TypeRep, typeRep)+import Distribution.Utils.MD5++import Data.Monoid (mconcat)++import qualified Data.Semigroup+import qualified Data.Foldable++#if !MIN_VERSION_base(4,8,0)+import Control.Applicative (pure)+import Data.Traversable (traverse)+#endif++#if !MIN_VERSION_base(4,7,0)+import Data.Typeable (Typeable1, typeOf1)+#endif+++-------------------------------------------------------------------------------+-- Types+-------------------------------------------------------------------------------++type TypeName = String+type ConstructorName = String++-- | A sematic version of a data type. Usually 0.+type TypeVersion = Word32++-- | Structure of a datatype.+--+-- It can be infinite, as far as 'TypeRep's involved are finite.+-- (e.g. polymorphic recursion might cause troubles).+--+data Structure+ = Nominal !TypeRep !TypeVersion TypeName [Structure] -- ^ nominal, yet can be parametrised by other structures.+ | Newtype !TypeRep !TypeVersion TypeName Structure -- ^ a newtype wrapper+ | Structure !TypeRep !TypeVersion TypeName SopStructure -- ^ sum-of-products structure+ deriving (Eq, Ord, Show, Generic)++type SopStructure = [(ConstructorName, [Structure])]++-- | A MD5 hash digest of 'Structure'.+hashStructure :: Structure -> MD5+hashStructure = md5 . LBS.toStrict . Builder.toLazyByteString . structureBuilder++-- | A van-Laarhoven lens into 'TypeVersion' of 'Structure'+--+-- @+-- 'typeVersion' :: Lens' 'Structure' 'TypeVersion'+-- @+typeVersion :: Functor f => (TypeVersion -> f TypeVersion) -> Structure -> f Structure+typeVersion f (Nominal t v n s) = fmap (\v' -> Nominal t v' n s) (f v)+typeVersion f (Newtype t v n s) = fmap (\v' -> Newtype t v' n s) (f v)+typeVersion f (Structure t v n s) = fmap (\v' -> Structure t v' n s) (f v)++-- | A van-Laarhoven lens into 'TypeName' of 'Structure'+--+-- @+-- 'typeName' :: Lens' 'Structure' 'TypeName'+-- @+typeName :: Functor f => (TypeName -> f TypeName) -> Structure -> f Structure+typeName f (Nominal t v n s) = fmap (\n' -> Nominal t v n' s) (f n)+typeName f (Newtype t v n s) = fmap (\n' -> Newtype t v n' s) (f n)+typeName f (Structure t v n s) = fmap (\n' -> Structure t v n' s) (f n)++-------------------------------------------------------------------------------+-- Builder+-------------------------------------------------------------------------------++-- | Flatten 'Structure' into something we can calculate hash of.+--+-- As 'Structure' can be potentially infinite. For mutually recursive types,+-- we keep track of 'TypeRep's, and put just 'TypeRep' name when it's occurred+-- another time.+structureBuilder :: Structure -> Builder.Builder+structureBuilder s0 = State.evalState (go s0) Map.empty where+ go :: Structure -> State.State (Map.Map String (NonEmpty TypeRep)) Builder.Builder+ go (Nominal t v n s) = withTypeRep t $ do+ s' <- traverse go s+ return $ mconcat $ Builder.word8 1 : Builder.word32LE v : Builder.stringUtf8 n : s'++ go (Newtype t v n s) = withTypeRep t $ do+ s' <- go s+ return $ mconcat [Builder.word8 2, Builder.word32LE v, Builder.stringUtf8 n, s']++ go (Structure t v n s) = withTypeRep t $ do+ s' <- goSop s+ return $ mconcat [Builder.word8 3, Builder.word32LE v, Builder.stringUtf8 n, s']++ withTypeRep t k = do+ acc <- State.get+ case insert t acc of+ Nothing -> return $ mconcat [ Builder.word8 0, Builder.stringUtf8 (show t) ]+ Just acc' -> do+ State.put acc'+ k ++ goSop :: SopStructure -> State.State (Map.Map String (NonEmpty TypeRep)) Builder.Builder+ goSop sop = do+ parts <- traverse part sop+ return $ mconcat parts++ part (cn, s) = do+ s' <- traverse go s+ return $ Data.Monoid.mconcat [ Builder.stringUtf8 cn, mconcat s' ]++ insert :: TypeRep -> Map.Map String (NonEmpty TypeRep) -> Maybe (Map.Map String (NonEmpty TypeRep))+ insert tr m = case Map.lookup trShown m of+ Nothing -> inserted+ Just ne | tr `Data.Foldable.elem` ne -> Nothing+ | otherwise -> inserted+ where+ inserted = Just (Map.insertWith (Data.Semigroup.<>) trShown (pure tr) m)+ trShown = show tr++-------------------------------------------------------------------------------+-- Classes+-------------------------------------------------------------------------------++-- | Class of types with a known 'Structure'.+--+-- For regular data types 'Structured' can be derived generically.+--+-- @+-- data Record = Record { a :: Int, b :: Bool, c :: [Char] } deriving ('Generic')+-- instance 'Structured' Record+-- @+--+-- @since 3.2.0.0+--+class Typeable a => Structured a where+ structure :: Proxy a -> Structure+ default structure :: (Generic a, GStructured (Rep a)) => Proxy a -> Structure+ structure = genericStructure++ -- This member is hidden. It's there to precalc+ structureHash' :: Tagged a MD5+ structureHash' = Tagged (hashStructure (structure (Proxy :: Proxy a)))++-- private Tagged+newtype Tagged a b = Tagged { untag :: b }++-- | Semantically @'hashStructure' . 'structure'@.+structureHash :: forall a. Structured a => Proxy a -> MD5+structureHash _ = untag (structureHash' :: Tagged a MD5)++-------------------------------------------------------------------------------+-- Functions+-------------------------------------------------------------------------------++-- | Structured 'Binary.encode'.+-- Encode a value to using binary serialisation to a lazy 'LBS.ByteString'.+-- Encoding starts with 16 byte large structure hash.+structuredEncode+ :: forall a. (Binary.Binary a, Structured a)+ => a -> LBS.ByteString+structuredEncode x = Binary.encode (Tag :: Tag a, x)++-- | Lazily serialise a value to a file+structuredEncodeFile :: (Binary.Binary a, Structured a) => FilePath -> a -> IO ()+structuredEncodeFile f = LBS.writeFile f . structuredEncode++-- | Structured 'Binary.decode'.+-- Decode a value from a lazy 'LBS.ByteString', reconstructing the original structure.+-- Throws pure exception on invalid inputs.+structuredDecode+ :: forall a. (Binary.Binary a, Structured a)+ => LBS.ByteString -> a+structuredDecode lbs = snd (Binary.decode lbs :: (Tag a, a))++structuredDecodeOrFailIO :: (Binary.Binary a, Structured a) => LBS.ByteString -> IO (Either String a)+structuredDecodeOrFailIO bs =+ catch (evaluate (structuredDecode bs) >>= return . Right) handler+ where+#if MIN_VERSION_base(4,9,0)+ handler (ErrorCallWithLocation str _) = return $ Left str+#else+ handler (ErrorCall str) = return $ Left str+#endif++-- | Lazily reconstruct a value previously written to a file.+structuredDecodeFileOrFail :: (Binary.Binary a, Structured a) => FilePath -> IO (Either String a)+structuredDecodeFileOrFail f = structuredDecodeOrFailIO =<< LBS.readFile f++-------------------------------------------------------------------------------+-- Helper data+-------------------------------------------------------------------------------++data Tag a = Tag++instance Structured a => Binary.Binary (Tag a) where+ get = do+ actual <- binaryGetMD5+ if actual == expected+ then return Tag+ else fail $ concat+ [ "Non-matching structured hashes: "+ , showMD5 actual+ , "; expected: "+ , showMD5 expected+ ]+ where+ expected = untag (structureHash' :: Tagged a MD5)++ put _ = binaryPutMD5 expected+ where+ expected = untag (structureHash' :: Tagged a MD5)++-------------------------------------------------------------------------------+-- Smart constructors+-------------------------------------------------------------------------------++-- | Use 'Typeable' to infer name+nominalStructure :: Typeable a => Proxy a -> Structure+nominalStructure p = Nominal tr 0 (show tr) [] where+ tr = typeRep p++#if MIN_VERSION_base(4,7,0)+containerStructure :: forall f a. (Typeable f, Structured a) => Proxy (f a) -> Structure+containerStructure _ = Nominal faTypeRep 0 (show fTypeRep)+ [ structure (Proxy :: Proxy a)+ ]+ where+ fTypeRep = typeRep (Proxy :: Proxy f)+ faTypeRep = typeRep (Proxy :: Proxy (f a))++#else+containerStructure :: forall f a. (Typeable1 f, Structured a) => Proxy (f a) -> Structure+containerStructure _ = Nominal faTypeRep 0 (show fTypeRep)+ [ structure (Proxy :: Proxy a)+ ]+ where+ fTypeRep = typeOf1 (undefined :: f ())+ faTypeRep = typeRep (Proxy :: Proxy (f a))+#endif++-------------------------------------------------------------------------------+-- Generic+-------------------------------------------------------------------------------++-- | Derive 'structure' genrically.+genericStructure :: forall a. (Typeable a, Generic a, GStructured (Rep a)) => Proxy a -> Structure+genericStructure _ = gstructured (typeRep (Proxy :: Proxy a)) (Proxy :: Proxy (Rep a)) 0++-- | Used to implement 'genericStructure'.+class GStructured (f :: Type -> Type) where+ gstructured :: TypeRep -> Proxy f -> TypeVersion -> Structure++instance (i ~ D, Datatype c, GStructuredSum f) => GStructured (M1 i c f) where+ gstructured tr _ v = case sop of+#if MIN_VERSION_base(4,7,0)+ [(_, [s])] | isNewtype p -> Newtype tr v name s+#endif+ _ -> Structure tr v name sop+ where+ p = undefined :: M1 i c f ()+ name = datatypeName p+ sop = gstructuredSum (Proxy :: Proxy f) []++class GStructuredSum (f :: Type -> Type) where+ gstructuredSum :: Proxy f -> SopStructure -> SopStructure++instance (i ~ C, Constructor c, GStructuredProd f) => GStructuredSum (M1 i c f) where+ gstructuredSum _ xs = (name, prod) : xs+ where+ name = conName (undefined :: M1 i c f ())+ prod = gstructuredProd (Proxy :: Proxy f) []++instance (GStructuredSum f, GStructuredSum g) => GStructuredSum (f :+: g) where+ gstructuredSum _ xs+ = gstructuredSum (Proxy :: Proxy f)+ $ gstructuredSum (Proxy :: Proxy g) xs++instance GStructuredSum V1 where+ gstructuredSum _ = id++class GStructuredProd (f :: Type -> Type) where+ gstructuredProd :: Proxy f -> [Structure] -> [Structure]++instance (i ~ S, GStructuredProd f) => GStructuredProd (M1 i c f) where+ gstructuredProd _ = gstructuredProd (Proxy :: Proxy f)++instance Structured c => GStructuredProd (K1 i c) where+ gstructuredProd _ xs = structure (Proxy :: Proxy c) : xs++instance GStructuredProd U1 where+ gstructuredProd _ = id++instance (GStructuredProd f, GStructuredProd g) => GStructuredProd (f :*: g) where+ gstructuredProd _ xs+ = gstructuredProd (Proxy :: Proxy f)+ $ gstructuredProd (Proxy :: Proxy g) xs++-------------------------------------------------------------------------------+-- instances+-------------------------------------------------------------------------------++instance Structured ()+instance Structured Bool+instance Structured Ordering++instance Structured Char where structure = nominalStructure+instance Structured Int where structure = nominalStructure+instance Structured Integer where structure = nominalStructure++instance Structured Data.Word.Word where structure = nominalStructure++instance Structured Int8 where structure = nominalStructure+instance Structured Int16 where structure = nominalStructure+instance Structured Int32 where structure = nominalStructure+instance Structured Int64 where structure = nominalStructure++instance Structured Word8 where structure = nominalStructure+instance Structured Word16 where structure = nominalStructure+instance Structured Word32 where structure = nominalStructure+instance Structured Word64 where structure = nominalStructure++instance Structured Float where structure = nominalStructure+instance Structured Double where structure = nominalStructure++instance Structured a => Structured (Maybe a)+instance (Structured a, Structured b) => Structured (Either a b)+instance Structured a => Structured (Ratio a) where structure = containerStructure+instance Structured a => Structured [a] where structure = containerStructure+instance Structured a => Structured (NonEmpty a) where structure = containerStructure++instance (Structured a1, Structured a2) => Structured (a1, a2)+instance (Structured a1, Structured a2, Structured a3) => Structured (a1, a2, a3)+instance (Structured a1, Structured a2, Structured a3, Structured a4) => Structured (a1, a2, a3, a4)+instance (Structured a1, Structured a2, Structured a3, Structured a4, Structured a5) => Structured (a1, a2, a3, a4, a5)+instance (Structured a1, Structured a2, Structured a3, Structured a4, Structured a5, Structured a6) => Structured (a1, a2, a3, a4, a5, a6)+instance (Structured a1, Structured a2, Structured a3, Structured a4, Structured a5, Structured a6, Structured a7) => Structured (a1, a2, a3, a4, a5, a6, a7)++instance Structured BS.ByteString where structure = nominalStructure+instance Structured LBS.ByteString where structure = nominalStructure++instance Structured T.Text where structure = nominalStructure+instance Structured LT.Text where structure = nominalStructure++instance (Structured k, Structured v) => Structured (Map.Map k v) where structure _ = Nominal (typeRep (Proxy :: Proxy (Map.Map k v))) 0 "Map" [ structure (Proxy :: Proxy k), structure (Proxy :: Proxy v) ]+instance (Structured k) => Structured (Set.Set k) where structure = containerStructure+instance (Structured v) => Structured (IM.IntMap v) where structure = containerStructure+instance Structured IS.IntSet where structure = nominalStructure+instance (Structured v) => Structured (Seq.Seq v) where structure = containerStructure++instance Structured Time.UTCTime where structure = nominalStructure+instance Structured Time.DiffTime where structure = nominalStructure+instance Structured Time.UniversalTime where structure = nominalStructure+instance Structured Time.NominalDiffTime where structure = nominalStructure+instance Structured Time.Day where structure = nominalStructure+instance Structured Time.TimeZone where structure = nominalStructure+instance Structured Time.TimeOfDay where structure = nominalStructure+instance Structured Time.LocalTime where structure = nominalStructure++-- Proxy isn't Typeable in base-4.8 / base++-- #if __GLASGOW_HASKELL__ >= 800+-- instance (Typeable k, Typeable (a :: k)) => Structured (Proxy a)+-- #else+-- instance (Typeable a) => Structured (Proxy a) where+-- structure p = Structure (typeRep p) 0 "Proxy" [("Proxy",[])]+-- #endif
cabal/Cabal/Distribution/Verbosity.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric #-} -----------------------------------------------------------------------------@@ -47,6 +48,10 @@ -- * timestamps verboseTimestamp, isVerboseTimestamp, verboseNoTimestamp,++ -- * Stderr+ verboseStderr, isVerboseStderr,+ verboseNoStderr, ) where import Prelude ()@@ -56,16 +61,19 @@ import Data.List (elemIndex) import Distribution.Parsec+import Distribution.Pretty import Distribution.Verbosity.Internal+import Distribution.Utils.Generic (isAsciiAlpha) import qualified Data.Set as Set import qualified Distribution.Compat.CharParsing as P+import qualified Text.PrettyPrint as PP data Verbosity = Verbosity { vLevel :: VerbosityLevel, vFlags :: Set VerbosityFlag, vQuiet :: Bool- } deriving (Generic, Show, Read)+ } deriving (Generic, Show, Read, Typeable) mkVerbosity :: VerbosityLevel -> Verbosity mkVerbosity l = Verbosity { vLevel = l, vFlags = Set.empty, vQuiet = False }@@ -85,6 +93,7 @@ maxBound = mkVerbosity maxBound instance Binary Verbosity+instance Structured Verbosity -- We shouldn't print /anything/ unless an error occurs in silent mode silent :: Verbosity@@ -144,74 +153,94 @@ -- | Parser verbosity -- -- >>> explicitEitherParsec parsecVerbosity "normal"--- Right (Right (Verbosity {vLevel = Normal, vFlags = fromList [], vQuiet = False}))+-- Right (Verbosity {vLevel = Normal, vFlags = fromList [], vQuiet = False}) -- -- >>> explicitEitherParsec parsecVerbosity "normal+nowrap "--- Right (Right (Verbosity {vLevel = Normal, vFlags = fromList [VNoWrap], vQuiet = False}))+-- Right (Verbosity {vLevel = Normal, vFlags = fromList [VNoWrap], vQuiet = False}) -- -- >>> explicitEitherParsec parsecVerbosity "normal+nowrap +markoutput"--- Right (Right (Verbosity {vLevel = Normal, vFlags = fromList [VNoWrap,VMarkOutput], vQuiet = False}))+-- Right (Verbosity {vLevel = Normal, vFlags = fromList [VNoWrap,VMarkOutput], vQuiet = False}) -- -- >>> explicitEitherParsec parsecVerbosity "normal +nowrap +markoutput"--- Right (Right (Verbosity {vLevel = Normal, vFlags = fromList [VNoWrap,VMarkOutput], vQuiet = False}))+-- Right (Verbosity {vLevel = Normal, vFlags = fromList [VNoWrap,VMarkOutput], vQuiet = False}) -- -- >>> explicitEitherParsec parsecVerbosity "normal+nowrap+markoutput"--- Right (Right (Verbosity {vLevel = Normal, vFlags = fromList [VNoWrap,VMarkOutput], vQuiet = False}))+-- Right (Verbosity {vLevel = Normal, vFlags = fromList [VNoWrap,VMarkOutput], vQuiet = False}) --+-- >>> explicitEitherParsec parsecVerbosity "deafening+nowrap+stdout+stderr+callsite+callstack"+-- Right (Verbosity {vLevel = Deafening, vFlags = fromList [VCallStack,VCallSite,VNoWrap,VStderr], vQuiet = False})+-- -- /Note:/ this parser will eat trailing spaces. ---parsecVerbosity :: CabalParsing m => m (Either Int Verbosity)+instance Parsec Verbosity where+ parsec = parsecVerbosity++instance Pretty Verbosity where+ pretty = PP.text . showForCabal++parsecVerbosity :: CabalParsing m => m Verbosity parsecVerbosity = parseIntVerbosity <|> parseStringVerbosity where- parseIntVerbosity = fmap Left P.integral- parseStringVerbosity = fmap Right $ do+ parseIntVerbosity = do+ i <- P.integral+ case intToVerbosity i of+ Just v -> return v+ Nothing -> P.unexpected $ "Bad integral verbosity: " ++ show i ++ ". Valid values are 0..3"++ parseStringVerbosity = do level <- parseVerbosityLevel _ <- P.spaces- extras <- many (parseExtra <* P.spaces)- return (foldr (.) id extras (mkVerbosity level))- parseVerbosityLevel = P.choice- [ P.string "silent" >> return Silent- , P.string "normal" >> return Normal- , P.string "verbose" >> return Verbose- , P.string "debug" >> return Deafening- , P.string "deafening" >> return Deafening- ]- parseExtra = P.char '+' >> P.choice- [ P.string "callsite" >> return verboseCallSite- , P.string "callstack" >> return verboseCallStack- , P.string "nowrap" >> return verboseNoWrap- , P.string "markoutput" >> return verboseMarkOutput- , P.string "timestamp" >> return verboseTimestamp- ]+ flags <- many (parseFlag <* P.spaces)+ return $ foldl' (flip ($)) (mkVerbosity level) flags -flagToVerbosity :: ReadE Verbosity-flagToVerbosity = parsecToReadE id $ do- e <- parsecVerbosity- case e of- Right v -> return v- Left i -> case intToVerbosity i of- Just v -> return v- Nothing -> fail $ "Bad verbosity: " ++ show i ++ ". Valid values are 0..3"+ parseVerbosityLevel = do+ token <- P.munch1 isAsciiAlpha+ case token of+ "silent" -> return Silent+ "normal" -> return Normal+ "verbose" -> return Verbose+ "debug" -> return Deafening+ "deafening" -> return Deafening+ _ -> P.unexpected $ "Bad verbosity level: " ++ token+ parseFlag = do+ _ <- P.char '+'+ token <- P.munch1 isAsciiAlpha+ case token of+ "callsite" -> return verboseCallSite+ "callstack" -> return verboseCallStack+ "nowrap" -> return verboseNoWrap+ "markoutput" -> return verboseMarkOutput+ "timestamp" -> return verboseTimestamp+ "stderr" -> return verboseStderr+ "stdout" -> return verboseNoStderr+ _ -> P.unexpected $ "Bad verbosity flag: " ++ token -showForCabal, showForGHC :: Verbosity -> String+flagToVerbosity :: ReadE Verbosity+flagToVerbosity = parsecToReadE id parsecVerbosity +showForCabal :: Verbosity -> String showForCabal v | Set.null (vFlags v) = maybe (error "unknown verbosity") show $ elemIndex v [silent,normal,verbose,deafening] | otherwise- = unwords $ (case vLevel v of- Silent -> "silent"- Normal -> "normal"- Verbose -> "verbose"- Deafening -> "debug")- : concatMap showFlag (Set.toList (vFlags v))+ = unwords+ $ showLevel (vLevel v)+ : concatMap showFlag (Set.toList (vFlags v)) where+ showLevel Silent = "silent"+ showLevel Normal = "normal"+ showLevel Verbose = "verbose"+ showLevel Deafening = "debug"+ showFlag VCallSite = ["+callsite"] showFlag VCallStack = ["+callstack"] showFlag VNoWrap = ["+nowrap"] showFlag VMarkOutput = ["+markoutput"] showFlag VTimestamp = ["+timestamp"]+ showFlag VStderr = ["+stderr"]++showForGHC :: Verbosity -> String showForGHC v = maybe (error "unknown verbosity") show $ elemIndex v [silent,normal,__,verbose,deafening] where __ = silent -- this will be always ignored by elemIndex@@ -249,6 +278,18 @@ verboseNoTimestamp :: Verbosity -> Verbosity verboseNoTimestamp = verboseNoFlag VTimestamp +-- | Turn on timestamps for log messages.+--+-- @since 3.4.0.0+verboseStderr :: Verbosity -> Verbosity+verboseStderr = verboseFlag VStderr++-- | Turn off timestamps for log messages.+--+-- @since 3.4.0.0+verboseNoStderr :: Verbosity -> Verbosity+verboseNoStderr = verboseNoFlag VStderr+ -- | Helper function for flag enabling functions verboseFlag :: VerbosityFlag -> (Verbosity -> Verbosity) verboseFlag flag v = v { vFlags = Set.insert flag (vFlags v) }@@ -284,9 +325,15 @@ isVerboseQuiet :: Verbosity -> Bool isVerboseQuiet = vQuiet --- | Test if if we should output timestamps when we log.+-- | Test if we should output timestamps when we log. isVerboseTimestamp :: Verbosity -> Bool isVerboseTimestamp = isVerboseFlag VTimestamp++-- | Test if we should output to stderr when we log.+--+-- @since 3.4.0.0+isVerboseStderr :: Verbosity -> Bool+isVerboseStderr = isVerboseFlag VStderr -- | Helper function for flag testing functions. isVerboseFlag :: VerbosityFlag -> Verbosity -> Bool
cabal/Cabal/Distribution/Verbosity/Internal.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric #-} module Distribution.Verbosity.Internal ( VerbosityLevel(..)@@ -8,9 +9,10 @@ import Distribution.Compat.Prelude data VerbosityLevel = Silent | Normal | Verbose | Deafening- deriving (Generic, Show, Read, Eq, Ord, Enum, Bounded)+ deriving (Generic, Show, Read, Eq, Ord, Enum, Bounded, Typeable) instance Binary VerbosityLevel+instance Structured VerbosityLevel data VerbosityFlag = VCallStack@@ -18,6 +20,8 @@ | VNoWrap | VMarkOutput | VTimestamp- deriving (Generic, Show, Read, Eq, Ord, Enum, Bounded)+ | VStderr -- ^ @since 3.4.0.0+ deriving (Generic, Show, Read, Eq, Ord, Enum, Bounded, Typeable) instance Binary VerbosityFlag+instance Structured VerbosityFlag
cabal/Cabal/Distribution/Version.hs view
@@ -97,23 +97,6 @@ -- Utilities on VersionRange requiring VersionInterval ------------------------------------------------------------------------------- --- | Does this 'VersionRange' place any restriction on the 'Version' or is it--- in fact equivalent to 'AnyVersion'.------ Note this is a semantic check, not simply a syntactic check. So for example--- the following is @True@ (for all @v@).------ > isAnyVersion (EarlierVersion v `UnionVersionRanges` orLaterVersion v)----isAnyVersion :: VersionRange -> Bool-isAnyVersion vr = case asVersionIntervals vr of- [(LowerBound v InclusiveBound, NoUpperBound)] | isVersion0 v -> True- _ -> False- where- isVersion0 :: Version -> Bool- isVersion0 = (== mkVersion [0])-- -- | This is the converse of 'isAnyVersion'. It check if the version range is -- empty, if there is no possible version that satisfies the version range. --
+ cabal/Cabal/Distribution/ZinzaPrelude.hs view
@@ -0,0 +1,43 @@+-- | A small prelude used in @zinza@ generated+-- template modules.+module Distribution.ZinzaPrelude (+ Writer,+ execWriter,+ tell,+ -- * Re-exports+ forM_,+ Generic,+ PackageName,+ Version,+ prettyShow+ ) where++import Distribution.Compat.Prelude+import Prelude ()++import Control.Monad (forM_)+import Distribution.Pretty (prettyShow)+import Distribution.Types.PackageName (PackageName)+import Distribution.Types.Version (Version)++newtype Writer a = W { unW :: ShowS -> (ShowS, a) }++instance Functor Writer where+ fmap = liftM++instance Applicative Writer where+ pure x = W $ \ss -> (ss, x)+ (<*>) = ap++instance Monad Writer where+ return = pure+ m >>= k = W $ \s1 ->+ let (s2, x) = unW m s1+ in unW (k x) s2+ {-# INLINE (>>=) #-}++execWriter :: Writer a -> String+execWriter w = fst (unW w id) ""++tell :: String -> Writer ()+tell s = W $ \s' -> (s' . showString s, ())
cabal/Cabal/LICENSE view
@@ -1,5 +1,8 @@-Copyright (c) 2003-2017, Cabal Development Team.+Copyright (c) 2003-2020, Cabal Development Team. See the AUTHORS file for the full list of copyright holders.++See */LICENSE for the copyright holders of the subcomponents.+ All rights reserved. Redistribution and use in source and binary forms, with or without
cabal/Cabal/Language/Haskell/Extension.hs view
@@ -1,5 +1,6 @@ {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE OverloadedStrings #-} ----------------------------------------------------------------------------- -- |@@ -58,6 +59,7 @@ deriving (Generic, Show, Read, Eq, Typeable, Data) instance Binary Language+instance Structured Language instance NFData Language where rnf = genericRnf @@ -109,6 +111,7 @@ deriving (Generic, Show, Read, Eq, Ord, Typeable, Data) instance Binary Extension+instance Structured Extension instance NFData Extension where rnf = genericRnf @@ -825,9 +828,31 @@ -- * <https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html#deriving-instances-for-empty-data-types> | EmptyDataDeriving + -- | Enable detection of complete user-supplied kind signatures.+ | CUSKs++ -- | Allows the syntax @import M qualified@.+ | ImportQualifiedPost++ -- | Allow the use of standalone kind signatures.+ | StandaloneKindSignatures++ -- | Enable unlifted newtypes.+ | UnliftedNewtypes++ -- | Use whitespace to determine whether the minus sign stands for negation or subtraction.+ | LexicalNegation++ -- | Enable qualified do-notation desugaring.+ | QualifiedDo++ -- | Enable linear types.+ | LinearTypes+ deriving (Generic, Show, Read, Eq, Ord, Enum, Bounded, Typeable, Data) instance Binary KnownExtension+instance Structured KnownExtension instance NFData KnownExtension where rnf = genericRnf
cabal/Cabal/Makefile view
@@ -1,4 +1,4 @@-VERSION=3.1.0.0+VERSION=3.3.0.0 #KIND=devel KIND=rc@@ -53,16 +53,17 @@ SPHINX_HTML_OUTDIR=dist/doc/users-guide +# do pip install everytime so we have up to date requirements when we build users-guide: .python-sphinx-virtualenv $(USERGUIDE_STAMP) $(USERGUIDE_STAMP) : doc/*.rst mkdir -p $(SPHINX_HTML_OUTDIR)- (. ./.python-sphinx-virtualenv/bin/activate && $(SPHINXCMD) doc $(SPHINX_HTML_OUTDIR))+ (. ./.python-sphinx-virtualenv/bin/activate && pip install -r doc/requirements.txt && $(SPHINXCMD) doc $(SPHINX_HTML_OUTDIR)) docs: haddock users-guide .python-sphinx-virtualenv:- virtualenv .python-sphinx-virtualenv- (. ./.python-sphinx-virtualenv/bin/activate && pip install sphinx && pip install sphinx_rtd_theme)+ python3 -m venv .python-sphinx-virtualenv+ (. ./.python-sphinx-virtualenv/bin/activate) clean: rm -rf dist/
cabal/Cabal/doc/README.md view
@@ -11,16 +11,11 @@ ### How to build it -* Currently requires python-2-* `> pip install sphinx`-* `> pip install sphinx_rtd_theme`+Building the documentation requires Python 3 be installed * `> cd Cabal` * `> make clean users-guide`-* if you are missing any other dependencies, install them with `pip` as needed-¯\\\_(ツ)_/¯ * Python on Mac OS X dislikes `LC_CTYPE=UTF-8`, unset the env var in terminal preferences and instead set `LC_ALL=en_US.UTF-8` or something-* On archlinux, package `python2-sphinx` is sufficient. ### Caveats, for newcomers to RST from MD RST does not allow you to skip section levels when nesting, like MD@@ -61,7 +56,7 @@ """""""""""""""""""""" ``` -* RST simply parses a file and interpretes headings to indicate the+* RST simply parses a file and interprets headings to indicate the start of a new block, * at the level implied by the header's *adornment*, if the adornment was previously encountered in this file,
+ cabal/Cabal/doc/buildinfo-fields-reference.rst view
@@ -0,0 +1,654 @@+.. _buildinfo-field-reference:++Field Syntax Reference+======================++Notation+---------------++Field syntax is described as they are in the latest cabal file format version.++* terminals are enclosed in quotes and type set in typewriter script:++ .. math::++ \mathord{"}\mathtt{example}\mathord{"}++* non-terminals are type set in italic:++ .. math::++ \mathit{version\text-range}++* character sets are type set resembling regular expression notation:+++ .. math::++ [ \mathord{"}\mathtt{1}\mathord{"} \cdots \mathord{"}\mathtt{9}\mathord{"} ]++ Character set complements have :math:`c` superscript:++ .. math::++ [ \mathord{"}\mathtt{1}\mathord{"} \cdots \mathord{"}\mathtt{9}\mathord{"} ]^c++* repetition is type set using regular expression inspired notation.+ Superscripts tell how many time to repeat:+ The generic notation is :math:`\in[n\ldots5]`, however there+ are common shorthands:+ :math:`\ast` for :math:`\in[0\ldots\infty]` (``many``),+ :math:`+` for :math:`\in[1\ldots\infty]` (``some``),+ :math:`?` for :math:`\in[0\ldots1]` (``optional``).++ Subscripts tell the used separator:++ .. math::++ \mathit{digit}^+_{\mathord{"}\mathtt{.}\mathord{"}}++ Would be ``digit(\.digit)*`` in common regex syntax.++* alternatives are listed in braces separated by vertical bar:++ .. math::++ \{ \mathit{foo} \mid \mathit{bar} \}++ In case of multiple alternatives, the stacked notation is used++ .. math::++ \left\{\begin{gathered}+ \mathit{one} \\+ \mathit{two} \\+ \mathit{three} \\+ \mathit{four} \\+ \mathit{five}+ \end{gathered}\right\}++* parenthesis are used only for grouping:++ .. math::++ \left(\mathit{foo} \mid \mathit{bar}\right)^+++* any amount of spaces, and at least single space are type set using+ :math:`\circ` and :math:`\bullet` respectively.+ They may appear standalone, not only as binary operators.++ .. math::++ \mathit{module} \bullet \mathord{``}\mathtt{as}\mathord{"} \bullet \mathit{module}++* While notation is heavily regular expression inspired, there+ are also fixed points, which allow represent recursive grammars+++ .. math::+ + \mathbf{fix}\; \mathit{expr}\; \mathbf{in}\; \mathit{digit}+ \mid \mathit{expr} \circ \mathord{``}\mathtt{+}\mathord{"} \circ \mathit{expr}+ \mid \mathord{``}\mathtt{(} \mathord{"} \circ \mathit{expr} \circ \mathord{``}\mathtt{)}\mathord{"} ++Lists+-----++Many fields in cabal file format are lists. There are three variations:++Space separated+ Are used for lists of things with simple grammars, for example :pkg-field:`ghc-options`++ .. math::+ {\mathop{\mathit{element}}}^\ast_{\bullet}++Comma separated+ Are used for lists of things with complicated grammars, for example :pkg-field:`build-depends`+ There can be leading or trailing comma (but not both) since ``cabal-version: 2.2``.+ Note, the comma cannot exist alone.++ .. math::+ \mathrm{commalist}(\mathit{element}) =+ \left\{ {\mathop{\mathit{element}}}^\ast_{\left(\circ\mathop{\mathord{``}\mathtt{\text{,}}\mathord{"}}\circ\right)}\mid\mathop{\mathord{``}\mathtt{\text{,}}\mathord{"}}\circ{\mathop{\mathit{element}}}^+_{\left(\circ\mathop{\mathord{``}\mathtt{\text{,}}\mathord{"}}\circ\right)}\mid{\mathop{\mathit{element}}}^+_{\left(\circ\mathop{\mathord{``}\mathtt{\text{,}}\mathord{"}}\circ\right)}\circ\mathop{\mathord{``}\mathtt{\text{,}}\mathord{"}} \right\}++Optional comma separated+ Surprisingly many fields can have optional comma separator.+ Since ``cabal-version: 3.0`` comma usage have to be consistent,+ in other words either used everywhere or nowhere.+ It's recommended to avoid using comma in these fields,+ an example field is :pkg-field:`default-extensions`.++ .. math::+ \mathrm{optcommalist}(\mathit{element}) =+ \left\{ \begin{gathered}{\mathop{\mathit{element}}}^\ast_{\bullet}\\{\mathop{\mathit{element}}}^\ast_{\left(\circ\mathop{\mathord{``}\mathtt{\text{,}}\mathord{"}}\circ\right)}\\\mathop{\mathord{``}\mathtt{\text{,}}\mathord{"}}\circ{\mathop{\mathit{element}}}^+_{\left(\circ\mathop{\mathord{``}\mathtt{\text{,}}\mathord{"}}\circ\right)}\\{\mathop{\mathit{element}}}^+_{\left(\circ\mathop{\mathord{``}\mathtt{\text{,}}\mathord{"}}\circ\right)}\circ\mathop{\mathord{``}\mathtt{\text{,}}\mathord{"}}\end{gathered} \right\}++Non-terminals+-------------++In the syntax definitions below the following non-terminal symbols are used:++hs-string+ String as in Haskell; it's recommended to avoid using Haskell-specific escapes.++ .. math::+ \mathop{\mathord{``}\mathtt{\text{"}}\mathord{"}}{\left\{ {[\mathop{\mathord{``}\mathtt{\text{"}}\mathord{"}}\mathop{\mathord{``}\mathtt{\text{\\}}\mathord{"}}]^c}\mid\left\{ \begin{gathered}\mathop{\mathord{``}\mathtt{\text{\\}\text{&}}\mathord{"}}\\\mathop{\mathord{``}\mathtt{\text{\\}\text{\\}}\mathord{"}}\\\left\{ \mathop{\mathord{``}\mathtt{\text{\\}n}\mathord{"}}\mid\mathop{\mathit{escapes}} \right\}\\\mathop{\mathord{``}\mathtt{\text{\\}}\mathord{"}}[\mathop{\mathord{``}\mathtt{0}\mathord{"}}\cdots\mathop{\mathord{``}\mathtt{9}\mathord{"}}]\\\mathop{\mathord{``}\mathtt{\text{\\}o}\mathord{"}}[\mathop{\mathord{``}\mathtt{0}\mathord{"}}\cdots\mathop{\mathord{``}\mathtt{7}\mathord{"}}]\\\mathop{\mathord{``}\mathtt{\text{\\}x}\mathord{"}}[\mathop{\mathord{``}\mathtt{0}\mathord{"}}\cdots\mathop{\mathord{``}\mathtt{9}\mathord{"}}\mathop{\mathord{``}\mathtt{A}\mathord{"}}\cdots\mathop{\mathord{``}\mathtt{F}\mathord{"}}\mathop{\mathord{``}\mathtt{a}\mathord{"}}\cdots\mathop{\mathord{``}\mathtt{f}\mathord{"}}]\\\left\{ \mathop{\mathord{``}\mathtt{\text{\\}\text{^}\text{@}}\mathord{"}}\mid\mathop{\mathit{control}} \right\}\\\left\{ \mathop{\mathord{``}\mathtt{\text{\\}NUL}\mathord{"}}\mid\mathop{\mathit{ascii}} \right\}\end{gathered} \right\} \right\}}^\ast_{}\mathop{\mathord{``}\mathtt{\text{"}}\mathord{"}}++unqual-name+ Unqualified component names are used for package names, component names etc. but not flag names. Unqualified component name consist of components separated by dash, each component is non-empty alphanumeric string, with at least one alphabetic character. In other words, component may not look like a number.++ .. math::+ {\left({\mathop{\mathit{alpha\text{-}num}}}^\ast_{}\mathop{\mathit{alpha}}{\mathop{\mathit{alpha\text{-}num}}}^\ast_{}\right)}^+_{\mathop{\mathord{``}\mathtt{\text{-}}\mathord{"}}}++module-name+ Haskell module name as recognized by Cabal parser.++ .. math::+ {\left(\mathop{\mathit{upper}}{\left\{ \mathop{\mathit{alpha\text{-}num}}\mid[\mathop{\mathord{``}\mathtt{\text{'}}\mathord{"}}\mathop{\mathord{``}\mathtt{\text{_}}\mathord{"}}] \right\}}^\ast_{}\right)}^+_{\mathop{\mathord{``}\mathtt{\text{.}}\mathord{"}}}++version+ Version is to first approximation numbers separated by dots, where leading zero is not allowed and each version digit is consists at most of nine characters.++ .. math::+ {\left\{ \mathop{\mathord{``}\mathtt{0}\mathord{"}}\mid[\mathop{\mathord{``}\mathtt{1}\mathord{"}}\cdots\mathop{\mathord{``}\mathtt{9}\mathord{"}}]{[\mathop{\mathord{``}\mathtt{0}\mathord{"}}\cdots\mathop{\mathord{``}\mathtt{9}\mathord{"}}]}^{\in [0\ldots8]}_{} \right\}}^+_{\mathop{\mathord{``}\mathtt{\text{.}}\mathord{"}}}++version-range+ Version range syntax is recursive. Also note the set syntax added in ``cabal-version: 3.0``, set cannot be empty.++ .. math::+ \mathbf{fix}\;\mathop{\mathit{version\text{-}range}}\;\mathbf{in}\;\left\{ \begin{gathered}\mathop{\mathord{``}\mathtt{\text{=}\text{=}}\mathord{"}}\circ\mathop{\mathit{version}}\\\mathop{\mathord{``}\mathtt{\text{>}}\mathord{"}}\circ\mathop{\mathit{version}}\\\mathop{\mathord{``}\mathtt{\text{<}}\mathord{"}}\circ\mathop{\mathit{version}}\\\mathop{\mathord{``}\mathtt{\text{<}\text{=}}\mathord{"}}\circ\mathop{\mathit{version}}\\\mathop{\mathord{``}\mathtt{\text{>}\text{=}}\mathord{"}}\circ\mathop{\mathit{version}}\\\mathop{\mathord{``}\mathtt{\text{^}\text{>}\text{=}}\mathord{"}}\circ\mathop{\mathit{version}}\\\mathop{\mathord{``}\mathtt{\text{=}\text{=}}\mathord{"}}\circ{\left\{ \mathop{\mathord{``}\mathtt{0}\mathord{"}}\mid[\mathop{\mathord{``}\mathtt{1}\mathord{"}}\cdots\mathop{\mathord{``}\mathtt{9}\mathord{"}}]{[\mathop{\mathord{``}\mathtt{0}\mathord{"}}\cdots\mathop{\mathord{``}\mathtt{9}\mathord{"}}]}^{\in [0\ldots8]}_{} \right\}}^+_{\mathop{\mathord{``}\mathtt{\text{.}}\mathord{"}}}\mathop{\mathord{``}\mathtt{\text{.}\text{*}}\mathord{"}}\\\mathop{\mathit{version\text{-}range}}\circ\mathop{\mathord{``}\mathtt{\text{|}\text{|}}\mathord{"}}\circ\mathop{\mathit{version\text{-}range}}\\\mathop{\mathit{version\text{-}range}}\circ\mathop{\mathord{``}\mathtt{\text{&}\text{&}}\mathord{"}}\circ\mathop{\mathit{version\text{-}range}}\\\mathop{\mathord{``}\mathtt{\text{(}}\mathord{"}}\circ\mathop{\mathit{version\text{-}range}}\circ\mathop{\mathord{``}\mathtt{\text{)}}\mathord{"}}\\\mathop{\mathord{``}\mathtt{\text{=}\text{=}}\mathord{"}}\circ\mathop{\mathord{``}\mathtt{\{}\mathord{"}}\circ{\mathop{\mathit{version}}}^+_{\left(\circ\mathop{\mathord{``}\mathtt{\text{,}}\mathord{"}}\circ\right)}\circ\mathop{\mathord{``}\mathtt{\}}\mathord{"}}\\\mathop{\mathord{``}\mathtt{\text{^}\text{>}\text{=}}\mathord{"}}\circ\mathop{\mathord{``}\mathtt{\{}\mathord{"}}\circ{\mathop{\mathit{version}}}^+_{\left(\circ\mathop{\mathord{``}\mathtt{\text{,}}\mathord{"}}\circ\right)}\circ\mathop{\mathord{``}\mathtt{\}}\mathord{"}}\end{gathered} \right\}+++Build info fields+-----------------++asm-options+ * Monoidal field+ * Available since ``cabal-version: 3.0``.+ * Documentation of :pkg-field:`asm-options`++ .. math::+ {\left\{ \mathop{\mathit{hs\text{-}string}}\mid{{[\mathop{\mathord{``}\mathtt{\ }\mathord{"}}]^c}}^+_{} \right\}}^\ast_{\bullet}++asm-sources+ * Monoidal field+ * Available since ``cabal-version: 3.0``.+ * Documentation of :pkg-field:`asm-sources`++ .. math::+ \mathrm{commalist}\left\{ \mathop{\mathit{hs\text{-}string}}\mid{{[\mathop{\mathord{``}\mathtt{\ }\mathord{"}}\mathop{\mathord{``}\mathtt{\text{,}}\mathord{"}}]^c}}^+_{} \right\}++autogen-includes+ * Monoidal field+ * Available since ``cabal-version: 3.0``.+ * Documentation of :pkg-field:`autogen-includes`++ .. math::+ \mathrm{optcommalist}\left\{ \mathop{\mathit{hs\text{-}string}}\mid{{[\mathop{\mathord{``}\mathtt{\ }\mathord{"}}\mathop{\mathord{``}\mathtt{\text{,}}\mathord{"}}]^c}}^+_{} \right\}++autogen-modules+ * Monoidal field+ * Available since ``cabal-version: 2.0``.+ * Documentation of :pkg-field:`autogen-modules`++ .. math::+ \mathrm{commalist}\left({\left(\mathop{\mathit{upper}}{\left\{ \mathop{\mathit{alpha\text{-}num}}\mid[\mathop{\mathord{``}\mathtt{\text{'}}\mathord{"}}\mathop{\mathord{``}\mathtt{\text{_}}\mathord{"}}] \right\}}^\ast_{}\right)}^+_{\mathop{\mathord{``}\mathtt{\text{.}}\mathord{"}}}\right)++build-depends+ * Monoidal field+ * Documentation of :pkg-field:`build-depends`++ .. math::+ \mathrm{commalist}\left(\mathop{\mathit{pkg\text{-}name}}{\left(\mathop{\mathord{``}\mathtt{\text{:}}\mathord{"}}\left\{ \mathop{\mathit{unqual\text{-}name}}\mid\mathop{\mathord{``}\mathtt{\{}\mathord{"}}\circ{\mathop{\mathit{unqual\text{-}name}}}^+_{\left(\circ\mathop{\mathord{``}\mathtt{\text{,}}\mathord{"}}\circ\right)}\circ\mathop{\mathord{``}\mathtt{\}}\mathord{"}} \right\}\right)}^?{\left(\circ\mathop{\mathit{version\text{-}range}}\right)}^?\right)++build-tool-depends+ * Monoidal field+ * Documentation of :pkg-field:`build-tool-depends`++ .. math::+ \mathrm{commalist}\mathsf{\color{red}{TODO}}++build-tools+ * Monoidal field+ * Deprecated since ``cabal-version: 2.0``: Please use 'build-tool-depends' field+ * Removed in ``cabal-version: 3.0``: Please use 'build-tool-depends' field.++ .. math::+ \mathrm{commalist}\mathsf{\color{red}{TODO}}++buildable+ * Boolean field+ * Default: ``True``+ * Documentation of :pkg-field:`buildable`++ .. math::+ \left\{ \mathop{\mathord{``}\mathtt{True}\mathord{"}}\mid\mathop{\mathord{``}\mathtt{False}\mathord{"}} \right\}++c-sources+ * Monoidal field+ * Documentation of :pkg-field:`c-sources`++ .. math::+ \mathrm{commalist}\left\{ \mathop{\mathit{hs\text{-}string}}\mid{{[\mathop{\mathord{``}\mathtt{\ }\mathord{"}}\mathop{\mathord{``}\mathtt{\text{,}}\mathord{"}}]^c}}^+_{} \right\}++cc-options+ * Monoidal field+ * Documentation of :pkg-field:`cc-options`++ .. math::+ {\left\{ \mathop{\mathit{hs\text{-}string}}\mid{{[\mathop{\mathord{``}\mathtt{\ }\mathord{"}}]^c}}^+_{} \right\}}^\ast_{\bullet}++cmm-options+ * Monoidal field+ * Available since ``cabal-version: 3.0``.+ * Documentation of :pkg-field:`cmm-options`++ .. math::+ {\left\{ \mathop{\mathit{hs\text{-}string}}\mid{{[\mathop{\mathord{``}\mathtt{\ }\mathord{"}}]^c}}^+_{} \right\}}^\ast_{\bullet}++cmm-sources+ * Monoidal field+ * Available since ``cabal-version: 3.0``.+ * Documentation of :pkg-field:`cmm-sources`++ .. math::+ \mathrm{commalist}\left\{ \mathop{\mathit{hs\text{-}string}}\mid{{[\mathop{\mathord{``}\mathtt{\ }\mathord{"}}\mathop{\mathord{``}\mathtt{\text{,}}\mathord{"}}]^c}}^+_{} \right\}++cpp-options+ * Monoidal field+ * Documentation of :pkg-field:`cpp-options`++ .. math::+ {\left\{ \mathop{\mathit{hs\text{-}string}}\mid{{[\mathop{\mathord{``}\mathtt{\ }\mathord{"}}]^c}}^+_{} \right\}}^\ast_{\bullet}++cxx-options+ * Monoidal field+ * Available since ``cabal-version: 2.2``.+ * Documentation of :pkg-field:`cxx-options`++ .. math::+ {\left\{ \mathop{\mathit{hs\text{-}string}}\mid{{[\mathop{\mathord{``}\mathtt{\ }\mathord{"}}]^c}}^+_{} \right\}}^\ast_{\bullet}++cxx-sources+ * Monoidal field+ * Available since ``cabal-version: 2.2``.+ * Documentation of :pkg-field:`cxx-sources`++ .. math::+ \mathrm{commalist}\left\{ \mathop{\mathit{hs\text{-}string}}\mid{{[\mathop{\mathord{``}\mathtt{\ }\mathord{"}}\mathop{\mathord{``}\mathtt{\text{,}}\mathord{"}}]^c}}^+_{} \right\}++default-extensions+ * Monoidal field+ * Available since ``cabal-version: 1.10``.+ * Documentation of :pkg-field:`default-extensions`++ .. math::+ \mathrm{optcommalist}\mathsf{\color{red}{TODO}}++default-language+ * Optional field+ * Available since ``cabal-version: 1.10``.+ * Documentation of :pkg-field:`default-language`++ .. math::+ \left\{ \mathop{\mathord{``}\mathtt{Haskell98}\mathord{"}}\mid\mathop{\mathord{``}\mathtt{Haskell2010}\mathord{"}} \right\}++extensions+ * Monoidal field+ * Deprecated since ``cabal-version: 1.12``: Please use 'default-extensions' or 'other-extensions' fields.+ * Removed in ``cabal-version: 3.0``: Please use 'default-extensions' or 'other-extensions' fields.++ .. math::+ \mathrm{optcommalist}\mathsf{\color{red}{TODO}}++extra-bundled-libraries+ * Monoidal field+ * Documentation of :pkg-field:`extra-bundled-libraries`++ .. math::+ \mathrm{commalist}\left\{ \mathop{\mathit{hs\text{-}string}}\mid{{[\mathop{\mathord{``}\mathtt{\ }\mathord{"}}\mathop{\mathord{``}\mathtt{\text{,}}\mathord{"}}]^c}}^+_{} \right\}++extra-dynamic-library-flavours+ * Monoidal field+ * Available since ``cabal-version: 3.0``.+ * Documentation of :pkg-field:`extra-dynamic-library-flavours`++ .. math::+ \mathrm{commalist}\left\{ \mathop{\mathit{hs\text{-}string}}\mid{{[\mathop{\mathord{``}\mathtt{\ }\mathord{"}}\mathop{\mathord{``}\mathtt{\text{,}}\mathord{"}}]^c}}^+_{} \right\}++extra-framework-dirs+ * Monoidal field+ * Documentation of :pkg-field:`extra-framework-dirs`++ .. math::+ \mathrm{optcommalist}\left\{ \mathop{\mathit{hs\text{-}string}}\mid{{[\mathop{\mathord{``}\mathtt{\ }\mathord{"}}\mathop{\mathord{``}\mathtt{\text{,}}\mathord{"}}]^c}}^+_{} \right\}++extra-ghci-libraries+ * Monoidal field+ * Documentation of :pkg-field:`extra-ghci-libraries`++ .. math::+ \mathrm{commalist}\left\{ \mathop{\mathit{hs\text{-}string}}\mid{{[\mathop{\mathord{``}\mathtt{\ }\mathord{"}}\mathop{\mathord{``}\mathtt{\text{,}}\mathord{"}}]^c}}^+_{} \right\}++extra-lib-dirs+ * Monoidal field+ * Documentation of :pkg-field:`extra-lib-dirs`++ .. math::+ \mathrm{optcommalist}\left\{ \mathop{\mathit{hs\text{-}string}}\mid{{[\mathop{\mathord{``}\mathtt{\ }\mathord{"}}\mathop{\mathord{``}\mathtt{\text{,}}\mathord{"}}]^c}}^+_{} \right\}++extra-libraries+ * Monoidal field+ * Documentation of :pkg-field:`extra-libraries`++ .. math::+ \mathrm{commalist}\left\{ \mathop{\mathit{hs\text{-}string}}\mid{{[\mathop{\mathord{``}\mathtt{\ }\mathord{"}}\mathop{\mathord{``}\mathtt{\text{,}}\mathord{"}}]^c}}^+_{} \right\}++extra-library-flavours+ * Monoidal field+ * Documentation of :pkg-field:`extra-library-flavours`++ .. math::+ \mathrm{commalist}\left\{ \mathop{\mathit{hs\text{-}string}}\mid{{[\mathop{\mathord{``}\mathtt{\ }\mathord{"}}\mathop{\mathord{``}\mathtt{\text{,}}\mathord{"}}]^c}}^+_{} \right\}++frameworks+ * Monoidal field+ * Documentation of :pkg-field:`frameworks`++ .. math::+ \mathrm{optcommalist}\left\{ \mathop{\mathit{hs\text{-}string}}\mid{{[\mathop{\mathord{``}\mathtt{\ }\mathord{"}}\mathop{\mathord{``}\mathtt{\text{,}}\mathord{"}}]^c}}^+_{} \right\}++ghc-options+ * Monoidal field+ * Documentation of :pkg-field:`ghc-options`++ .. math::+ {\left\{ \mathop{\mathit{hs\text{-}string}}\mid{{[\mathop{\mathord{``}\mathtt{\ }\mathord{"}}]^c}}^+_{} \right\}}^\ast_{\bullet}++ghc-prof-options+ * Monoidal field+ * Documentation of :pkg-field:`ghc-prof-options`++ .. math::+ {\left\{ \mathop{\mathit{hs\text{-}string}}\mid{{[\mathop{\mathord{``}\mathtt{\ }\mathord{"}}]^c}}^+_{} \right\}}^\ast_{\bullet}++ghc-shared-options+ * Monoidal field+ * Documentation of :pkg-field:`ghc-shared-options`++ .. math::+ {\left\{ \mathop{\mathit{hs\text{-}string}}\mid{{[\mathop{\mathord{``}\mathtt{\ }\mathord{"}}]^c}}^+_{} \right\}}^\ast_{\bullet}++ghcjs-options+ * Monoidal field+ * Documentation of :pkg-field:`ghcjs-options`++ .. math::+ {\left\{ \mathop{\mathit{hs\text{-}string}}\mid{{[\mathop{\mathord{``}\mathtt{\ }\mathord{"}}]^c}}^+_{} \right\}}^\ast_{\bullet}++ghcjs-prof-options+ * Monoidal field+ * Documentation of :pkg-field:`ghcjs-prof-options`++ .. math::+ {\left\{ \mathop{\mathit{hs\text{-}string}}\mid{{[\mathop{\mathord{``}\mathtt{\ }\mathord{"}}]^c}}^+_{} \right\}}^\ast_{\bullet}++ghcjs-shared-options+ * Monoidal field+ * Documentation of :pkg-field:`ghcjs-shared-options`++ .. math::+ {\left\{ \mathop{\mathit{hs\text{-}string}}\mid{{[\mathop{\mathord{``}\mathtt{\ }\mathord{"}}]^c}}^+_{} \right\}}^\ast_{\bullet}++hs-source-dir+ * Monoidal field+ * Deprecated since ``cabal-version: 1.2``: Please use 'hs-source-dirs'+ * Removed in ``cabal-version: 3.0``: Please use 'hs-source-dirs' field.++ .. math::+ \mathrm{optcommalist}\left\{ \mathop{\mathit{hs\text{-}string}}\mid{{[\mathop{\mathord{``}\mathtt{\ }\mathord{"}}\mathop{\mathord{``}\mathtt{\text{,}}\mathord{"}}]^c}}^+_{} \right\}++hs-source-dirs+ * Monoidal field+ * Documentation of :pkg-field:`hs-source-dirs`++ .. math::+ \mathrm{optcommalist}\left\{ \mathop{\mathit{hs\text{-}string}}\mid{{[\mathop{\mathord{``}\mathtt{\ }\mathord{"}}\mathop{\mathord{``}\mathtt{\text{,}}\mathord{"}}]^c}}^+_{} \right\}++include-dirs+ * Monoidal field+ * Documentation of :pkg-field:`include-dirs`++ .. math::+ \mathrm{optcommalist}\left\{ \mathop{\mathit{hs\text{-}string}}\mid{{[\mathop{\mathord{``}\mathtt{\ }\mathord{"}}\mathop{\mathord{``}\mathtt{\text{,}}\mathord{"}}]^c}}^+_{} \right\}++includes+ * Monoidal field+ * Documentation of :pkg-field:`includes`++ .. math::+ \mathrm{optcommalist}\left\{ \mathop{\mathit{hs\text{-}string}}\mid{{[\mathop{\mathord{``}\mathtt{\ }\mathord{"}}\mathop{\mathord{``}\mathtt{\text{,}}\mathord{"}}]^c}}^+_{} \right\}++install-includes+ * Monoidal field+ * Documentation of :pkg-field:`install-includes`++ .. math::+ \mathrm{optcommalist}\left\{ \mathop{\mathit{hs\text{-}string}}\mid{{[\mathop{\mathord{``}\mathtt{\ }\mathord{"}}\mathop{\mathord{``}\mathtt{\text{,}}\mathord{"}}]^c}}^+_{} \right\}++js-sources+ * Monoidal field+ * Documentation of :pkg-field:`js-sources`++ .. math::+ \mathrm{commalist}\left\{ \mathop{\mathit{hs\text{-}string}}\mid{{[\mathop{\mathord{``}\mathtt{\ }\mathord{"}}\mathop{\mathord{``}\mathtt{\text{,}}\mathord{"}}]^c}}^+_{} \right\}++ld-options+ * Monoidal field+ * Documentation of :pkg-field:`ld-options`++ .. math::+ {\left\{ \mathop{\mathit{hs\text{-}string}}\mid{{[\mathop{\mathord{``}\mathtt{\ }\mathord{"}}]^c}}^+_{} \right\}}^\ast_{\bullet}++mixins+ * Monoidal field+ * Available since ``cabal-version: 2.0``.+ * Documentation of :pkg-field:`mixins`++ .. math::+ \mathrm{commalist}\left(\mathop{\mathit{package\text{-}name}}{\left(\mathop{\mathord{``}\mathtt{\text{:}}\mathord{"}}\mathop{\mathit{library\text{-}name}}\right)}^?{\left(\bullet\left\{ \mid\mathop{\mathord{``}\mathtt{hiding}\mathord{"}}\circ\mathop{\mathord{``}\mathtt{\text{(}}\mathord{"}}\circ{\mathop{\mathit{module\text{-}name}}}^\ast_{\left(\circ\mathop{\mathord{``}\mathtt{\text{,}}\mathord{"}}\circ\right)}\circ\mathop{\mathord{``}\mathtt{\text{)}}\mathord{"}}\mid\mathop{\mathord{``}\mathtt{\text{(}}\mathord{"}}\circ{\left(\mathop{\mathit{module\text{-}name}}{\left(\bullet\mathop{\mathord{``}\mathtt{as}\mathord{"}}\bullet\mathop{\mathit{module\text{-}name}}\right)}^?\right)}^\ast_{\left(\circ\mathop{\mathord{``}\mathtt{\text{,}}\mathord{"}}\circ\right)}\circ\mathop{\mathord{``}\mathtt{\text{)}}\mathord{"}} \right\}{\left(\circ\mathop{\mathord{``}\mathtt{requires}\mathord{"}}\bullet\left\{ \mid\mathop{\mathord{``}\mathtt{hiding}\mathord{"}}\circ\mathop{\mathord{``}\mathtt{\text{(}}\mathord{"}}\circ{\mathop{\mathit{module\text{-}name}}}^\ast_{\left(\circ\mathop{\mathord{``}\mathtt{\text{,}}\mathord{"}}\circ\right)}\circ\mathop{\mathord{``}\mathtt{\text{)}}\mathord{"}}\mid\mathop{\mathord{``}\mathtt{\text{(}}\mathord{"}}\circ{\left(\mathop{\mathit{module\text{-}name}}{\left(\bullet\mathop{\mathord{``}\mathtt{as}\mathord{"}}\bullet\mathop{\mathit{module\text{-}name}}\right)}^?\right)}^\ast_{\left(\circ\mathop{\mathord{``}\mathtt{\text{,}}\mathord{"}}\circ\right)}\circ\mathop{\mathord{``}\mathtt{\text{)}}\mathord{"}} \right\}\right)}^?\right)}^?\right)++other-extensions+ * Monoidal field+ * Available since ``cabal-version: 1.10``.+ * Documentation of :pkg-field:`other-extensions`++ .. math::+ \mathrm{optcommalist}\mathsf{\color{red}{TODO}}++other-languages+ * Monoidal field+ * Available since ``cabal-version: 1.10``.+ * Documentation of :pkg-field:`other-languages`++ .. math::+ \mathrm{optcommalist}\left\{ \mathop{\mathord{``}\mathtt{Haskell98}\mathord{"}}\mid\mathop{\mathord{``}\mathtt{Haskell2010}\mathord{"}} \right\}++other-modules+ * Monoidal field+ * Documentation of :pkg-field:`other-modules`++ .. math::+ \mathrm{commalist}\left({\left(\mathop{\mathit{upper}}{\left\{ \mathop{\mathit{alpha\text{-}num}}\mid[\mathop{\mathord{``}\mathtt{\text{'}}\mathord{"}}\mathop{\mathord{``}\mathtt{\text{_}}\mathord{"}}] \right\}}^\ast_{}\right)}^+_{\mathop{\mathord{``}\mathtt{\text{.}}\mathord{"}}}\right)++pkgconfig-depends+ * Monoidal field+ * Documentation of :pkg-field:`pkgconfig-depends`++ .. math::+ \mathrm{commalist}\mathsf{\color{red}{TODO}}++virtual-modules+ * Monoidal field+ * Available since ``cabal-version: 2.2``.+ * Documentation of :pkg-field:`virtual-modules`++ .. math::+ \mathrm{commalist}\left({\left(\mathop{\mathit{upper}}{\left\{ \mathop{\mathit{alpha\text{-}num}}\mid[\mathop{\mathord{``}\mathtt{\text{'}}\mathord{"}}\mathop{\mathord{``}\mathtt{\text{_}}\mathord{"}}] \right\}}^\ast_{}\right)}^+_{\mathop{\mathord{``}\mathtt{\text{.}}\mathord{"}}}\right)+++Package description fields+--------------------------++author+ * Free text field+ * Documentation of :pkg-field:`author`++bug-reports+ * Free text field+ * Documentation of :pkg-field:`bug-reports`++build-type+ * Optional field+ * Documentation of :pkg-field:`build-type`++ .. math::+ \left\{ \begin{gathered}\mathop{\mathord{``}\mathtt{Simple}\mathord{"}}\\\mathop{\mathord{``}\mathtt{Configure}\mathord{"}}\\\mathop{\mathord{``}\mathtt{Custom}\mathord{"}}\\\mathop{\mathord{``}\mathtt{Make}\mathord{"}}\\\mathop{\mathord{``}\mathtt{Default}\mathord{"}}\end{gathered} \right\}++cabal-version+ * Optional field+ * Default: ``>=1.0``+ * Documentation of :pkg-field:`cabal-version`++ .. math::+ \mathop{\mathord{``}\mathtt{3\text{.}4}\mathord{"}}++category+ * Free text field+ * Documentation of :pkg-field:`category`++copyright+ * Free text field+ * Documentation of :pkg-field:`copyright`++data-dir+ * Optional field+ * Default: ``""``+ * Documentation of :pkg-field:`data-dir`++ .. math::+ \left\{ \mathop{\mathit{hs\text{-}string}}\mid{{[\mathop{\mathord{``}\mathtt{\ }\mathord{"}}\mathop{\mathord{``}\mathtt{\text{,}}\mathord{"}}]^c}}^+_{} \right\}++data-files+ * Monoidal field+ * Documentation of :pkg-field:`data-files`++ .. math::+ \mathrm{commalist}\left\{ \mathop{\mathit{hs\text{-}string}}\mid{{[\mathop{\mathord{``}\mathtt{\ }\mathord{"}}\mathop{\mathord{``}\mathtt{\text{,}}\mathord{"}}]^c}}^+_{} \right\}++description+ * Free text field+ * Documentation of :pkg-field:`description`++extra-doc-files+ * Monoidal field+ * Documentation of :pkg-field:`extra-doc-files`++ .. math::+ \mathrm{commalist}\left\{ \mathop{\mathit{hs\text{-}string}}\mid{{[\mathop{\mathord{``}\mathtt{\ }\mathord{"}}\mathop{\mathord{``}\mathtt{\text{,}}\mathord{"}}]^c}}^+_{} \right\}++extra-source-files+ * Monoidal field+ * Documentation of :pkg-field:`extra-source-files`++ .. math::+ \mathrm{commalist}\left\{ \mathop{\mathit{hs\text{-}string}}\mid{{[\mathop{\mathord{``}\mathtt{\ }\mathord{"}}\mathop{\mathord{``}\mathtt{\text{,}}\mathord{"}}]^c}}^+_{} \right\}++extra-tmp-files+ * Monoidal field+ * Documentation of :pkg-field:`extra-tmp-files`++ .. math::+ \mathrm{commalist}\left\{ \mathop{\mathit{hs\text{-}string}}\mid{{[\mathop{\mathord{``}\mathtt{\ }\mathord{"}}\mathop{\mathord{``}\mathtt{\text{,}}\mathord{"}}]^c}}^+_{} \right\}++homepage+ * Free text field+ * Documentation of :pkg-field:`homepage`++license+ * Optional field+ * Default: ``NONE``+ * Documentation of :pkg-field:`license`++ .. math::+ \mathsf{\color{red}{TODO}}++license-file+ * Monoidal field+ * Documentation of :pkg-field:`license-file`++ .. math::+ \mathrm{optcommalist}\left\{ \mathop{\mathit{hs\text{-}string}}\mid{{[\mathop{\mathord{``}\mathtt{\ }\mathord{"}}\mathop{\mathord{``}\mathtt{\text{,}}\mathord{"}}]^c}}^+_{} \right\}++maintainer+ * Free text field+ * Documentation of :pkg-field:`maintainer`++name+ * Required field+ * Documentation of :pkg-field:`name`++ .. math::+ \mathop{\mathit{unqual\text{-}name}}++package-url+ * Free text field+ * Documentation of :pkg-field:`package-url`++stability+ * Free text field+ * Documentation of :pkg-field:`stability`++synopsis+ * Free text field+ * Documentation of :pkg-field:`synopsis`++tested-with+ * Monoidal field+ * Documentation of :pkg-field:`tested-with`++ .. math::+ \mathrm{optcommalist}\mathsf{\color{red}{TODO}}++version+ * Required field+ * Documentation of :pkg-field:`version`++ .. math::+ {\left\{ \mathop{\mathord{``}\mathtt{0}\mathord{"}}\mid[\mathop{\mathord{``}\mathtt{1}\mathord{"}}\cdots\mathop{\mathord{``}\mathtt{9}\mathord{"}}]{[\mathop{\mathord{``}\mathtt{0}\mathord{"}}\cdots\mathop{\mathord{``}\mathtt{9}\mathord{"}}]}^{\in [0\ldots8]}_{} \right\}}^+_{\mathop{\mathord{``}\mathtt{\text{.}}\mathord{"}}}+++Test-suite fields+-----------------++main-is+ * Optional field+ * Documentation of :pkg-field:`test-suite:main-is`++ .. math::+ \left\{ \mathop{\mathit{hs\text{-}string}}\mid{{[\mathop{\mathord{``}\mathtt{\ }\mathord{"}}\mathop{\mathord{``}\mathtt{\text{,}}\mathord{"}}]^c}}^+_{} \right\}++test-module+ * Optional field+ * Documentation of :pkg-field:`test-suite:test-module`++ .. math::+ {\left(\mathop{\mathit{upper}}{\left\{ \mathop{\mathit{alpha\text{-}num}}\mid[\mathop{\mathord{``}\mathtt{\text{'}}\mathord{"}}\mathop{\mathord{``}\mathtt{\text{_}}\mathord{"}}] \right\}}^\ast_{}\right)}^+_{\mathop{\mathord{``}\mathtt{\text{.}}\mathord{"}}}++type+ * Optional field+ * Documentation of :pkg-field:`test-suite:type`++ .. math::+ \left\{ \mathop{\mathord{``}\mathtt{exitcode\text{-}stdio\text{-}1\text{.}0}\mathord{"}}\mid\mathop{\mathord{``}\mathtt{detailed\text{-}0\text{.}9}\mathord{"}} \right\}++
+ cabal/Cabal/doc/cabal-commands.rst view
@@ -0,0 +1,402 @@+cabal-install Commands+======================++We now give an in-depth description of all the commands, describing the+arguments and flags they accept.++cabal v2-configure+-------------------++``cabal v2-configure`` takes a set of arguments and writes a+``cabal.project.local`` file based on the flags passed to this command.+``cabal v2-configure FLAGS; cabal v2-build`` is roughly equivalent to+``cabal v2-build FLAGS``, except that with ``v2-configure`` the flags+are persisted to all subsequent calls to ``v2-build``.++``cabal v2-configure`` is intended to be a convenient way to write out+a ``cabal.project.local`` for simple configurations; e.g.,+``cabal v2-configure -w ghc-7.8`` would ensure that all subsequent+builds with ``cabal v2-build`` are performed with the compiler+``ghc-7.8``. For more complex configuration, we recommend writing the+``cabal.project.local`` file directly (or placing it in+``cabal.project``!)++``cabal v2-configure`` inherits options from ``Cabal``. semantics:++- Any flag accepted by ``./Setup configure``.++- Any flag accepted by ``cabal configure`` beyond+ ``./Setup configure``, namely ``--cabal-lib-version``,+ ``--constraint``, ``--preference`` and ``--solver.``++- Any flag accepted by ``cabal install`` beyond ``./Setup configure``.++- Any flag accepted by ``./Setup haddock``.++The options of all of these flags apply only to *local* packages in a+project; this behavior is different than that of ``cabal install``,+which applies flags to every package that would be built. The motivation+for this is to avoid an innocuous addition to the flags of a package+resulting in a rebuild of every package in the store (which might need+to happen if a flag actually applied to every transitive dependency). To+apply options to an external package, use a ``package`` stanza in a+``cabal.project`` file.++cabal v2-update+----------------++``cabal v2-update`` updates the state of the package index. If the+project contains multiple remote package repositories it will update+the index of all of them (e.g. when using overlays).++Some examples:++::++ $ cabal v2-update # update all remote repos+ $ cabal v2-update head.hackage # update only head.hackage++cabal v2-build+---------------++``cabal v2-build`` takes a set of targets and builds them. It+automatically handles building and installing any dependencies of these+targets.++A target can take any of the following forms:++- A package target: ``package``, which specifies that all enabled+ components of a package to be built. By default, test suites and+ benchmarks are *not* enabled, unless they are explicitly requested+ (e.g., via ``--enable-tests``.)++- A component target: ``[package:][ctype:]component``, which specifies+ a specific component (e.g., a library, executable, test suite or+ benchmark) to be built.++- All packages: ``all``, which specifies all packages within the project.++- Components of a particular type: ``package:ctypes``, ``all:ctypes``:+ which specifies all components of the given type. Where valid+ ``ctypes`` are:++ - ``libs``, ``libraries``,+ - ``flibs``, ``foreign-libraries``,+ - ``exes``, ``executables``,+ - ``tests``,+ - ``benches``, ``benchmarks``.++- A module target: ``[package:][ctype:]module``, which specifies that the+ component of which the given module is a part of will be built.++- A filepath target: ``[package:][ctype:]filepath``, which specifies that the+ component of which the given filepath is a part of will be built.++In component targets, ``package:`` and ``ctype:`` (valid component types+are ``lib``, ``flib``, ``exe``, ``test`` and ``bench``) can be used to+disambiguate when multiple packages define the same component, or the+same component name is used in a package (e.g., a package ``foo``+defines both an executable and library named ``foo``). We always prefer+interpreting a target as a package name rather than as a component name.++Some example targets:++::++ $ cabal v2-build lib:foo-pkg # build the library named foo-pkg+ $ cabal v2-build foo-pkg:foo-tests # build foo-tests in foo-pkg+ $ cabal v2-build src/Lib.s # build the library component to+ # which "src/Lib.hs" belongs+ $ cabal v2-build app/Main.hs # build the executable component of+ # "app/Main.hs"+ $ cabal v2-build Lib # build the library component to+ # which the module "Lib" belongs++Beyond a list of targets, ``cabal v2-build`` accepts all the flags that+``cabal v2-configure`` takes. Most of these flags are only taken into+consideration when building local packages; however, some flags may+cause extra store packages to be built (for example,+``--enable-profiling`` will automatically make sure profiling libraries+for all transitive dependencies are built and installed.)++In addition ``cabal v2-build`` accepts these flags:++- ``--only-configure``: When given we will forego performing a full build and+ abort after running the configure phase of each target package.+++cabal v2-repl+--------------++``cabal v2-repl TARGET`` loads all of the modules of the target into+GHCi as interpreted bytecode. In addition to ``cabal v2-build``'s flags,+it takes an additional ``--repl-options`` flag.++To avoid ``ghci`` specific flags from triggering unneeded global rebuilds these+flags are now stripped from the internal configuration. As a result+``--ghc-options`` will no longer (reliably) work to pass flags to ``ghci`` (or+other repls). Instead, you should use the new ``--repl-options`` flag to+specify these options to the invoked repl. (This flag also works on ``cabal+repl`` and ``Setup repl`` on sufficiently new versions of Cabal.)++Currently, it is not supported to pass multiple targets to ``v2-repl``+(``v2-repl`` will just successively open a separate GHCi session for+each target.)++It also provides a way to experiment with libraries without needing to download+them manually or to install them globally.++This command opens a REPL with the current default target loaded, and a version+of the ``vector`` package matching that specification exposed.++::++ $ cabal v2-repl --build-depends "vector >= 0.12 && < 0.13"++Both of these commands do the same thing as the above, but only exposes ``base``,+``vector``, and the ``vector`` package's transitive dependencies even if the user+is in a project context.++::++ $ cabal v2-repl --ignore-project --build-depends "vector >= 0.12 && < 0.13"+ $ cabal v2-repl --project='' --build-depends "vector >= 0.12 && < 0.13"++This command would add ``vector``, but not (for example) ``primitive``, because+it only includes the packages specified on the command line (and ``base``, which+cannot be excluded for technical reasons).++::++ $ cabal v2-repl --build-depends vector --no-transitive-deps++cabal v2-run+-------------++``cabal v2-run [TARGET [ARGS]]`` runs the executable specified by the+target, which can be a component, a package or can be left blank, as+long as it can uniquely identify an executable within the project.+Tests and benchmarks are also treated as executables.++See `the v2-build section <#cabal-v2-build>`__ for the target syntax.++Except in the case of the empty target, the strings after it will be+passed to the executable as arguments.++If one of the arguments starts with ``-`` it will be interpreted as+a cabal flag, so if you need to pass flags to the executable you+have to separate them with ``--``.++::++ $ cabal v2-run target -- -a -bcd --argument++``v2-run`` also supports running script files that use a certain format. With+a script that looks like:++::++ #!/usr/bin/env cabal+ {- cabal:+ build-depends: base ^>= 4.11+ , shelly ^>= 1.8.1+ -}++ main :: IO ()+ main = do+ ...++It can either be executed like any other script, using ``cabal`` as an+interpreter, or through this command:++::++ $ cabal v2-run script.hs+ $ cabal v2-run script.hs -- --arg1 # args are passed like this++cabal v2-freeze+----------------++``cabal v2-freeze`` writes out a **freeze file** which records all of+the versions and flags that are picked by the solver under the+current index and flags. Default name of this file is+``cabal.project.freeze`` but in combination with a+``--project-file=my.project`` flag (see :ref:`project-file+<cmdoption-project-file>`)+the name will be ``my.project.freeze``.+A freeze file has the same syntax as ``cabal.project`` and looks+something like this:++.. highlight:: cabal++::++ constraints: HTTP ==4000.3.3,+ HTTP +warp-tests -warn-as-error -network23 +network-uri -mtl1 -conduit10,+ QuickCheck ==2.9.1,+ QuickCheck +templatehaskell,+ -- etc...+++For end-user executables, it is recommended that you distribute the+``cabal.project.freeze`` file in your source repository so that all+users see a consistent set of dependencies. For libraries, this is not+recommended: users often need to build against different versions of+libraries than what you developed against.++cabal v2-bench+---------------++``cabal v2-bench [TARGETS] [OPTIONS]`` runs the specified benchmarks+(all the benchmarks in the current package by default), first ensuring+they are up to date.++cabal v2-test+--------------++``cabal v2-test [TARGETS] [OPTIONS]`` runs the specified test suites+(all the test suites in the current package by default), first ensuring+they are up to date.++cabal v2-haddock+-----------------++``cabal v2-haddock [FLAGS] [TARGET]`` builds Haddock documentation for+the specified packages within the project.++If a target is not a library :cfg-field:`haddock-benchmarks`,+:cfg-field:`haddock-executables`, :cfg-field:`haddock-internal`,+:cfg-field:`haddock-tests` will be implied as necessary.++cabal v2-exec+---------------++``cabal v2-exec [FLAGS] [--] COMMAND [--] [ARGS]`` runs the specified command+using the project's environment. That is, passing the right flags to compiler+invocations and bringing the project's executables into scope.++cabal v2-install+-----------------++``cabal v2-install [FLAGS] PACKAGES`` builds the specified packages and+symlinks/copies their executables in ``installdir`` (usually ``~/.cabal/bin``).++For example this command will build the latest ``cabal-install`` and symlink+its ``cabal`` executable:++::++ $ cabal v2-install cabal-install++In addition, it's possible to use ``cabal v2-install`` to install components+of a local project. For example, with an up-to-date Git clone of the Cabal+repository, this command will build cabal-install HEAD and symlink the+``cabal`` executable:++::++ $ cabal v2-install exe:cabal++Where symlinking is not possible (eg. on some Windows versions) the ``copy``+method is used by default. You can specify the install method+by using ``--install-method`` flag:++::++ $ cabal v2-install exe:cabal --install-method=copy --installdir=$HOME/bin++Note that copied executables are not self-contained, since they might use+data-files from the store.++It is also possible to "install" libraries using the ``--lib`` flag. For+example, this command will build the latest Cabal library and install it:++::++ $ cabal v2-install --lib Cabal++This works by managing GHC environments. By default, it is writing to the+global environment in ``~/.ghc/$ARCH-$OS-$GHCVER/environments/default``.+``v2-install`` provides the ``--package-env`` flag to control which of+these environments is modified.++This command will modify the environment file in the current directory:++::++ $ cabal v2-install --lib Cabal --package-env .++This command will modify the environment file in the ``~/foo`` directory:++::++ $ cabal v2-install --lib Cabal --package-env foo/++Do note that the results of the previous two commands will be overwritten by+the use of other v2-style commands, so it is not recommended to use them inside+a project directory.++This command will modify the environment in the ``local.env`` file in the+current directory:++::++ $ cabal v2-install --lib Cabal --package-env local.env++This command will modify the ``myenv`` named global environment:++::++ $ cabal v2-install --lib Cabal --package-env myenv++If you wish to create a named environment file in the current directory where+the name does not contain an extension, you must reference it as ``./myenv``.++You can learn more about how to use these environments in `this section of the+GHC manual <https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/packages.html#package-environments>`_.++cabal v2-clean+---------------++``cabal v2-clean [FLAGS]`` cleans up the temporary files and build artifacts+stored in the ``dist-newstyle`` folder.++By default, it removes the entire folder, but it can also spare the configuration+and caches if the ``--save-config`` option is given, in which case it only removes+the build artefacts (``.hi``, ``.o`` along with any other temporary files generated+by the compiler, along with the build output).++cabal v2-sdist+---------------++``cabal v2-sdist [FLAGS] [TARGETS]`` takes the crucial files needed to build ``TARGETS``+and puts them into an archive format ready for upload to Hackage. These archives are stable+and two archives of the same format built from the same source will hash to the same value.++``cabal v2-sdist`` takes the following flags:++- ``-l``, ``--list-only``: Rather than creating an archive, lists files that would be included.+ Output is to ``stdout`` by default. The file paths are relative to the project's root+ directory.++- ``-o``, ``--output-directory``: Sets the output dir, if a non-default one is desired. The default is+ ``dist-newstyle/sdist/``. ``--output-directory -`` will send output to ``stdout``+ unless multiple archives are being created.++- ``--null-sep``: Only used with ``--list-only``. Separates filenames with a NUL+ byte instead of newlines.++``v2-sdist`` is inherently incompatible with sdist hooks (which were removed in `Cabal-3.0`),+not due to implementation but due to fundamental core invariants+(same source code should result in the same tarball, byte for byte)+that must be satisfied for it to function correctly in the larger v2-build ecosystem.+``autogen-modules`` is able to replace uses of the hooks to add generated modules, along with+the custom publishing of Haddock documentation to Hackage.++.. warning::++ Packages that use Backpack will stop working if uploaded to+ Hackage, due to `issue #6005 <https://github.com/haskell/cabal/issues/6005>`_.+ While this is happening, we recommend not uploading these packages+ to Hackage (and instead referencing the package directly+ as a ``source-repository-package``).
+ cabal/Cabal/doc/cabal-package.rst view
@@ -0,0 +1,3335 @@+Package Description+===================++The Cabal package is the unit of distribution. When installed, its+purpose is to make available:++- One or more Haskell programs.++- At most one library, exposing a number of Haskell modules.++However having both a library and executables in a package does not work+very well; if the executables depend on the library, they must+explicitly list all the modules they directly or indirectly import from+that library. Fortunately, starting with Cabal 1.8.0.4, executables can+also declare the package that they are in as a dependency, and Cabal+will treat them as if they were in another package that depended on the+library.++Internally, the package may consist of much more than a bunch of Haskell+modules: it may also have C source code and header files, source code+meant for preprocessing, documentation, test cases, auxiliary tools etc.++A package is identified by a globally-unique *package name*, which+consists of one or more alphanumeric words separated by hyphens. To+avoid ambiguity, each of these words should contain at least one letter.+Chaos will result if two distinct packages with the same name are+installed on the same system. A particular version of the package is+distinguished by a *version number*, consisting of a sequence of one or+more integers separated by dots. These can be combined to form a single+text string called the *package ID*, using a hyphen to separate the name+from the version, e.g. "``HUnit-1.1``".++.. Note::++ Packages are not part of the Haskell language; they simply+ populate the hierarchical space of module names. In GHC 6.6 and later a+ program may contain multiple modules with the same name if they come+ from separate packages; in all other current Haskell systems packages+ may not overlap in the modules they provide, including hidden modules.++Creating a package+------------------++Suppose you have a directory hierarchy containing the source files that+make up your package. You will need to add two more files to the root+directory of the package:++:file:`{package-name}.cabal`+ a Unicode UTF-8 text file containing a package description. For+ details of the syntax of this file, see the section on+ `package descriptions`_.++:file:`Setup.hs`+ a single-module Haskell program to perform various setup tasks (with+ the interface described in the section on :ref:`installing-packages`).+ This module should import only modules that will be present in all Haskell+ implementations, including modules of the Cabal library. The content of+ this file is determined by the :pkg-field:`build-type` setting in the+ ``.cabal`` file. In most cases it will be trivial, calling on the Cabal+ library to do most of the work.++Once you have these, you can create a source bundle of this directory+for distribution. Building of the package is discussed in the section on+:ref:`installing-packages`.++One of the purposes of Cabal is to make it easier to build a package+with different Haskell implementations. So it provides abstractions of+features present in different Haskell implementations and wherever+possible it is best to take advantage of these to increase portability.+Where necessary however it is possible to use specific features of+specific implementations. For example one of the pieces of information a+package author can put in the package's ``.cabal`` file is what language+extensions the code uses. This is far preferable to specifying flags for+a specific compiler as it allows Cabal to pick the right flags for the+Haskell implementation that the user picks. It also allows Cabal to+figure out if the language extension is even supported by the Haskell+implementation that the user picks. Where compiler-specific options are+needed however, there is an "escape hatch" available. The developer can+specify implementation-specific options and more generally there is a+configuration mechanism to customise many aspects of how a package is+built depending on the Haskell implementation, the Operating system,+computer architecture and user-specified configuration flags.++::++ name: Foo+ version: 1.0++ library+ build-depends: base >= 4 && < 5+ exposed-modules: Foo+ extensions: ForeignFunctionInterface+ ghc-options: -Wall+ if os(windows)+ build-depends: Win32 >= 2.1 && < 2.6++Example: A package containing a simple library+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^++The HUnit package contains a file ``HUnit.cabal`` containing:++::++ name: HUnit+ version: 1.1.1+ synopsis: A unit testing framework for Haskell+ homepage: http://hunit.sourceforge.net/+ category: Testing+ author: Dean Herington+ license: BSD3+ license-file: LICENSE+ cabal-version: 1.12+ build-type: Simple++ library+ build-depends: base >= 2 && < 4+ exposed-modules: Test.HUnit.Base, Test.HUnit.Lang,+ Test.HUnit.Terminal, Test.HUnit.Text, Test.HUnit+ default-extensions: CPP++and the following ``Setup.hs``:++.. code-block:: haskell++ import Distribution.Simple+ main = defaultMain++Example: A package containing executable programs+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^++::++ name: TestPackage+ version: 0.0+ synopsis: Small package with two programs+ author: Angela Author+ license: BSD3+ build-type: Simple+ cabal-version: >= 1.8++ executable program1+ build-depends: HUnit >= 1.1.1 && < 1.2+ main-is: Main.hs+ hs-source-dirs: prog1++ executable program2+ main-is: Main.hs+ build-depends: HUnit >= 1.1.1 && < 1.2+ hs-source-dirs: prog2+ other-modules: Utils++with ``Setup.hs`` the same as above.++Example: A package containing a library and executable programs+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^++::++ name: TestPackage+ version: 0.0+ synopsis: Package with library and two programs+ license: BSD3+ author: Angela Author+ build-type: Simple+ cabal-version: >= 1.8++ library+ build-depends: HUnit >= 1.1.1 && < 1.2+ exposed-modules: A, B, C++ executable program1+ main-is: Main.hs+ hs-source-dirs: prog1+ other-modules: A, B++ executable program2+ main-is: Main.hs+ hs-source-dirs: prog2+ other-modules: A, C, Utils++with ``Setup.hs`` the same as above. Note that any library modules+required (directly or indirectly) by an executable must be listed again.++The trivial setup script used in these examples uses the *simple build+infrastructure* provided by the Cabal library (see+`Distribution.Simple <../release/cabal-latest/doc/API/Cabal/Distribution-Simple.html>`__).+The simplicity lies in its interface rather that its implementation. It+automatically handles preprocessing with standard preprocessors, and+builds packages for all the Haskell implementations.++The simple build infrastructure can also handle packages where building+is governed by system-dependent parameters, if you specify a little more+(see the section on `system-dependent parameters`_).+A few packages require `more elaborate solutions <more complex packages>`_.++.. _pkg-desc:++Package descriptions+--------------------++The package description file must have a name ending in "``.cabal``". It+must be a Unicode text file encoded using valid UTF-8. There must be+exactly one such file in the directory. The first part of the name is+usually the package name, and some of the tools that operate on Cabal+packages require this; specifically, Hackage rejects packages which+don't follow this rule.++In the package description file, lines whose first non-whitespace+characters are "``--``" are treated as comments and ignored.++This file should contain a number global property descriptions and+several sections.++- The `package properties`_ describe the package+ as a whole, such as name, license, author, etc.++- Optionally, a number of *configuration flags* can be declared. These+ can be used to enable or disable certain features of a package. (see+ the section on `configurations`_).++- The (optional) library section specifies the `library`_ properties and+ relevant `build information`_.++- Following is an arbitrary number of executable sections which describe+ an executable program and relevant `build information`_.++Each section consists of a number of property descriptions in the form+of field/value pairs, with a syntax roughly like mail message headers.++- Case is not significant in field names, but is significant in field+ values.++- To continue a field value, indent the next line relative to the field+ name.++- Field names may be indented, but all field values in the same section+ must use the same indentation.++- Tabs are *not* allowed as indentation characters due to a missing+ standard interpretation of tab width.++- Before Cabal 3.0, to get a blank line in a field value, use an indented "``.``"++The syntax of the value depends on the field. Field types include:++*token*, *filename*, *directory*+ Either a sequence of one or more non-space non-comma characters, or+ a quoted string in Haskell 98 lexical syntax. The latter can be used+ for escaping whitespace, for example:+ ``ghc-options: -Wall "-with-rtsopts=-T -I1"``. Unless otherwise+ stated, relative filenames and directories are interpreted from the+ package root directory.+*freeform*, *URL*, *address*+ An arbitrary, uninterpreted string.+*identifier*+ A letter followed by zero or more alphanumerics or underscores.+*compiler*+ A compiler flavor (one of: ``GHC``, ``UHC`` or ``LHC``)+ followed by a version range. For example, ``GHC ==6.10.3``, or+ ``LHC >=0.6 && <0.8``.++Modules and preprocessors+^^^^^^^^^^^^^^^^^^^^^^^^^++Haskell module names listed in the :pkg-field:`library:exposed-modules` and+:pkg-field:`library:other-modules` fields may correspond to Haskell source+files, i.e. with names ending in "``.hs``" or "``.lhs``", or to inputs for+various Haskell preprocessors. The simple build infrastructure understands the+extensions:++- ``.gc`` (:hackage-pkg:`greencard`)+- ``.chs`` (:hackage-pkg:`c2hs`)+- ``.hsc`` (:hackage-pkg:`hsc2hs`)+- ``.y`` and ``.ly`` (happy_)+- ``.x`` (alex_)+- ``.cpphs`` (cpphs_)++When building, Cabal will automatically run the appropriate preprocessor+and compile the Haskell module it produces. For the ``c2hs`` and+``hsc2hs`` preprocessors, Cabal will also automatically add, compile and+link any C sources generated by the preprocessor (produced by+``hsc2hs``'s ``#def`` feature or ``c2hs``'s auto-generated wrapper+functions). Dependencies on pre-processors are specified via the+:pkg-field:`build-tools` or :pkg-field:`build-tool-depends` fields.++Some fields take lists of values, which are optionally separated by+commas, except for the :pkg-field:`build-depends` field, where the commas are+mandatory.++Some fields are marked as required. All others are optional, and unless+otherwise specified have empty default values.++Package properties+^^^^^^^^^^^^^^^^^^++These fields may occur in the first top-level properties section and+describe the package as a whole:++.. pkg-field:: name: package-name (required)++ The unique name of the package, without the version number.++ As pointed out in the section on `package descriptions`_, some+ tools require the package-name specified for this field to match+ the package description's file-name :file:`{package-name}.cabal`.++ Package names are case-sensitive and must match the regular expression+ (i.e. alphanumeric "words" separated by dashes; each alphanumeric+ word must contain at least one letter):+ ``[[:digit:]]*[[:alpha:]][[:alnum:]]*(-[[:digit:]]*[[:alpha:]][[:alnum:]]*)*``.++ Or, expressed in ABNF_:++ .. code-block:: abnf++ package-name = package-name-part *("-" package-name-part)+ package-name-part = *DIGIT UALPHA *UALNUM++ UALNUM = UALPHA / DIGIT+ UALPHA = ... ; set of alphabetic Unicode code-points++ .. note::++ Hackage restricts package names to the ASCII subset.++.. pkg-field:: version: numbers (required)++ The package version number, usually consisting of a sequence of+ natural numbers separated by dots, i.e. as the regular+ expression ``[0-9]+([.][0-9]+)*`` or expressed in ABNF_:++ .. code-block:: abnf++ package-version = 1*DIGIT *("." 1*DIGIT)++.. pkg-field:: cabal-version: x.y[.z]++ The version of the Cabal specification that this package+ description uses. The Cabal specification does slowly evolve (see+ also :ref:`spec-history`), introducing new features and+ occasionally changing the meaning of existing features.+ Specifying which version of the specification you are using+ enables programs which process the package description to know+ what syntax to expect and what each part means.++ The version number you specify will affect both compatibility and+ behaviour. Most tools (including the Cabal library and the ``cabal``+ program) understand a range of versions of the Cabal specification.+ Older tools will of course only work with older versions of the+ Cabal specification that was known at the time. Most of the time,+ tools that are too old will recognise this fact and produce a+ suitable error message. Likewise, ``cabal check`` will tell you+ whether the version number is sufficiently high for the features+ you use in the package description.++ As for behaviour, new versions of the Cabal specification can change the+ meaning of existing syntax. This means if you want to take advantage+ of the new meaning or behaviour then you must specify the newer+ Cabal version. Tools are expected to use the meaning and behaviour+ appropriate to the version given in the package description.++ In particular, the syntax of package descriptions changed+ significantly with Cabal version 1.2 and the :pkg-field:`cabal-version`+ field is now required. Files written in the old syntax are still+ recognized, so if you require compatibility with very old Cabal+ versions then you may write your package description file using the+ old syntax. Please consult the user's guide of an older Cabal+ version for a description of that syntax.++ Starting with ``cabal-version: 2.2`` this field is only valid if+ fully contained in the very first line of a package description+ and ought to adhere to the ABNF_ grammar++ .. code-block:: abnf++ newstyle-spec-version-decl = "cabal-version" *WS ":" *WS newstyle-spec-version *WS++ newstyle-spec-version = NUM "." NUM [ "." NUM ]++ NUM = DIGIT0 / DIGITP 1*DIGIT0+ DIGIT0 = %x30-39+ DIGITP = %x31-39+ WS = %20+++ .. note::++ For package descriptions using a format prior to+ ``cabal-version: 1.12`` the legacy syntax resembling a version+ range syntax++ .. code-block:: cabal++ cabal-version: >= 1.10++ needs to be used.++ This legacy syntax is supported up until ``cabal-version: >=+ 2.0`` it is however strongly recommended to avoid using the+ legacy syntax. See also :issue:`4899`.++++.. pkg-field:: build-type: identifier++ :default: ``Custom`` or ``Simple``++ The type of build used by this package. Build types are the+ constructors of the+ `BuildType <../release/cabal-latest/doc/API/Cabal/Distribution-PackageDescription.html#t:BuildType>`__+ type. This field is optional and when missing, its default value+ is inferred according to the following rules:++ - When :pkg-field:`cabal-version` is set to ``2.2`` or higher,+ the default is ``Simple`` unless a :pkg-section:`custom-setup`+ exists, in which case the inferred default is ``Custom``.++ - For lower :pkg-field:`cabal-version` values, the default is+ ``Custom`` unconditionally.++ If the build type is anything other than ``Custom``, then the+ ``Setup.hs`` file *must* be exactly the standardized content+ discussed below. This is because in these cases, ``cabal`` will+ ignore the ``Setup.hs`` file completely, whereas other methods of+ package management, such as ``runhaskell Setup.hs [CMD]``, still+ rely on the ``Setup.hs`` file.++ For build type ``Simple``, the contents of ``Setup.hs`` must be:++ .. code-block:: haskell++ import Distribution.Simple+ main = defaultMain++ For build type ``Configure`` (see the section on `system-dependent+ parameters`_ below), the contents of+ ``Setup.hs`` must be:++ .. code-block:: haskell++ import Distribution.Simple+ main = defaultMainWithHooks autoconfUserHooks++ For build type ``Make`` (see the section on `more complex packages`_ below),+ the contents of ``Setup.hs`` must be:++ .. code-block:: haskell++ import Distribution.Make+ main = defaultMain++ For build type ``Custom``, the file ``Setup.hs`` can be customized,+ and will be used both by ``cabal`` and other tools.++ For most packages, the build type ``Simple`` is sufficient.++.. pkg-field:: license: SPDX expression++ :default: ``NONE``++ The type of license under which this package is distributed.++ Starting with ``cabal-version: 2.2`` the ``license`` field takes a+ (case-sensitive) SPDX expression such as++ .. code-block:: cabal++ license: Apache-2.0 AND (MIT OR GPL-2.0-or-later)++ See `SPDX IDs: How to use <https://spdx.org/ids-how>`__ for more+ examples of SPDX expressions.++ The version of the+ `list of SPDX license identifiers <https://spdx.org/licenses/>`__+ is a function of the :pkg-field:`cabal-version` value as defined+ in the following table:++ +--------------------------+--------------------++ | Cabal specification | SPDX license list |+ | version | version |+ | | |+ +==========================+====================++ | ``cabal-version: 2.2`` | ``3.0 2017-12-28`` |+ +--------------------------+--------------------++ | ``cabal-version: 2.4`` | ``3.2 2018-07-10`` |+ +--------------------------+--------------------+++ **Pre-SPDX Legacy Identifiers**++ The license identifier in the table below are defined for+ ``cabal-version: 2.0`` and previous versions of the Cabal+ specification.++ +--------------------------+-----------------++ | :pkg-field:`license` | Note |+ | identifier | |+ | | |+ +==========================+=================++ | ``GPL`` | |+ | ``GPL-2`` | |+ | ``GPL-3`` | |+ +--------------------------+-----------------++ | ``LGPL`` | |+ | ``LGPL-2.1`` | |+ | ``LGPL-3`` | |+ +--------------------------+-----------------++ | ``AGPL`` | since 1.18 |+ | ``AGPL-3`` | |+ +--------------------------+-----------------++ | ``BSD2`` | since 1.20 |+ +--------------------------+-----------------++ | ``BSD3`` | |+ +--------------------------+-----------------++ | ``MIT`` | |+ +--------------------------+-----------------++ | ``ISC`` | since 1.22 |+ +--------------------------+-----------------++ | ``MPL-2.0`` | since 1.20 |+ +--------------------------+-----------------++ | ``Apache`` | |+ | ``Apache-2.0`` | |+ +--------------------------+-----------------++ | ``PublicDomain`` | |+ +--------------------------+-----------------++ | ``AllRightsReserved`` | |+ +--------------------------+-----------------++ | ``OtherLicense`` | |+ +--------------------------+-----------------++++.. pkg-field:: license-file: filename++ See :pkg-field:`license-files`.++.. pkg-field:: license-files: filename list+ :since: 1.20++ The name of a file(s) containing the precise copyright license for+ this package. The license file(s) will be installed with the+ package.++ If you have multiple license files then use the :pkg-field:`license-files`+ field instead of (or in addition to) the :pkg-field:`license-file` field.++.. pkg-field:: copyright: freeform++ The content of a copyright notice, typically the name of the holder+ of the copyright on the package and the year(s) from which copyright+ is claimed. For example::++ copyright: (c) 2006-2007 Joe Bloggs++.. pkg-field:: author: freeform++ The original author of the package.++ Remember that ``.cabal`` files are Unicode, using the UTF-8+ encoding.++.. pkg-field:: maintainer: address++ The current maintainer or maintainers of the package. This is an+ e-mail address to which users should send bug reports, feature+ requests and patches.++.. pkg-field:: stability: freeform++ The stability level of the package, e.g. ``alpha``,+ ``experimental``, ``provisional``, ``stable``.++.. pkg-field:: homepage: URL++ The package homepage.++.. pkg-field:: bug-reports: URL++ The URL where users should direct bug reports. This would normally+ be either:++ - A ``mailto:`` URL, e.g. for a person or a mailing list.++ - An ``http:`` (or ``https:``) URL for an online bug tracking+ system.++ For example Cabal itself uses a web-based bug tracking system++ ::++ bug-reports: https://github.com/haskell/cabal/issues++.. pkg-field:: package-url: URL++ The location of a source bundle for the package. The distribution+ should be a Cabal package.++.. pkg-field:: synopsis: freeform++ A very short description of the package, for use in a table of+ packages. This is your headline, so keep it short (one line) but as+ informative as possible. Save space by not including the package+ name or saying it's written in Haskell.++.. pkg-field:: description: freeform++ Description of the package. This may be several paragraphs, and+ should be aimed at a Haskell programmer who has never heard of your+ package before.++ For library packages, this field is used as prologue text by+ :ref:`setup-haddock` and thus may contain the same markup as Haddock_+ documentation comments.++.. pkg-field:: category: freeform++ A classification category for future use by the package catalogue+ Hackage_. These categories have not+ yet been specified, but the upper levels of the module hierarchy+ make a good start.++.. pkg-field:: tested-with: compiler list++ A list of compilers and versions against which the package has been+ tested (or at least built). The value of this field is not used by Cabal+ and is rather intended as extra metadata for use by third party+ tooling, such as e.g. CI tooling.++ Here's a typical usage example++ ::++ tested-with: GHC == 8.6.3, GHC == 8.4.4, GHC == 8.2.2, GHC == 8.0.2,+ GHC == 7.10.3, GHC == 7.8.4, GHC == 7.6.3, GHC == 7.4.2++ which can (starting with Cabal 3.0) also be written using the more+ concise set notation syntax++ ::++ tested-with: GHC == { 8.6.3, 8.4.4, 8.2.2, 8.0.2, 7.10.3, 7.8.4, 7.6.3, 7.4.2 }++.. pkg-field:: data-files: filename list++ A list of files to be installed for run-time use by the package.+ This is useful for packages that use a large amount of static data,+ such as tables of values or code templates. Cabal provides a way to+ `find these files at run-time <#accessing-data-files-from-package-code>`_.++ A limited form of ``*`` wildcards in file names, for example+ ``data-files: images/*.png`` matches all the ``.png`` files in the+ ``images`` directory. ``data-files: audio/**/*.mp3`` matches all+ the ``.mp3`` files in the ``audio`` directory, including+ subdirectories.++ The specific limitations of this wildcard syntax are++ - ``*`` wildcards are only allowed in place of the file name, not+ in the directory name or file extension. It must replace the+ whole file name (e.g., ``*.html`` is allowed, but+ ``chapter-*.html`` is not). If a wildcard is used, it must be+ used with an extension, so ``data-files: data/*`` is not+ allowed.++ - Prior to Cabal 2.4, when matching a wildcard plus extension, a+ file's full extension must match exactly, so ``*.gz`` matches+ ``foo.gz`` but not ``foo.tar.gz``. This restriction has been+ lifted when ``cabal-version: 2.4`` or greater so that ``*.gz``+ does match ``foo.tar.gz``++ - ``*`` wildcards will not match if the file name is empty (e.g.,+ ``*.html`` will not match ``foo/.html``).++ - ``**`` wildcards can only appear as the final path component+ before the file name (e.g., ``data/**/images/*.jpg`` is not+ allowed). If a ``**`` wildcard is used, then the file name must+ include a ``*`` wildcard (e.g., ``data/**/README.rst`` is not+ allowed).++ - A wildcard that does not match any files is an error.++ The reason for providing only a very limited form of wildcard is to+ concisely express the common case of a large number of related files+ of the same file type without making it too easy to accidentally+ include unwanted files.++ On efficiency: if you use ``**`` patterns, the directory tree will+ be walked starting with the parent directory of the ``**``. If+ that's the root of the project, this might include ``.git/``,+ ``dist-newstyle/``, or other large directories! To avoid this+ behaviour, put the files that wildcards will match against in+ their own folder.++ ``**`` wildcards are available starting in Cabal 2.4.++.. pkg-field:: data-dir: directory++ The directory where Cabal looks for data files to install, relative+ to the source directory. By default, Cabal will look in the source+ directory itself.++.. pkg-field:: extra-source-files: filename list++ A list of additional files to be included in source distributions+ built with :ref:`setup-sdist`. As with :pkg-field:`data-files` it can use+ a limited form of ``*`` wildcards in file names.++.. pkg-field:: extra-doc-files: filename list+ :since: 1.18++ A list of additional files to be included in source distributions,+ and also copied to the html directory when Haddock documentation is+ generated. As with :pkg-field:`data-files` it can use a limited form of+ ``*`` wildcards in file names.++.. pkg-field:: extra-tmp-files: filename list++ A list of additional files or directories to be removed by+ :ref:`setup-clean`. These would typically be additional files created by+ additional hooks, such as the scheme described in the section on+ `system-dependent parameters`_++Library+^^^^^^^++.. pkg-section:: library name+ :synopsis: Library build information.++ Build information for libraries.++ Currently, there can only be one publicly exposed library in a+ package, and its name is the same as package name set by global+ :pkg-field:`name` field. In this case, the ``name`` argument to+ the :pkg-section:`library` section must be omitted.++ Starting with Cabal 2.0, private internal sub-library components+ can be defined by setting the ``name`` field to a name+ different from the current package's name; see section on+ :ref:`Internal Libraries <sublibs>` for more information.++The library section should contain the following fields:++.. pkg-field:: exposed-modules: identifier list++ :required: if this package contains a library++ A list of modules added by this package.++.. pkg-field:: virtual-modules: identifier list+ :since: 2.2++ A list of virtual modules provided by this package. Virtual modules+ are modules without a source file. See for example the ``GHC.Prim``+ module from the ``ghc-prim`` package. Modules listed here will not be+ built, but still end up in the list of ``exposed-modules`` in the+ installed package info when the package is registered in the package+ database.++.. pkg-field:: exposed: boolean++ :default: ``True``++ Some Haskell compilers (notably GHC) support the notion of packages+ being "exposed" or "hidden" which means the modules they provide can+ be easily imported without always having to specify which package+ they come from. However this only works effectively if the modules+ provided by all exposed packages do not overlap (otherwise a module+ import would be ambiguous).++ Almost all new libraries use hierarchical module names that do not+ clash, so it is very uncommon to have to use this field. However it+ may be necessary to set ``exposed: False`` for some old libraries+ that use a flat module namespace or where it is known that the+ exposed modules would clash with other common modules.++.. pkg-field:: visibility: visibility specifiers++ :since: 3.0++ :default: ``private`` for internal libraries. Cannot be set for public library.++ Cabal recognizes ``public`` and ``private`` here...++ Multiple public libraries...++.. pkg-field:: reexported-modules: exportlist+ :since: 1.22++ Supported only in GHC 7.10 and later. A list of modules to+ *reexport* from this package. The syntax of this field is+ ``orig-pkg:Name as NewName`` to reexport module ``Name`` from+ ``orig-pkg`` with the new name ``NewName``. We also support+ abbreviated versions of the syntax: if you omit ``as NewName``,+ we'll reexport without renaming; if you omit ``orig-pkg``, then we+ will automatically figure out which package to reexport from, if+ it's unambiguous.++ Reexported modules are useful for compatibility shims when a package+ has been split into multiple packages, and they have the useful+ property that if a package provides a module, and another package+ reexports it under the same name, these are not considered a+ conflict (as would be the case with a stub module.) They can also be+ used to resolve name conflicts.++.. pkg-field:: signatures: signature list+ :since: 2.0++ Supported only in GHC 8.2 and later. A list of `module signatures <https://downloads.haskell.org/~ghc/master/users-guide/separate_compilation.html#module-signatures>`__ required by this package.++ Module signatures are part of the Backpack_ extension to+ the Haskell module system.++ Packages that do not export any modules and only export required signatures+ are called "signature-only packages", and their signatures are subjected to+ `signature thinning+ <https://wiki.haskell.org/Module_signature#How_to_use_a_signature_package>`__.++++The library section may also contain build information fields (see the+section on `build information`_).++.. _sublibs:++**Internal Libraries**++Cabal 2.0 and later support "internal libraries", which are extra named+libraries (as opposed to the usual unnamed library section). For+example, suppose that your test suite needs access to some internal+modules in your library, which you do not otherwise want to export. You+could put these modules in an internal library, which the main library+and the test suite :pkg-field:`build-depends` upon. Then your Cabal file might+look something like this:++::++ cabal-version: 2.0+ name: foo+ version: 0.1.0.0+ license: BSD3+ build-type: Simple++ library foo-internal+ exposed-modules: Foo.Internal+ -- NOTE: no explicit constraints on base needed+ -- as they're inherited from the 'library' stanza+ build-depends: base++ library+ exposed-modules: Foo.Public+ build-depends: foo-internal, base >= 4.3 && < 5++ test-suite test-foo+ type: exitcode-stdio-1.0+ main-is: test-foo.hs+ -- NOTE: no constraints on 'foo-internal' as same-package+ -- dependencies implicitly refer to the same package instance+ build-depends: foo-internal, base++Internal libraries are also useful for packages that define multiple+executables, but do not define a publicly accessible library. Internal+libraries are only visible internally in the package (so they can only+be added to the :pkg-field:`build-depends` of same-package libraries,+executables, test suites, etc.) Internal libraries locally shadow any+packages which have the same name; consequently, don't name an internal+library with the same name as an external dependency if you need to be+able to refer to the external dependency in a+:pkg-field:`build-depends` declaration.++Shadowing can be used to vendor an external dependency into a package+and thus emulate *private dependencies*. Below is an example based on+a real-world use case:++::++ cabal-version: 2.2+ name: haddock-library+ version: 1.6.0++ library+ build-depends:+ , base ^>= 4.11.1.0+ , bytestring ^>= 0.10.2.0+ , containers ^>= 0.4.2.1 || ^>= 0.5.0.0+ , transformers ^>= 0.5.0.0++ hs-source-dirs: src++ -- internal sub-lib+ build-depends: attoparsec++ exposed-modules:+ Documentation.Haddock++ library attoparsec+ build-depends:+ , base ^>= 4.11.1.0+ , bytestring ^>= 0.10.2.0+ , deepseq ^>= 1.4.0.0++ hs-source-dirs: vendor/attoparsec-0.13.1.0++ -- NB: haddock-library needs only small part of lib:attoparsec+ -- internally, so we only bundle that subset here+ exposed-modules:+ Data.Attoparsec.ByteString+ Data.Attoparsec.Combinator++ other-modules:+ Data.Attoparsec.Internal++ ghc-options: -funbox-strict-fields -Wall -fwarn-tabs -O2+++Opening an interpreter session+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^++While developing a package, it is often useful to make its code+available inside an interpreter session. This can be done with the+``repl`` command:++.. code-block:: console++ $ cabal repl++The name comes from the acronym+`REPL <http://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop>`__,+which stands for "read-eval-print-loop". By default ``cabal repl`` loads+the first component in a package. If the package contains several named+components, the name can be given as an argument to ``repl``. The name+can be also optionally prefixed with the component's type for+disambiguation purposes. Example:++.. code-block:: console++ $ cabal repl foo+ $ cabal repl exe:foo+ $ cabal repl test:bar+ $ cabal repl bench:baz++Freezing dependency versions+""""""""""""""""""""""""""""++If a package is built in several different environments, such as a+development environment, a staging environment and a production+environment, it may be necessary or desirable to ensure that the same+dependency versions are selected in each environment. This can be done+with the ``freeze`` command:++.. code-block:: console++ $ cabal freeze++The command writes the selected version for all dependencies to the+``cabal.config`` file. All environments which share this file will use+the dependency versions specified in it.++Generating dependency version bounds+""""""""""""""""""""""""""""""""""""++Cabal also has the ability to suggest dependency version bounds that+conform to `Package Versioning Policy`_, which is+a recommended versioning system for publicly released Cabal packages.+This is done by running the ``gen-bounds`` command:++.. code-block:: console++ $ cabal gen-bounds++For example, given the following dependencies specified in+:pkg-field:`build-depends`:++::++ build-depends:+ foo == 0.5.2+ bar == 1.1++``gen-bounds`` will suggest changing them to the following:++::++ build-depends:+ foo >= 0.5.2 && < 0.6+ bar >= 1.1 && < 1.2++Listing outdated dependency version bounds+""""""""""""""""""""""""""""""""""""""""""++Manually updating dependency version bounds in a ``.cabal`` file or a+freeze file can be tedious, especially when there's a lot of+dependencies. The ``cabal outdated`` command is designed to help with+that. It will print a list of packages for which there is a new+version on Hackage that is outside the version bound specified in the+``build-depends`` field. The ``outdated`` command can also be+configured to act on the freeze file (both old- and v2-style) and+ignore major (or all) version bumps on Hackage for a subset of+dependencies.++The following flags are supported by the ``outdated`` command:++``--freeze-file``+ Read dependency version bounds from the freeze file (``cabal.config``)+ instead of the package description file (``$PACKAGENAME.cabal``).+ ``--v1-freeze-file`` is an alias for this flag starting in Cabal 2.4.+``--v2-freeze-file``+ :since: 2.4++ Read dependency version bounds from the v2-style freeze file+ (by default, ``cabal.project.freeze``) instead of the package+ description file. ``--new-freeze-file`` is an alias for this flag+ that can be used with pre-2.4 ``cabal``.+``--project-file`` *PROJECTFILE*+ :since: 2.4++ Read dependendency version bounds from the v2-style freeze file+ related to the named project file (i.e., ``$PROJECTFILE.freeze``)+ instead of the package desctription file. If multiple ``--project-file``+ flags are provided, only the final one is considered. This flag+ must only be passed in when ``--new-freeze-file`` is present.+``--simple-output``+ Print only the names of outdated dependencies, one per line.+``--exit-code``+ Exit with a non-zero exit code when there are outdated dependencies.+``-q, --quiet``+ Don't print any output. Implies ``-v0`` and ``--exit-code``.+``--ignore`` *PACKAGENAMES*+ Don't warn about outdated dependency version bounds for the packages in this+ list.+``--minor`` *[PACKAGENAMES]*+ Ignore major version bumps for these packages. E.g. if there's a version 2.0+ of a package ``pkg`` on Hackage and the freeze file specifies the constraint+ ``pkg == 1.9``, ``cabal outdated --freeze --minor=pkg`` will only consider+ the ``pkg`` outdated when there's a version of ``pkg`` on Hackage satisfying+ ``pkg > 1.9 && < 2.0``. ``--minor`` can also be used without arguments, in+ that case major version bumps are ignored for all packages.++Examples:++.. code-block:: console++ $ cd /some/package+ $ cabal outdated+ Outdated dependencies:+ haskell-src-exts <1.17 (latest: 1.19.1)+ language-javascript <0.6 (latest: 0.6.0.9)+ unix ==2.7.2.0 (latest: 2.7.2.1)++ $ cabal outdated --simple-output+ haskell-src-exts+ language-javascript+ unix++ $ cabal outdated --ignore=haskell-src-exts+ Outdated dependencies:+ language-javascript <0.6 (latest: 0.6.0.9)+ unix ==2.7.2.0 (latest: 2.7.2.1)++ $ cabal outdated --ignore=haskell-src-exts,language-javascript,unix+ All dependencies are up to date.++ $ cabal outdated --ignore=haskell-src-exts,language-javascript,unix -q+ $ echo $?+ 0++ $ cd /some/other/package+ $ cabal outdated --freeze-file+ Outdated dependencies:+ HTTP ==4000.3.3 (latest: 4000.3.4)+ HUnit ==1.3.1.1 (latest: 1.5.0.0)++ $ cabal outdated --freeze-file --ignore=HTTP --minor=HUnit+ Outdated dependencies:+ HUnit ==1.3.1.1 (latest: 1.3.1.2)+++Executables+^^^^^^^^^^^++.. pkg-section:: executable name+ :synopsis: Executable build info section.++ Executable sections (if present) describe executable programs contained+ in the package and must have an argument after the section label, which+ defines the name of the executable. This is a freeform argument but may+ not contain spaces.++The executable may be described using the following fields, as well as+build information fields (see the section on `build information`_).++.. pkg-field:: main-is: filename (required)++ The name of the ``.hs`` or ``.lhs`` file containing the ``Main``+ module. Note that it is the ``.hs`` filename that must be listed,+ even if that file is generated using a preprocessor. The source file+ must be relative to one of the directories listed in+ :pkg-field:`hs-source-dirs`. Further, while the name of the file may+ vary, the module itself must be named ``Main``.++ Starting with ``cabal-version: 1.18`` this field supports+ specifying a C, C++, or objC source file as the main entry point.++.. pkg-field:: scope: token+ :since: 2.0++ Whether the executable is ``public`` (default) or ``private``, i.e. meant to+ be run by other programs rather than the user. Private executables are+ installed into `$libexecdir/$libexecsubdir`.++Running executables+"""""""""""""""""""++You can have Cabal build and run your executables by using the ``run``+command:++.. code-block:: console++ $ cabal run EXECUTABLE [-- EXECUTABLE_FLAGS]++This command will configure, build and run the executable+``EXECUTABLE``. The double dash separator is required to distinguish+executable flags from ``run``'s own flags. If there is only one+executable defined in the whole package, the executable's name can be+omitted. See the output of ``cabal help run`` for a list of options you+can pass to ``cabal run``.++Test suites+^^^^^^^^^^^++.. pkg-section:: test-suite name+ :synopsis: Test suite build information.++ Test suite sections (if present) describe package test suites and must+ have an argument after the section label, which defines the name of the+ test suite. This is a freeform argument, but may not contain spaces. It+ should be unique among the names of the package's other test suites, the+ package's executables, and the package itself. Using test suite sections+ requires at least Cabal version 1.9.2.++The test suite may be described using the following fields, as well as+build information fields (see the section on `build information`_).++.. pkg-field:: type: interface (required)++ The interface type and version of the test suite. Cabal supports two+ test suite interfaces, called ``exitcode-stdio-1.0`` and+ ``detailed-0.9``. Each of these types may require or disallow other+ fields as described below.++Test suites using the ``exitcode-stdio-1.0`` interface are executables+that indicate test failure with a non-zero exit code when run; they may+provide human-readable log information through the standard output and+error channels. The ``exitcode-stdio-1.0`` type requires the ``main-is``+field.++.. pkg-field:: main-is: filename+ :synopsis: Module containing tests main function.++ :required: ``exitcode-stdio-1.0``+ :disallowed: ``detailed-0.9``++ The name of the ``.hs`` or ``.lhs`` file containing the ``Main``+ module. Note that it is the ``.hs`` filename that must be listed,+ even if that file is generated using a preprocessor. The source file+ must be relative to one of the directories listed in+ :pkg-field:`hs-source-dirs`. This field is analogous to the ``main-is`` field+ of an executable section.++Test suites using the ``detailed-0.9`` interface are modules exporting+the symbol ``tests :: IO [Test]``. The ``Test`` type is exported by the+module ``Distribution.TestSuite`` provided by Cabal. For more details,+see the example below.++The ``detailed-0.9`` interface allows Cabal and other test agents to+inspect a test suite's results case by case, producing detailed human-+and machine-readable log files. The ``detailed-0.9`` interface requires+the :pkg-field:`test-module` field.++.. pkg-field:: test-module: identifier++ :required: ``detailed-0.9``+ :disallowed: ``exitcode-stdio-1.0``++ The module exporting the ``tests`` symbol.++Example: Package using ``exitcode-stdio-1.0`` interface+"""""""""""""""""""""""""""""""""""""""""""""""""""""""++The example package description and executable source file below+demonstrate the use of the ``exitcode-stdio-1.0`` interface.++.. code-block:: cabal+ :caption: foo.cabal++ Name: foo+ Version: 1.0+ License: BSD3+ Cabal-Version: >= 1.9.2+ Build-Type: Simple++ Test-Suite test-foo+ type: exitcode-stdio-1.0+ main-is: test-foo.hs+ build-depends: base >= 4 && < 5++.. code-block:: haskell+ :caption: test-foo.hs++ module Main where++ import System.Exit (exitFailure)++ main = do+ putStrLn "This test always fails!"+ exitFailure++Example: Package using ``detailed-0.9`` interface+"""""""""""""""""""""""""""""""""""""""""""""""""++The example package description and test module source file below+demonstrate the use of the ``detailed-0.9`` interface. The test module+also develops a simple implementation of the interface set by+``Distribution.TestSuite``, but in actual usage the implementation would+be provided by the library that provides the testing facility.++.. code-block:: cabal+ :caption: bar.cabal++ Name: bar+ Version: 1.0+ License: BSD3+ Cabal-Version: >= 1.9.2+ Build-Type: Simple++ Test-Suite test-bar+ type: detailed-0.9+ test-module: Bar+ build-depends: base >= 4 && < 5, Cabal >= 1.9.2 && < 2+++.. code-block:: haskell+ :caption: Bar.hs++ module Bar ( tests ) where++ import Distribution.TestSuite++ tests :: IO [Test]+ tests = return [ Test succeeds, Test fails ]+ where+ succeeds = TestInstance+ { run = return $ Finished Pass+ , name = "succeeds"+ , tags = []+ , options = []+ , setOption = \_ _ -> Right succeeds+ }+ fails = TestInstance+ { run = return $ Finished $ Fail "Always fails!"+ , name = "fails"+ , tags = []+ , options = []+ , setOption = \_ _ -> Right fails+ }++Running test suites+"""""""""""""""""""++You can have Cabal run your test suites using its built-in test runner:++::++ $ cabal configure --enable-tests+ $ cabal build+ $ cabal test++See the output of ``cabal help test`` for a list of options you can pass+to ``cabal test``.++Benchmarks+^^^^^^^^^^++.. pkg-section:: benchmark name+ :since: 1.9.2+ :synopsis: Benchmark build information.++ Benchmark sections (if present) describe benchmarks contained in the+ package and must have an argument after the section label, which defines+ the name of the benchmark. This is a freeform argument, but may not+ contain spaces. It should be unique among the names of the package's+ other benchmarks, the package's test suites, the package's executables,+ and the package itself. Using benchmark sections requires at least Cabal+ version 1.9.2.++The benchmark may be described using the following fields, as well as+build information fields (see the section on `build information`_).++.. pkg-field:: type: interface (required)++ The interface type and version of the benchmark. At the moment Cabal+ only support one benchmark interface, called ``exitcode-stdio-1.0``.++Benchmarks using the ``exitcode-stdio-1.0`` interface are executables+that indicate failure to run the benchmark with a non-zero exit code+when run; they may provide human-readable information through the+standard output and error channels.++.. pkg-field:: main-is: filename++ :required: ``exitcode-stdio-1.0``++ The name of the ``.hs`` or ``.lhs`` file containing the ``Main``+ module. Note that it is the ``.hs`` filename that must be listed,+ even if that file is generated using a preprocessor. The source file+ must be relative to one of the directories listed in+ :pkg-field:`hs-source-dirs`. This field is analogous to the ``main-is``+ field of an executable section. Further, while the name of the file may+ vary, the module itself must be named ``Main``.++Example: Package using ``exitcode-stdio-1.0`` interface+"""""""""""""""""""""""""""""""""""""""""""""""""""""""++The example package description and executable source file below+demonstrate the use of the ``exitcode-stdio-1.0`` interface.++.. code-block:: cabal+ :caption: foo.cabal+ :name: foo-bench.cabal++ Name: foo+ Version: 1.0+ License: BSD3+ Cabal-Version: >= 1.9.2+ Build-Type: Simple++ Benchmark bench-foo+ type: exitcode-stdio-1.0+ main-is: bench-foo.hs+ build-depends: base >= 4 && < 5, time >= 1.1 && < 1.7++.. code-block:: haskell+ :caption: bench-foo.hs++ {-# LANGUAGE BangPatterns #-}+ module Main where++ import Data.Time.Clock++ fib 0 = 1+ fib 1 = 1+ fib n = fib (n-1) + fib (n-2)++ main = do+ start <- getCurrentTime+ let !r = fib 20+ end <- getCurrentTime+ putStrLn $ "fib 20 took " ++ show (diffUTCTime end start)++Running benchmarks+""""""""""""""""""++You can have Cabal run your benchmark using its built-in benchmark+runner:++::++ $ cabal configure --enable-benchmarks+ $ cabal build+ $ cabal bench++See the output of ``cabal help bench`` for a list of options you can+pass to ``cabal bench``.++Foreign libraries+^^^^^^^^^^^^^^^^^++Foreign libraries are system libraries intended to be linked against+programs written in C or other "foreign" languages. They+come in two primary flavours: dynamic libraries (``.so`` files on Linux,+``.dylib`` files on OSX, ``.dll`` files on Windows, etc.) are linked against+executables when the executable is run (or even lazily during+execution), while static libraries (``.a`` files on Linux/OSX, ``.lib``+files on Windows) get linked against the executable at compile time.++Foreign libraries only work with GHC 7.8 and later.++A typical stanza for a foreign library looks like++::++ foreign-library myforeignlib+ type: native-shared+ lib-version-info: 6:3:2++ if os(Windows)+ options: standalone+ mod-def-file: MyForeignLib.def++ other-modules: MyForeignLib.SomeModule+ MyForeignLib.SomeOtherModule+ build-depends: base >=4.7 && <4.9+ hs-source-dirs: src+ c-sources: csrc/MyForeignLibWrapper.c+ default-language: Haskell2010+++.. pkg-section:: foreign-library name+ :since: 2.0+ :synopsis: Foreign library build information.++ Build information for `foreign libraries`_.++.. pkg-field:: type: foreign library type++ Cabal recognizes ``native-static`` and ``native-shared`` here, although+ we currently only support building `native-shared` libraries.++.. pkg-field:: options: foreign library option list++ Options for building the foreign library, typically specific to the+ specified type of foreign library. Currently we only support+ ``standalone`` here. A standalone dynamic library is one that does not+ have any dependencies on other (Haskell) shared libraries; without+ the ``standalone`` option the generated library would have dependencies+ on the Haskell runtime library (``libHSrts``), the base library+ (``libHSbase``), etc. Currently, ``standalone`` *must* be used on Windows+ and *must not* be used on any other platform.++.. pkg-field:: mod-def-file: filename++ This option can only be used when creating dynamic Windows libraries+ (that is, when using ``native-shared`` and the ``os`` is ``Windows``). If+ used, it must be a path to a *module definition file*. The details of+ module definition files are beyond the scope of this document; see the+ `GHC <https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/win32-dlls.html>`_+ manual for some details and some further pointers.++.. pkg-field:: lib-version-info: current:revision:age++ This field is currently only used on Linux.++ This field specifies a Libtool-style version-info field that sets+ an appropriate ABI version for the foreign library. Note that the+ three numbers specified in this field do not directly specify the+ actual ABI version: ``6:3:2`` results in library version ``4.2.3``.++ With this field set, the SONAME of the library is set, and symlinks+ are installed.++ How you should bump this field on an ABI change depends on the+ breakage you introduce:++ - Programs using the previous version may use the new version as+ drop-in replacement, and programs using the new version can also+ work with the previous one. In other words, no recompiling nor+ relinking is needed. In this case, bump ``revision`` only, don't+ touch current nor age.+ - Programs using the previous version may use the new version as+ drop-in replacement, but programs using the new version may use+ APIs not present in the previous one. In other words, a program+ linking against the new version may fail with "unresolved+ symbols" if linking against the old version at runtime: set+ revision to 0, bump current and age.+ - Programs may need to be changed, recompiled, and relinked in+ order to use the new version. Bump current, set revision and age+ to 0.++ Also refer to the Libtool documentation on the version-info field.++.. pkg-field:: lib-version-linux: version++ This field is only used on Linux.++ Specifies the library ABI version directly for foreign libraries+ built on Linux: so specifying ``4.2.3`` causes a library+ ``libfoo.so.4.2.3`` to be built with SONAME ``libfoo.so.4``, and+ appropriate symlinks ``libfoo.so.4`` and ``libfoo.so`` to be+ installed.++Note that typically foreign libraries should export a way to initialize+and shutdown the Haskell runtime. In the example above, this is done by+the ``csrc/MyForeignLibWrapper.c`` file, which might look something like++.. code-block:: c++ #include <stdlib.h>+ #include "HsFFI.h"++ HsBool myForeignLibInit(void){+ int argc = 2;+ char *argv[] = { "+RTS", "-A32m", NULL };+ char **pargv = argv;++ // Initialize Haskell runtime+ hs_init(&argc, &pargv);++ // do any other initialization here and+ // return false if there was a problem+ return HS_BOOL_TRUE;+ }++ void myForeignLibExit(void){+ hs_exit();+ }++With modern ghc regular libraries are installed in directories that contain+package keys. This isn't usually a problem because the package gets registered+in ghc's package DB and so we can figure out what the location of the library+is. Foreign libraries however don't get registered, which means that we'd have+to have a way of finding out where a platform library got installed (other than by+searching the ``lib/`` directory). Instead, we install foreign libraries in+``~/.cabal/lib``, much like we install executables in ``~/.cabal/bin``.++Build information+^^^^^^^^^^^^^^^^^+.. pkg-section:: None++The following fields may be optionally present in a library, executable,+test suite or benchmark section, and give information for the building+of the corresponding library or executable. See also the sections on+`system-dependent parameters`_ and `configurations`_ for a way to supply+system-dependent values for these fields.++.. pkg-field:: build-depends: library list++ Declares the *library* dependencies required to build the current+ package component; see :pkg-field:`build-tool-depends` for+ declaring build-time *tool* dependencies. External library+ dependencies should be annotated with a version constraint.++ **Library Names**++ External libraries are identified by the package's name they're+ provided by (currently a package can only publicly expose its+ main library component; in future, packages with multiple exposed+ public library components will be supported and a syntax for+ referring to public sub-libraries will be provided).++ In order to specify an intra-package dependency on an internal+ library component you can use the unqualified name of the+ library component. Note that locally defined sub-library+ names shadow external package names of the same name. See section on+ :ref:`Internal Libraries <sublibs>` for examples and more information.++ **Version Constraints**++ Version constraints use the operators ``==, >=, >, <, <=`` and a+ version number. Multiple constraints can be combined using ``&&`` or+ ``||``. If no version constraint is specified, any version is+ assumed to be acceptable. For example:++ ::++ library+ build-depends:+ base >= 2,+ foo >= 1.2.3 && < 1.3,+ bar++ Dependencies like ``foo >= 1.2.3 && < 1.3`` turn out to be very+ common because it is recommended practice for package versions to+ correspond to API versions (see PVP_).++ Since Cabal 1.6, there is a special wildcard syntax to help with+ such ranges++ ::++ build-depends: foo ==1.2.*++ It is only syntactic sugar. It is exactly equivalent to+ ``foo >= 1.2 && < 1.3``.++ .. Warning::++ A potential pitfall of the wildcard syntax is that the+ constraint ``nats == 1.0.*`` doesn't match the release+ ``nats-1`` because the version ``1`` is lexicographically less+ than ``1.0``. This is not an issue with the caret-operator+ ``^>=`` described below.++ Starting with Cabal 2.0, there's a new version operator to express+ PVP_-style major upper bounds conveniently, and is inspired by similar+ syntactic sugar found in other language ecosystems where it's often+ called the "Caret" operator:++ ::++ build-depends:+ foo ^>= 1.2.3.4,+ bar ^>= 1++ This allows to assert the positive knowledge that this package is+ *known* to be semantically compatible with the releases+ ``foo-1.2.3.4`` and ``bar-1`` respectively. The information+ encoded via such ``^>=``-assertions is used by the cabal solver to+ infer version constraints describing semantically compatible+ version ranges according to the PVP_ contract (see below).++ Another way to say this is that ``foo < 1.3`` expresses *negative*+ information, i.e. "``foo-1.3`` or ``foo-1.4.2`` will *not* be+ compatible"; whereas ``foo ^>= 1.2.3.4`` asserts the *positive*+ information that "``foo-1.2.3.4`` is *known* to be compatible" and (in+ the absence of additional information) according to the PVP_+ contract we can (positively) infer right away that all versions+ satisfying ``foo >= 1.2.3.4 && < 1.3`` will be compatible as well.++ .. Note::++ More generally, the PVP_ contract implies that we can safely+ relax the lower bound to ``>= 1.2``, because if we know that+ ``foo-1.2.3.4`` is semantically compatible, then so is+ ``foo-1.2`` (if it typechecks). But we'd need to perform+ additional static analysis (i.e. perform typechecking) in order+ to know if our package in the role of an API consumer will+ successfully typecheck against the dependency ``foo-1.2``. But+ since we cannot do this analysis during constraint solving and+ to keep things simple, we pragmatically use ``foo >= 1.2.3.4``+ as the initially inferred approximation for the lower bound+ resulting from the assertion ``foo ^>= 1.2.3.4``. If further+ evidence becomes available that e.g. ``foo-1.2`` typechecks,+ one can simply revise the dependency specification to include+ the assertion ``foo ^>= 1.2``.++ The subtle but important difference in signaling allows tooling to+ treat explicitly expressed ``<``-style constraints and inferred+ (``^>=``-style) upper bounds differently. For instance,+ :cfg-field:`allow-newer`'s ``^``-modifier allows to relax only+ ``^>=``-style bounds while leaving explicitly stated+ ``<``-constraints unaffected.++ Ignoring the signaling intent, the default syntactic desugaring rules are++ - ``^>= x`` == ``>= x && < x.1``+ - ``^>= x.y`` == ``>= x.y && < x.(y+1)``+ - ``^>= x.y.z`` == ``>= x.y.z && < x.(y+1)``+ - ``^>= x.y.z.u`` == ``>= x.y.z.u && < x.(y+1)``+ - etc.++ .. Note::++ One might expect the desugaring to truncate all version+ components below (and including) the patch-level, i.e.+ ``^>= x.y.z.u`` == ``>= x.y.z && < x.(y+1)``,+ as the major and minor version components alone are supposed to+ uniquely identify the API according to the PVP_. However, by+ designing ``^>=`` to be closer to the ``>=`` operator, we avoid+ the potentially confusing effect of ``^>=`` being more liberal+ than ``>=`` in the presence of patch-level versions.++ Consequently, the example declaration above is equivalent to++ ::++ build-depends:+ foo >= 1.2.3.4 && < 1.3,+ bar >= 1 && < 1.1++ .. Note::++ Prior to Cabal 1.8, ``build-depends`` specified in each+ section were global to all sections. This was unintentional, but+ some packages were written to depend on it, so if you need your+ :pkg-field:`build-depends` to be local to each section, you must specify+ at least ``Cabal-Version: >= 1.8`` in your ``.cabal`` file.++ .. Note::++ Cabal 1.20 experimentally supported module thinning and+ renaming in ``build-depends``; however, this support has since been+ removed and should not be used.++ Starting with Cabal 3.0, a set notation for the ``==`` and ``^>=`` operator+ is available. For instance,++ ::++ tested-with: GHC == 8.6.3, GHC == 8.4.4, GHC == 8.2.2, GHC == 8.0.2,+ GHC == 7.10.3, GHC == 7.8.4, GHC == 7.6.3, GHC == 7.4.2++ build-depends: network ^>= 2.6.3.6 || ^>= 2.7.0.2 || ^>= 2.8.0.0 || ^>= 3.0.1.0++ can be then written in a more convenient and concise form++ ::++ tested-with: GHC == { 8.6.3, 8.4.4, 8.2.2, 8.0.2, 7.10.3, 7.8.4, 7.6.3, 7.4.2 }++ build-depends: network ^>= { 2.6.3.6, 2.7.0.2, 2.8.0.0, 3.0.1.0 }+++.. pkg-field:: other-modules: identifier list++ A list of modules used by the component but not exposed to users.+ For a library component, these would be hidden modules of the+ library. For an executable, these would be auxiliary modules to be+ linked with the file named in the ``main-is`` field.++ .. Note::++ Every module in the package *must* be listed in one of+ :pkg-field:`other-modules`, :pkg-field:`library:exposed-modules` or+ :pkg-field:`executable:main-is` fields.++.. pkg-field:: hs-source-dir: directory list+ :deprecated: 2.0+ :removed: 3.0++ :default: ``.``++ Root directories for the module hierarchy.++ Deprecated in favor of :pkg-field:`hs-source-dirs`.++.. pkg-field:: hs-source-dirs: directory list++ :default: ``.``++ Root directories for the module hierarchy.++ .. note::++ Components can share source directories but modules found there will be+ recompiled even if other components already built them, i.e., if a+ library and an executable share a source directory and the executable+ depends on the library and imports its ``Foo`` module, ``Foo`` will be+ compiled twice, once as part of the library and again for the executable.++.. pkg-field:: default-extensions: identifier list+ :since: 1.12++ A list of Haskell extensions used by every module. These determine+ corresponding compiler options enabled for all files. Extension+ names are the constructors of the+ `Extension <../release/cabal-latest/doc/API/Cabal/Language-Haskell-Extension.html#t:Extension>`__+ type. For example, ``CPP`` specifies that Haskell source files are+ to be preprocessed with a C preprocessor.++.. pkg-field:: other-extensions: identifier list+ :since: 1.12++ A list of Haskell extensions used by some (but not necessarily all)+ modules. From GHC version 6.6 onward, these may be specified by+ placing a ``LANGUAGE`` pragma in the source files affected e.g.++ .. code-block:: haskell++ {-# LANGUAGE CPP, MultiParamTypeClasses #-}++ In Cabal-1.24 the dependency solver will use this and+ :pkg-field:`default-extensions` information. Cabal prior to 1.24 will abort+ compilation if the current compiler doesn't provide the extensions.++ If you use some extensions conditionally, using CPP or conditional+ module lists, it is good to replicate the condition in+ :pkg-field:`other-extensions` declarations:++ ::++ other-extensions: CPP+ if impl(ghc >= 7.5)+ other-extensions: PolyKinds++ You could also omit the conditionally used extensions, as they are+ for information only, but it is recommended to replicate them in+ :pkg-field:`other-extensions` declarations.++.. pkg-field:: default-language: identifier+ :since: 1.12++ TBW++.. pkg-field:: other-languages: identifier+ :since: 1.12++ TBW++.. pkg-field:: extensions: identifier list+ :deprecated: 1.12+ :removed: 3.0++ Deprecated in favor of :pkg-field:`default-extensions`.++.. pkg-field:: build-tool-depends: package:executable list+ :since: 2.0++ A list of Haskell executables needed to build this component. Executables are provided+ during the whole duration of the component, so this field can be used for executables+ needed during :pkg-section:`test-suite` as well.++ Each is specified by the package containing the executable and the name of the+ executable itself, separated by a colon, and optionally followed by a version bound.++ All executables defined in the given Cabal file are termed as *internal* dependencies+ as opposed to the rest which are *external* dependencies.++ Each of the two is handled differently:++ 1. External dependencies can (and should) contain a version bound like conventional+ :pkg-field:`build-depends` dependencies.+ 2. Internal dependencies should not contain a version bound, as they will be always+ resolved within the same configuration of the package in the build plan.+ Specifically, version bounds that include the package's version will be warned for+ being extraneous, and version bounds that exclude the package's version will raise+ an error for being impossible to follow.++ For example (1) using a test-suite to make sure README.md Haskell snippets are tested using+ `markdown-unlit <http://hackage.haskell.org/package/markdown-unlit>`__:++ ::++ build-tool-depends: markdown-unlit:markdown-unlit >= 0.5.0 && < 0.6++ For example (2) using a test-suite to test executable behaviour in the same package:++ ::++ build-tool-depends: mypackage:executable++ Cabal tries to make sure that all specified programs are atomically built and prepended+ on the ``$PATH`` shell variable before building the component in question, but can only do+ so for Nix-style builds. Specifically:++ a) For Nix-style local builds, both internal and external dependencies.+ b) For old-style builds, only for internal dependencies [#old-style-build-tool-depends]_.+ It's up to the user to provide needed executables in this case under `$PATH.`+++ .. note::++ :pkg-field:`build-tool-depends` was added in Cabal 2.0, and it will+ be ignored (with a warning) with old versions of Cabal. See+ :pkg-field:`build-tools` for more information about backwards+ compatibility.++.. pkg-field:: build-tools: program list+ :deprecated: 2.0+ :removed: 3.0++ Deprecated in favor of :pkg-field:`build-tool-depends`, but :ref:`see below for backwards compatibility information <buildtoolsbc>`.++ A list of Haskell programs needed to build this component.+ Each may be followed by an optional version bound.+ Confusingly, each program in the list either refer to one of three things:++ 1. Another executables in the same package (supported since Cabal 1.12)++ 2. Tool name contained in Cabal's :ref:`hard-coded set of common tools <buildtoolsmap>`++ 3. A pre-built executable that should already be on the ``PATH``+ (supported since Cabal 2.0)++ These cases are listed in order of priority:+ an executable in the package will override any of the hard-coded packages with the same name,+ and a hard-coded package will override any executable on the ``PATH``.++ In the first two cases, the list entry is desugared into a :pkg-field:`build-tool-depends` entry.+ In the first case, the entry is desugared into a :pkg-field:`build-tool-depends` entry by prefixing with ``$pkg:``.+ In the second case, it is desugared by looking up the package and executable name in a hard-coded table.+ In either case, the optional version bound is passed through unchanged.+ Refer to the documentation for :pkg-field:`build-tool-depends` to understand the desugared field's meaning, along with restrictions on version bounds.++ .. _buildtoolsbc:++ **Backward Compatibility**++ Although this field is deprecated in favor of :pkg-field:`build-tool-depends`, there are some situations where you may prefer to use :pkg-field:`build-tools` in cases (1) and (2), as it is supported by more versions of Cabal.+ In case (3), :pkg-field:`build-tool-depends` is better for backwards-compatibility, as it will be ignored by old versions of Cabal; if you add the executable to :pkg-field:`build-tools`, a setup script built against old Cabal will choke.+ If an old version of Cabal is used, an end-user will have to manually arrange for the requested executable to be in your ``PATH``.++ .. _buildtoolsmap:++ **Set of Known Tool Names**++ Identifiers specified in :pkg-field:`build-tools` are desugared into their respective equivalent :pkg-field:`build-tool-depends` form according to the table below. Consequently, a legacy specification such as::++ build-tools: alex >= 3.2.1 && < 3.3, happy >= 1.19.5 && < 1.20++ is simply desugared into the equivalent specification::++ build-tool-depends: alex:alex >= 3.2.1 && < 3.3, happy:happy >= 1.19.5 && < 1.20++ +--------------------------+-----------------------------------+-----------------++ | :pkg-field:`build-tools` | desugared | Note |+ | identifier | :pkg-field:`build-tool-depends` | |+ | | identifier | |+ +==========================+===================================+=================++ | ``alex`` | ``alex:alex`` | |+ +--------------------------+-----------------------------------+-----------------++ | ``c2hs`` | ``c2hs:c2hs`` | |+ +--------------------------+-----------------------------------+-----------------++ | ``cpphs`` | ``cpphs:cpphs`` | |+ +--------------------------+-----------------------------------+-----------------++ | ``greencard`` | ``greencard:greencard`` | |+ +--------------------------+-----------------------------------+-----------------++ | ``haddock`` | ``haddock:haddock`` | |+ +--------------------------+-----------------------------------+-----------------++ | ``happy`` | ``happy:happy`` | |+ +--------------------------+-----------------------------------+-----------------++ | ``hsc2hs`` | ``hsc2hs:hsc2hs`` | |+ +--------------------------+-----------------------------------+-----------------++ | ``hscolour`` | ``hscolour:hscolour`` | |+ +--------------------------+-----------------------------------+-----------------++ | ``hspec-discover`` | ``hspec-discover:hspec-discover`` | since Cabal 2.0 |+ +--------------------------+-----------------------------------+-----------------+++ This built-in set can be programmatically extended via ``Custom`` setup scripts; this, however, is of limited use since the Cabal solver cannot access information injected by ``Custom`` setup scripts.++.. pkg-field:: buildable: boolean++ :default: ``True``++ Is the component buildable? Like some of the other fields below,+ this field is more useful with the slightly more elaborate form of+ the simple build infrastructure described in the section on+ `system-dependent parameters`_.++.. pkg-field:: ghc-options: token list++ Additional options for GHC. You can often achieve the same effect+ using the :pkg-field:`default-extensions` field, which is preferred.++ Options required only by one module may be specified by placing an+ ``OPTIONS_GHC`` pragma in the source file affected.++ As with many other fields, whitespace can be escaped by using+ Haskell string syntax. Example:+ ``ghc-options: -Wcompat "-with-rtsopts=-T -I1" -Wall``.++.. pkg-field:: ghc-prof-options: token list++ Additional options for GHC when the package is built with profiling+ enabled.++ Note that as of Cabal-1.24, the default profiling detail level+ defaults to ``exported-functions`` for libraries and+ ``toplevel-functions`` for executables. For GHC these correspond to+ the flags ``-fprof-auto-exported`` and ``-fprof-auto-top``. Prior to+ Cabal-1.24 the level defaulted to ``none``. These levels can be+ adjusted by the person building the package with the+ ``--profiling-detail`` and ``--library-profiling-detail`` flags.++ It is typically better for the person building the package to pick+ the profiling detail level rather than for the package author. So+ unless you have special needs it is probably better not to specify+ any of the GHC ``-fprof-auto*`` flags here. However if you wish to+ override the profiling detail level, you can do so using the+ :pkg-field:`ghc-prof-options` field: use ``-fno-prof-auto`` or one of the+ other ``-fprof-auto*`` flags.++.. pkg-field:: ghc-shared-options: token list++ Additional options for GHC when the package is built as shared+ library. The options specified via this field are combined with the+ ones specified via :pkg-field:`ghc-options`, and are passed to GHC during+ both the compile and link phases.++.. pkg-field:: ghcjs-options: token list++ Like :pkg-field:`ghc-options` but applies to GHCJS++.. pkg-field:: ghcjs-prof-options: token list++ Like :pkg-field:`ghc-prof-options` but applies to GHCJS++.. pkg-field:: ghcjs-shared-options: token list++ Like :pkg-field:`ghc-shared-options` but applies to GHCJS++.. pkg-field:: includes: filename list++ A list of header files to be included in any compilations via C.+ This field applies to both header files that are already installed+ on the system and to those coming with the package to be installed.+ The former files should be found in absolute paths, while the latter+ files should be found in paths relative to the top of the source+ tree or relative to one of the directories listed in+ :pkg-field:`include-dirs`.++ These files typically contain function prototypes for foreign+ imports used by the package. This is in contrast to+ :pkg-field:`install-includes`, which lists header files that are intended+ to be exposed to other packages that transitively depend on this+ library.++.. pkg-field:: install-includes: filename list++ A list of header files from this package to be installed into+ ``$libdir/includes`` when the package is installed. Files listed in+ :pkg-field:`install-includes` should be found in relative to the top of the+ source tree or relative to one of the directories listed in+ :pkg-field:`include-dirs`.++ :pkg-field:`install-includes` is typically used to name header files that+ contain prototypes for foreign imports used in Haskell code in this+ package, for which the C implementations are also provided with the+ package. For example, here is a ``.cabal`` file for a hypothetical+ ``bindings-clib`` package that bundles the C source code for ``clib``::++ include-dirs: cbits+ c-sources: clib.c+ install-includes: clib.h++ Now any package that depends (directly or transitively) on the+ ``bindings-clib`` library can use ``clib.h``.++ Note that in order for files listed in :pkg-field:`install-includes` to be+ usable when compiling the package itself, they need to be listed in+ the :pkg-field:`includes` field as well.++.. pkg-field:: include-dirs: directory list++ A list of directories to search for header files, when preprocessing+ with ``c2hs``, ``hsc2hs``, ``cpphs`` or the C preprocessor, and also+ when compiling via C. Directories can be absolute paths (e.g., for+ system directories) or paths that are relative to the top of the+ source tree. Cabal looks in these directories when attempting to+ locate files listed in :pkg-field:`includes` and+ :pkg-field:`install-includes`.++.. pkg-field:: c-sources: filename list++ A list of C source files to be compiled and linked with the Haskell+ files.++.. pkg-field:: cxx-sources: filename list+ :since: 2.2++ A list of C++ source files to be compiled and linked with the Haskell+ files. Useful for segregating C and C++ sources when supplying different+ command-line arguments to the compiler via the :pkg-field:`cc-options`+ and the :pkg-field:`cxx-options` fields. The files listed in the+ :pkg-field:`cxx-sources` can reference files listed in the+ :pkg-field:`c-sources` field and vice-versa. The object files will be linked+ appropriately.++.. pkg-field:: asm-sources: filename list+ :since: 3.0++ A list of assembly source files to be compiled and linked with the+ Haskell files.++.. pkg-field:: cmm-sources: filename list+ :since: 3.0++ A list of C-- source files to be compiled and linked with the Haskell+ files.++.. pkg-field:: js-sources: filename list++ A list of JavaScript source files to be linked with the Haskell+ files (only for JavaScript targets).++.. pkg-field:: extra-libraries: token list++ A list of extra libraries to link with.++.. pkg-field:: extra-ghci-libraries: token list++ A list of extra libraries to be used instead of 'extra-libraries'+ when the package is loaded with GHCi.++.. pkg-field:: extra-bundled-libraries: token list+ :since: 2.2++ A list of libraries that are supposed to be copied from the build+ directory alongside the produced Haskell libraries. Note that you+ are under the obligation to produce those libraries in the build+ directory (e.g. via a custom setup). Libraries listed here will+ be included when ``copy``-ing packages and be listed in the+ ``hs-libraries`` of the package configuration in the package database.+ Library names must either be prefixed with "HS" or "C" and corresponding+ library file names must match:++ - Libraries with name "HS<library-name>":+ - `libHS<library-name>.a`+ - `libHS<library-name>-ghc<ghc-flavour><ghc-version>.<dyn-library-extension>*`+ - Libraries with name "C<library-name>":+ - `libC<library-name>.a`+ - `lib<library-name>.<dyn-library-extension>*`++.. pkg-field:: extra-lib-dirs: directory list++ A list of directories to search for libraries.++.. pkg-field:: extra-library-flavours: notsure++ TBW++.. pkg-field:: extra-dynamic-library-flavours: notsure++ TBW++.. pkg-field:: cc-options: token list++ Command-line arguments to be passed to the C compiler. Since the+ arguments are compiler-dependent, this field is more useful with the+ setup described in the section on `system-dependent parameters`_.++.. pkg-field:: cpp-options: token list++ Command-line arguments for pre-processing Haskell code. Applies to+ Haskell source and other pre-processed Haskell source like .hsc+ .chs. Does not apply to C code, that's what cc-options is for.++.. pkg-field:: cxx-options: token list+ :since: 2.2++ Command-line arguments to be passed to the compiler when compiling+ C++ code. The C++ sources to which these command-line arguments+ should be applied can be specified with the :pkg-field:`cxx-sources`+ field. Command-line options for C and C++ can be passed separately to+ the compiler when compiling both C and C++ sources by segregating the C+ and C++ sources with the :pkg-field:`c-sources` and+ :pkg-field:`cxx-sources` fields respectively, and providing different+ command-line arguments with the :pkg-field:`cc-options` and the+ :pkg-field:`cxx-options` fields.++.. pkg-field:: cmm-options: token list+ :since: 3.0++ Command-line arguments to be passed to the compiler when compiling+ C-- code. See also :pkg-field:`cmm-sources`.++.. pkg-field:: asm-options: token list+ :since: 3.0++ Command-line arguments to be passed to the assembler when compiling+ assembler code. See also :pkg-field:`asm-sources`.++.. pkg-field:: ld-options: token list++ Command-line arguments to be passed to the linker. Since the+ arguments are compiler-dependent, this field is more useful with the+ setup described in the section on `system-dependent parameters`_.++.. pkg-field:: pkgconfig-depends: package list++ A list of+ `pkg-config <http://www.freedesktop.org/wiki/Software/pkg-config/>`__+ packages, needed to build this package. They can be annotated with+ versions, e.g. ``gtk+-2.0 >= 2.10, cairo >= 1.0``. If no version+ constraint is specified, any version is assumed to be acceptable.+ Cabal uses ``pkg-config`` to find if the packages are available on+ the system and to find the extra compilation and linker options+ needed to use the packages.++ If you need to bind to a C library that supports ``pkg-config`` then+ it is much preferable to use this field rather than hard code options+ into the other fields. ``pkg-config --list-all`` will show you all+ supported libraries. Depending on your system you may need to adjust+ ``PKG_CONFIG_PATH``.++.. pkg-field:: frameworks: token list++ On Darwin/MacOS X, a list of frameworks to link to. See Apple's+ developer documentation for more details on frameworks. This entry+ is ignored on all other platforms.++.. pkg-field:: extra-framework-dirs: directory list+ :since: 1.24++ On Darwin/MacOS X, a list of directories to search for frameworks.+ This entry is ignored on all other platforms.++.. pkg-field:: mixins: mixin list+ :since: 2.0++ Supported only in GHC 8.2 and later. A list of packages mentioned in the+ :pkg-field:`build-depends` field, each optionally accompanied by a list of+ module and module signature renamings.++ The simplest mixin syntax is simply the name of a package mentioned in the+ :pkg-field:`build-depends` field. For example:++ ::++ library+ build-depends:+ foo ^>= 1.2.3+ mixins:+ foo++ But this doesn't have any effect. More interesting is to use the mixin+ entry to rename one or more modules from the package, like this:++ ::++ library+ mixins:+ foo (Foo.Bar as AnotherFoo.Bar, Foo.Baz as AnotherFoo.Baz)++ Note that renaming a module like this will hide all the modules+ that are not explicitly named.++ Modules can also be hidden:++ ::++ library:+ mixins:+ foo hiding (Foo.Bar)++ Hiding modules exposes everything that is not explicitly hidden.++ .. Note::++ The current version of Cabal suffers from an infelicity in how the+ entries of :pkg-field:`mixins` are parsed: an entry will fail to parse+ if the provided renaming clause has whitespace after the opening+ parenthesis. This will be fixed in future versions of Cabal.++ See issues :issue:`5150`, :issue:`4864`, and :issue:`5293`.++ There can be multiple mixin entries for a given package, in effect creating+ multiple copies of the dependency:++ ::++ library+ mixins:+ foo (Foo.Bar as AnotherFoo.Bar, Foo.Baz as AnotherFoo.Baz),+ foo (Foo.Bar as YetAnotherFoo.Bar)++ The ``requires`` clause is used to rename the module signatures required by+ a package:++ ::++ library+ mixins:+ foo (Foo.Bar as AnotherFoo.Bar) requires (Foo.SomeSig as AnotherFoo.SomeSig)++ Signature-only packages don't have any modules, so only the signatures can+ be renamed, with the following syntax:++ ::++ library+ mixins:+ sigonly requires (SigOnly.SomeSig as AnotherSigOnly.SomeSig)++ See the :pkg-field:`library:signatures` field for more details.++ Mixin packages are part of the Backpack_ extension to the+ Haskell module system.++ The matching of the module signatures required by a+ :pkg-field:`build-depends` dependency with the implementation modules+ present in another dependency is triggered by a coincidence of names. When+ the names of the signature and of the implementation are already the same,+ the matching is automatic. But when the names don't coincide, or we want to+ instantiate a signature in two different ways, adding mixin entries that+ perform renamings becomes necessary.++ .. Warning::++ Backpack_ has the limitation that implementation modules that instantiate+ signatures required by a :pkg-field:`build-depends` dependency can't+ reside in the same component that has the dependency. They must reside+ in a different package dependency, or at least in a separate internal+ library.++Configurations+^^^^^^^^^^^^^^++Library and executable sections may include conditional blocks, which+test for various system parameters and configuration flags. The flags+mechanism is rather generic, but most of the time a flag represents+certain feature, that can be switched on or off by the package user.+Here is an example package description file using configurations:++Example: A package containing a library and executable programs+"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""++::++ Name: Test1+ Version: 0.0.1+ Cabal-Version: >= 1.8+ License: BSD3+ Author: Jane Doe+ Synopsis: Test package to test configurations+ Category: Example+ Build-Type: Simple++ Flag Debug+ Description: Enable debug support+ Default: False+ Manual: True++ Flag WebFrontend+ Description: Include API for web frontend.+ Default: False+ Manual: True++ Flag NewDirectory+ description: Whether to build against @directory >= 1.2@+ -- This is an automatic flag which the solver will+ -- assign automatically while searching for a solution++ Library+ Build-Depends: base >= 4.2 && < 4.9+ Exposed-Modules: Testing.Test1+ Extensions: CPP++ GHC-Options: -Wall+ if flag(Debug)+ CPP-Options: -DDEBUG+ if !os(windows)+ CC-Options: "-DDEBUG"+ else+ CC-Options: "-DNDEBUG"++ if flag(WebFrontend)+ Build-Depends: cgi >= 0.42 && < 0.44+ Other-Modules: Testing.WebStuff+ CPP-Options: -DWEBFRONTEND++ if flag(NewDirectory)+ build-depends: directory >= 1.2 && < 1.4+ Build-Depends: time >= 1.0 && < 1.9+ else+ build-depends: directory == 1.1.*+ Build-Depends: old-time >= 1.0 && < 1.2++ Executable test1+ Main-is: T1.hs+ Other-Modules: Testing.Test1+ Build-Depends: base >= 4.2 && < 4.9++ if flag(debug)+ CC-Options: "-DDEBUG"+ CPP-Options: -DDEBUG++Layout+""""""++Flags, conditionals, library and executable sections use layout to+indicate structure. This is very similar to the Haskell layout rule.+Entries in a section have to all be indented to the same level which+must be more than the section header. Tabs are not allowed to be used+for indentation.++As an alternative to using layout you can also use explicit braces+``{}``. In this case the indentation of entries in a section does not+matter, though different fields within a block must be on different+lines. Here is a bit of the above example again, using braces:++Example: Using explicit braces rather than indentation for layout+"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""++::++ Name: Test1+ Version: 0.0.1+ Cabal-Version: >= 1.8+ License: BSD3+ Author: Jane Doe+ Synopsis: Test package to test configurations+ Category: Example+ Build-Type: Simple++ Flag Debug {+ Description: Enable debug support+ Default: False+ Manual: True+ }++ Library {+ Build-Depends: base >= 4.2 && < 4.9+ Exposed-Modules: Testing.Test1+ Extensions: CPP+ if flag(debug) {+ CPP-Options: -DDEBUG+ if !os(windows) {+ CC-Options: "-DDEBUG"+ } else {+ CC-Options: "-DNDEBUG"+ }+ }+ }++Configuration Flags+"""""""""""""""""""++.. pkg-section:: flag name+ :synopsis: Flag declaration.++ Flag section declares a flag which can be used in `conditional blocks`_.++ Flag names are case-insensitive and must match ``[[:alnum:]_][[:alnum:]_-]*``+ regular expression, or expressed as ABNF_:++ .. code-block:: abnf++ flag-name = (UALNUM / "_") *(UALNUM / "_" / "-")++ UALNUM = UALPHA / DIGIT+ UALPHA = ... ; set of alphabetic Unicode code-points++ .. note::++ Hackage accepts ASCII-only flags, ``[a-zA-Z0-9_][a-zA-Z0-9_-]*`` regexp.++.. pkg-field:: description: freeform++ The description of this flag.++.. pkg-field:: default: boolean++ :default: ``True``++ The default value of this flag.++ .. note::++ This value may be `overridden in several+ ways <installing-packages.html#controlling-flag-assignments>`__. The+ rationale for having flags default to True is that users usually+ want new features as soon as they are available. Flags representing+ features that are not (yet) recommended for most users (such as+ experimental features or debugging support) should therefore+ explicitly override the default to False.++.. pkg-field:: manual: boolean++ :default: ``False``+ :since: 1.6++ By default, Cabal will first try to satisfy dependencies with the+ default flag value and then, if that is not possible, with the+ negated value. However, if the flag is manual, then the default+ value (which can be overridden by commandline flags) will be used.++Conditional Blocks+^^^^^^^^^^^^^^^^^^++Conditional blocks may appear anywhere inside a library or executable+section. They have to follow rather strict formatting rules. Conditional+blocks must always be of the shape++::++ if condition+ property-descriptions-or-conditionals++or++::++ if condition+ property-descriptions-or-conditionals+ else+ property-descriptions-or-conditionals++Note that the ``if`` and the condition have to be all on the same line.++Since Cabal 2.2 conditional blocks support ``elif`` construct.++::++ if condition1+ property-descriptions-or-conditionals+ elif condition2+ property-descriptions-or-conditionals+ else+ property-descriptions-or-conditionals++Conditions+""""""""""++Conditions can be formed using boolean tests and the boolean operators+``||`` (disjunction / logical "or"), ``&&`` (conjunction / logical+"and"), or ``!`` (negation / logical "not"). The unary ``!`` takes+highest precedence, ``||`` takes lowest. Precedence levels may be+overridden through the use of parentheses. For example,+``os(darwin) && !arch(i386) || os(freebsd)`` is equivalent to+``(os(darwin) && !(arch(i386))) || os(freebsd)``.++The following tests are currently supported.++:samp:`os({name})`+ Tests if the current operating system is *name*. The argument is+ tested against ``System.Info.os`` on the target system. There is+ unfortunately some disagreement between Haskell implementations+ about the standard values of ``System.Info.os``. Cabal canonicalises+ it so that in particular ``os(windows)`` works on all+ implementations. If the canonicalised os names match, this test+ evaluates to true, otherwise false. The match is case-insensitive.+:samp:`arch({name})`+ Tests if the current architecture is *name*. The argument is matched+ against ``System.Info.arch`` on the target system. If the arch names+ match, this test evaluates to true, otherwise false. The match is+ case-insensitive.+:samp:`impl({compiler})`+ Tests for the configured Haskell implementation. An optional version+ constraint may be specified (for example ``impl(ghc >= 6.6.1)``). If+ the configured implementation is of the right type and matches the+ version constraint, then this evaluates to true, otherwise false.+ The match is case-insensitive.++ Note that including a version constraint in an ``impl`` test causes+ it to check for two properties:++ - The current compiler has the specified name, and++ - The compiler's version satisfied the specified version constraint++ As a result, ``!impl(ghc >= x.y.z)`` is not entirely equivalent to+ ``impl(ghc < x.y.z)``. The test ``!impl(ghc >= x.y.z)`` checks that:++ - The current compiler is not GHC, or++ - The version of GHC is earlier than version x.y.z.++:samp:`flag({name})`+ Evaluates to the current assignment of the flag of the given name.+ Flag names are case insensitive. Testing for flags that have not+ been introduced with a flag section is an error.+``true``+ Constant value true.+``false``+ Constant value false.++Resolution of Conditions and Flags+""""""""""""""""""""""""""""""""""++If a package descriptions specifies configuration flags the package user+can `control these in several+ways <installing-packages.html#controlling-flag-assignments>`__. If the+user does not fix the value of a flag, Cabal will try to find a flag+assignment in the following way.++- For each flag specified, it will assign its default value, evaluate+ all conditions with this flag assignment, and check if all+ dependencies can be satisfied. If this check succeeded, the package+ will be configured with those flag assignments.++- If dependencies were missing, the last flag (as by the order in which+ the flags were introduced in the package description) is tried with+ its alternative value and so on. This continues until either an+ assignment is found where all dependencies can be satisfied, or all+ possible flag assignments have been tried.++To put it another way, Cabal does a complete backtracking search to find+a satisfiable package configuration. It is only the dependencies+specified in the :pkg-field:`build-depends` field in conditional blocks that+determine if a particular flag assignment is satisfiable+(:pkg-field:`build-tools` are not considered). The order of the declaration and+the default value of the flags determines the search order. Flags+overridden on the command line fix the assignment of that flag, so no+backtracking will be tried for that flag.++If no suitable flag assignment could be found, the configuration phase+will fail and a list of missing dependencies will be printed. Note that+this resolution process is exponential in the worst case (i.e., in the+case where dependencies cannot be satisfied). There are some+optimizations applied internally, but the overall complexity remains+unchanged.++Meaning of field values when using conditionals+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^++During the configuration phase, a flag assignment is chosen, all+conditionals are evaluated, and the package description is combined into+a flat package descriptions. If the same field is declared both inside+a conditional and outside then they are combined using the following rules.++- Boolean fields are combined using conjunction (logical "and").++- List fields are combined by appending the inner items to the outer+ items, for example++ ::++ other-extensions: CPP+ if impl(ghc)+ other-extensions: MultiParamTypeClasses++ when compiled using GHC will be combined to++ ::++ other-extensions: CPP, MultiParamTypeClasses++ Similarly, if two conditional sections appear at the same nesting+ level, properties specified in the latter will come after properties+ specified in the former.++- All other fields must not be specified in ambiguous ways. For example++ ::++ Main-is: Main.hs+ if flag(useothermain)+ Main-is: OtherMain.hs++ will lead to an error. Instead use++ ::++ if flag(useothermain)+ Main-is: OtherMain.hs+ else+ Main-is: Main.hs++.. _common-stanzas:++Common stanzas+^^^^^^^^^^^^^^++.. pkg-section:: common name+ :since: 2.2+ :synopsis: Common build info section++Starting with Cabal-2.2 it's possible to use common build info stanzas.++::++ common deps+ build-depends: base ^>= 4.11+ ghc-options: -Wall++ common test-deps+ build-depends: tasty ^>= 0.12.0.1++ library+ import: deps+ exposed-modules: Foo++ test-suite tests+ import: deps, test-deps+ type: exitcode-stdio-1.0+ main-is: Tests.hs+ build-depends: foo++- You can use `build information`_ fields in common stanzas.++- Common stanzas must be defined before use.++- Common stanzas can import other common stanzas.++- You can import multiple stanzas at once. Stanza names must be separated by commas.++- ``import`` must be the first field in a section. Since Cabal 3.0 imports+ are also allowed inside conditionals.++.. Note::++ The name `import` was chosen, because there is ``includes`` field.++.. pkg-section:: None++.. pkg-field:: import: token-list++ TBW++Source Repositories+^^^^^^^^^^^^^^^^^^^++.. pkg-section:: source-repository+ :since: 1.6++It is often useful to be able to specify a source revision control+repository for a package. Cabal lets you specify this information in+a relatively structured form which enables other tools to interpret and+make effective use of the information. For example the information+should be sufficient for an automatic tool to checkout the sources.++Cabal supports specifying different information for various common+source control systems. Obviously not all automated tools will support+all source control systems.++Cabal supports specifying repositories for different use cases. By+declaring which case we mean automated tools can be more useful. There+are currently two kinds defined:++- The ``head`` kind refers to the latest development branch of the+ package. This may be used for example to track activity of a project+ or as an indication to outside developers what sources to get for+ making new contributions.++- The ``this`` kind refers to the branch and tag of a repository that+ contains the sources for this version or release of a package. For+ most source control systems this involves specifying a tag, id or+ hash of some form and perhaps a branch. The purpose is to be able to+ reconstruct the sources corresponding to a particular package+ version. This might be used to indicate what sources to get if+ someone needs to fix a bug in an older branch that is no longer an+ active head branch.++You can specify one kind or the other or both. As an example here are+the repositories for the Cabal library. Note that the ``this`` kind of+repository specifies a tag.++::++ source-repository head+ type: darcs+ location: http://darcs.haskell.org/cabal/++ source-repository this+ type: darcs+ location: http://darcs.haskell.org/cabal-branches/cabal-1.6/+ tag: 1.6.1++The exact fields are as follows:++.. pkg-field:: type: token++ The name of the source control system used for this repository. The+ currently recognised types are:++ - ``darcs``+ - ``git``+ - ``svn``+ - ``cvs``+ - ``mercurial`` (or alias ``hg``)+ - ``bazaar`` (or alias ``bzr``)+ - ``arch``+ - ``monotone``++ This field is required.++.. pkg-field:: location: URL++ The location of the repository. The exact form of this field depends+ on the repository type. For example:++ - for darcs: ``http://code.haskell.org/foo/``+ - for git: ``git://github.com/foo/bar.git``+ - for CVS: ``anoncvs@cvs.foo.org:/cvs``++ This field is required.++.. pkg-field:: module: token++ CVS requires a named module, as each CVS server can host multiple+ named repositories.++ This field is required for the CVS repository type and should not be+ used otherwise.++.. pkg-field:: branch: token++ Many source control systems support the notion of a branch, as a+ distinct concept from having repositories in separate locations. For+ example CVS, SVN and git use branches while darcs uses different+ locations for different branches. If you need to specify a branch to+ identify a your repository then specify it in this field.++ This field is optional.++.. pkg-field:: tag: token++ A tag identifies a particular state of a source repository. The tag+ can be used with a ``this`` repository kind to identify the state of+ a repository corresponding to a particular package version or+ release. The exact form of the tag depends on the repository type.++ This field is required for the ``this`` repository kind.++.. pkg-field:: subdir: directory++ Some projects put the sources for multiple packages under a single+ source repository. This field lets you specify the relative path+ from the root of the repository to the top directory for the+ package, i.e. the directory containing the package's ``.cabal``+ file.++ This field is optional. It defaults to empty which corresponds to the+ root directory of the repository.++Downloading a package's source+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^++The ``cabal get`` command allows to access a package's source code -+either by unpacking a tarball downloaded from Hackage (the default) or+by checking out a working copy from the package's source repository.++::++ $ cabal get [FLAGS] PACKAGES++The ``get`` command supports the following options:++``-d --destdir`` *PATH*+ Where to place the package source, defaults to (a subdirectory of)+ the current directory.+``-s --source-repository`` *[head\|this\|...]*+ Fork the package's source repository using the appropriate version+ control system. The optional argument allows to choose a specific+ repository kind.+``--index-state`` *[HEAD\|@<unix-timestamp>\|<iso8601-utc-timestamp>]*+ Use source package index state as it existed at a previous time. Accepts+ unix-timestamps (e.g. ``@1474732068``), ISO8601 UTC timestamps (e.g.+ ``2016-09-24T17:47:48Z``), or ``HEAD`` (default).+ This determines which package versions are available as well as which+ ``.cabal`` file revision is selected (unless ``--pristine`` is used).+``--pristine``+ Unpack the original pristine tarball, rather than updating the+ ``.cabal`` file with the latest revision from the package archive.++Custom setup scripts+--------------------++Since Cabal 1.24, custom ``Setup.hs`` are required to accurately track+their dependencies by declaring them in the ``.cabal`` file rather than+rely on dependencies being implicitly in scope. Please refer to+`this article <https://www.well-typed.com/blog/2015/07/cabal-setup-deps/>`__+for more details.++As of Cabal library version 3.0, ``defaultMain*`` variants implement support+for response files. Custom ``Setup.hs`` files that do not use one of these+main functions are required to implement their own support, such as by using+``GHC.ResponseFile.getArgsWithResponseFiles``.++Declaring a ``custom-setup`` stanza also enables the generation of+``MIN_VERSION_package_(A,B,C)`` CPP macros for the Setup component.++.. pkg-section:: custom-setup+ :synopsis: Custom Setup.hs build information.+ :since: 1.24++ The optional :pkg-section:`custom-setup` stanza contains information needed+ for the compilation of custom ``Setup.hs`` scripts,++::++ custom-setup+ setup-depends:+ base >= 4.5 && < 4.11,+ Cabal >= 1.14 && < 1.25++.. pkg-field:: setup-depends: package list+ :since: 1.24++ The dependencies needed to compile ``Setup.hs``. See the+ :pkg-field:`build-depends` field for a description of the syntax expected by+ this field.++ If the field is not specified the implicit package set will be used.+ The package set contains packages bundled with GHC (i.e. ``base``,+ ``bytestring``) and specifically ``Cabal``.+ The specific bounds are put on ``Cabal`` dependency:+ lower-bound is inferred from :pkg-field:`cabal-version`,+ and the upper-bound is ``< 1.25``.++ ``Cabal`` version is additionally restricted by GHC,+ with absolute minimum being ``1.20``, and for example ``Custom``+ builds with GHC-8.10 require at least ``Cabal-3.2``.+++Backward compatibility and ``custom-setup``+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^++Versions prior to Cabal 1.24 don't recognise ``custom-setup`` stanzas,+and will behave agnostic to them (except for warning about an unknown+section). Consequently, versions prior to Cabal 1.24 can't ensure the+declared dependencies ``setup-depends`` are in scope, and instead+whatever is registered in the current package database environment+will become eligible (and resolved by the compiler) for the+``Setup.hs`` module.++The availability of the+``MIN_VERSION_package_(A,B,C)`` CPP macros+inside ``Setup.hs`` scripts depends on the condition that either++- a ``custom-setup`` section has been declared (or ``cabal v2-build`` is being+ used which injects an implicit hard-coded ``custom-setup`` stanza if it's missing), or+- GHC 8.0 or later is used (which natively injects package version CPP macros)++Consequently, if you need to write backward compatible ``Setup.hs``+scripts using CPP, you should declare a ``custom-setup`` stanza and+use the pattern below:++.. code-block:: haskell++ {-# LANGUAGE CPP #-}+ import Distribution.Simple++ #if defined(MIN_VERSION_Cabal)+ -- version macros are available and can be used as usual+ # if MIN_VERSION_Cabal(a,b,c)+ -- code specific to lib:Cabal >= a.b.c+ # else+ -- code specific to lib:Cabal < a.b.c+ # endif+ #else+ # warning Enabling heuristic fall-back. Please upgrade cabal-install to 1.24 or later if Setup.hs fails to compile.++ -- package version macros not available; except for exotic environments,+ -- you can heuristically assume that lib:Cabal's version is correlated+ -- with __GLASGOW_HASKELL__, and specifically since we can assume that+ -- GHC < 8.0, we can assume that lib:Cabal is version 1.22 or older.+ #endif++ main = ...++The simplified (heuristic) CPP pattern shown below is useful if all you need+is to distinguish ``Cabal < 2.0`` from ``Cabal >= 2.0``.++.. code-block:: haskell++ {-# LANGUAGE CPP #-}+ import Distribution.Simple++ #if !defined(MIN_VERSION_Cabal)+ # define MIN_VERSION_Cabal(a,b,c) 0+ #endif++ #if MIN_VERSION_Cabal(2,0,0)+ -- code for lib:Cabal >= 2.0+ #else+ -- code for lib:Cabal < 2.0+ #endif++ main = ...++++Autogenerated modules and includes+----------------------------------++.. pkg-section:: None++Modules that are built automatically at setup, created with a custom+setup script, must appear on :pkg-field:`other-modules` for the library,+executable, test-suite or benchmark stanzas or also on+:pkg-field:`library:exposed-modules` for libraries to be used, but are not+really on the package when distributed. This makes commands like sdist fail+because the file is not found.++These special modules must appear again on the :pkg-field:`autogen-modules`+field of the stanza that is using them, besides :pkg-field:`other-modules` or+:pkg-field:`library:exposed-modules`. With this there is no need to create+complex build hooks for this poweruser case.++.. pkg-field:: autogen-modules: module list+ :since: 2.0++ .. todo:: document autogen-modules field++Right now :pkg-field:`executable:main-is` modules are not supported on+:pkg-field:`autogen-modules`.++::++ Library+ default-language: Haskell2010+ build-depends: base+ exposed-modules:+ MyLibrary+ MyLibHelperModule+ other-modules:+ MyLibModule+ autogen-modules:+ MyLibHelperModule++ Executable Exe+ default-language: Haskell2010+ main-is: Dummy.hs+ build-depends: base+ other-modules:+ MyExeModule+ MyExeHelperModule+ autogen-modules:+ MyExeHelperModule++.. pkg-field:: autogen-includes: filename list+ :since: 3.0++ A list of header files from this package which are autogenerated+ (e.g. by a ``configure`` script). Autogenerated header files are not+ packaged by ``sdist`` command.++Virtual modules+---------------++TBW++.. pkg-field:: virtual-modules: module list+ :since: 2.2++ TBW++++Accessing data files from package code+--------------------------------------++The placement on the target system of files listed in+the :pkg-field:`data-files` field varies between systems, and in some cases+one can even move packages around after installation (see `prefix+independence <installing-packages.html#prefix-independence>`__). To+enable packages to find these files in a portable way, Cabal generates a+module called :file:`Paths_{pkgname}` (with any hyphens in *pkgname*+replaced by underscores) during building, so that it may be imported by+modules of the package. This module defines a function++.. code-block:: haskell++ getDataFileName :: FilePath -> IO FilePath++If the argument is a filename listed in the :pkg-field:`data-files` field, the+result is the name of the corresponding file on the system on which the+program is running.++.. Note::++ If you decide to import the :file:`Paths_{pkgname}` module then it+ *must* be listed in the :pkg-field:`other-modules` field just like any other+ module in your package and on :pkg-field:`autogen-modules` as the file is+ autogenerated.++The :file:`Paths_{pkgname}` module is not platform independent, as any+other autogenerated module, so it does not get included in the source+tarballs generated by ``sdist``.++The :file:`Paths_{pkgname}` module also includes some other useful+functions and values, which record the version of the package and some+other directories which the package has been configured to be installed+into (e.g. data files live in ``getDataDir``):++.. code-block:: haskell++ version :: Version++ getBinDir :: IO FilePath+ getLibDir :: IO FilePath+ getDynLibDir :: IO FilePath+ getDataDir :: IO FilePath+ getLibexecDir :: IO FilePath+ getSysconfDir :: IO FilePath++The actual location of all these directories can be individually+overridden at runtime using environment variables of the form+``pkg_name_var``, where ``pkg_name`` is the name of the package with all+hyphens converted into underscores, and ``var`` is either ``bindir``,+``libdir``, ``dynlibdir``, ``datadir``, ``libexedir`` or ``sysconfdir``. For example,+the configured data directory for ``pretty-show`` is controlled with the+``pretty_show_datadir`` environment variable.++Accessing the package version+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^++The aforementioned auto generated :file:`Paths_{pkgname}` module also+exports the constant ``version ::``+`Version <http://hackage.haskell.org/package/base/docs/Data-Version.html>`__+which is defined as the version of your package as specified in the+``version`` field.++System-dependent parameters+---------------------------++For some packages, especially those interfacing with C libraries,+implementation details and the build procedure depend on the build+environment. The ``build-type`` ``Configure`` can be used to handle many+such situations. In this case, ``Setup.hs`` should be:++.. code-block:: haskell++ import Distribution.Simple+ main = defaultMainWithHooks autoconfUserHooks++Most packages, however, would probably do better using the ``Simple``+build type and `configurations`_.++The :pkg-field:`build-type` ``Configure`` differs from ``Simple`` in two ways:++- The package root directory must contain a shell script called+ ``configure``. The configure step will run the script. This+ ``configure`` script may be produced by+ `autoconf <http://www.gnu.org/software/autoconf/>`__ or may be+ hand-written. The ``configure`` script typically discovers+ information about the system and records it for later steps, e.g. by+ generating system-dependent header files for inclusion in C source+ files and preprocessed Haskell source files. (Clearly this won't work+ for Windows without MSYS or Cygwin: other ideas are needed.)++- If the package root directory contains a file called+ *package*\ ``.buildinfo`` after the configuration step, subsequent+ steps will read it to obtain additional settings for `build+ information`_ fields,to be merged with the ones+ given in the ``.cabal`` file. In particular, this file may be+ generated by the ``configure`` script mentioned above, allowing these+ settings to vary depending on the build environment.++The build information file should have the following structure:++ *buildinfo*++ ``executable:`` *name* *buildinfo*++ ``executable:`` *name* *buildinfo* ...++where each *buildinfo* consists of settings of fields listed in the+section on `build information`_. The first one (if+present) relates to the library, while each of the others relate to the+named executable. (The names must match the package description, but you+don't have to have entries for all of them.)++Neither of these files is required. If they are absent, this setup+script is equivalent to ``defaultMain``.++Example: Using autoconf+^^^^^^^^^^^^^^^^^^^^^^^++This example is for people familiar with the+`autoconf <http://www.gnu.org/software/autoconf/>`__ tools.++In the X11 package, the file ``configure.ac`` contains:++.. code-block:: shell++ AC_INIT([Haskell X11 package], [1.1], [libraries@haskell.org], [X11])++ # Safety check: Ensure that we are in the correct source directory.+ AC_CONFIG_SRCDIR([X11.cabal])++ # Header file to place defines in+ AC_CONFIG_HEADERS([include/HsX11Config.h])++ # Check for X11 include paths and libraries+ AC_PATH_XTRA+ AC_TRY_CPP([#include <X11/Xlib.h>],,[no_x=yes])++ # Build the package if we found X11 stuff+ if test "$no_x" = yes+ then BUILD_PACKAGE_BOOL=False+ else BUILD_PACKAGE_BOOL=True+ fi+ AC_SUBST([BUILD_PACKAGE_BOOL])++ AC_CONFIG_FILES([X11.buildinfo])+ AC_OUTPUT++Then the setup script will run the ``configure`` script, which checks+for the presence of the X11 libraries and substitutes for variables in+the file ``X11.buildinfo.in``:++::++ buildable: @BUILD_PACKAGE_BOOL@+ cc-options: @X_CFLAGS@+ ld-options: @X_LIBS@++This generates a file ``X11.buildinfo`` supplying the parameters needed+by later stages:++::++ buildable: True+ cc-options: -I/usr/X11R6/include+ ld-options: -L/usr/X11R6/lib++The ``configure`` script also generates a header file+``include/HsX11Config.h`` containing C preprocessor defines recording+the results of various tests. This file may be included by C source+files and preprocessed Haskell source files in the package.++.. Note::++ Packages using these features will also need to list additional+ files such as ``configure``, templates for ``.buildinfo`` files, files+ named only in ``.buildinfo`` files, header files and so on in the+ :pkg-field:`extra-source-files` field to ensure that they are included in+ source distributions. They should also list files and directories generated+ by ``configure`` in the :pkg-field:`extra-tmp-files` field to ensure that+ they are removed by ``setup clean``.++Quite often the files generated by ``configure`` need to be listed+somewhere in the package description (for example, in the+:pkg-field:`install-includes` field). However, we usually don't want generated+files to be included in the source tarball. The solution is again+provided by the ``.buildinfo`` file. In the above example, the following+line should be added to ``X11.buildinfo``:++::++ install-includes: HsX11Config.h++In this way, the generated ``HsX11Config.h`` file won't be included in+the source tarball in addition to ``HsX11Config.h.in``, but it will be+copied to the right location during the install process. Packages that+use custom ``Setup.hs`` scripts can update the necessary fields+programmatically instead of using the ``.buildinfo`` file.++Conditional compilation+-----------------------++Sometimes you want to write code that works with more than one version+of a dependency. You can specify a range of versions for the dependency+in the :pkg-field:`build-depends`, but how do you then write the code that can+use different versions of the API?++Haskell lets you preprocess your code using the C preprocessor (either+the real C preprocessor, or ``cpphs``). To enable this, add+``extensions: CPP`` to your package description. When using CPP, Cabal+provides some pre-defined macros to let you test the version of+dependent packages; for example, suppose your package works with either+version 3 or version 4 of the ``base`` package, you could select the+available version in your Haskell modules like this:++.. code-block:: cpp++ #if MIN_VERSION_base(4,0,0)+ ... code that works with base-4 ...+ #else+ ... code that works with base-3 ...+ #endif++In general, Cabal supplies a macro+``MIN_VERSION_``\ *``package``*\ ``_(A,B,C)`` for each package depended+on via :pkg-field:`build-depends`. This macro is true if the actual version of+the package in use is greater than or equal to ``A.B.C`` (using the+conventional ordering on version numbers, which is lexicographic on the+sequence, but numeric on each component, so for example 1.2.0 is greater+than 1.0.3).++Since version 1.20, the ``MIN_TOOL_VERSION_``\ *``tool``*+family of macros lets you condition on the version of build tools used to+build the program (e.g. ``hsc2hs``).++Since version 1.24, the macro ``CURRENT_COMPONENT_ID``, which+expands to the string of the component identifier that uniquely+identifies this component. Furthermore, if the package is a library,+the macro ``CURRENT_PACKAGE_KEY`` records the identifier that was passed+to GHC for use in symbols and for type equality.++Since version 2.0, the macro ``CURRENT_PACKAGE_VERSION`` expands+to the string version number of the current package.++Cabal places the definitions of these macros into an+automatically-generated header file, which is included when+preprocessing Haskell source code by passing options to the C+preprocessor.++Cabal also allows to detect when the source code is being used for+generating documentation. The ``__HADDOCK_VERSION__`` macro is defined+only when compiling via Haddock_+instead of a normal Haskell compiler. The value of the+``__HADDOCK_VERSION__`` macro is defined as ``A*1000 + B*10 + C``, where+``A.B.C`` is the Haddock version. This can be useful for working around+bugs in Haddock or generating prettier documentation in some special+cases.++More complex packages+---------------------++For packages that don't fit the simple schemes described above, you have+a few options:++- By using the :pkg-field:`build-type` ``Custom``, you can supply your own+ ``Setup.hs`` file, and customize the simple build infrastructure+ using *hooks*. These allow you to perform additional actions before+ and after each command is run, and also to specify additional+ preprocessors. A typical ``Setup.hs`` may look like this:++ .. code-block:: haskell++ import Distribution.Simple+ main = defaultMainWithHooks simpleUserHooks { postHaddock = posthaddock }++ posthaddock args flags desc info = ....++ See ``UserHooks`` in+ `Distribution.Simple <../release/cabal-latest/doc/API/Cabal/Distribution-Simple.html>`__+ for the details, but note that this interface is experimental, and+ likely to change in future releases.++ If you use a custom ``Setup.hs`` file you should strongly consider+ adding a :pkg-section:`custom-setup` stanza with a+ :pkg-field:`custom-setup:setup-depends` field to ensure that your setup+ script does not break with future dependency versions.++- You could delegate all the work to ``make``, though this is unlikely+ to be very portable. Cabal supports this with the :pkg-field:`build-type`+ ``Make`` and a trivial setup library+ `Distribution.Make <../release/cabal-latest/doc/API/Cabal/Distribution-Make.html>`__,+ which simply parses the command line arguments and invokes ``make``.+ Here ``Setup.hs`` should look like this:++ .. code-block:: haskell++ import Distribution.Make+ main = defaultMain++ The root directory of the package should contain a ``configure``+ script, and, after that has run, a ``Makefile`` with a default target+ that builds the package, plus targets ``install``, ``register``,+ ``unregister``, ``clean``, ``dist`` and ``docs``. Some options to+ commands are passed through as follows:++ - The ``--with-hc-pkg``, ``--prefix``, ``--bindir``, ``--libdir``,+ ``--dynlibdir``, ``--datadir``, ``--libexecdir`` and ``--sysconfdir`` options to+ the ``configure`` command are passed on to the ``configure``+ script. In addition the value of the ``--with-compiler`` option is+ passed in a ``--with-hc`` option and all options specified with+ ``--configure-option=`` are passed on.++ - The ``--destdir`` option to the ``copy`` command becomes a setting+ of a ``destdir`` variable on the invocation of ``make copy``. The+ supplied ``Makefile`` should provide a ``copy`` target, which will+ probably look like this:++ .. code-block:: make++ copy :+ $(MAKE) install prefix=$(destdir)/$(prefix) \+ bindir=$(destdir)/$(bindir) \+ libdir=$(destdir)/$(libdir) \+ dynlibdir=$(destdir)/$(dynlibdir) \+ datadir=$(destdir)/$(datadir) \+ libexecdir=$(destdir)/$(libexecdir) \+ sysconfdir=$(destdir)/$(sysconfdir) \++- Finally, with the :pkg-field:`build-type` ``Custom``, you can also write your+ own setup script from scratch. It must conform to the interface+ described in the section on `building and installing+ packages <installing-packages.html>`__, and you may use the Cabal+ library for all or part of the work. One option is to copy the source+ of ``Distribution.Simple``, and alter it for your needs. Good luck.+++.. include:: references.inc++.. rubric:: Footnotes++.. [#old-style-build-tool-depends]++ Some packages (ab)use :pkg-field:`build-depends` on old-style builds, but this has a few major drawbacks:++ - using Nix-style builds it's considered an error if you depend on a exe-only package via build-depends: the solver will refuse it.+ - it may or may not place the executable on ``$PATH``.+ - it does not ensure the correct version of the package is installed, so you might end up overwriting versions with each other.
+ cabal/Cabal/doc/cabal-project.rst view
@@ -0,0 +1,1549 @@+cabal.project Reference+=======================++``cabal.project`` files support a variety of options which configure the+details of your build. The general syntax of a ``cabal.project`` file is+similar to that of a Cabal file: there are a number of fields, some of+which live inside stanzas:++::++ packages: */*.cabal+ with-compiler: /opt/ghc/8.0.1/bin/ghc++ package cryptohash+ optimization: False++In general, the accepted field names coincide with the accepted command+line flags that ``cabal install`` and other commands take. For example,+``cabal v2-configure --enable-profiling`` will write out a project+file with ``profiling: True``.++The full configuration of a project is determined by combining the+following sources (later entries override earlier ones):++1. ``~/.cabal/config`` (the user-wide global configuration)++2. ``cabal.project`` (the project configuration)++3. ``cabal.project.freeze`` (the output of ``cabal v2-freeze``)++4. ``cabal.project.local`` (the output of ``cabal v2-configure``)+++Specifying the local packages+-----------------------------++The following top-level options specify what the local packages of a+project are:++.. cfg-field:: packages: package location list (space or comma separated)+ :synopsis: Project packages.++ :default: ``./*.cabal``++ Specifies the list of package locations which contain the local+ packages to be built by this project. Package locations can take the+ following forms:++ 1. They can specify a Cabal file, or a directory containing a Cabal+ file, e.g., ``packages: Cabal cabal-install/cabal-install.cabal``.++ 2. They can specify a glob-style wildcards, which must match one or+ more (a) directories containing a (single) Cabal file, (b) Cabal+ files (extension ``.cabal``), or (c) tarballs which contain Cabal+ packages (extension ``.tar.gz``).+ For example, to match all Cabal files in all+ subdirectories, as well as the Cabal projects in the parent+ directories ``foo`` and ``bar``, use+ ``packages: */*.cabal ../{foo,bar}/``++ 3. They can specify an ``http``, ``https`` or ``file``+ URL, representing the path to a remote tarball to be downloaded+ and built.++ There is no command line variant of this field; see :issue:`3585`.++.. cfg-field:: optional-packages: package location list (space or comma-separated)+ :synopsis: Optional project packages.++ :default: empty++ Like :cfg-field:`packages`, specifies a list of package locations+ containing local packages to be built. Unlike :cfg-field:`packages`,+ if we glob for a package, it is permissible for the glob to match against+ zero packages. The intended use-case for :cfg-field:`optional-packages`+ is to make it so that vendored packages can be automatically picked up if+ they are placed in a subdirectory, but not error if there aren't any.++ There is no command line variant of this field.++.. cfg-field:: extra-packages: package list with version bounds (comma separated)+ :synopsis: Adds external packages as local++ [STRIKEOUT:Specifies a list of external packages from Hackage which+ should be considered local packages.] (Not implemented)++ There is no command line variant of this field.++++All local packages are *vendored*, in the sense that if other packages+(including external ones from Hackage) depend on a package with the name+of a local package, the local package is preferentially used.+For subdirectories to be considered local packages, the following setting+can be used::++ packages: ./*.cabal+ optional-packages: ./*/*.cabal++...then any package can be vendored simply by making a checkout in the+top-level project directory, as might be seen in this hypothetical+directory layout::++ foo.cabal+ foo-helper/ # local package+ unix/ # vendored external package++All of these options support globs. ``cabal v2-build`` has its own glob+format:++- Anywhere in a path, as many times as you like, you can specify an+ asterisk ``*`` wildcard. E.g., ``*/*.cabal`` matches all ``.cabal``+ files in all immediate subdirectories. Like in glob(7), asterisks do+ not match hidden files unless there is an explicit period, e.g.,+ ``.*/foo.cabal`` will match ``.private/foo.cabal`` (but+ ``*/foo.cabal`` will not).++- You can use braces to specify specific directories; e.g.,+ ``{vendor,pkgs}/*.cabal`` matches all Cabal files in the ``vendor``+ and ``pkgs`` subdirectories.++Formally, the format is described by the following BNF:++.. todo::+ convert globbing grammar to proper ABNF_ syntax++.. code-block:: abnf++ FilePathGlob ::= FilePathRoot FilePathGlobRel+ FilePathRoot ::= {- empty -} # relative to cabal.project+ | "/" # Unix root+ | [a-zA-Z] ":" [/\\] # Windows root+ | "~" # home directory+ FilePathGlobRel ::= Glob "/" FilePathGlobRel # Unix directory+ | Glob "\\" FilePathGlobRel # Windows directory+ | Glob # file+ | {- empty -} # trailing slash+ Glob ::= GlobPiece *+ GlobPiece ::= "*" # wildcard+ | [^*{},/\\] * # literal string+ | "\\" [*{},] # escaped reserved character+ | "{" Glob "," ... "," Glob "}" # union (match any of these)+++Specifying Packages from Remote Version Control Locations+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^++Starting with Cabal 2.4, there is now a stanza+``source-repository-package`` for specifying packages from an external+version control which supports the following fields:++- :pkg-field:`source-repository:type`+- :pkg-field:`source-repository:location`+- :pkg-field:`source-repository:tag`+- :pkg-field:`source-repository:subdir`++A simple example is shown below:++.. code-block:: cabal++ packages: .++ source-repository-package+ type: git+ location: https://github.com/hvr/HsYAML.git+ tag: e70cf0c171c9a586b62b3f75d72f1591e4e6aaa1++ source-repository-package+ type: git+ location: https://github.com/well-typed/cborg+ tag: 3d274c14ca3077c3a081ba7ad57c5182da65c8c1+ subdir: cborg++Global configuration options+----------------------------++The following top-level configuration options are not specific to any+package, and thus apply globally:+++.. cfg-field:: verbose: nat+ --verbose=n, -vn+ :synopsis: Build verbosity level.++ :default: 1++ Control the verbosity of ``cabal`` commands, valid values are from 0+ to 3.++ The command line variant of this field is ``--verbose=2``; a short+ form ``-v2`` is also supported.++.. cfg-field:: jobs: nat or $ncpus+ --jobs=n, -jn, --jobs=$ncpus+ :synopsis: Number of builds running in parallel.++ :default: 1++ Run *nat* jobs simultaneously when building. If ``$ncpus`` is+ specified, run the number of jobs equal to the number of CPUs.+ Package building is often quite parallel, so turning on parallelism+ can speed up build times quite a bit!++ The command line variant of this field is ``--jobs=2``; a short form+ ``-j2`` is also supported; a bare ``--jobs`` or ``-j`` is equivalent+ to ``--jobs=$ncpus``.++.. cfg-field:: keep-going: boolean+ --keep-going+ :synopsis: Try to continue building on failure.++ :default: False++ If true, after a build failure, continue to build other unaffected+ packages.++ The command line variant of this field is ``--keep-going``.++.. option:: --builddir=DIR++ Specifies the name of the directory where build products for+ build will be stored; defaults to ``dist-newstyle``. If a+ relative name is specified, this directory is resolved relative+ to the root of the project (i.e., where the ``cabal.project``+ file lives.)++ This option cannot be specified via a ``cabal.project`` file.++.. _cmdoption-project-file:+.. option:: --project-file=FILE++ Specifies the name of the project file used to specify the+ rest of the top-level configuration; defaults to ``cabal.project``.+ This name not only specifies the name of the main project file,+ but also the auxiliary project files ``cabal.project.freeze``+ and ``cabal.project.local``; for example, if you specify+ ``--project-file=my.project``, then the other files that will+ be probed are ``my.project.freeze`` and ``my.project.local``.++ If the specified project file is a relative path, we will+ look for the file relative to the current working directory,+ and then for the parent directory, until the project file is+ found or we have hit the top of the user's home directory.++ This option cannot be specified via a ``cabal.project`` file.++.. option:: --store-dir=DIR++ Specifies the name of the directory of the global package store.++Solver configuration options+----------------------------++The following settings control the behavior of the dependency solver:++.. cfg-field:: constraints: constraints list (comma separated)+ --constraint="pkg >= 2.0"+ :synopsis: Extra dependencies constraints.++ Add extra constraints to the version bounds, flag settings,+ and other properties a solver can pick for a+ package. For example:++ ::++ constraints: bar == 2.1++ A package can be specified multiple times in ``constraints``, in+ which case the specified constraints are intersected. This is+ useful, since the syntax does not allow you to specify multiple+ constraints at once. For example, to specify both version bounds and+ flag assignments, you would write:++ ::++ constraints: bar == 2.1,+ bar +foo -baz++ Valid constraints take the same form as for the `constraint+ command line option+ <installing-packages.html#cmdoption-setup-configure-constraint>`__.++.. cfg-field:: preferences: preference (comma separated)+ --preference="pkg >= 2.0"+ :synopsis: Preferred dependency versions.++ Like :cfg-field:`constraints`, but the solver will attempt to satisfy+ these preferences on a best-effort basis. The resulting install is locally+ optimal with respect to preferences; specifically, no single package+ could be replaced with a more preferred version that still satisfies+ the hard constraints.++ Operationally, preferences can cause the solver to attempt certain+ version choices of a package before others, which can improve+ dependency solver runtime.++ One way to use :cfg-field:`preferences` is to take a known working set of+ constraints (e.g., via ``cabal v2-freeze``) and record them as+ preferences. In this case, the solver will first attempt to use this+ configuration, and if this violates hard constraints, it will try to+ find the minimal number of upgrades to satisfy the hard constraints+ again.++ The command line variant of this field is+ ``--preference="pkg >= 2.0"``; to specify multiple preferences, pass+ the flag multiple times.++.. cfg-field:: allow-newer: none, all or list of scoped package names (space or comma separated)+ --allow-newer, --allow-newer=[none,all,[scope:][^]pkg]+ :synopsis: Lift dependencies upper bound constraints.++ :default: ``none``++ Allow the solver to pick an newer version of some packages than+ would normally be permitted by than the :pkg-field:`build-depends` bounds+ of packages in the install plan. This option may be useful if the+ dependency solver cannot otherwise find a valid install plan.++ For example, to relax ``pkg``\ s :pkg-field:`build-depends` upper bound on+ ``dep-pkg``, write a scoped package name of the form:++ ::++ allow-newer: pkg:dep-pkg++ If the scope shall be limited to specific releases of ``pkg``, the+ extended form as in++ ::++ allow-newer: pkg-1.2.3:dep-pkg, pkg-1.1.2:dep-pkg++ can be used to limit the relaxation of dependencies on+ ``dep-pkg`` by the ``pkg-1.2.3`` and ``pkg-1.1.2`` releases only.++ The scoped syntax is recommended, as it is often only a single package+ whose upper bound is misbehaving. In this case, the upper bounds of+ other packages should still be respected; indeed, relaxing the bound+ can break some packages which test the selected version of packages.++ The syntax also allows to prefix the dependee package with a+ modifier symbol to modify the scope/semantic of the relaxation+ transformation in a additional ways. Currently only one modifier+ symbol is defined, i.e. ``^`` (i.e. caret) which causes the+ relaxation to be applied only to ``^>=`` operators and leave all other+ version operators untouched.++ However, in some situations (e.g., when attempting to build packages+ on a new version of GHC), it is useful to disregard *all*+ upper-bounds, with respect to a package or all packages. This can be+ done by specifying just a package name, or using the keyword ``all``+ to specify all packages:++ ::++ -- Disregard upper bounds involving the dependencies on+ -- packages bar, baz. For quux only, relax+ -- 'quux ^>= ...'-style constraints only.+ allow-newer: bar, baz, ^quux++ -- Disregard all upper bounds when dependency solving+ allow-newer: all++ -- Disregard all `^>=`-style upper bounds when dependency solving+ allow-newer: ^all+++ For consistency, there is also the explicit wildcard scope syntax+ ``*`` (or its alphabetic synonym ``all``). Consequently, the+ examples above are equivalent to the explicitly scoped variants:++ ::++ allow-newer: all:bar, *:baz, *:^quux++ allow-newer: *:*+ allow-newer: all:all++ allow-newer: *:^*+ allow-newer: all:^all++ In order to ignore all bounds specified by a package ``pkg-1.2.3``+ you can combine scoping with a right-hand-side wildcard like so++ ::++ -- Disregard any upper bounds specified by pkg-1.2.3+ allow-newer: pkg-1.2.3:*++ -- Disregard only `^>=`-style upper bounds in pkg-1.2.3+ allow-newer: pkg-1.2.3:^*+++ :cfg-field:`allow-newer` is often used in conjunction with a constraint+ (in the cfg-field:`constraints` field) forcing the usage of a specific,+ newer version of a package.++ The command line variant of this field is e.g. ``--allow-newer=bar``. A+ bare ``--allow-newer`` is equivalent to ``--allow-newer=all``.++.. cfg-field:: allow-older: none, all, list of scoped package names (space or comma separated)+ --allow-older, --allow-older=[none,all,[scope:][^]pkg]+ :synopsis: Lift dependency lower bound constraints.+ :since: 2.0++ :default: ``none``++ Like :cfg-field:`allow-newer`, but applied to lower bounds rather than+ upper bounds.++ The command line variant of this field is ``--allow-older=all``. A+ bare ``--allow-older`` is equivalent to ``--allow-older=all``.+++.. cfg-field:: index-state: HEAD, unix-timestamp, ISO8601 UTC timestamp.+ :synopsis: Use source package index state as it existed at a previous time.+ :since: 2.0++ :default: ``HEAD``++ This allows to change the source package index state the solver uses+ to compute install-plans. This is particularly useful in+ combination with freeze-files in order to also freeze the state the+ package index was in at the time the install-plan was frozen.++ ::++ -- UNIX timestamp format example+ index-state: @1474739268++ -- ISO8601 UTC timestamp format example+ -- This format is used by 'cabal v2-configure'+ -- for storing `--index-state` values.+ index-state: 2016-09-24T17:47:48Z++ -- Specify different index-states per package repository+ -- Supported since 3.4+ index-state:+ , hackage.haskell.org 2020-05-06T22:33:27Z+ , head.hackage 2020-04-29T04:11:05Z++.. cfg-field:: active-repositories: reponame1, reponame2++ :synopsis: Specify active package repositories+ :since: 3.4++ :default: ``:rest``++ This allows to specify the active package repositories,+ when multiple are specified. This is useful as you+ can specify the order and the way active repositories are merged.++ ::++ -- for packages in head.hackage+ -- only versions in head.hackage are considered+ active-repositories:+ , hackage.haskell.org+ , head.hackage:override++ -- Force head.hackage to be the primary repository considered+ active-repositories: :rest, head.hackage++ -- "Offline" mode+ active-repositories: none+++.. cfg-field:: reject-unconstrained-dependencies: all, none+ --reject-unconstrained-dependencies=[all|none]+ :synopsis: Restrict the solver to packages that have constraints on them.++ :default: none+ :since: 2.6++ By default, the dependency solver can include any package that it's+ aware of in a build plan. If you wish to restrict the build plan to+ a closed set of packages (e.g., from a freeze file), use this flag.++ When set to `all`, all non-local packages that aren't goals must be+ explicitly constrained. When set to `none`, the solver will+ consider all packages.+++Package configuration options+-----------------------------++Package options affect the building of specific packages. There are three+ways a package option can be specified:++- They can be specified at the top-level, in which case they apply only+ to **local package**, or++- They can be specified inside a ``package`` stanza, in which case they+ apply to the build of the package, whether or not it is local or+ external.++- They can be specified inside an ``package *`` stanza, in which case they+ apply to all packages, local ones from the project and also external+ dependencies.+++For example, the following options specify that :cfg-field:`optimization`+should be turned off for all local packages, and that ``bytestring`` (possibly+an external dependency) should be built with ``-fno-state-hack``::++ optimization: False++ package bytestring+ ghc-options: -fno-state-hack++``ghc-options`` is not specifically described in this documentation,+but is one of many fields for configuring programs. They take the form+``progname-options`` and ``progname-location``, and+can only be set inside package stanzas. (TODO: They are not supported+at top-level, see :issue:`3579`.)++At the moment, there is no way to specify an option to apply to all+external packages or all inplace packages. Additionally, it is only+possible to specify these options on the command line for all local+packages (there is no per-package command line interface.)++Some flags were added by more recent versions of the Cabal library. This+means that they are NOT supported by packages which use Custom setup+scripts that require a version of the Cabal library older than when the+feature was added.++.. cfg-field:: flags: list of +flagname or -flagname (space separated)+ --flags="+foo -bar", -ffoo, -f-bar+ :synopsis: Enable or disable package flags.++ Force all flags specified as ``+flagname`` to be true, and all flags+ specified as ``-flagname`` to be false. For example, to enable the+ flag ``foo`` and disable ``bar``, set:++ ::++ flags: +foo -bar++ If there is no leading punctuation, it is assumed that the flag+ should be enabled; e.g., this is equivalent:++ ::++ flags: foo -bar++ Flags are *per-package*, so it doesn't make much sense to specify+ flags at the top-level, unless you happen to know that *all* of your+ local packages support the same named flags. If a flag is not+ supported by a package, it is ignored.++ See also the solver configuration field :cfg-field:`constraints`.++ The command line variant of this flag is ``--flags``. There is also+ a shortened form ``-ffoo -f-bar``.++ A common mistake is to say ``cabal v2-build -fhans``, where+ ``hans`` is a flag for a transitive dependency that is not in the+ local package; in this case, the flag will be silently ignored. If+ ``haskell-tor`` is the package you want this flag to apply to, try+ ``--constraint="haskell-tor +hans"`` instead.++.. cfg-field:: with-compiler: executable+ --with-compiler=executable+ :synopsis: Path to compiler executable.++ Specify the path to a particular compiler to be used. If not an+ absolute path, it will be resolved according to the :envvar:`PATH`+ environment. The type of the compiler (GHC, GHCJS, etc) must be+ consistent with the setting of the :cfg-field:`compiler` field.++ The most common use of this option is to specify a different version+ of your compiler to be used; e.g., if you have ``ghc-7.8`` in your+ path, you can specify ``with-compiler: ghc-7.8`` to use it.++ This flag also sets the default value of :cfg-field:`with-hc-pkg`, using+ the heuristic that it is named ``ghc-pkg-7.8`` (if your executable name+ is suffixed with a version number), or is the executable named+ ``ghc-pkg`` in the same directory as the ``ghc`` directory. If this+ heuristic does not work, set :cfg-field:`with-hc-pkg` explicitly.++ For inplace packages, ``cabal v2-build`` maintains a separate build+ directory for each version of GHC, so you can maintain multiple+ build trees for different versions of GHC without clobbering each+ other.++ At the moment, it's not possible to set :cfg-field:`with-compiler` on a+ per-package basis, but eventually we plan on relaxing this+ restriction. If this is something you need, give us a shout.++ The command line variant of this flag is+ ``--with-compiler=ghc-7.8``; there is also a short version+ ``-w ghc-7.8``.++.. cfg-field:: with-hc-pkg: executable+ --with-hc-pkg=executable+ :synopsis: Specifies package tool.++ Specify the path to the package tool, e.g., ``ghc-pkg``. This+ package tool must be compatible with the compiler specified by+ :cfg-field:`with-compiler` (generally speaking, it should be precisely+ the tool that was distributed with the compiler). If this option is+ omitted, the default value is determined from :cfg-field:`with-compiler`.++ The command line variant of this flag is+ ``--with-hc-pkg=ghc-pkg-7.8``.++.. cfg-field:: optimization: nat+ --enable-optimization+ --disable-optimization+ :synopsis: Build with optimization.++ :default: ``1``++ Build with optimization. This is appropriate for production use,+ taking more time to build faster libraries and programs.++ The optional *nat* value is the optimisation level. Some compilers+ support multiple optimisation levels. The range is 0 to 2. Level 0+ disables optimization, level 1 is the default. Level 2 is higher+ optimisation if the compiler supports it. Level 2 is likely to lead+ to longer compile times and bigger generated code. If you are not+ planning to run code, turning off optimization will lead to better+ build times and less code to be rebuilt when a module changes.++ When optimizations are enabled, Cabal passes ``-O2`` to the C compiler.++ We also accept ``True`` (equivalent to 1) and ``False`` (equivalent+ to 0).++ Note that as of GHC 8.0, GHC does not recompile when optimization+ levels change (see :ghc-ticket:`10923`), so if+ you change the optimization level for a local package you may need+ to blow away your old build products in order to rebuild with the+ new optimization level.++ The command line variant of this flag is ``-O2`` (with ``-O1``+ equivalent to ``-O``). There are also long-form variants+ ``--enable-optimization`` and ``--disable-optimization``.++.. cfg-field:: configure-options: args (space separated)+ --configure-option=arg+ :synopsis: Options to pass to configure script.++ A list of extra arguments to pass to the external ``./configure``+ script, if one is used. This is only useful for packages which have+ the ``Configure`` build type. See also the section on+ `system-dependent+ parameters <developing-packages.html#system-dependent-parameters>`__.++ The command line variant of this flag is ``--configure-option=arg``,+ which can be specified multiple times to pass multiple options.++.. cfg-field:: compiler: ghc, ghcjs, jhc, lhc, uhc or haskell-suite+ --compiler=compiler+ :synopsis: Compiler to build with.++ :default: ``ghc``++ Specify which compiler toolchain to be used. This is independent of+ ``with-compiler``, because the choice of toolchain affects Cabal's+ build logic.++ The command line variant of this flag is ``--compiler=ghc``.++.. cfg-field:: tests: boolean+ --enable-tests+ --disable-tests+ :synopsis: Build tests.++ :default: ``False``++ Force test suites to be enabled. For most users this should not be+ needed, as we always attempt to solve for test suite dependencies,+ even when this value is ``False``; furthermore, test suites are+ automatically enabled if they are requested as a built target.++ The command line variant of this flag is ``--enable-tests`` and+ ``--disable-tests``.++.. cfg-field:: benchmarks: boolean+ --enable-benchmarks+ --disable-benchmarks+ :synopsis: Build benchmarks.++ :default: ``False``++ Force benchmarks to be enabled. For most users this should not be+ needed, as we always attempt to solve for benchmark dependencies,+ even when this value is ``False``; furthermore, benchmarks are+ automatically enabled if they are requested as a built target.++ The command line variant of this flag is ``--enable-benchmarks`` and+ ``--disable-benchmarks``.++.. cfg-field:: extra-prog-path: paths (newline or comma separated)+ --extra-prog-path=PATH+ :synopsis: Add directories to program search path.+ :since: 1.18++ A list of directories to search for extra required programs. Most+ users should not need this, as programs like ``happy`` and ``alex``+ will automatically be installed and added to the path. This can be+ useful if a ``Custom`` setup script relies on an exotic extra+ program.++ The command line variant of this flag is ``--extra-prog-path=PATH``,+ which can be specified multiple times.++.. cfg-field:: run-tests: boolean+ --run-tests+ :synopsis: Run package test suite upon installation.++ :default: ``False``++ Run the package test suite upon installation. This is useful for+ saying "When this package is installed, check that the test suite+ passes, terminating the rest of the build if it is broken."++ .. warning::++ One deficiency: the :cfg-field:`run-tests` setting of a package is NOT+ recorded as part of the hash, so if you install something without+ :cfg-field:`run-tests` and then turn on ``run-tests``, we won't+ subsequently test the package. If this is causing you problems, give+ us a shout.++ The command line variant of this flag is ``--run-tests``.++Object code options+^^^^^^^^^^^^^^^^^^^++.. cfg-field:: debug-info: integer+ --enable-debug-info=<n>+ --disable-debug-info+ :synopsis: Build with debug info enabled.+ :since: 1.22++ :default: False++ If the compiler (e.g., GHC 7.10 and later) supports outputing OS+ native debug info (e.g., DWARF), setting ``debug-info: True`` will+ instruct it to do so. See the GHC wiki page on :ghc-wiki:`DWARF`+ for more information about this feature.++ (This field also accepts numeric syntax, but until GHC 8.2 this didn't+ do anything.)++ The command line variant of this flag is ``--enable-debug-info`` and+ ``--disable-debug-info``.++.. cfg-field:: split-sections: boolean+ --enable-split-sections+ --disable-split-sections+ :synopsis: Use GHC's split sections feature.+ :since: 2.2++ :default: False++ Use the GHC ``-split-sections`` feature when building the library. This+ reduces the final size of the executables that use the library by+ allowing them to link with only the bits that they use rather than+ the entire library. The downside is that building the library takes+ longer and uses a bit more memory.++ This feature is supported by GHC 8.0 and later.++ The command line variant of this flag is ``--enable-split-sections`` and+ ``--disable-split-sections``.++.. cfg-field:: split-objs: boolean+ --enable-split-objs+ --disable-split-objs+ :synopsis: Use GHC's split objects feature.++ :default: False++ Use the GHC ``-split-objs`` feature when building the library. This+ reduces the final size of the executables that use the library by+ allowing them to link with only the bits that they use rather than+ the entire library. The downside is that building the library takes+ longer and uses considerably more memory.++ It is generally recommend that you use ``split-sections`` instead+ of ``split-objs`` where possible.++ The command line variant of this flag is ``--enable-split-objs`` and+ ``--disable-split-objs``.++.. cfg-field:: executable-stripping: boolean+ --enable-executable-stripping+ --disable-executable-stripping+ :synopsis: Strip installed programs.++ :default: True++ When installing binary executable programs, run the ``strip``+ program on the binary. This can considerably reduce the size of the+ executable binary file. It does this by removing debugging+ information and symbols.++ Not all Haskell implementations generate native binaries. For such+ implementations this option has no effect.++ If ``debug-info`` is set explicitly then ``executable-stripping`` is set+ to ``False`` as otherwise all the debug symbols will be stripped.++ The command line variant of this flag is+ ``--enable-executable-stripping`` and+ ``--disable-executable-stripping``.++.. cfg-field:: library-stripping: boolean+ --enable-library-stripping+ --disable-library-stripping+ :synopsis: Strip installed libraries.+ :since: 1.20++ When installing binary libraries, run the ``strip`` program on the+ binary, saving space on the file system. See also+ ``executable-stripping``.++ If ``debug-info`` is set explicitly then ``library-stripping`` is set+ to ``False`` as otherwise all the debug symbols will be stripped.++ The command line variant of this flag is+ ``--enable-library-stripping`` and ``--disable-library-stripping``.++Executable options+^^^^^^^^^^^^^^^^^^++.. cfg-field:: program-prefix: prefix+ --program-prefix=prefix+ :synopsis: Prepend prefix to program names.++ [STRIKEOUT:Prepend *prefix* to installed program names.] (Currently+ implemented in a silly and not useful way. If you need this to work+ give us a shout.)++ *prefix* may contain the following path variables: ``$pkgid``,+ ``$pkg``, ``$version``, ``$compiler``, ``$os``, ``$arch``, ``$abi``,+ ``$abitag``++ The command line variant of this flag is ``--program-prefix=foo-``.++.. cfg-field:: program-suffix: suffix+ --program-suffix=suffix+ :synopsis: Append refix to program names.++ [STRIKEOUT:Append *suffix* to installed program names.] (Currently+ implemented in a silly and not useful way. If you need this to work+ give us a shout.)++ The most obvious use for this is to append the program's version+ number to make it possible to install several versions of a program+ at once: ``program-suffix: $version``.++ *suffix* may contain the following path variables: ``$pkgid``,+ ``$pkg``, ``$version``, ``$compiler``, ``$os``, ``$arch``, ``$abi``,+ ``$abitag``++ The command line variant of this flag is+ ``--program-suffix='$version'``.++Dynamic linking options+^^^^^^^^^^^^^^^^^^^^^^^++.. cfg-field:: shared: boolean+ --enable-shared+ --disable-shared+ :synopsis: Build shared library.++ :default: False++ Build shared library. This implies a separate compiler run to+ generate position independent code as required on most platforms.++ The command line variant of this flag is ``--enable-shared`` and+ ``--disable-shared``.++.. cfg-field:: executable-dynamic: boolean+ --enable-executable-dynamic+ --disable-executable-dynamic+ :synopsis: Link executables dynamically.++ :default: False++ Link executables dynamically. The executable's library dependencies+ should be built as shared objects. This implies ``shared: True``+ unless ``shared: False`` is explicitly specified.++ The command line variant of this flag is+ ``--enable-executable-dynamic`` and+ ``--disable-executable-dynamic``.++.. cfg-field:: library-for-ghci: boolean+ --enable-library-for-ghci+ --disable-library-for-ghci+ :synopsis: Build libraries suitable for use with GHCi.++ :default: True++ Build libraries suitable for use with GHCi. This involves an extra+ linking step after the build.++ Not all platforms support GHCi and indeed on some platforms, trying+ to build GHCi libs fails. In such cases, consider setting+ ``library-for-ghci: False``.++ The command line variant of this flag is+ ``--enable-library-for-ghci`` and ``--disable-library-for-ghci``.++.. cfg-field:: relocatable:+ --relocatable+ :synopsis: Build relocatable package.+ :since: 1.22++ :default: False++ [STRIKEOUT:Build a package which is relocatable.] (TODO: It is not+ clear what this actually does, or if it works at all.)++ The command line variant of this flag is ``--relocatable``.++Static linking options+^^^^^^^^^^^^^^^^^^^^^^++.. cfg-field:: static: boolean+ --enable-static+ --disable-static+ :synopsis: Build static library.+++ :default: False++ Roll this and all dependent libraries into a combined ``.a`` archive.+ This uses GHCs ``-staticlib`` flag, which is available for iOS and with+ GHC 8.4 and later for other platforms as well.++.. cfg-field:: executable-static: boolean+ --enable-executable-static+ --disable-executable-static+ :synopsis: Build fully static executables.+++ :default: False++ Build fully static executables.+ This link all dependent libraries into executables statically,+ including libc.+ This passes ``-static`` and ``-optl=-static`` to GHC.++Foreign function interface options+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^++.. cfg-field:: extra-include-dirs: directories (comma or newline separated list)+ --extra-include-dirs=DIR+ :synopsis: Adds C header search path.++ An extra directory to search for C header files. You can use this+ flag multiple times to get a list of directories.++ You might need to use this flag if you have standard system header+ files in a non-standard location that is not mentioned in the+ package's ``.cabal`` file. Using this option has the same affect as+ appending the directory *dir* to the :pkg-field:`include-dirs` field in each+ library and executable in the package's ``.cabal`` file. The+ advantage of course is that you do not have to modify the package at+ all. These extra directories will be used while building the package+ and for libraries it is also saved in the package registration+ information and used when compiling modules that use the library.++ The command line variant of this flag is+ ``--extra-include-dirs=DIR``, which can be specified multiple times.++.. cfg-field:: extra-lib-dirs: directories (comma or newline separated list)+ --extra-lib-dirs=DIR+ :synopsis: Adds library search directory.++ An extra directory to search for system libraries files.++ The command line variant of this flag is ``--extra-lib-dirs=DIR``,+ which can be specified multiple times.++.. cfg-field:: extra-framework-dirs: directories (comma or newline separated list)+ --extra-framework-dirs=DIR+ :synopsis: Adds framework search directory (OS X only).++ An extra directory to search for frameworks (OS X only).++ You might need to use this flag if you have standard system+ libraries in a non-standard location that is not mentioned in the+ package's ``.cabal`` file. Using this option has the same affect as+ appending the directory *dir* to the :cfg-field:`extra-lib-dirs` field in+ each library and executable in the package's ``.cabal`` file. The+ advantage of course is that you do not have to modify the package at+ all. These extra directories will be used while building the package+ and for libraries it is also saved in the package registration+ information and used when compiling modules that use the library.++ The command line variant of this flag is+ ``--extra-framework-dirs=DIR``, which can be specified multiple+ times.++Profiling options+^^^^^^^^^^^^^^^^^++.. cfg-field:: profiling: boolean+ --enable-profiling+ --disable-profiling+ :synopsis: Enable profiling builds.+ :since: 1.22++ :default: False++ Build libraries and executables with profiling enabled (for+ compilers that support profiling as a separate mode). It is only+ necessary to specify :cfg-field:`profiling` for the specific package you+ want to profile; ``cabal v2-build`` will ensure that all of its+ transitive dependencies are built with profiling enabled.++ To enable profiling for only libraries or executables, see+ :cfg-field:`library-profiling` and :cfg-field:`executable-profiling`.++ For useful profiling, it can be important to control precisely what+ cost centers are allocated; see :cfg-field:`profiling-detail`.++ The command line variant of this flag is ``--enable-profiling`` and+ ``--disable-profiling``.++.. cfg-field:: profiling-detail: level+ --profiling-detail=level+ :synopsis: Profiling detail level.+ :since: 1.24++ Some compilers that support profiling, notably GHC, can allocate+ costs to different parts of the program and there are different+ levels of granularity or detail with which this can be done. In+ particular for GHC this concept is called "cost centers", and GHC+ can automatically add cost centers, and can do so in different ways.++ This flag covers both libraries and executables, but can be+ overridden by the ``library-profiling-detail`` field.++ Currently this setting is ignored for compilers other than GHC. The+ levels that cabal currently supports are:++ default+ For GHC this uses ``exported-functions`` for libraries and+ ``toplevel-functions`` for executables.+ none+ No costs will be assigned to any code within this component.+ exported-functions+ Costs will be assigned at the granularity of all top level+ functions exported from each module. In GHC, this+ is for non-inline functions. Corresponds to ``-fprof-auto-exported``.+ toplevel-functions+ Costs will be assigned at the granularity of all top level+ functions in each module, whether they are exported from the+ module or not. In GHC specifically, this is for non-inline+ functions. Corresponds to ``-fprof-auto-top``.+ all-functions+ Costs will be assigned at the granularity of all functions in+ each module, whether top level or local. In GHC specifically,+ this is for non-inline toplevel or where-bound functions or+ values. Corresponds to ``-fprof-auto``.++ The command line variant of this flag is+ ``--profiling-detail=none``.++.. cfg-field:: library-profiling-detail: level+ --library-profiling-detail=level+ :synopsis: Libraries profiling detail level.+ :since: 1.24++ Like :cfg-field:`profiling-detail`, but applied only to libraries++ The command line variant of this flag is+ ``--library-profiling-detail=none``.++.. cfg-field:: library-vanilla: boolean+ --enable-library-vanilla+ --disable-library-vanilla+ :synopsis: Build libraries without profiling.++ :default: True++ Build ordinary libraries (as opposed to profiling libraries).+ Mostly, you can set this to False to avoid building ordinary+ libraries when you are profiling.++ The command line variant of this flag is+ ``--enable-library-vanilla`` and ``--disable-library-vanilla``.++.. cfg-field:: library-profiling: boolean+ --enable-library-profiling+ --disable-library-profiling+ :synopsis: Build libraries with profiling enabled.+ :since: 1.22++ :default: False++ Build libraries with profiling enabled. You probably want+ to use :cfg-field:`profiling` instead.++ The command line variant of this flag is+ ``--enable-library-profiling`` and ``--disable-library-profiling``.++.. cfg-field:: executable-profiling: boolean+ --enable-executable-profiling+ --disable-executable-profiling+ :synopsis: Build executables with profiling enabled.+ :since: 1.22++ :default: False++ Build executables with profiling enabled. You probably want+ to use :cfg-field:`profiling` instead.++ The command line variant of this flag is+ ``--enable-executable-profiling`` and+ ``--disable-executable-profiling``.++Coverage options+^^^^^^^^^^^^^^^^++.. cfg-field:: coverage: boolean+ --enable-coverage+ --disable-coverage+ :synopsis: Build with coverage enabled.+ :since: 1.22++ :default: False++ Build libraries and executables (including test suites) with Haskell+ Program Coverage enabled. Running the test suites will automatically+ generate coverage reports with HPC.++ The command line variant of this flag is ``--enable-coverage`` and+ ``--disable-coverage``.++.. cfg-field:: library-coverage: boolean+ --enable-library-coverage+ --disable-library-coverage+ :since: 1.22+ :deprecated:++ :default: False++ Deprecated, use :cfg-field:`coverage`.++ The command line variant of this flag is+ ``--enable-library-coverage`` and ``--disable-library-coverage``.++Haddock options+^^^^^^^^^^^^^^^++.. cfg-field:: documentation: boolean+ --enable-documentation+ --disable-documentation+ :synopsis: Enable building of documentation.++ :default: False++ Enables building of Haddock documentation++ The command line variant of this flag is ``--enable-documentation``+ and ``--disable-documentation``.++ `documentation: true` does not imply :cfg-field:`haddock-benchmarks`,+ :cfg-field:`haddock-executables`, :cfg-field:`haddock-internal` or+ :cfg-field:`haddock-tests`. These need to be enabled separately if+ desired.++.. cfg-field:: doc-index-file: templated path+ --doc-index-file=TEMPLATE+ :synopsis: Path to haddock templates.++ A central index of Haddock API documentation (template cannot use+ ``$pkgid``), which should be updated as documentation is built.++ The command line variant of this flag is+ ``--doc-index-file=TEMPLATE``++The following commands are equivalent to ones that would be passed when+running ``setup haddock``. (TODO: Where does the documentation get put.)++.. cfg-field:: haddock-hoogle: boolean+ :synopsis: Generate Hoogle file.++ :default: False++ Generate a text file which can be converted by Hoogle_+ into a database for searching. This is equivalent to running ``haddock``+ with the ``--hoogle`` flag.++ The command line variant of this flag is ``--hoogle`` (for the+ ``haddock`` command).++.. cfg-field:: haddock-html: boolean+ :synopsis: Build HTML documentation.++ :default: True++ Build HTML documentation.++ The command line variant of this flag is ``--html`` (for the+ ``haddock`` command).++.. cfg-field:: haddock-html-location: templated path+ --html-location=TEMPLATE+ :synopsis: Haddock HTML templates location.++ Specify a template for the location of HTML documentation for+ prerequisite packages. The substitutions are applied to the template+ to obtain a location for each package, which will be used by+ hyperlinks in the generated documentation. For example, the+ following command generates links pointing at [Hackage] pages:++ ::++ html-location: http://hackage.haskell.org/packages/archive/$pkg/latest/doc/html++ The command line variant of this flag is ``--html-location`` (for+ the ``haddock`` subcommand).++ ::++ --html-location='http://hackage.haskell.org/packages/archive/$pkg/latest/doc/html'++ Here the argument is quoted to prevent substitution by the shell. If+ this option is omitted, the location for each package is obtained+ using the package tool (e.g. ``ghc-pkg``).++.. cfg-field:: haddock-executables: boolean+ :synopsis: Generate documentation for executables.++ :default: False++ Run haddock on all executable programs.++ The command line variant of this flag is ``--executables`` (for the+ ``haddock`` subcommand).++.. cfg-field:: haddock-tests: boolean+ :synopsis: Generate documentation for tests.++ :default: False++ Run haddock on all test suites.++ The command line variant of this flag is ``--tests`` (for the+ ``haddock`` subcommand).++.. cfg-field:: haddock-benchmarks: boolean+ :synopsis: Generate documentation for benchmarks.++ :default: False++ Run haddock on all benchmarks.++ The command line variant of this flag is ``--benchmarks`` (for the+ ``haddock`` subcommand).++.. cfg-field:: haddock-all: boolean+ :synopsis: Generate documentation for everything++ :default: False++ Run haddock on all components.++ The command line variant of this flag is ``--all`` (for the+ ``haddock`` subcommand).++.. cfg-field:: haddock-internal: boolean+ :synopsis: Generate documentation for internal modules++ :default: False++ Build haddock documentation which includes unexposed modules and+ symbols.++ The command line variant of this flag is ``--internal`` (for the+ ``haddock`` subcommand).++.. cfg-field:: haddock-css: path+ :synopsis: Location of Haddoc CSS file.++ The CSS file that should be used to style the generated+ documentation (overriding haddock's default.)++ The command line variant of this flag is ``--css`` (for the+ ``haddock`` subcommand).++.. cfg-field:: haddock-hyperlink-source: boolean+ :synopsis: Generate hyperlinked source code for documentation++ :default: False++ Generated hyperlinked source code using `HsColour`_, and have+ Haddock documentation link to it.++ The command line variant of this flag is ``--hyperlink-source`` (for+ the ``haddock`` subcommand).++.. cfg-field:: haddock-hscolour-css: path+ :synopsis: Location of CSS file for HsColour++ The CSS file that should be used to style the generated hyperlinked+ source code (from `HsColour`_).++ The command line variant of this flag is ``--hscolour-css`` (for the+ ``haddock`` subcommand).++.. cfg-field:: haddock-contents-location: URL+ :synopsis: URL for contents page.++ A baked-in URL to be used as the location for the contents page.++ The command line variant of this flag is ``--contents-location``+ (for the ``haddock`` subcommand).++.. cfg-field:: haddock-keep-temp-files: boolean+ :synopsis: Keep temporary Haddock files.++ Keep temporary files.++ The command line variant of this flag is ``--keep-temp-files`` (for+ the ``haddock`` subcommand).++Advanced global configuration options+-------------------------------------++.. cfg-field:: write-ghc-environment-files: always, never, or ghc8.4.4++ --write-ghc-environment-files=policy+ :synopsis: Whether a ``.ghc.environment`` should be created after a successful build.++ :default: ``never``++ Whether a `GHC package environment file <https://downloads.haskell.org/~ghc/master/users-guide/packages.html#package-environments>`_+ should be created after a successful build.++ Since Cabal 3.0, defaults to ``never``. Before that, defaulted to+ creating them only when compiling with GHC 8.4.4 and older (GHC+ 8.4.4 `is the first version+ <https://gitlab.haskell.org/ghc/ghc/-/issues/13753>`_ that supports+ the ``-package-env -`` option that allows ignoring the package+ environment files).+++.. cfg-field:: http-transport: curl, wget, powershell, or plain-http+ --http-transport=transport+ :synopsis: Transport to use with http(s) requests.++ :default: ``curl``++ Set a transport to be used when making http(s) requests.++ The command line variant of this field is ``--http-transport=curl``.++.. cfg-field:: ignore-expiry: boolean+ --ignore-expiry+ :synopsis: Ignore Hackage expiration dates.++ :default: False++ If ``True``, we will ignore expiry dates on metadata from Hackage.++ In general, you should not set this to ``True`` as it will leave you+ vulnerable to stale cache attacks. However, it may be temporarily+ useful if the main Hackage server is down, and we need to rely on+ mirrors which have not been updated for longer than the expiry+ period on the timestamp.++ The command line variant of this field is ``--ignore-expiry``.++.. cfg-field:: remote-repo-cache: directory+ --remote-repo-cache=DIR+ :synopsis: Location of packages cache.++ :default: ``~/.cabal/packages``++ [STRIKEOUT:The location where packages downloaded from remote+ repositories will be cached.] Not implemented yet.++ The command line variant of this flag is+ ``--remote-repo-cache=DIR``.++.. cfg-field:: logs-dir: directory+ --logs-dir=DIR+ :synopsis: Directory to store build logs.++ :default: ``~/.cabal/logs``++ [STRIKEOUT:The location where build logs for packages are stored.]+ Not implemented yet.++ The command line variant of this flag is ``--logs-dir=DIR``.++.. cfg-field:: build-summary: template filepath+ --build-summary=TEMPLATE+ :synopsis: Build summaries location.++ :default: ``~/.cabal/logs/build.log``++ [STRIKEOUT:The file to save build summaries. Valid variables which+ can be used in the path are ``$pkgid``, ``$compiler``, ``$os`` and+ ``$arch``.] Not implemented yet.++ The command line variant of this flag is+ ``--build-summary=TEMPLATE``.++.. cfg-field:: world-file: path+ --world-file=FILE+ :deprecated:++ [STRIKEOUT:The location of the world file.] Deprecated.++ The command line variant of this flag is ``--world-file=FILE``.++Undocumented fields: ``root-cmd``, ``symlink-bindir``, ``build-log``,+``remote-build-reporting``, ``report-planned-failure``, ``one-shot``,+``offline``.++Advanced solver options+^^^^^^^^^^^^^^^^^^^^^^^++Most users generally won't need these.++.. cfg-field:: solver: modular+ --solver=modular+ :synopsis: Which solver to use.++ This field is reserved to allow the specification of alternative+ dependency solvers. At the moment, the only accepted option is+ ``modular``.++ The command line variant of this field is ``--solver=modular``.++.. cfg-field:: max-backjumps: nat+ --max-backjumps=N+ :synopsis: Maximum number of solver backjumps.++ :default: 4000++ Maximum number of backjumps (backtracking multiple steps) allowed+ while solving. Set -1 to allow unlimited backtracking, and 0 to+ disable backtracking completely.++ The command line variant of this field is ``--max-backjumps=4000``.++.. cfg-field:: reorder-goals: boolean+ --reorder-goals+ --no-reorder-goals+ :synopsis: Allow solver to reorder goals.++ :default: False++ When enabled, the solver will reorder goals according to certain+ heuristics. Slows things down on average, but may make backtracking+ faster for some packages. It's unlikely to help for small projects,+ but for big install plans it may help you find a plan when otherwise+ this is not possible. See :issue:`1780` for more commentary.++ The command line variant of this field is ``--(no-)reorder-goals``.++.. cfg-field:: count-conflicts: boolean+ --count-conflicts+ --no-count-conflicts+ :synopsis: Solver prefers versions with less conflicts.++ :default: True++ Try to speed up solving by preferring goals that are involved in a+ lot of conflicts.++ The command line variant of this field is+ ``--(no-)count-conflicts``.++.. cfg-field:: fine-grained-conflicts: boolean+ --fine-grained-conflicts+ --no-fine-grained-conflicts+ :synopsis: Skip a version of a package if it does not resolve any conflicts+ encountered in the last version (solver optimization).++ :default: True++ When enabled, the solver will skip a version of a package if it does not+ resolve any of the conflicts encountered in the last version of that+ package. For example, if ``foo-1.2`` depended on ``bar``, and the solver+ couldn't find consistent versions for ``bar``'s dependencies, then the+ solver would skip ``foo-1.1`` if it also depended on ``bar``.++ The command line variant of this field is+ ``--(no-)fine-grained-conflicts``.++.. cfg-field:: minimize-conflict-set: boolean+ --minimize-conflict-set+ --no-minimize-conflict-set+ :synopsis: Try to improve the solver error message when there is no+ solution.++ :default: False++ When there is no solution, try to improve the solver error message+ by finding a minimal conflict set. This option may increase run+ time significantly, so it is off by default.++ The command line variant of this field is+ ``--(no-)minimize-conflict-set``.++.. cfg-field:: strong-flags: boolean+ --strong-flags+ --no-strong-flags+ :synopsis: Do not defer flag choices when solving.++ :default: False++ Do not defer flag choices. (TODO: Better documentation.)++ The command line variant of this field is ``--(no-)strong-flags``.++.. cfg-field:: allow-boot-library-installs: boolean+ --allow-boot-library-installs+ --no-allow-boot-library-installs+ :synopsis: Allow cabal to install or upgrade any package.++ :default: False++ By default, the dependency solver doesn't allow ``base``,+ ``ghc-prim``, ``integer-simple``, ``integer-gmp``, and+ ``template-haskell`` to be installed or upgraded. This flag+ removes the restriction.++ The command line variant of this field is+ ``--(no-)allow-boot-library-installs``.++.. cfg-field:: cabal-lib-version: version+ --cabal-lib-version=version+ :synopsis: Version of Cabal library used to build package.++ This field selects the version of the Cabal library which should be+ used to build packages. This option is intended primarily for+ internal development use (e.g., forcing a package to build with a+ newer version of Cabal, to test a new version of Cabal.) (TODO:+ Specify its semantics more clearly.)++ The command line variant of this field is+ ``--cabal-lib-version=1.24.0.1``.++.. include:: references.inc
cabal/Cabal/doc/cabaldomain.py view
@@ -26,12 +26,12 @@ .. rst:directive:: .. cabal::cfg-section - Describes a package.cabal section, such as library or exectuble.+ Describes a package.cabal section, such as library or executable. All following `pkg-field` directives will add section name to their fields name for disambiguating duplicates. - You can reset the section disambguation with with `.. pkg-section:: None`.+ You can reset the section disambiguation with `.. pkg-section:: None`. .. rst::role:: pkg-section @@ -86,7 +86,7 @@ These should act in a way similar to `.. std::option` directive, but with extra meta. And should also end up in reference. - At least setup and 'new-build` subcommands should get special directvies+ At least setup and 'new-build` subcommands should get special directives - Improve rendering of flags in `.. cfg-field::` directive. It should be possible without copy-pasting code from sphinx.directives.ObjectDescription@@ -122,7 +122,7 @@ from sphinx.directives import ObjectDescription from sphinx.domains import ObjType, Domain, Index from sphinx.domains.std import StandardDomain-from sphinx.locale import l_, _+from sphinx.locale import _ from sphinx.roles import XRefRole from sphinx.util.docfields import Field, DocFieldTransformer from sphinx.util.nodes import make_refnode@@ -150,7 +150,7 @@ name = parts[0] names.append(name) sig = sep + ' '.join(parts[1:])- sig = re.sub(ur'<([-a-zA-Z ]+)>', ur'⟨\1⟩', sig)+ sig = re.sub(r'<([-a-zA-Z ]+)>', r'⟨\1⟩', sig) if i > 0: signode += addnodes.desc_name(', ', ', ') signode += addnodes.desc_name(name, name)@@ -200,7 +200,7 @@ if isinstance(kid, nodes.title): return kid.astext(), section_id - print section_name, section_id+ print(section_name, section_id) return section_name, section_id @@ -323,7 +323,7 @@ def get_index_entry(self, env, name): '''- Should return index entry and achor+ Should return index entry and anchor By default uses indextemplate attribute to generate name and index entry by joining directive name, section and field name@@ -813,10 +813,10 @@ name = 'cabal' label = 'Cabal' object_types = {- 'pkg-section': ObjType(l_('pkg-section'), 'pkg-section'),- 'pkg-field' : ObjType(l_('pkg-field') , 'pkg-field' ),- 'cfg-section': ObjType(l_('cfg-section'), 'cfg-section'),- 'cfg-field' : ObjType(l_('cfg-field') , 'cfg-field' ),+ 'pkg-section': ObjType(_('pkg-section'), 'pkg-section'),+ 'pkg-field' : ObjType(_('pkg-field') , 'pkg-field' ),+ 'cfg-section': ObjType(_('cfg-section'), 'cfg-section'),+ 'cfg-field' : ObjType(_('cfg-field') , 'cfg-field' ), } directives = { 'pkg-section': CabalPackageSection,@@ -853,9 +853,12 @@ def clear_doc(self, docname): for k in ['pkg-sections', 'pkg-fields', 'cfg-sections', 'cfg-fields', 'cfg-flags']:+ to_del = [] for name, (fn, _, _) in self.data[k].items(): if fn == docname:- del self.data[k][name]+ to_del.append(name)+ for name in to_del:+ del self.data[k][name] try: del self.data['index-num'][docname] except KeyError:@@ -910,5 +913,5 @@ def setup(app): app.add_domain(CabalDomain)- app.add_lexer('cabal', CabalLexer())+ app.add_lexer('cabal', CabalLexer)
cabal/Cabal/doc/conf.py view
@@ -13,7 +13,7 @@ sys.path.insert(0, os.path.abspath('.')) import cabaldomain -version = "3.1.0.0"+version = "3.3.0.0" extensions = ['sphinx.ext.extlinks', 'sphinx.ext.todo'] @@ -26,15 +26,15 @@ extlinks = { 'issue': ('https://github.com/haskell/cabal/issues/%s', '#'), - 'ghc-wiki': ('http://ghc.haskell.org/trac/ghc/wiki/%s', ''),- 'ghc-ticket': ('http://ghc.haskell.org/trac/ghc/ticket/%s', 'GHC #'),+ 'ghc-wiki': ('https://gitlab.haskell.org/ghc/ghc/-/wikis/%s', ''),+ 'ghc-ticket': ('https://gitlab.haskell.org/ghc/ghc/-/issues/%s', 'GHC #'), 'hackage-pkg': ('http://hackage.haskell.org/package/%s', ''), } # General information about the project. project = u'Cabal'-copyright = u'2003-2017, Cabal Team'+copyright = u'2003-2020, Cabal Team' # N.B. version comes from ghc_config release = version # The full version, including alpha/beta/rc tags. @@ -90,13 +90,16 @@ # Output file base name for HTML help builder. htmlhelp_basename = 'CabalUsersGuide' +# MathJax to use SVG rendering by default+mathjax_path = 'https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/latest.js?config=TeX-AMS-MML_SVG' + # -- Options for LaTeX output --------------------------------------------- latex_elements = { 'inputenc': '', 'utf8extra': '',- 'preamble': '''+ 'preamble': r''' \usepackage{fontspec} \usepackage{makeidx} \setsansfont{DejaVu Sans}@@ -171,7 +174,7 @@ name = parts[0] names.append(name) sig = sep + ' '.join(parts[1:])- sig = re.sub(ur'<([-a-zA-Z ]+)>', ur'⟨\1⟩', sig)+ sig = re.sub(r'<([-a-zA-Z ]+)>', r'⟨\1⟩', sig) if i > 0: signode += addnodes.desc_name(', ', ', ') signode += addnodes.desc_name(name, name)
cabal/Cabal/doc/developing-packages.rst view
@@ -1,3752 +1,488 @@ Quickstart ========== -Lets assume we have created a project directory and already have a-Haskell module or two.--Every project needs a name, we'll call this example "proglet".--.. highlight:: console--::-- $ cd proglet/- $ ls- Proglet.hs--It is assumed that (apart from external dependencies) all the files that-make up a package live under a common project root directory. This-simple example has all the project files in one directory, but most-packages will use one or more subdirectories.--To turn this into a Cabal package we need two extra files in the-project's root directory:--- ``proglet.cabal``: containing package metadata and build information.--- ``Setup.hs``: usually containing a few standardized lines of code,- but can be customized if necessary.--We can create both files manually or we can use ``cabal init`` to create-them for us.--Using "cabal init"---------------------The ``cabal init`` command is interactive. It asks us a number of-questions starting with the package name and version.--::-- $ cabal init- Package name [default "proglet"]?- Package version [default "0.1"]?- ...--It also asks questions about various other bits of package metadata. For-a package that you never intend to distribute to others, these fields-can be left blank.--One of the important questions is whether the package contains a library-or an executable. Libraries are collections of Haskell modules that can-be re-used by other Haskell libraries and programs, while executables-are standalone programs.--::-- What does the package build:- 1) Library- 2) Executable- Your choice?--For the moment these are the only choices. For more complex packages-(e.g. a library and multiple executables or test suites) the ``.cabal``-file can be edited afterwards.--Finally, ``cabal init`` creates the initial ``proglet.cabal`` and-``Setup.hs`` files, and depending on your choice of license, a-``LICENSE`` file as well.--::-- Generating LICENSE...- Generating Setup.hs...- Generating proglet.cabal...-- You may want to edit the .cabal file and add a Description field.--As this stage the ``proglet.cabal`` is not quite complete and before you-are able to build the package you will need to edit the file and add-some build information about the library or executable.--Editing the .cabal file--------------------------.. highlight:: cabal--Load up the ``.cabal`` file in a text editor. The first part of the-``.cabal`` file has the package metadata and towards the end of the file-you will find the :pkg-section:`executable` or :pkg-section:`library` section.--You will see that the fields that have yet to be filled in are commented-out. Cabal files use "``--``" Haskell-style comment syntax. (Note that-comments are only allowed on lines on their own. Trailing comments on-other lines are not allowed because they could be confused with program-options.)--If you selected earlier to create a library package then your ``.cabal``-file will have a section that looks like this:--::-- library- exposed-modules: Proglet- -- other-modules:- -- build-depends:--Alternatively, if you selected an executable then there will be a-section like:--::-- executable proglet- -- main-is:- -- other-modules:- -- build-depends:--The build information fields listed (but commented out) are just the few-most important and common fields. There are many others that are covered-later in this chapter.--Most of the build information fields are the same between libraries and-executables. The difference is that libraries have a number of "exposed"-modules that make up the public interface of the library, while-executables have a file containing a ``Main`` module.--The name of a library always matches the name of the package, so it is-not specified in the library section. Executables often follow the name-of the package too, but this is not required and the name is given-explicitly.--Modules included in the package----------------------------------For a library, ``cabal init`` looks in the project directory for files-that look like Haskell modules and adds all the modules to the-:pkg-field:`library:exposed-modules` field. For modules that do not form part-of your package's public interface, you can move those modules to the-:pkg-field:`other-modules` field. Either way, all modules in the library need-to be listed.--For an executable, ``cabal init`` does not try to guess which file-contains your program's ``Main`` module. You will need to fill in the-:pkg-field:`executable:main-is` field with the file name of your program's-``Main`` module (including ``.hs`` or ``.lhs`` extension). Other modules-included in the executable should be listed in the :pkg-field:`other-modules`-field.--Modules imported from other packages---------------------------------------While your library or executable may include a number of modules, it-almost certainly also imports a number of external modules from the-standard libraries or other pre-packaged libraries. (These other-libraries are of course just Cabal packages that contain a library.)--You have to list all of the library packages that your library or-executable imports modules from. Or to put it another way: you have to-list all the other packages that your package depends on.--For example, suppose the example ``Proglet`` module imports the module-``Data.Map``. The ``Data.Map`` module comes from the ``containers``-package, so we must list it:--::-- library- exposed-modules: Proglet- other-modules:- build-depends: containers, base == 4.*--In addition, almost every package also depends on the ``base`` library-package because it exports the standard ``Prelude`` module plus other-basic modules like ``Data.List``.--You will notice that we have listed ``base == 4.*``. This gives a-constraint on the version of the base package that our package will work-with. The most common kinds of constraints are:--- ``pkgname >= n``-- ``pkgname ^>= n`` (since Cabal 2.0)-- ``pkgname >= n && < m``-- ``pkgname == n.*`` (since Cabal 1.6)--The last is just shorthand, for example ``base == 4.*`` means exactly-the same thing as ``base >= 4 && < 5``. Please refer to the documentation-on the :pkg-field:`build-depends` field for more information.--Also, you can factor out shared ``build-depends`` (and other fields such-as ``ghc-options``) into a ``common`` stanza which you can ``import`` in-your libraries and executable sections. For example:--::-- common shared-properties- default-language: Haskell2010- build-depends:- base == 4.*- ghc-options:- -Wall-- library- import: shared-properties- exposed-modules:- Proglet--Note that the ``import`` **must** be the first thing in the stanza. For more-information see the `Common stanzas`_ section.--Building the package-----------------------For simple packages that's it! We can now try configuring and building-the package:--.. code-block:: console-- $ cabal configure- $ cabal build--Assuming those two steps worked then you can also install the package:--.. code-block:: console-- $ cabal install--For libraries this makes them available for use in GHCi or to be used by-other packages. For executables it installs the program so that you can-run it (though you may first need to adjust your system's ``$PATH``).--Next steps-------------What we have covered so far should be enough for very simple packages-that you use on your own system.--The next few sections cover more details needed for more complex-packages and details needed for distributing packages to other people.--The previous chapter covers building and installing packages -- your own-packages or ones developed by other people.--Package concepts-================--Before diving into the details of writing packages it helps to-understand a bit about packages in the Haskell world and the particular-approach that Cabal takes.--The point of packages------------------------Packages are a mechanism for organising and distributing code. Packages-are particularly suited for "programming in the large", that is building-big systems by using and re-using code written by different people at-different times.--People organise code into packages based on functionality and-dependencies. Social factors are also important: most packages have a-single author, or a relatively small team of authors.--Packages are also used for distribution: the idea is that a package can-be created in one place and be moved to a different computer and be-usable in that different environment. There are a surprising number of-details that have to be got right for this to work, and a good package-system helps to simplify this process and make it reliable.--Packages come in two main flavours: libraries of reusable code, and-complete programs. Libraries present a code interface, an API, while-programs can be run directly. In the Haskell world, library packages-expose a set of Haskell modules as their public interface. Cabal-packages can contain a library or executables or both.--Some programming languages have packages as a builtin language concept.-For example in Java, a package provides a local namespace for types and-other definitions. In the Haskell world, packages are not a part of the-language itself. Haskell programs consist of a number of modules, and-packages just provide a way to partition the modules into sets of-related functionality. Thus the choice of module names in Haskell is-still important, even when using packages.--Package names and versions-----------------------------All packages have a name, e.g. "HUnit". Package names are assumed to be-unique. Cabal package names may contain letters, numbers and hyphens,-but not spaces and may also not contain a hyphened section consisting of-only numbers. The namespace for Cabal packages is flat, not-hierarchical.--Packages also have a version, e.g "1.1". This matches the typical way in-which packages are developed. Strictly speaking, each version of a-package is independent, but usually they are very similar. Cabal package-versions follow the conventional numeric style, consisting of a sequence-of digits such as "1.0.1" or "2.0". There are a range of common-conventions for "versioning" packages, that is giving some meaning to-the version number in terms of changes in the package, such as-e.g. `SemVer <http://semver.org>`__; however, for packages intended to be-distributed via Hackage Haskell's `Package Versioning Policy`_ applies-(see also the `PVP/SemVer FAQ section <https://pvp.haskell.org/faq/#semver>`__).--The combination of package name and version is called the *package ID*-and is written with a hyphen to separate the name and version, e.g.-"HUnit-1.1".--For Cabal packages, the combination of the package name and version-*uniquely* identifies each package. Or to put it another way: two-packages with the same name and version are considered to *be* the same.--Strictly speaking, the package ID only identifies each Cabal *source*-package; the same Cabal source package can be configured and built in-different ways. There is a separate installed package ID that uniquely-identifies each installed package instance. Most of the time however,-users need not be aware of this detail.--Kinds of package: Cabal vs GHC vs system-------------------------------------------It can be slightly confusing at first because there are various-different notions of package floating around. Fortunately the details-are not very complicated.--Cabal packages- Cabal packages are really source packages. That is they contain- Haskell (and sometimes C) source code.-- Cabal packages can be compiled to produce GHC packages. They can- also be translated into operating system packages.--GHC packages- This is GHC's view on packages. GHC only cares about library- packages, not executables. Library packages have to be registered- with GHC for them to be available in GHCi or to be used when- compiling other programs or packages.-- The low-level tool ``ghc-pkg`` is used to register GHC packages and- to get information on what packages are currently registered.-- You never need to make GHC packages manually. When you build and- install a Cabal package containing a library then it gets registered- with GHC automatically.-- Haskell implementations other than GHC have essentially the same- concept of registered packages. For the most part, Cabal hides the- slight differences.--Operating system packages- On operating systems like Linux and Mac OS X, the system has a- specific notion of a package and there are tools for installing and- managing packages.-- The Cabal package format is designed to allow Cabal packages to be- translated, mostly-automatically, into operating system packages.- They are usually translated 1:1, that is a single Cabal package- becomes a single system package.-- It is also possible to make Windows installers from Cabal packages,- though this is typically done for a program together with all of its- library dependencies, rather than packaging each library separately.--Unit of distribution-----------------------The Cabal package is the unit of distribution. What this means is that-each Cabal package can be distributed on its own in source or binary-form. Of course there may dependencies between packages, but there is-usually a degree of flexibility in which versions of packages can work-together so distributing them independently makes sense.--It is perhaps easiest to see what being "the unit of distribution"-means by contrast to an alternative approach. Many projects are made up-of several interdependent packages and during development these might-all be kept under one common directory tree and be built and tested-together. When it comes to distribution however, rather than-distributing them all together in a single tarball, it is required that-they each be distributed independently in their own tarballs.--Cabal's approach is to say that if you can specify a dependency on a-package then that package should be able to be distributed-independently. Or to put it the other way round, if you want to-distribute it as a single unit, then it should be a single package.--Explicit dependencies and automatic package management---------------------------------------------------------Cabal takes the approach that all packages dependencies are specified-explicitly and specified in a declarative way. The point is to enable-automatic package management. This means tools like ``cabal`` can-resolve dependencies and install a package plus all of its dependencies-automatically. Alternatively, it is possible to mechanically (or mostly-mechanically) translate Cabal packages into system packages and let the-system package manager install dependencies automatically.--It is important to track dependencies accurately so that packages can-reliably be moved from one system to another system and still be able to-build it there. Cabal is therefore relatively strict about specifying-dependencies. For example Cabal's default build system will not even let-code build if it tries to import a module from a package that isn't-listed in the ``.cabal`` file, even if that package is actually-installed. This helps to ensure that there are no "untracked-dependencies" that could cause the code to fail to build on some other-system.--The explicit dependency approach is in contrast to the traditional-"./configure" approach where instead of specifying dependencies-declaratively, the ``./configure`` script checks if the dependencies are-present on the system. Some manual work is required to transform a-``./configure`` based package into a Linux distribution package (or-similar). This conversion work is usually done by people other than the-package author(s). The practical effect of this is that only the most-popular packages will benefit from automatic package management.-Instead, Cabal forces the original author to specify the dependencies-but the advantage is that every package can benefit from automatic-package management.--The "./configure" approach tends to encourage packages that adapt-themselves to the environment in which they are built, for example by-disabling optional features so that they can continue to work when a-particular dependency is not available. This approach makes sense in a-world where installing additional dependencies is a tiresome manual-process and so minimising dependencies is important. The automatic-package management view is that packages should just declare what they-need and the package manager will take responsibility for ensuring that-all the dependencies are installed.--Sometimes of course optional features and optional dependencies do make-sense. Cabal packages can have optional features and varying-dependencies. These conditional dependencies are still specified in a-declarative way however and remain compatible with automatic package-management. The need to remain compatible with automatic package-management means that Cabal's conditional dependencies system is a bit-less flexible than with the "./configure" approach.--.. note::- `GNU autoconf places restrictions on paths, including the- path that the user builds a package from.- <https://www.gnu.org/software/autoconf/manual/autoconf.html#File-System-Conventions>`_- Package authors using ``build-type: configure`` should be aware of- these restrictions; because users may be unexpectedly constrained and- face mysterious errors, it is recommended that ``build-type: configure``- is only used where strictly necessary.--Portability--------------One of the purposes of Cabal is to make it easier to build packages on-different platforms (operating systems and CPU architectures), with-different compiler versions and indeed even with different Haskell-implementations. (Yes, there are Haskell implementations other than-GHC!)--Cabal provides abstractions of features present in different Haskell-implementations and wherever possible it is best to take advantage of-these to increase portability. Where necessary however it is possible to-use specific features of specific implementations.--For example a package author can list in the package's ``.cabal`` what-language extensions the code uses. This allows Cabal to figure out if-the language extension is supported by the Haskell implementation that-the user picks. Additionally, certain language extensions such as-Template Haskell require special handling from the build system and by-listing the extension it provides the build system with enough-information to do the right thing.--Another similar example is linking with foreign libraries. Rather than-specifying GHC flags directly, the package author can list the libraries-that are needed and the build system will take care of using the right-flags for the compiler. Additionally this makes it easier for tools to-discover what system C libraries a package needs, which is useful for-tracking dependencies on system libraries (e.g. when translating into-Linux distribution packages).--In fact both of these examples fall into the category of explicitly-specifying dependencies. Not all dependencies are other Cabal packages.-Foreign libraries are clearly another kind of dependency. It's also-possible to think of language extensions as dependencies: the package-depends on a Haskell implementation that supports all those extensions.--Where compiler-specific options are needed however, there is an "escape-hatch" available. The developer can specify implementation-specific-options and more generally there is a configuration mechanism to-customise many aspects of how a package is built depending on the-Haskell implementation, the operating system, computer architecture and-user-specified configuration flags.--Developing packages-===================--The Cabal package is the unit of distribution. When installed, its-purpose is to make available:--- One or more Haskell programs.--- At most one library, exposing a number of Haskell modules.--However having both a library and executables in a package does not work-very well; if the executables depend on the library, they must-explicitly list all the modules they directly or indirectly import from-that library. Fortunately, starting with Cabal 1.8.0.4, executables can-also declare the package that they are in as a dependency, and Cabal-will treat them as if they were in another package that depended on the-library.--Internally, the package may consist of much more than a bunch of Haskell-modules: it may also have C source code and header files, source code-meant for preprocessing, documentation, test cases, auxiliary tools etc.--A package is identified by a globally-unique *package name*, which-consists of one or more alphanumeric words separated by hyphens. To-avoid ambiguity, each of these words should contain at least one letter.-Chaos will result if two distinct packages with the same name are-installed on the same system. A particular version of the package is-distinguished by a *version number*, consisting of a sequence of one or-more integers separated by dots. These can be combined to form a single-text string called the *package ID*, using a hyphen to separate the name-from the version, e.g. "``HUnit-1.1``".--.. Note::-- Packages are not part of the Haskell language; they simply- populate the hierarchical space of module names. In GHC 6.6 and later a- program may contain multiple modules with the same name if they come- from separate packages; in all other current Haskell systems packages- may not overlap in the modules they provide, including hidden modules.--Creating a package---------------------Suppose you have a directory hierarchy containing the source files that-make up your package. You will need to add two more files to the root-directory of the package:--:file:`{package-name}.cabal`- a Unicode UTF-8 text file containing a package description. For- details of the syntax of this file, see the section on- `package descriptions`_.--:file:`Setup.hs`- a single-module Haskell program to perform various setup tasks (with- the interface described in the section on :ref:`installing-packages`).- This module should import only modules that will be present in all Haskell- implementations, including modules of the Cabal library. The content of- this file is determined by the :pkg-field:`build-type` setting in the- ``.cabal`` file. In most cases it will be trivial, calling on the Cabal- library to do most of the work.--Once you have these, you can create a source bundle of this directory-for distribution. Building of the package is discussed in the section on-:ref:`installing-packages`.--One of the purposes of Cabal is to make it easier to build a package-with different Haskell implementations. So it provides abstractions of-features present in different Haskell implementations and wherever-possible it is best to take advantage of these to increase portability.-Where necessary however it is possible to use specific features of-specific implementations. For example one of the pieces of information a-package author can put in the package's ``.cabal`` file is what language-extensions the code uses. This is far preferable to specifying flags for-a specific compiler as it allows Cabal to pick the right flags for the-Haskell implementation that the user picks. It also allows Cabal to-figure out if the language extension is even supported by the Haskell-implementation that the user picks. Where compiler-specific options are-needed however, there is an "escape hatch" available. The developer can-specify implementation-specific options and more generally there is a-configuration mechanism to customise many aspects of how a package is-built depending on the Haskell implementation, the Operating system,-computer architecture and user-specified configuration flags.--::-- name: Foo- version: 1.0-- library- build-depends: base >= 4 && < 5- exposed-modules: Foo- extensions: ForeignFunctionInterface- ghc-options: -Wall- if os(windows)- build-depends: Win32 >= 2.1 && < 2.6--Example: A package containing a simple library-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--The HUnit package contains a file ``HUnit.cabal`` containing:--::-- name: HUnit- version: 1.1.1- synopsis: A unit testing framework for Haskell- homepage: http://hunit.sourceforge.net/- category: Testing- author: Dean Herington- license: BSD3- license-file: LICENSE- cabal-version: 1.12- build-type: Simple-- library- build-depends: base >= 2 && < 4- exposed-modules: Test.HUnit.Base, Test.HUnit.Lang,- Test.HUnit.Terminal, Test.HUnit.Text, Test.HUnit- default-extensions: CPP--and the following ``Setup.hs``:--.. code-block:: haskell-- import Distribution.Simple- main = defaultMain--Example: A package containing executable programs-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--::-- name: TestPackage- version: 0.0- synopsis: Small package with two programs- author: Angela Author- license: BSD3- build-type: Simple- cabal-version: >= 1.8-- executable program1- build-depends: HUnit >= 1.1.1 && < 1.2- main-is: Main.hs- hs-source-dirs: prog1-- executable program2- main-is: Main.hs- build-depends: HUnit >= 1.1.1 && < 1.2- hs-source-dirs: prog2- other-modules: Utils--with ``Setup.hs`` the same as above.--Example: A package containing a library and executable programs-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--::-- name: TestPackage- version: 0.0- synopsis: Package with library and two programs- license: BSD3- author: Angela Author- build-type: Simple- cabal-version: >= 1.8-- library- build-depends: HUnit >= 1.1.1 && < 1.2- exposed-modules: A, B, C-- executable program1- main-is: Main.hs- hs-source-dirs: prog1- other-modules: A, B-- executable program2- main-is: Main.hs- hs-source-dirs: prog2- other-modules: A, C, Utils--with ``Setup.hs`` the same as above. Note that any library modules-required (directly or indirectly) by an executable must be listed again.--The trivial setup script used in these examples uses the *simple build-infrastructure* provided by the Cabal library (see-`Distribution.Simple <../release/cabal-latest/doc/API/Cabal/Distribution-Simple.html>`__).-The simplicity lies in its interface rather that its implementation. It-automatically handles preprocessing with standard preprocessors, and-builds packages for all the Haskell implementations.--The simple build infrastructure can also handle packages where building-is governed by system-dependent parameters, if you specify a little more-(see the section on `system-dependent parameters`_).-A few packages require `more elaborate solutions <more complex packages>`_.--.. _pkg-desc:--Package descriptions-----------------------The package description file must have a name ending in "``.cabal``". It-must be a Unicode text file encoded using valid UTF-8. There must be-exactly one such file in the directory. The first part of the name is-usually the package name, and some of the tools that operate on Cabal-packages require this; specifically, Hackage rejects packages which-don't follow this rule.--In the package description file, lines whose first non-whitespace-characters are "``--``" are treated as comments and ignored.--This file should contain of a number global property descriptions and-several sections.--- The `package properties`_ describe the package- as a whole, such as name, license, author, etc.--- Optionally, a number of *configuration flags* can be declared. These- can be used to enable or disable certain features of a package. (see- the section on `configurations`_).--- The (optional) library section specifies the `library`_ properties and- relevant `build information`_.--- Following is an arbitrary number of executable sections which describe- an executable program and relevant `build information`_.--Each section consists of a number of property descriptions in the form-of field/value pairs, with a syntax roughly like mail message headers.--- Case is not significant in field names, but is significant in field- values.--- To continue a field value, indent the next line relative to the field- name.--- Field names may be indented, but all field values in the same section- must use the same indentation.--- Tabs are *not* allowed as indentation characters due to a missing- standard interpretation of tab width.--- Before Cabal 3.0, to get a blank line in a field value, use an indented "``.``"--The syntax of the value depends on the field. Field types include:--*token*, *filename*, *directory*- Either a sequence of one or more non-space non-comma characters, or- a quoted string in Haskell 98 lexical syntax. The latter can be used- for escaping whitespace, for example:- ``ghc-options: -Wall "-with-rtsopts=-T -I1"``. Unless otherwise- stated, relative filenames and directories are interpreted from the- package root directory.-*freeform*, *URL*, *address*- An arbitrary, uninterpreted string.-*identifier*- A letter followed by zero or more alphanumerics or underscores.-*compiler*- A compiler flavor (one of: ``GHC``, ``UHC`` or ``LHC``)- followed by a version range. For example, ``GHC ==6.10.3``, or- ``LHC >=0.6 && <0.8``.--Modules and preprocessors-^^^^^^^^^^^^^^^^^^^^^^^^^--Haskell module names listed in the :pkg-field:`library:exposed-modules` and-:pkg-field:`library:other-modules` fields may correspond to Haskell source-files, i.e. with names ending in "``.hs``" or "``.lhs``", or to inputs for-various Haskell preprocessors. The simple build infrastructure understands the-extensions:--- ``.gc`` (:hackage-pkg:`greencard`)-- ``.chs`` (:hackage-pkg:`c2hs`)-- ``.hsc`` (:hackage-pkg:`hsc2hs`)-- ``.y`` and ``.ly`` (happy_)-- ``.x`` (alex_)-- ``.cpphs`` (cpphs_)--When building, Cabal will automatically run the appropriate preprocessor-and compile the Haskell module it produces. For the ``c2hs`` and-``hsc2hs`` preprocessors, Cabal will also automatically add, compile and-link any C sources generated by the preprocessor (produced by-``hsc2hs``'s ``#def`` feature or ``c2hs``'s auto-generated wrapper-functions). Dependencies on pre-processors are specified via the-:pkg-field:`build-tools` or :pkg-field:`build-tool-depends` fields.--Some fields take lists of values, which are optionally separated by-commas, except for the :pkg-field:`build-depends` field, where the commas are-mandatory.--Some fields are marked as required. All others are optional, and unless-otherwise specified have empty default values.--Package properties-^^^^^^^^^^^^^^^^^^--These fields may occur in the first top-level properties section and-describe the package as a whole:--.. pkg-field:: name: package-name (required)-- The unique name of the package, without the version number.-- As pointed out in the section on `package descriptions`_, some- tools require the package-name specified for this field to match- the package description's file-name :file:`{package-name}.cabal`.-- Package names are case-sensitive and must match the regular expression- (i.e. alphanumeric "words" separated by dashes; each alphanumeric- word must contain at least one letter):- ``[[:digit:]]*[[:alpha:]][[:alnum:]]*(-[[:digit:]]*[[:alpha:]][[:alnum:]]*)*``.-- Or, expressed in ABNF_:-- .. code-block:: abnf-- package-name = package-name-part *("-" package-name-part)- package-name-part = *DIGIT UALPHA *UALNUM-- UALNUM = UALPHA / DIGIT- UALPHA = ... ; set of alphabetic Unicode code-points-- .. note::-- Hackage restricts package names to the ASCII subset.--.. pkg-field:: version: numbers (required)-- The package version number, usually consisting of a sequence of- natural numbers separated by dots, i.e. as the regular- expression ``[0-9]+([.][0-9]+)*`` or expressed in ABNF_:-- .. code-block:: abnf-- package-version = 1*DIGIT *("." 1*DIGIT)--.. pkg-field:: cabal-version: x.y[.z]-- The version of the Cabal specification that this package- description uses. The Cabal specification does slowly evolve (see- also :ref:`spec-history`), introducing new features and- occasionally changing the meaning of existing features. By- specifying which version of the specification you are using it- enables programs which process the package description to know- what syntax to expect and what each part means.-- The version number you specify will affect both compatibility and- behaviour. Most tools (including the Cabal library and the ``cabal``- program) understand a range of versions of the Cabal specification.- Older tools will of course only work with older versions of the- Cabal specification that was known at the time. Most of the time,- tools that are too old will recognise this fact and produce a- suitable error message. Likewise, ``cabal check`` will tell you- whether the version number is sufficiently high for the features- you use in the package description.-- As for behaviour, new versions of the Cabal specification can change the- meaning of existing syntax. This means if you want to take advantage- of the new meaning or behaviour then you must specify the newer- Cabal version. Tools are expected to use the meaning and behaviour- appropriate to the version given in the package description.-- In particular, the syntax of package descriptions changed- significantly with Cabal version 1.2 and the :pkg-field:`cabal-version`- field is now required. Files written in the old syntax are still- recognized, so if you require compatibility with very old Cabal- versions then you may write your package description file using the- old syntax. Please consult the user's guide of an older Cabal- version for a description of that syntax.-- Starting with ``cabal-version: 2.2`` this field is only valid if- fully contained in the very first line of a package description- and ought to adhere to the ABNF_ grammar-- .. code-block:: abnf-- newstyle-spec-version-decl = "cabal-version" *WS ":" *WS newstyle-spec-version *WS-- newstyle-spec-version = NUM "." NUM [ "." NUM ]-- NUM = DIGIT0 / DIGITP 1*DIGIT0- DIGIT0 = %x30-39- DIGITP = %x31-39- WS = %20--- .. note::-- For package descriptions using a format prior to- ``cabal-version: 1.12`` the legacy syntax resembling a version- range syntax-- .. code-block:: cabal-- cabal-version: >= 1.10-- needs to be used.-- This legacy syntax is supported up until ``cabal-version: >=- 2.0`` it is however strongly recommended to avoid using the- legacy syntax. See also :issue:`4899`.----.. pkg-field:: build-type: identifier-- :default: ``Custom`` or ``Simple``-- The type of build used by this package. Build types are the- constructors of the- `BuildType <../release/cabal-latest/doc/API/Cabal/Distribution-PackageDescription.html#t:BuildType>`__- type. This field is optional and when missing, its default value- is inferred according to the following rules:-- - When :pkg-field:`cabal-version` is set to ``2.2`` or higher,- the default is ``Simple`` unless a :pkg-section:`custom-setup`- exists, in which case the inferred default is ``Custom``.-- - For lower :pkg-field:`cabal-version` values, the default is- ``Custom`` unconditionally.-- If the build type is anything other than ``Custom``, then the- ``Setup.hs`` file *must* be exactly the standardized content- discussed below. This is because in these cases, ``cabal`` will- ignore the ``Setup.hs`` file completely, whereas other methods of- package management, such as ``runhaskell Setup.hs [CMD]``, still- rely on the ``Setup.hs`` file.-- For build type ``Simple``, the contents of ``Setup.hs`` must be:-- .. code-block:: haskell-- import Distribution.Simple- main = defaultMain-- For build type ``Configure`` (see the section on `system-dependent- parameters`_ below), the contents of- ``Setup.hs`` must be:-- .. code-block:: haskell-- import Distribution.Simple- main = defaultMainWithHooks autoconfUserHooks-- For build type ``Make`` (see the section on `more complex packages`_ below),- the contents of ``Setup.hs`` must be:-- .. code-block:: haskell-- import Distribution.Make- main = defaultMain-- For build type ``Custom``, the file ``Setup.hs`` can be customized,- and will be used both by ``cabal`` and other tools.-- For most packages, the build type ``Simple`` is sufficient.--.. pkg-field:: license: SPDX expression-- :default: ``NONE``-- The type of license under which this package is distributed.-- Starting with ``cabal-version: 2.2`` the ``license`` field takes a- (case-sensitive) SPDX expression such as-- .. code-block:: cabal-- license: Apache-2.0 AND (MIT OR GPL-2.0-or-later)-- See `SPDX IDs: How to use <https://spdx.org/ids-how>`__ for more- examples of SPDX expressions.-- The version of the- `list of SPDX license identifiers <https://spdx.org/licenses/>`__- is a function of the :pkg-field:`cabal-version` value as defined- in the following table:-- +--------------------------+--------------------+- | Cabal specification | SPDX license list |- | version | version |- | | |- +==========================+====================+- | ``cabal-version: 2.2`` | ``3.0 2017-12-28`` |- +--------------------------+--------------------+- | ``cabal-version: 2.4`` | ``3.2 2018-07-10`` |- +--------------------------+--------------------+-- **Pre-SPDX Legacy Identifiers**-- The license identifier in the table below are defined for- ``cabal-version: 2.0`` and previous versions of the Cabal- specification.-- +--------------------------+-----------------+- | :pkg-field:`license` | Note |- | identifier | |- | | |- +==========================+=================+- | ``GPL`` | |- | ``GPL-2`` | |- | ``GPL-3`` | |- +--------------------------+-----------------+- | ``LGPL`` | |- | ``LGPL-2.1`` | |- | ``LGPL-3`` | |- +--------------------------+-----------------+- | ``AGPL`` | since 1.18 |- | ``AGPL-3`` | |- +--------------------------+-----------------+- | ``BSD2`` | since 1.20 |- +--------------------------+-----------------+- | ``BSD3`` | |- +--------------------------+-----------------+- | ``MIT`` | |- +--------------------------+-----------------+- | ``ISC`` | since 1.22 |- +--------------------------+-----------------+- | ``MPL-2.0`` | since 1.20 |- +--------------------------+-----------------+- | ``Apache`` | |- | ``Apache-2.0`` | |- +--------------------------+-----------------+- | ``PublicDomain`` | |- +--------------------------+-----------------+- | ``AllRightsReserved`` | |- +--------------------------+-----------------+- | ``OtherLicense`` | |- +--------------------------+-----------------+---.. pkg-field:: license-file: filename-- See :pkg-field:`license-files`.--.. pkg-field:: license-files: filename list- :since: 1.20-- The name of a file(s) containing the precise copyright license for- this package. The license file(s) will be installed with the- package.-- If you have multiple license files then use the :pkg-field:`license-files`- field instead of (or in addition to) the :pkg-field:`license-file` field.--.. pkg-field:: copyright: freeform-- The content of a copyright notice, typically the name of the holder- of the copyright on the package and the year(s) from which copyright- is claimed. For example::-- copyright: (c) 2006-2007 Joe Bloggs--.. pkg-field:: author: freeform-- The original author of the package.-- Remember that ``.cabal`` files are Unicode, using the UTF-8- encoding.--.. pkg-field:: maintainer: address-- The current maintainer or maintainers of the package. This is an- e-mail address to which users should send bug reports, feature- requests and patches.--.. pkg-field:: stability: freeform-- The stability level of the package, e.g. ``alpha``,- ``experimental``, ``provisional``, ``stable``.--.. pkg-field:: homepage: URL-- The package homepage.--.. pkg-field:: bug-reports: URL-- The URL where users should direct bug reports. This would normally- be either:-- - A ``mailto:`` URL, e.g. for a person or a mailing list.-- - An ``http:`` (or ``https:``) URL for an online bug tracking- system.-- For example Cabal itself uses a web-based bug tracking system-- ::-- bug-reports: https://github.com/haskell/cabal/issues--.. pkg-field:: package-url: URL-- The location of a source bundle for the package. The distribution- should be a Cabal package.--.. pkg-field:: synopsis: freeform-- A very short description of the package, for use in a table of- packages. This is your headline, so keep it short (one line) but as- informative as possible. Save space by not including the package- name or saying it's written in Haskell.--.. pkg-field:: description: freeform-- Description of the package. This may be several paragraphs, and- should be aimed at a Haskell programmer who has never heard of your- package before.-- For library packages, this field is used as prologue text by- :ref:`setup-haddock` and thus may contain the same markup as Haddock_- documentation comments.--.. pkg-field:: category: freeform-- A classification category for future use by the package catalogue- Hackage_. These categories have not- yet been specified, but the upper levels of the module hierarchy- make a good start.--.. pkg-field:: tested-with: compiler list-- A list of compilers and versions against which the package has been- tested (or at least built). The value of this field is not used by Cabal- and is rather intended as extra metadata for use by third party- tooling, such as e.g. CI tooling.-- Here's a typical usage example-- ::-- tested-with: GHC == 8.6.3, GHC == 8.4.4, GHC == 8.2.2, GHC == 8.0.2,- GHC == 7.10.3, GHC == 7.8.4, GHC == 7.6.3, GHC == 7.4.2-- which can (starting with Cabal 3.0) also be written using the more- concise set notation syntax-- ::-- tested-with: GHC == { 8.6.3, 8.4.4, 8.2.2, 8.0.2, 7.10.3, 7.8.4, 7.6.3, 7.4.2 }--.. pkg-field:: data-files: filename list-- A list of files to be installed for run-time use by the package.- This is useful for packages that use a large amount of static data,- such as tables of values or code templates. Cabal provides a way to- `find these files at run-time <#accessing-data-files-from-package-code>`_.-- A limited form of ``*`` wildcards in file names, for example- ``data-files: images/*.png`` matches all the ``.png`` files in the- ``images`` directory. ``data-files: audio/**/*.mp3`` matches all- the ``.mp3`` files in the ``audio`` directory, including- subdirectories.-- The specific limitations of this wildcard syntax are-- - ``*`` wildcards are only allowed in place of the file name, not- in the directory name or file extension. It must replace the- whole file name (e.g., ``*.html`` is allowed, but- ``chapter-*.html`` is not). If a wildcard is used, it must be- used with an extension, so ``data-files: data/*`` is not- allowed.-- - Prior to Cabal 2.4, when matching a wildcard plus extension, a- file's full extension must match exactly, so ``*.gz`` matches- ``foo.gz`` but not ``foo.tar.gz``. This restriction has been- lifted when ``cabal-version: 2.4`` or greater so that ``*.gz``- does match ``foo.tar.gz``-- - ``*`` wildcards will not match if the file name is empty (e.g.,- ``*.html`` will not match ``foo/.html``).-- - ``**`` wildcards can only appear as the final path component- before the file name (e.g., ``data/**/images/*.jpg`` is not- allowed). If a ``**`` wildcard is used, then the file name must- include a ``*`` wildcard (e.g., ``data/**/README.rst`` is not- allowed).-- - A wildcard that does not match any files is an error.-- The reason for providing only a very limited form of wildcard is to- concisely express the common case of a large number of related files- of the same file type without making it too easy to accidentally- include unwanted files.-- On efficiency: if you use ``**`` patterns, the directory tree will- be walked starting with the parent directory of the ``**``. If- that's the root of the project, this might include ``.git/``,- ``dist-newstyle/``, or other large directories! To avoid this- behaviour, put the files that wildcards will match against in- their own folder.-- ``**`` wildcards are available starting in Cabal 2.4.--.. pkg-field:: data-dir: directory-- The directory where Cabal looks for data files to install, relative- to the source directory. By default, Cabal will look in the source- directory itself.--.. pkg-field:: extra-source-files: filename list-- A list of additional files to be included in source distributions- built with :ref:`setup-sdist`. As with :pkg-field:`data-files` it can use- a limited form of ``*`` wildcards in file names.--.. pkg-field:: extra-doc-files: filename list- :since: 1.18-- A list of additional files to be included in source distributions,- and also copied to the html directory when Haddock documentation is- generated. As with :pkg-field:`data-files` it can use a limited form of- ``*`` wildcards in file names.--.. pkg-field:: extra-tmp-files: filename list-- A list of additional files or directories to be removed by- :ref:`setup-clean`. These would typically be additional files created by- additional hooks, such as the scheme described in the section on- `system-dependent parameters`_--Library-^^^^^^^--.. pkg-section:: library name- :synopsis: Library build information.-- Build information for libraries.-- Currently, there can only be one publicly exposed library in a- package, and its name is the same as package name set by global- :pkg-field:`name` field. In this case, the ``name`` argument to- the :pkg-section:`library` section must be omitted.-- Starting with Cabal 2.0, private internal sub-library components- can be defined by using setting the ``name`` field to a name- different from the current package's name; see section on- :ref:`Internal Libraries <sublibs>` for more information.--The library section should contain the following fields:--.. pkg-field:: exposed-modules: identifier list-- :required: if this package contains a library-- A list of modules added by this package.--.. pkg-field:: virtual-modules: identifier list- :since: 2.2-- A list of virtual modules provided by this package. Virtual modules- are modules without a source file. See for example the ``GHC.Prim``- module from the ``ghc-prim`` package. Modules listed here will not be- built, but still end up in the list of ``exposed-modules`` in the- installed package info when the package is registered in the package- database.--.. pkg-field:: exposed: boolean-- :default: ``True``-- Some Haskell compilers (notably GHC) support the notion of packages- being "exposed" or "hidden" which means the modules they provide can- be easily imported without always having to specify which package- they come from. However this only works effectively if the modules- provided by all exposed packages do not overlap (otherwise a module- import would be ambiguous).-- Almost all new libraries use hierarchical module names that do not- clash, so it is very uncommon to have to use this field. However it- may be necessary to set ``exposed: False`` for some old libraries- that use a flat module namespace or where it is known that the- exposed modules would clash with other common modules.--.. pkg-field:: visibility: visibilty specifiers-- :since 3.0-- :default: ``private`` for internal libraries. Cannot be set for public library.-- Cabal recognizes ``public`` and ``private`` here...-- Multiple public libraries...--.. pkg-field:: reexported-modules: exportlist- :since: 1.22-- Supported only in GHC 7.10 and later. A list of modules to- *reexport* from this package. The syntax of this field is- ``orig-pkg:Name as NewName`` to reexport module ``Name`` from- ``orig-pkg`` with the new name ``NewName``. We also support- abbreviated versions of the syntax: if you omit ``as NewName``,- we'll reexport without renaming; if you omit ``orig-pkg``, then we- will automatically figure out which package to reexport from, if- it's unambiguous.-- Reexported modules are useful for compatibility shims when a package- has been split into multiple packages, and they have the useful- property that if a package provides a module, and another package- reexports it under the same name, these are not considered a- conflict (as would be the case with a stub module.) They can also be- used to resolve name conflicts.--.. pkg-field:: signatures: signature list- :since: 2.0-- Supported only in GHC 8.2 and later. A list of `module signatures <https://downloads.haskell.org/~ghc/master/users-guide/separate_compilation.html#module-signatures>`__ required by this package.-- Module signatures are part of the Backpack_ extension to- the Haskell module system.-- Packages that do not export any modules and only export required signatures- are called "signature-only packages", and their signatures are subjected to- `signature thinning- <https://wiki.haskell.org/Module_signature#How_to_use_a_signature_package>`__.----The library section may also contain build information fields (see the-section on `build information`_).--.. _sublibs:--**Internal Libraries**--Cabal 2.0 and later support "internal libraries", which are extra named-libraries (as opposed to the usual unnamed library section). For-example, suppose that your test suite needs access to some internal-modules in your library, which you do not otherwise want to export. You-could put these modules in an internal library, which the main library-and the test suite :pkg-field:`build-depends` upon. Then your Cabal file might-look something like this:--::-- cabal-version: 2.0- name: foo- version: 0.1.0.0- license: BSD3- build-type: Simple-- library foo-internal- exposed-modules: Foo.Internal- -- NOTE: no explicit constraints on base needed- -- as they're inherited from the 'library' stanza- build-depends: base-- library- exposed-modules: Foo.Public- build-depends: foo-internal, base >= 4.3 && < 5-- test-suite test-foo- type: exitcode-stdio-1.0- main-is: test-foo.hs- -- NOTE: no constraints on 'foo-internal' as same-package- -- dependencies implicitly refer to the same package instance- build-depends: foo-internal, base--Internal libraries are also useful for packages that define multiple-executables, but do not define a publicly accessible library. Internal-libraries are only visible internally in the package (so they can only-be added to the :pkg-field:`build-depends` of same-package libraries,-executables, test suites, etc.) Internal libraries locally shadow any-packages which have the same name; consequently, don't name an internal-library with the same name as an external dependency if you need to be-able to refer to the external dependency in a-:pkg-field:`build-depends` declaration.--Shadowing can be used to vendor an external dependency into a package-and thus emulate *private dependencies*. Below is an example based on-a real-world use case:--::-- cabal-version: 2.2- name: haddock-library- version: 1.6.0-- library- build-depends:- , base ^>= 4.11.1.0- , bytestring ^>= 0.10.2.0- , containers ^>= 0.4.2.1 || ^>= 0.5.0.0- , transformers ^>= 0.5.0.0-- hs-source-dirs: src-- -- internal sub-lib- build-depends: attoparsec-- exposed-modules:- Documentation.Haddock-- library attoparsec- build-depends:- , base ^>= 4.11.1.0- , bytestring ^>= 0.10.2.0- , deepseq ^>= 1.4.0.0-- hs-source-dirs: vendor/attoparsec-0.13.1.0-- -- NB: haddock-library needs only small part of lib:attoparsec- -- internally, so we only bundle that subset here- exposed-modules:- Data.Attoparsec.ByteString- Data.Attoparsec.Combinator-- other-modules:- Data.Attoparsec.Internal-- ghc-options: -funbox-strict-fields -Wall -fwarn-tabs -O2---Opening an interpreter session-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--While developing a package, it is often useful to make its code-available inside an interpreter session. This can be done with the-``repl`` command:--.. code-block:: console-- $ cabal repl--The name comes from the acronym-`REPL <http://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop>`__,-which stands for "read-eval-print-loop". By default ``cabal repl`` loads-the first component in a package. If the package contains several named-components, the name can be given as an argument to ``repl``. The name-can be also optionally prefixed with the component's type for-disambiguation purposes. Example:--.. code-block:: console-- $ cabal repl foo- $ cabal repl exe:foo- $ cabal repl test:bar- $ cabal repl bench:baz--Freezing dependency versions-""""""""""""""""""""""""""""--If a package is built in several different environments, such as a-development environment, a staging environment and a production-environment, it may be necessary or desirable to ensure that the same-dependency versions are selected in each environment. This can be done-with the ``freeze`` command:--.. code-block:: console-- $ cabal freeze--The command writes the selected version for all dependencies to the-``cabal.config`` file. All environments which share this file will use-the dependency versions specified in it.--Generating dependency version bounds-""""""""""""""""""""""""""""""""""""--Cabal also has the ability to suggest dependency version bounds that-conform to `Package Versioning Policy`_, which is-a recommended versioning system for publicly released Cabal packages.-This is done by running the ``gen-bounds`` command:--.. code-block:: console-- $ cabal gen-bounds--For example, given the following dependencies specified in-:pkg-field:`build-depends`:--::-- build-depends:- foo == 0.5.2- bar == 1.1--``gen-bounds`` will suggest changing them to the following:--::-- build-depends:- foo >= 0.5.2 && < 0.6- bar >= 1.1 && < 1.2--Listing outdated dependency version bounds-""""""""""""""""""""""""""""""""""""""""""--Manually updating dependency version bounds in a ``.cabal`` file or a-freeze file can be tedious, especially when there's a lot of-dependencies. The ``cabal outdated`` command is designed to help with-that. It will print a list of packages for which there is a new-version on Hackage that is outside the version bound specified in the-``build-depends`` field. The ``outdated`` command can also be-configured to act on the freeze file (both old- and v2-style) and-ignore major (or all) version bumps on Hackage for a subset of-dependencies.--The following flags are supported by the ``outdated`` command:--``--freeze-file``- Read dependency version bounds from the freeze file (``cabal.config``)- instead of the package description file (``$PACKAGENAME.cabal``).- ``--v1-freeze-file`` is an alias for this flag starting in Cabal 2.4.-``--v2-freeze-file``- :since: 2.4-- Read dependency version bounds from the v2-style freeze file- (by default, ``cabal.project.freeze``) instead of the package- description file. ``--new-freeze-file`` is an alias for this flag- that can be used with pre-2.4 ``cabal``.-``--project-file`` *PROJECTFILE*- :since: 2.4-- Read dependendency version bounds from the v2-style freeze file- related to the named project file (i.e., ``$PROJECTFILE.freeze``)- instead of the package desctription file. If multiple ``--project-file``- flags are provided, only the final one is considered. This flag- must only be passed in when ``--new-freeze-file`` is present.-``--simple-output``- Print only the names of outdated dependencies, one per line.-``--exit-code``- Exit with a non-zero exit code when there are outdated dependencies.-``-q, --quiet``- Don't print any output. Implies ``-v0`` and ``--exit-code``.-``--ignore`` *PACKAGENAMES*- Don't warn about outdated dependency version bounds for the packages in this- list.-``--minor`` *[PACKAGENAMES]*- Ignore major version bumps for these packages. E.g. if there's a version 2.0- of a package ``pkg`` on Hackage and the freeze file specifies the constraint- ``pkg == 1.9``, ``cabal outdated --freeze --minor=pkg`` will only consider- the ``pkg`` outdated when there's a version of ``pkg`` on Hackage satisfying- ``pkg > 1.9 && < 2.0``. ``--minor`` can also be used without arguments, in- that case major version bumps are ignored for all packages.--Examples:--.. code-block:: console-- $ cd /some/package- $ cabal outdated- Outdated dependencies:- haskell-src-exts <1.17 (latest: 1.19.1)- language-javascript <0.6 (latest: 0.6.0.9)- unix ==2.7.2.0 (latest: 2.7.2.1)-- $ cabal outdated --simple-output- haskell-src-exts- language-javascript- unix-- $ cabal outdated --ignore=haskell-src-exts- Outdated dependencies:- language-javascript <0.6 (latest: 0.6.0.9)- unix ==2.7.2.0 (latest: 2.7.2.1)-- $ cabal outdated --ignore=haskell-src-exts,language-javascript,unix- All dependencies are up to date.-- $ cabal outdated --ignore=haskell-src-exts,language-javascript,unix -q- $ echo $?- 0-- $ cd /some/other/package- $ cabal outdated --freeze-file- Outdated dependencies:- HTTP ==4000.3.3 (latest: 4000.3.4)- HUnit ==1.3.1.1 (latest: 1.5.0.0)-- $ cabal outdated --freeze-file --ignore=HTTP --minor=HUnit- Outdated dependencies:- HUnit ==1.3.1.1 (latest: 1.3.1.2)---Executables-^^^^^^^^^^^--.. pkg-section:: executable name- :synopsis: Executable build info section.-- Executable sections (if present) describe executable programs contained- in the package and must have an argument after the section label, which- defines the name of the executable. This is a freeform argument but may- not contain spaces.--The executable may be described using the following fields, as well as-build information fields (see the section on `build information`_).--.. pkg-field:: main-is: filename (required)-- The name of the ``.hs`` or ``.lhs`` file containing the ``Main``- module. Note that it is the ``.hs`` filename that must be listed,- even if that file is generated using a preprocessor. The source file- must be relative to one of the directories listed in- :pkg-field:`hs-source-dirs`. Further, while the name of the file may- vary, the module itself must be named ``Main``.-- Starting with ``cabal-version: 1.18`` this field supports- specifying a C, C++, or objC source file as the main entry point.--.. pkg-field:: scope: token- :since: 2.0-- Whether the executable is ``public`` (default) or ``private``, i.e. meant to- be run by other programs rather than the user. Private executables are- installed into `$libexecdir/$libexecsubdir`.--Running executables-"""""""""""""""""""--You can have Cabal build and run your executables by using the ``run``-command:--.. code-block:: console-- $ cabal run EXECUTABLE [-- EXECUTABLE_FLAGS]--This command will configure, build and run the executable-``EXECUTABLE``. The double dash separator is required to distinguish-executable flags from ``run``'s own flags. If there is only one-executable defined in the whole package, the executable's name can be-omitted. See the output of ``cabal help run`` for a list of options you-can pass to ``cabal run``.--Test suites-^^^^^^^^^^^--.. pkg-section:: test-suite name- :synopsis: Test suite build information.-- Test suite sections (if present) describe package test suites and must- have an argument after the section label, which defines the name of the- test suite. This is a freeform argument, but may not contain spaces. It- should be unique among the names of the package's other test suites, the- package's executables, and the package itself. Using test suite sections- requires at least Cabal version 1.9.2.--The test suite may be described using the following fields, as well as-build information fields (see the section on `build information`_).--.. pkg-field:: type: interface (required)-- The interface type and version of the test suite. Cabal supports two- test suite interfaces, called ``exitcode-stdio-1.0`` and- ``detailed-0.9``. Each of these types may require or disallow other- fields as described below.--Test suites using the ``exitcode-stdio-1.0`` interface are executables-that indicate test failure with a non-zero exit code when run; they may-provide human-readable log information through the standard output and-error channels. The ``exitcode-stdio-1.0`` type requires the ``main-is``-field.--.. pkg-field:: main-is: filename- :synopsis: Module containing tests main function.-- :required: ``exitcode-stdio-1.0``- :disallowed: ``detailed-0.9``-- The name of the ``.hs`` or ``.lhs`` file containing the ``Main``- module. Note that it is the ``.hs`` filename that must be listed,- even if that file is generated using a preprocessor. The source file- must be relative to one of the directories listed in- :pkg-field:`hs-source-dirs`. This field is analogous to the ``main-is`` field- of an executable section.--Test suites using the ``detailed-0.9`` interface are modules exporting-the symbol ``tests :: IO [Test]``. The ``Test`` type is exported by the-module ``Distribution.TestSuite`` provided by Cabal. For more details,-see the example below.--The ``detailed-0.9`` interface allows Cabal and other test agents to-inspect a test suite's results case by case, producing detailed human--and machine-readable log files. The ``detailed-0.9`` interface requires-the :pkg-field:`test-module` field.--.. pkg-field:: test-module: identifier-- :required: ``detailed-0.9``- :disallowed: ``exitcode-stdio-1.0``-- The module exporting the ``tests`` symbol.--Example: Package using ``exitcode-stdio-1.0`` interface-"""""""""""""""""""""""""""""""""""""""""""""""""""""""--The example package description and executable source file below-demonstrate the use of the ``exitcode-stdio-1.0`` interface.--.. code-block:: cabal- :caption: foo.cabal-- Name: foo- Version: 1.0- License: BSD3- Cabal-Version: >= 1.9.2- Build-Type: Simple-- Test-Suite test-foo- type: exitcode-stdio-1.0- main-is: test-foo.hs- build-depends: base >= 4 && < 5--.. code-block:: haskell- :caption: test-foo.hs-- module Main where-- import System.Exit (exitFailure)-- main = do- putStrLn "This test always fails!"- exitFailure--Example: Package using ``detailed-0.9`` interface-"""""""""""""""""""""""""""""""""""""""""""""""""--The example package description and test module source file below-demonstrate the use of the ``detailed-0.9`` interface. The test module-also develops a simple implementation of the interface set by-``Distribution.TestSuite``, but in actual usage the implementation would-be provided by the library that provides the testing facility.--.. code-block:: cabal- :caption: bar.cabal-- Name: bar- Version: 1.0- License: BSD3- Cabal-Version: >= 1.9.2- Build-Type: Simple-- Test-Suite test-bar- type: detailed-0.9- test-module: Bar- build-depends: base >= 4 && < 5, Cabal >= 1.9.2 && < 2---.. code-block:: haskell- :caption: Bar.hs-- module Bar ( tests ) where-- import Distribution.TestSuite-- tests :: IO [Test]- tests = return [ Test succeeds, Test fails ]- where- succeeds = TestInstance- { run = return $ Finished Pass- , name = "succeeds"- , tags = []- , options = []- , setOption = \_ _ -> Right succeeds- }- fails = TestInstance- { run = return $ Finished $ Fail "Always fails!"- , name = "fails"- , tags = []- , options = []- , setOption = \_ _ -> Right fails- }--Running test suites-"""""""""""""""""""--You can have Cabal run your test suites using its built-in test runner:--::-- $ cabal configure --enable-tests- $ cabal build- $ cabal test--See the output of ``cabal help test`` for a list of options you can pass-to ``cabal test``.--Benchmarks-^^^^^^^^^^--.. pkg-section:: benchmark name- :since: 1.9.2- :synopsis: Benchmark build information.-- Benchmark sections (if present) describe benchmarks contained in the- package and must have an argument after the section label, which defines- the name of the benchmark. This is a freeform argument, but may not- contain spaces. It should be unique among the names of the package's- other benchmarks, the package's test suites, the package's executables,- and the package itself. Using benchmark sections requires at least Cabal- version 1.9.2.--The benchmark may be described using the following fields, as well as-build information fields (see the section on `build information`_).--.. pkg-field:: type: interface (required)-- The interface type and version of the benchmark. At the moment Cabal- only support one benchmark interface, called ``exitcode-stdio-1.0``.--Benchmarks using the ``exitcode-stdio-1.0`` interface are executables-that indicate failure to run the benchmark with a non-zero exit code-when run; they may provide human-readable information through the-standard output and error channels.--.. pkg-field:: main-is: filename-- :required: ``exitcode-stdio-1.0``-- The name of the ``.hs`` or ``.lhs`` file containing the ``Main``- module. Note that it is the ``.hs`` filename that must be listed,- even if that file is generated using a preprocessor. The source file- must be relative to one of the directories listed in- :pkg-field:`hs-source-dirs`. This field is analogous to the ``main-is``- field of an executable section. Further, while the name of the file may- vary, the module itself must be named ``Main``.--Example: Package using ``exitcode-stdio-1.0`` interface-"""""""""""""""""""""""""""""""""""""""""""""""""""""""--The example package description and executable source file below-demonstrate the use of the ``exitcode-stdio-1.0`` interface.--.. code-block:: cabal- :caption: foo.cabal- :name: foo-bench.cabal-- Name: foo- Version: 1.0- License: BSD3- Cabal-Version: >= 1.9.2- Build-Type: Simple-- Benchmark bench-foo- type: exitcode-stdio-1.0- main-is: bench-foo.hs- build-depends: base >= 4 && < 5, time >= 1.1 && < 1.7--.. code-block:: haskell- :caption: bench-foo.hs-- {-# LANGUAGE BangPatterns #-}- module Main where-- import Data.Time.Clock-- fib 0 = 1- fib 1 = 1- fib n = fib (n-1) + fib (n-2)-- main = do- start <- getCurrentTime- let !r = fib 20- end <- getCurrentTime- putStrLn $ "fib 20 took " ++ show (diffUTCTime end start)--Running benchmarks-""""""""""""""""""--You can have Cabal run your benchmark using its built-in benchmark-runner:--::-- $ cabal configure --enable-benchmarks- $ cabal build- $ cabal bench--See the output of ``cabal help bench`` for a list of options you can-pass to ``cabal bench``.--Foreign libraries-^^^^^^^^^^^^^^^^^--Foreign libraries are system libraries intended to be linked against-programs written in C or other "foreign" languages. They-come in two primary flavours: dynamic libraries (``.so`` files on Linux,-``.dylib`` files on OSX, ``.dll`` files on Windows, etc.) are linked against-executables when the executable is run (or even lazily during-execution), while static libraries (``.a`` files on Linux/OSX, ``.lib``-files on Windows) get linked against the executable at compile time.--Foreign libraries only work with GHC 7.8 and later.--A typical stanza for a foreign library looks like--::-- foreign-library myforeignlib- type: native-shared- lib-version-info: 6:3:2-- if os(Windows)- options: standalone- mod-def-file: MyForeignLib.def-- other-modules: MyForeignLib.SomeModule- MyForeignLib.SomeOtherModule- build-depends: base >=4.7 && <4.9- hs-source-dirs: src- c-sources: csrc/MyForeignLibWrapper.c- default-language: Haskell2010---.. pkg-section:: foreign-library name- :since: 2.0- :synopsis: Foriegn library build information.-- Build information for `foreign libraries`_.--.. pkg-field:: type: foreign library type-- Cabal recognizes ``native-static`` and ``native-shared`` here, although- we currently only support building `native-shared` libraries.--.. pkg-field:: options: foreign library option list-- Options for building the foreign library, typically specific to the- specified type of foreign library. Currently we only support- ``standalone`` here. A standalone dynamic library is one that does not- have any dependencies on other (Haskell) shared libraries; without- the ``standalone`` option the generated library would have dependencies- on the Haskell runtime library (``libHSrts``), the base library- (``libHSbase``), etc. Currently, ``standalone`` *must* be used on Windows- and *must not* be used on any other platform.--.. pkg-field:: mod-def-file: filename-- This option can only be used when creating dynamic Windows libraries- (that is, when using ``native-shared`` and the ``os`` is ``Windows``). If- used, it must be a path to a *module definition file*. The details of- module definition files are beyond the scope of this document; see the- `GHC <https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/win32-dlls.html>`_- manual for some details and some further pointers.--.. pkg-field:: lib-version-info: current:revision:age-- This field is currently only used on Linux.-- This field specifies a Libtool-style version-info field that sets- an appropriate ABI version for the foreign library. Note that the- three numbers specified in this field do not directly specify the- actual ABI version: ``6:3:2`` results in library version ``4.2.3``.-- With this field set, the SONAME of the library is set, and symlinks- are installed.-- How you should bump this field on an ABI change depends on the- breakage you introduce:-- - Programs using the previous version may use the new version as- drop-in replacement, and programs using the new version can also- work with the previous one. In other words, no recompiling nor- relinking is needed. In this case, bump ``revision`` only, don't- touch current nor age.- - Programs using the previous version may use the new version as- drop-in replacement, but programs using the new version may use- APIs not present in the previous one. In other words, a program- linking against the new version may fail with "unresolved- symbols" if linking against the old version at runtime: set- revision to 0, bump current and age.- - Programs may need to be changed, recompiled, and relinked in- order to use the new version. Bump current, set revision and age- to 0.-- Also refer to the Libtool documentation on the version-info field.--.. pkg-field:: lib-version-linux: version-- This field is only used on Linux.-- Specifies the library ABI version directly for foreign libraries- built on Linux: so specifying ``4.2.3`` causes a library- ``libfoo.so.4.2.3`` to be built with SONAME ``libfoo.so.4``, and- appropriate symlinks ``libfoo.so.4`` and ``libfoo.so`` to be- installed.--Note that typically foreign libraries should export a way to initialize-and shutdown the Haskell runtime. In the example above, this is done by-the ``csrc/MyForeignLibWrapper.c`` file, which might look something like--.. code-block:: c-- #include <stdlib.h>- #include "HsFFI.h"-- HsBool myForeignLibInit(void){- int argc = 2;- char *argv[] = { "+RTS", "-A32m", NULL };- char **pargv = argv;-- // Initialize Haskell runtime- hs_init(&argc, &pargv);-- // do any other initialization here and- // return false if there was a problem- return HS_BOOL_TRUE;- }-- void myForeignLibExit(void){- hs_exit();- }--With modern ghc regular libraries are installed in directories that contain-package keys. This isn't usually a problem because the package gets registered-in ghc's package DB and so we can figure out what the location of the library-is. Foreign libraries however don't get registered, which means that we'd have-to have a way of finding out where a platform library got installed (other than by-searching the ``lib/`` directory). Instead, we install foreign libraries in-``~/.cabal/lib``, much like we install executables in ``~/.cabal/bin``.--Build information-^^^^^^^^^^^^^^^^^-.. pkg-section:: None--The following fields may be optionally present in a library, executable,-test suite or benchmark section, and give information for the building-of the corresponding library or executable. See also the sections on-`system-dependent parameters`_ and `configurations`_ for a way to supply-system-dependent values for these fields.--.. pkg-field:: build-depends: library list-- Declares the *library* dependencies required to build the current- package component; see :pkg-field:`build-tool-depends` for- declaring build-time *tool* dependencies. External library- dependencies should be annotated with a version constraint.-- **Library Names**-- External libraries are identified by the package's name they're- provided by (currently a package can only publicly expose its- main library compeonent; in future, packages with multiple exposed- public library components will be supported and a syntax for- referring to public sub-libraries will be provided).-- In order to specify an intra-package dependency on an internal- library component you can use the unqualified name of the- component library component. Note that locally defined sub-library- names shadow external package names of the same name. See section on- :ref:`Internal Libraries <sublibs>` for examples and more information.-- **Version Constraints**-- Version constraints use the operators ``==, >=, >, <, <=`` and a- version number. Multiple constraints can be combined using ``&&`` or- ``||``. If no version constraint is specified, any version is- assumed to be acceptable. For example:-- ::-- library- build-depends:- base >= 2,- foo >= 1.2.3 && < 1.3,- bar-- Dependencies like ``foo >= 1.2.3 && < 1.3`` turn out to be very- common because it is recommended practise for package versions to- correspond to API versions (see PVP_).-- Since Cabal 1.6, there is a special wildcard syntax to help with- such ranges-- ::-- build-depends: foo ==1.2.*-- It is only syntactic sugar. It is exactly equivalent to- ``foo >= 1.2 && < 1.3``.-- .. Warning::-- A potential pitfall of the wildcard syntax is that the- constraint ``nats == 1.0.*`` doesn't match the release- ``nats-1`` because the version ``1`` is lexicographically less- than ``1.0``. This is not an issue with the caret-operator- ``^>=`` described below.-- Starting with Cabal 2.0, there's a new version operator to express- PVP_-style major upper bounds conveniently, and is inspired by similar- syntactic sugar found in other language ecosystems where it's often- called the "Caret" operator:-- ::-- build-depends:- foo ^>= 1.2.3.4,- bar ^>= 1-- This allows to assert the positive knowledge that this package is- *known* to be semantically compatible with the releases- ``foo-1.2.3.4`` and ``bar-1`` respectively. The information- encoded via such ``^>=``-assertions is used by the cabal solver to- infer version constraints describing semantically compatible- version ranges according to the PVP_ contract (see below).-- Another way to say this is that ``foo < 1.3`` expresses *negative*- information, i.e. "``foo-1.3`` or ``foo-1.4.2`` will *not* be- compatible"; whereas ``foo ^>= 1.2.3.4`` asserts the *positive*- information that "``foo-1.2.3.4`` is *known* to be compatible" and (in- the absence of additional information) according to the PVP_- contract we can (positively) infer right away that all versions- satisfying ``foo >= 1.2.3.4 && < 1.3`` will be compatible as well.-- .. Note::-- More generally, the PVP_ contract implies that we can safely- relax the lower bound to ``>= 1.2``, because if we know that- ``foo-1.2.3.4`` is semantically compatible, then so is- ``foo-1.2`` (if it typechecks). But we'd need to perform- additional static analysis (i.e. perform typechecking) in order- to know if our package in the role of an API consumer will- successfully typecheck against the dependency ``foo-1.2``. But- since we cannot do this analysis during constraint solving and- to keep things simple, we pragmatically use ``foo >= 1.2.3.4``- as the initially inferred approximation for the lower bound- resulting from the assertion ``foo ^>= 1.2.3.4``. If further- evidence becomes available that e.g. ``foo-1.2`` typechecks,- one can simply revise the dependency specification to include- the assertion ``foo ^>= 1.2``.-- The subtle but important difference in signaling allows tooling to- treat explicitly expressed ``<``-style constraints and inferred- (``^>=``-style) upper bounds differently. For instance,- :option:`--allow-newer`'s ``^``-modifier allows to relax only- ``^>=``-style bounds while leaving explicitly stated- ``<``-constraints unaffected.-- Ignoring the signaling intent, the default syntactic desugaring rules are-- - ``^>= x`` == ``>= x && < x.1``- - ``^>= x.y`` == ``>= x.y && < x.(y+1)``- - ``^>= x.y.z`` == ``>= x.y.z && < x.(y+1)``- - ``^>= x.y.z.u`` == ``>= x.y.z.u && < x.(y+1)``- - etc.-- .. Note::-- One might expected the desugaring to truncate all version- components below (and including) the patch-level, i.e.- ``^>= x.y.z.u`` == ``>= x.y.z && < x.(y+1)``,- as the major and minor version components alone are supposed to- uniquely identify the API according to the PVP_. However, by- designing ``^>=`` to be closer to the ``>=`` operator, we avoid- the potentially confusing effect of ``^>=`` being more liberal- than ``>=`` in the presence of patch-level versions.-- Consequently, the example declaration above is equivalent to-- ::-- build-depends:- foo >= 1.2.3.4 && < 1.3,- bar >= 1 && < 1.1-- .. Note::-- Prior to Cabal 1.8, ``build-depends`` specified in each- section were global to all sections. This was unintentional, but- some packages were written to depend on it, so if you need your- :pkg-field:`build-depends` to be local to each section, you must specify- at least ``Cabal-Version: >= 1.8`` in your ``.cabal`` file.-- .. Note::-- Cabal 1.20 experimentally supported module thinning and- renaming in ``build-depends``; however, this support has since been- removed and should not be used.-- Starting with Cabal 3.0, a set notation for the ``==`` and ``^>=`` operator- is available. For instance,-- ::-- tested-with: GHC == 8.6.3, GHC == 8.4.4, GHC == 8.2.2, GHC == 8.0.2,- GHC == 7.10.3, GHC == 7.8.4, GHC == 7.6.3, GHC == 7.4.2-- build-depends: network ^>= 2.6.3.6 || ^>= 2.7.0.2 || ^>= 2.8.0.0 || ^>= 3.0.1.0-- can be then written in a more convenient and concise form-- ::-- tested-with: GHC == { 8.6.3, 8.4.4, 8.2.2, 8.0.2, 7.10.3, 7.8.4, 7.6.3, 7.4.2 }-- build-depends: network ^>= { 2.6.3.6, 2.7.0.2, 2.8.0.0, 3.0.1.0 }---.. pkg-field:: other-modules: identifier list-- A list of modules used by the component but not exposed to users.- For a library component, these would be hidden modules of the- library. For an executable, these would be auxiliary modules to be- linked with the file named in the ``main-is`` field.-- .. Note::-- Every module in the package *must* be listed in one of- :pkg-field:`other-modules`, :pkg-field:`library:exposed-modules` or- :pkg-field:`executable:main-is` fields.--.. pkg-field:: hs-source-dir: directory list- :deprecated: 2.0- :removed: 3.0- :default: ``.``-- Root directories for the module hierarchy.-- Deprecated in favor of :pkg-field:`hs-source-dirs`.--.. pkg-field:: hs-source-dirs: directory list-- :default: ``.``-- Root directories for the module hierarchy.-- .. note::-- Components can share source directories but modules found there will be- recompiled even if other components already built them, i.e., if a- library and an executable share a source directory and the executable- depends on the library and imports its ``Foo`` module, ``Foo`` will be- compiled twice, once as part of the library and again for the executable.--.. pkg-field:: default-extensions: identifier list-- A list of Haskell extensions used by every module. These determine- corresponding compiler options enabled for all files. Extension- names are the constructors of the- `Extension <../release/cabal-latest/doc/API/Cabal/Language-Haskell-Extension.html#t:Extension>`__- type. For example, ``CPP`` specifies that Haskell source files are- to be preprocessed with a C preprocessor.--.. pkg-field:: other-extensions: identifier list-- A list of Haskell extensions used by some (but not necessarily all)- modules. From GHC version 6.6 onward, these may be specified by- placing a ``LANGUAGE`` pragma in the source files affected e.g.-- .. code-block:: haskell-- {-# LANGUAGE CPP, MultiParamTypeClasses #-}-- In Cabal-1.24 the dependency solver will use this and- :pkg-field:`default-extensions` information. Cabal prior to 1.24 will abort- compilation if the current compiler doesn't provide the extensions.-- If you use some extensions conditionally, using CPP or conditional- module lists, it is good to replicate the condition in- :pkg-field:`other-extensions` declarations:-- ::-- other-extensions: CPP- if impl(ghc >= 7.5)- other-extensions: PolyKinds-- You could also omit the conditionally used extensions, as they are- for information only, but it is recommended to replicate them in- :pkg-field:`other-extensions` declarations.--.. pkg-field:: extensions: identifier list- :deprecated: 1.12- :removed: 3.0-- Deprecated in favor of :pkg-field:`default-extensions`.--.. pkg-field:: build-tool-depends: package:executable list- :since: 2.0-- A list of Haskell executables needed to build this component. Executables are provided- during the whole duration of the component, so this field can be used for executables- needed during :pkg-section:`test-suite` as well.-- Each is specified by the package containing the executable and the name of the- executable itself, separated by a colon, and optionally followed by a version bound.-- All executables defined in the given Cabal file are termed as *internal* dependencies- as opposed to the rest which are *external* dependencies.-- Each of the two is handled differently:-- 1. External dependencies can (and should) contain a version bound like conventional- :pkg-field:`build-depends` dependencies.- 2. Internal depenedencies should not contain a version bound, as they will be always- resolved within the same configuration of the package in the build plan.- Specifically, version bounds that include the package's version will be warned for- being extraneous, and version bounds that exclude the package's version will raise- an error for being impossible to follow.-- For example (1) using a test-suite to make sure README.md Haskell snippets are tested using- `markdown-unlit <http://hackage.haskell.org/package/markdown-unlit>`__:-- ::-- build-tool-depends: markdown-unlit:markdown-unlit >= 0.5.0 && < 0.6-- For example (2) using a test-suite to test executable behaviour in the same package:-- ::-- build-tool-depends: mypackage:executable-- Cabal tries to make sure that all specified programs are atomically built and prepended- on the ``$PATH`` shell variable before building the component in question, but can only do- so for Nix-style builds. Specifically:-- a) For Nix-style local builds, both internal and external dependencies.- b) For old-style builds, only for internal dependencies [#old-style-build-tool-depends]_.- It's up to the user to provide needed executables in this case under `$PATH.`--- .. note::-- :pkg-field:`build-tool-depends` was added in Cabal 2.0, and it will- be ignored (with a warning) with old versions of Cabal. See- :pkg-field:`build-tools` for more information about backwards- compatibility.--.. pkg-field:: build-tools: program list- :deprecated: 2.0- :removed: 3.0-- Deprecated in favor of :pkg-field:`build-tool-depends`, but :ref:`see below for backwards compatibility information <buildtoolsbc>`.-- A list of Haskell programs needed to build this component.- Each may be followed by an optional version bound.- Confusingly, each program in the list either refer to one of three things:-- 1. Another executables in the same package (supported since Cabal 1.12)-- 2. Tool name contained in Cabal's :ref:`hard-coded set of common tools <buildtoolsmap>`-- 3. A pre-built executable that should already be on the ``PATH``- (supported since Cabal 2.0)-- These cases are listed in order of priority:- an executable in the package will override any of the hard-coded packages with the same name,- and a hard-coded package will override any executable on the ``PATH``.-- In the first two cases, the list entry is desugared into a :pkg-field:`build-tool-depends` entry.- In the first case, the entry is desugared into a :pkg-field:`build-tool-depends` entry by prefixing with ``$pkg:``.- In the second case, it is desugared by looking up the package and executable name in a hard-coded table.- In either case, the optional version bound is passed through unchanged.- Refer to the documentation for :pkg-field:`build-tool-depends` to understand the desugared field's meaning, along with restrictions on version bounds.-- .. _buildtoolsbc:-- **Backward Compatibility**-- Although this field is deprecated in favor of :pkg-field:`build-tool-depends`, there are some situations where you may prefer to use :pkg-field:`build-tools` in cases (1) and (2), as it is supported by more versions of Cabal.- In case (3), :pkg-field:`build-tool-depends` is better for backwards-compatibility, as it will be ignored by old versions of Cabal; if you add the executable to :pkg-field:`build-tools`, a setup script built against old Cabal will choke.- If an old version of Cabal is used, an end-user will have to manually arrange for the requested executable to be in your ``PATH``.-- .. _buildtoolsmap:-- **Set of Known Tool Names**-- Identifiers specified in :pkg-field:`build-tools` are desugared into their respective equivalent :pkg-field:`build-tool-depends` form according to the table below. Consequently, a legacy specification such as::-- build-tools: alex >= 3.2.1 && < 3.3, happy >= 1.19.5 && < 1.20-- is simply desugared into the equivalent specification::-- build-tool-depends: alex:alex >= 3.2.1 && < 3.3, happy:happy >= 1.19.5 && < 1.20-- +--------------------------+-----------------------------------+-----------------+- | :pkg-field:`build-tools` | desugared | Note |- | identifier | :pkg-field:`build-tool-depends` | |- | | identifier | |- +==========================+===================================+=================+- | ``alex`` | ``alex:alex`` | |- +--------------------------+-----------------------------------+-----------------+- | ``c2hs`` | ``c2hs:c2hs`` | |- +--------------------------+-----------------------------------+-----------------+- | ``cpphs`` | ``cpphs:cpphs`` | |- +--------------------------+-----------------------------------+-----------------+- | ``greencard`` | ``greencard:greencard`` | |- +--------------------------+-----------------------------------+-----------------+- | ``haddock`` | ``haddock:haddock`` | |- +--------------------------+-----------------------------------+-----------------+- | ``happy`` | ``happy:happy`` | |- +--------------------------+-----------------------------------+-----------------+- | ``hsc2hs`` | ``hsc2hs:hsc2hs`` | |- +--------------------------+-----------------------------------+-----------------+- | ``hscolour`` | ``hscolour:hscolour`` | |- +--------------------------+-----------------------------------+-----------------+- | ``hspec-discover`` | ``hspec-discover:hspec-discover`` | since Cabal 2.0 |- +--------------------------+-----------------------------------+-----------------+-- This built-in set can be programmatically extended via ``Custom`` setup scripts; this, however, is of limited use since the Cabal solver cannot access information injected by ``Custom`` setup scripts.--.. pkg-field:: buildable: boolean-- :default: ``True``-- Is the component buildable? Like some of the other fields below,- this field is more useful with the slightly more elaborate form of- the simple build infrastructure described in the section on- `system-dependent parameters`_.--.. pkg-field:: ghc-options: token list-- Additional options for GHC. You can often achieve the same effect- using the :pkg-field:`extensions` field, which is preferred.-- Options required only by one module may be specified by placing an- ``OPTIONS_GHC`` pragma in the source file affected.-- As with many other fields, whitespace can be escaped by using- Haskell string syntax. Example:- ``ghc-options: -Wcompat "-with-rtsopts=-T -I1" -Wall``.--.. pkg-field:: ghc-prof-options: token list-- Additional options for GHC when the package is built with profiling- enabled.-- Note that as of Cabal-1.24, the default profiling detail level- defaults to ``exported-functions`` for libraries and- ``toplevel-functions`` for executables. For GHC these correspond to- the flags ``-fprof-auto-exported`` and ``-fprof-auto-top``. Prior to- Cabal-1.24 the level defaulted to ``none``. These levels can be- adjusted by the person building the package with the- ``--profiling-detail`` and ``--library-profiling-detail`` flags.-- It is typically better for the person building the package to pick- the profiling detail level rather than for the package author. So- unless you have special needs it is probably better not to specify- any of the GHC ``-fprof-auto*`` flags here. However if you wish to- override the profiling detail level, you can do so using the- :pkg-field:`ghc-prof-options` field: use ``-fno-prof-auto`` or one of the- other ``-fprof-auto*`` flags.--.. pkg-field:: ghc-shared-options: token list-- Additional options for GHC when the package is built as shared- library. The options specified via this field are combined with the- ones specified via :pkg-field:`ghc-options`, and are passed to GHC during- both the compile and link phases.--.. pkg-field:: includes: filename list-- A list of header files to be included in any compilations via C.- This field applies to both header files that are already installed- on the system and to those coming with the package to be installed.- The former files should be found in absolute paths, while the latter- files should be found in paths relative to the top of the source- tree or relative to one of the directories listed in- :pkg-field:`include-dirs`.-- These files typically contain function prototypes for foreign- imports used by the package. This is in contrast to- :pkg-field:`install-includes`, which lists header files that are intended- to be exposed to other packages that transitively depend on this- library.--.. pkg-field:: install-includes: filename list-- A list of header files from this package to be installed into- ``$libdir/includes`` when the package is installed. Files listed in- :pkg-field:`install-includes` should be found in relative to the top of the- source tree or relative to one of the directories listed in- :pkg-field:`include-dirs`.-- :pkg-field:`install-includes` is typically used to name header files that- contain prototypes for foreign imports used in Haskell code in this- package, for which the C implementations are also provided with the- package. For example, here is a ``.cabal`` file for a hypothetical- ``bindings-clib`` package that bundles the C source code for ``clib``::-- include-dirs: cbits- c-sources: clib.c- install-includes: clib.h-- Now any package that depends (directly or transitively) on the- ``bindings-clib`` library can use ``clib.h``.-- Note that in order for files listed in :pkg-field:`install-includes` to be- usable when compiling the package itself, they need to be listed in- the :pkg-field:`includes` field as well.--.. pkg-field:: include-dirs: directory list-- A list of directories to search for header files, when preprocessing- with ``c2hs``, ``hsc2hs``, ``cpphs`` or the C preprocessor, and also- when compiling via C. Directories can be absolute paths (e.g., for- system directories) or paths that are relative to the top of the- source tree. Cabal looks in these directories when attempting to- locate files listed in :pkg-field:`includes` and- :pkg-field:`install-includes`.--.. pkg-field:: c-sources: filename list-- A list of C source files to be compiled and linked with the Haskell- files.--.. pkg-field:: cxx-sources: filename list- :since: 2.2-- A list of C++ source files to be compiled and linked with the Haskell- files. Useful for segregating C and C++ sources when supplying different- command-line arguments to the compiler via the :pkg-field:`cc-options`- and the :pkg-field:`cxx-options` fields. The files listed in the- :pkg-field:`cxx-sources` can reference files listed in the- :pkg-field:`c-sources` field and vice-versa. The object files will be linked- appropriately.--.. pkg-field:: asm-sources: filename list- :since: 3.0-- A list of assembly source files to be compiled and linked with the- Haskell files.--.. pkg-field:: cmm-sources: filename list- :since: 3.0-- A list of C-- source files to be compiled and linked with the Haskell- files.--.. pkg-field:: js-sources: filename list-- A list of JavaScript source files to be linked with the Haskell- files (only for JavaScript targets).--.. pkg-field:: extra-libraries: token list-- A list of extra libraries to link with.--.. pkg-field:: extra-ghci-libraries: token list-- A list of extra libraries to be used instead of 'extra-libraries'- when the package is loaded with GHCi.--.. pkg-field:: extra-bundled-libraries: token list- :since: 2.2-- A list of libraries that are supposed to be copied from the build- directory alongside the produced Haskell libraries. Note that you- are under the obligation to produce those libraries in the build- directory (e.g. via a custom setup). Libraries listed here will- be included when ``copy``-ing packages and be listed in the- ``hs-libraries`` of the package configuration in the package database.- Library names must either be prefixed with "HS" or "C" and corresponding- library file names must match:-- - Libraries with name "HS<library-name>":- - `libHS<library-name>.a`- - `libHS<library-name>-ghc<ghc-flavour><ghc-version>.<dyn-library-extension>*`- - Libraries with name "C<library-name>":- - `libC<library-name>.a`- - `lib<library-name>.<dyn-library-extension>*`--.. pkg-field:: extra-lib-dirs: directory list-- A list of directories to search for libraries.--.. pkg-field:: cc-options: token list-- Command-line arguments to be passed to the C compiler. Since the- arguments are compiler-dependent, this field is more useful with the- setup described in the section on `system-dependent parameters`_.--.. pkg-field:: cpp-options: token list-- Command-line arguments for pre-processing Haskell code. Applies to- Haskell source and other pre-processed Haskell source like .hsc- .chs. Does not apply to C code, that's what cc-options is for.--.. pkg-field:: cxx-options: token list- :since: 2.2-- Command-line arguments to be passed to the compiler when compiling- C++ code. The C++ sources to which these command-line arguments- should be applied can be specified with the :pkg-field:`cxx-sources`- field. Command-line options for C and C++ can be passed separately to- the compiler when compiling both C and C++ sources by segregating the C- and C++ sources with the :pkg-field:`c-sources` and- :pkg-field:`cxx-sources` fields respectively, and providing different- command-line arguments with the :pkg-field:`cc-options` and the- :pkg-field:`cxx-options` fields.--.. pkg-field:: cmm-options: token list- :since: 3.0-- Command-line arguments to be passed to the compiler when compiling- C-- code. See also :pkg-field:`cmm-sources`.--.. pkg-field:: asm-options: token list- :since: 3.0-- Command-line arguments to be passed to the assembler when compiling- assembler code. See also :pkg-field:`asm-sources`.--.. pkg-field:: ld-options: token list-- Command-line arguments to be passed to the linker. Since the- arguments are compiler-dependent, this field is more useful with the- setup described in the section on `system-dependent parameters`_.--.. pkg-field:: pkgconfig-depends: package list-- A list of- `pkg-config <http://www.freedesktop.org/wiki/Software/pkg-config/>`__- packages, needed to build this package. They can be annotated with- versions, e.g. ``gtk+-2.0 >= 2.10, cairo >= 1.0``. If no version- constraint is specified, any version is assumed to be acceptable.- Cabal uses ``pkg-config`` to find if the packages are available on- the system and to find the extra compilation and linker options- needed to use the packages.-- If you need to bind to a C library that supports ``pkg-config`` then- it is much preferable to use this field rather than hard code options- into the other fields. ``pkg-config --list-all`` will show you all- supported libraries. Depending on your system you may need to adjust- ``PKG_CONFIG_PATH``.--.. pkg-field:: frameworks: token list-- On Darwin/MacOS X, a list of frameworks to link to. See Apple's- developer documentation for more details on frameworks. This entry- is ignored on all other platforms.--.. pkg-field:: extra-frameworks-dirs: directory list- :since: 1.24-- On Darwin/MacOS X, a list of directories to search for frameworks.- This entry is ignored on all other platforms.--.. pkg-field:: mixins: mixin list- :since: 2.0-- Supported only in GHC 8.2 and later. A list of packages mentioned in the- :pkg-field:`build-depends` field, each optionally accompanied by a list of- module and module signature renamings.-- The simplest mixin syntax is simply the name of a package mentioned in the- :pkg-field:`build-depends` field. For example:-- ::-- library- build-depends:- foo ^>= 1.2.3- mixins:- foo-- But this doesn't have any effect. More interesting is to use the mixin- entry to rename one or more modules from the package, like this:-- ::-- library- mixins:- foo (Foo.Bar as AnotherFoo.Bar, Foo.Baz as AnotherFoo.Baz)-- Note that renaming a module like this will hide all the modules- that are not explicitly named.-- Modules can also be hidden:-- ::-- library:- mixins:- foo hiding (Foo.Bar)-- Hiding modules exposes everything that is not explicitly hidden.-- .. Note::-- The current version of Cabal suffers from an infelicity in how the- entries of :pkg-field:`mixins` are parsed: an entry will fail to parse- if the provided renaming clause has whitespace after the opening- parenthesis. This will be fixed in future versions of Cabal.-- See issues :issue:`5150`, :issue:`4864`, and :issue:`5293`.-- There can be multiple mixin entries for a given package, in effect creating- multiple copies of the dependency:-- ::-- library- mixins:- foo (Foo.Bar as AnotherFoo.Bar, Foo.Baz as AnotherFoo.Baz),- foo (Foo.Bar as YetAnotherFoo.Bar)-- The ``requires`` clause is used to rename the module signatures required by- a package:-- ::-- library- mixins:- foo (Foo.Bar as AnotherFoo.Bar) requires (Foo.SomeSig as AnotherFoo.SomeSig)-- Signature-only packages don't have any modules, so only the signatures can- be renamed, with the following syntax:-- ::-- library- mixins:- sigonly requires (SigOnly.SomeSig as AnotherSigOnly.SomeSig)-- See the :pkg-field:`library:signatures` field for more details.-- Mixin packages are part of the Backpack_ extension to the- Haskell module system.-- The matching of the module signatures required by a- :pkg-field:`build-depends` dependency with the implementation modules- present in another dependency is triggered by a coincidence of names. When- the names of the signature and of the implementation are already the same,- the matching is automatic. But when the names don't coincide, or we want to- instantiate a signature in two different ways, adding mixin entries that- perform renamings becomes necessary.-- .. Warning::-- Backpack_ has the limitation that implementation modules that instantiate- signatures required by a :pkg-field:`build-depends` dependency can't- reside in the same component that has the dependency. They must reside- in a different package dependency, or at least in a separate internal- library.--Configurations-^^^^^^^^^^^^^^--Library and executable sections may include conditional blocks, which-test for various system parameters and configuration flags. The flags-mechanism is rather generic, but most of the time a flag represents-certain feature, that can be switched on or off by the package user.-Here is an example package description file using configurations:--Example: A package containing a library and executable programs-"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""--::-- Name: Test1- Version: 0.0.1- Cabal-Version: >= 1.8- License: BSD3- Author: Jane Doe- Synopsis: Test package to test configurations- Category: Example- Build-Type: Simple-- Flag Debug- Description: Enable debug support- Default: False- Manual: True-- Flag WebFrontend- Description: Include API for web frontend.- Default: False- Manual: True-- Flag NewDirectory- description: Whether to build against @directory >= 1.2@- -- This is an automatic flag which the solver will be- -- assign automatically while searching for a solution-- Library- Build-Depends: base >= 4.2 && < 4.9- Exposed-Modules: Testing.Test1- Extensions: CPP-- GHC-Options: -Wall- if flag(Debug)- CPP-Options: -DDEBUG- if !os(windows)- CC-Options: "-DDEBUG"- else- CC-Options: "-DNDEBUG"-- if flag(WebFrontend)- Build-Depends: cgi >= 0.42 && < 0.44- Other-Modules: Testing.WebStuff- CPP-Options: -DWEBFRONTEND-- if flag(NewDirectory)- build-depends: directory >= 1.2 && < 1.4- Build-Depends: time >= 1.0 && < 1.9- else- build-depends: directory == 1.1.*- Build-Depends: old-time >= 1.0 && < 1.2-- Executable test1- Main-is: T1.hs- Other-Modules: Testing.Test1- Build-Depends: base >= 4.2 && < 4.9-- if flag(debug)- CC-Options: "-DDEBUG"- CPP-Options: -DDEBUG--Layout-""""""--Flags, conditionals, library and executable sections use layout to-indicate structure. This is very similar to the Haskell layout rule.-Entries in a section have to all be indented to the same level which-must be more than the section header. Tabs are not allowed to be used-for indentation.--As an alternative to using layout you can also use explicit braces-``{}``. In this case the indentation of entries in a section does not-matter, though different fields within a block must be on different-lines. Here is a bit of the above example again, using braces:--Example: Using explicit braces rather than indentation for layout-"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""--::-- Name: Test1- Version: 0.0.1- Cabal-Version: >= 1.8- License: BSD3- Author: Jane Doe- Synopsis: Test package to test configurations- Category: Example- Build-Type: Simple-- Flag Debug {- Description: Enable debug support- Default: False- Manual: True- }-- Library {- Build-Depends: base >= 4.2 && < 4.9- Exposed-Modules: Testing.Test1- Extensions: CPP- if flag(debug) {- CPP-Options: -DDEBUG- if !os(windows) {- CC-Options: "-DDEBUG"- } else {- CC-Options: "-DNDEBUG"- }- }- }--Configuration Flags-"""""""""""""""""""--.. pkg-section:: flag name- :synopsis: Flag declaration.-- Flag section declares a flag which can be used in `conditional blocks`_.-- Flag names are case-insensitive and must match ``[[:alnum:]_][[:alnum:]_-]*``- regular expression, or expressed as ABNF_:-- .. code-block:: abnf-- flag-name = (UALNUM / "_") *(UALNUM / "_" / "-")-- UALNUM = UALPHA / DIGIT- UALPHA = ... ; set of alphabetic Unicode code-points-- .. note::-- Hackage accepts ASCII-only flags, ``[a-zA-Z0-9_][a-zA-Z0-9_-]*`` regexp.--.. pkg-field:: description: freeform-- The description of this flag.--.. pkg-field:: default: boolean-- :default: ``True``-- The default value of this flag.-- .. note::-- This value may be `overridden in several- ways <installing-packages.html#controlling-flag-assignments>`__. The- rationale for having flags default to True is that users usually- want new features as soon as they are available. Flags representing- features that are not (yet) recommended for most users (such as- experimental features or debugging support) should therefore- explicitly override the default to False.--.. pkg-field:: manual: boolean-- :default: ``False``- :since: 1.6-- By default, Cabal will first try to satisfy dependencies with the- default flag value and then, if that is not possible, with the- negated value. However, if the flag is manual, then the default- value (which can be overridden by commandline flags) will be used.--Conditional Blocks-^^^^^^^^^^^^^^^^^^--Conditional blocks may appear anywhere inside a library or executable-section. They have to follow rather strict formatting rules. Conditional-blocks must always be of the shape--::-- if condition- property-descriptions-or-conditionals--or--::-- if condition- property-descriptions-or-conditionals- else- property-descriptions-or-conditionals--Note that the ``if`` and the condition have to be all on the same line.--Since Cabal 2.2 conditional blocks support ``elif`` construct.--::-- if condition1- property-descriptions-or-conditionals- elif condition2- property-descriptions-or-conditionals- else- property-descriptions-or-conditionals--Conditions-""""""""""--Conditions can be formed using boolean tests and the boolean operators-``||`` (disjunction / logical "or"), ``&&`` (conjunction / logical-"and"), or ``!`` (negation / logical "not"). The unary ``!`` takes-highest precedence, ``||`` takes lowest. Precedence levels may be-overridden through the use of parentheses. For example,-``os(darwin) && !arch(i386) || os(freebsd)`` is equivalent to-``(os(darwin) && !(arch(i386))) || os(freebsd)``.--The following tests are currently supported.--:samp:`os({name})`- Tests if the current operating system is *name*. The argument is- tested against ``System.Info.os`` on the target system. There is- unfortunately some disagreement between Haskell implementations- about the standard values of ``System.Info.os``. Cabal canonicalises- it so that in particular ``os(windows)`` works on all- implementations. If the canonicalised os names match, this test- evaluates to true, otherwise false. The match is case-insensitive.-:samp:`arch({name})`- Tests if the current architecture is *name*. The argument is matched- against ``System.Info.arch`` on the target system. If the arch names- match, this test evaluates to true, otherwise false. The match is- case-insensitive.-:samp:`impl({compiler})`- Tests for the configured Haskell implementation. An optional version- constraint may be specified (for example ``impl(ghc >= 6.6.1)``). If- the configured implementation is of the right type and matches the- version constraint, then this evaluates to true, otherwise false.- The match is case-insensitive.-- Note that including a version constraint in an ``impl`` test causes- it to check for two properties:-- - The current compiler has the specified name, and-- - The compiler's version satisfied the specified version constraint-- As a result, ``!impl(ghc >= x.y.z)`` is not entirely equivalent to- ``impl(ghc < x.y.z)``. The test ``!impl(ghc >= x.y.z)`` checks that:-- - The current compiler is not GHC, or-- - The version of GHC is earlier than version x.y.z.--:samp:`flag({name})`- Evaluates to the current assignment of the flag of the given name.- Flag names are case insensitive. Testing for flags that have not- been introduced with a flag section is an error.-``true``- Constant value true.-``false``- Constant value false.--Resolution of Conditions and Flags-""""""""""""""""""""""""""""""""""--If a package descriptions specifies configuration flags the package user-can `control these in several-ways <installing-packages.html#controlling-flag-assignments>`__. If the-user does not fix the value of a flag, Cabal will try to find a flag-assignment in the following way.--- For each flag specified, it will assign its default value, evaluate- all conditions with this flag assignment, and check if all- dependencies can be satisfied. If this check succeeded, the package- will be configured with those flag assignments.--- If dependencies were missing, the last flag (as by the order in which- the flags were introduced in the package description) is tried with- its alternative value and so on. This continues until either an- assignment is found where all dependencies can be satisfied, or all- possible flag assignments have been tried.--To put it another way, Cabal does a complete backtracking search to find-a satisfiable package configuration. It is only the dependencies-specified in the :pkg-field:`build-depends` field in conditional blocks that-determine if a particular flag assignment is satisfiable-(:pkg-field:`build-tools` are not considered). The order of the declaration and-the default value of the flags determines the search order. Flags-overridden on the command line fix the assignment of that flag, so no-backtracking will be tried for that flag.--If no suitable flag assignment could be found, the configuration phase-will fail and a list of missing dependencies will be printed. Note that-this resolution process is exponential in the worst case (i.e., in the-case where dependencies cannot be satisfied). There are some-optimizations applied internally, but the overall complexity remains-unchanged.--Meaning of field values when using conditionals-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--During the configuration phase, a flag assignment is chosen, all-conditionals are evaluated, and the package description is combined into-a flat package descriptions. If the same field both inside a conditional-and outside then they are combined using the following rules.--- Boolean fields are combined using conjunction (logical "and").--- List fields are combined by appending the inner items to the outer- items, for example-- ::-- other-extensions: CPP- if impl(ghc)- other-extensions: MultiParamTypeClasses-- when compiled using GHC will be combined to-- ::-- other-extensions: CPP, MultiParamTypeClasses-- Similarly, if two conditional sections appear at the same nesting- level, properties specified in the latter will come after properties- specified in the former.--- All other fields must not be specified in ambiguous ways. For example-- ::-- Main-is: Main.hs- if flag(useothermain)- Main-is: OtherMain.hs-- will lead to an error. Instead use-- ::-- if flag(useothermain)- Main-is: OtherMain.hs- else- Main-is: Main.hs--Common stanzas-^^^^^^^^^^^^^^--.. pkg-section:: common name- :since: 2.2- :synopsis: Common build info section--Starting with Cabal-2.2 it's possible to use common build info stanzas.--::-- common deps- build-depends: base ^>= 4.11- ghc-options: -Wall-- common test-deps- build-depends: tasty ^>= 0.12.0.1-- library- import: deps- exposed-modules: Foo-- test-suite tests- import: deps, test-deps- type: exitcode-stdio-1.0- main-is: Tests.hs- build-depends: foo--- You can use `build information`_ fields in common stanzas.--- Common stanzas must be defined before use.--- Common stanzas can import other common stanzas.--- You can import multiple stanzas at once. Stanza names must be separated by commas.--- ``import`` must be the first field in a section. Since Cabal 3.0 imports- are also allowed inside conditionals.--.. Note::-- The name `import` was chosen, because there is ``includes`` field.--Source Repositories-^^^^^^^^^^^^^^^^^^^--.. pkg-section:: source-repository- :since: 1.6--It is often useful to be able to specify a source revision control-repository for a package. Cabal lets you specifying this information in-a relatively structured form which enables other tools to interpret and-make effective use of the information. For example the information-should be sufficient for an automatic tool to checkout the sources.--Cabal supports specifying different information for various common-source control systems. Obviously not all automated tools will support-all source control systems.--Cabal supports specifying repositories for different use cases. By-declaring which case we mean automated tools can be more useful. There-are currently two kinds defined:--- The ``head`` kind refers to the latest development branch of the- package. This may be used for example to track activity of a project- or as an indication to outside developers what sources to get for- making new contributions.--- The ``this`` kind refers to the branch and tag of a repository that- contains the sources for this version or release of a package. For- most source control systems this involves specifying a tag, id or- hash of some form and perhaps a branch. The purpose is to be able to- reconstruct the sources corresponding to a particular package- version. This might be used to indicate what sources to get if- someone needs to fix a bug in an older branch that is no longer an- active head branch.--You can specify one kind or the other or both. As an example here are-the repositories for the Cabal library. Note that the ``this`` kind of-repository specifies a tag.--::-- source-repository head- type: darcs- location: http://darcs.haskell.org/cabal/-- source-repository this- type: darcs- location: http://darcs.haskell.org/cabal-branches/cabal-1.6/- tag: 1.6.1--The exact fields are as follows:--.. pkg-field:: type: token-- The name of the source control system used for this repository. The- currently recognised types are:-- - ``darcs``- - ``git``- - ``svn``- - ``cvs``- - ``mercurial`` (or alias ``hg``)- - ``bazaar`` (or alias ``bzr``)- - ``arch``- - ``monotone``-- This field is required.--.. pkg-field:: location: URL-- The location of the repository. The exact form of this field depends- on the repository type. For example:-- - for darcs: ``http://code.haskell.org/foo/``- - for git: ``git://github.com/foo/bar.git``- - for CVS: ``anoncvs@cvs.foo.org:/cvs``-- This field is required.--.. pkg-field:: module: token-- CVS requires a named module, as each CVS server can host multiple- named repositories.-- This field is required for the CVS repository type and should not be- used otherwise.--.. pkg-field:: branch: token-- Many source control systems support the notion of a branch, as a- distinct concept from having repositories in separate locations. For- example CVS, SVN and git use branches while for darcs uses different- locations for different branches. If you need to specify a branch to- identify a your repository then specify it in this field.-- This field is optional.--.. pkg-field:: tag: token-- A tag identifies a particular state of a source repository. The tag- can be used with a ``this`` repository kind to identify the state of- a repository corresponding to a particular package version or- release. The exact form of the tag depends on the repository type.-- This field is required for the ``this`` repository kind.--.. pkg-field:: subdir: directory-- Some projects put the sources for multiple packages under a single- source repository. This field lets you specify the relative path- from the root of the repository to the top directory for the- package, i.e. the directory containing the package's ``.cabal``- file.-- This field is optional. It default to empty which corresponds to the- root directory of the repository.--Downloading a package's source-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--The ``cabal get`` command allows to access a package's source code --either by unpacking a tarball downloaded from Hackage (the default) or-by checking out a working copy from the package's source repository.--::-- $ cabal get [FLAGS] PACKAGES--The ``get`` command supports the following options:--``-d --destdir`` *PATH*- Where to place the package source, defaults to (a subdirectory of)- the current directory.-``-s --source-repository`` *[head\|this\|...]*- Fork the package's source repository using the appropriate version- control system. The optional argument allows to choose a specific- repository kind.-``--index-state`` *[HEAD\|@<unix-timestamp>\|<iso8601-utc-timestamp>]*- Use source package index state as it existed at a previous time. Accepts- unix-timestamps (e.g. ``@1474732068``), ISO8601 UTC timestamps (e.g.- ``2016-09-24T17:47:48Z``), or ``HEAD`` (default).- This determines which package versions are available as well as which- ``.cabal`` file revision is selected (unless ``--pristine`` is used).-``--pristine``- Unpack the original pristine tarball, rather than updating the- ``.cabal`` file with the latest revision from the package archive.--Custom setup scripts-----------------------Since Cabal 1.24, custom ``Setup.hs`` are required to accurately track-their dependencies by declaring them in the ``.cabal`` file rather than-rely on dependencies being implicitly in scope. Please refer-`this article <https://www.well-typed.com/blog/2015/07/cabal-setup-deps/>`__-for more details.--As of Cabal library version 3.0, ``defaultMain*`` variants implement support-for response files. Custom ``Setup.hs`` files that do not use one of these-main functions are required to implement their own support, such as by using-``GHC.ResponseFile.getArgsWithResponseFiles``.--Declaring a ``custom-setup`` stanza also enables the generation of-``MIN_VERSION_package_(A,B,C)`` CPP macros for the Setup component.--.. pkg-section:: custom-setup- :synopsis: Custom Setup.hs build information.- :since: 1.24-- The optional :pkg-section:`custom-setup` stanza contains information needed- for the compilation of custom ``Setup.hs`` scripts,--::-- custom-setup- setup-depends:- base >= 4.5 && < 4.11,- Cabal >= 1.14 && < 1.25--.. pkg-field:: setup-depends: package list- :since: 1.24-- The dependencies needed to compile ``Setup.hs``. See the- :pkg-field:`build-depends` field for a description of the syntax expected by- this field.--Backward compatibility and ``custom-setup``-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--Versions prior to Cabal 1.24 don't recognise ``custom-setup`` stanzas,-and will behave agnostic to them (except for warning about an unknown-section). Consequently, versions prior to Cabal 1.24 can't ensure the-declared dependencies ``setup-depends`` are in scope, and instead-whatever is registered in the current package database environment-will become eligible (and resolved by the compiler) for the-``Setup.hs`` module.--The availability of the-``MIN_VERSION_package_(A,B,C)`` CPP macros-inside ``Setup.hs`` scripts depends on the condition that either--- a ``custom-setup`` section has been declared (or ``cabal v2-build`` is being- used which injects an implicit hard-coded ``custom-setup`` stanza if it's missing), or-- GHC 8.0 or later is used (which natively injects package version CPP macros)--Consequently, if you need to write backward compatible ``Setup.hs``-scripts using CPP, you should declare a ``custom-setup`` stanza and-use the pattern below:--.. code-block:: haskell-- {-# LANGUAGE CPP #-}- import Distribution.Simple-- #if defined(MIN_VERSION_Cabal)- -- version macros are available and can be used as usual- # if MIN_VERSION_Cabal(a,b,c)- -- code specific to lib:Cabal >= a.b.c- # else- -- code specific to lib:Cabal < a.b.c- # endif- #else- # warning Enabling heuristic fall-back. Please upgrade cabal-install to 1.24 or later if Setup.hs fails to compile.-- -- package version macros not available; except for exotic environments,- -- you can heuristically assume that lib:Cabal's version is correlated- -- with __GLASGOW_HASKELL__, and specifically since we can assume that- -- GHC < 8.0, we can assume that lib:Cabal is version 1.22 or older.- #endif-- main = ...--The simplified (heuristic) CPP pattern shown below is useful if all you need-is to distinguish ``Cabal < 2.0`` from ``Cabal >= 2.0``.--.. code-block:: haskell-- {-# LANGUAGE CPP #-}- import Distribution.Simple-- #if !defined(MIN_VERSION_Cabal)- # define MIN_VERSION_Cabal(a,b,c) 0- #endif-- #if MIN_VERSION_Cabal(2,0,0)- -- code for lib:Cabal >= 2.0- #else- -- code for lib:Cabal < 2.0- #endif-- main = ...----Autogenerated modules and includes-------------------------------------Modules that are built automatically at setup, created with a custom-setup script, must appear on :pkg-field:`other-modules` for the library,-executable, test-suite or benchmark stanzas or also on-:pkg-field:`library:exposed-modules` for libraries to be used, but are not-really on the package when distributed. This makes commands like sdist fail-because the file is not found.--These special modules must appear again on the :pkg-field:`autogen-modules`-field of the stanza that is using it, besides :pkg-field:`other-modules` or-:pkg-field:`library:exposed-modules`. With this there is no need to create-complex build hooks for this poweruser case.--.. pkg-field:: autogen-modules: module list- :since: 2.0-- .. todo:: document autogen-modules field--Right now :pkg-field:`executable:main-is` modules are not supported on-:pkg-field:`autogen-modules`.--::-- Library- default-language: Haskell2010- build-depends: base- exposed-modules:- MyLibrary- MyLibHelperModule- other-modules:- MyLibModule- autogen-modules:- MyLibHelperModule-- Executable Exe- default-language: Haskell2010- main-is: Dummy.hs- build-depends: base- other-modules:- MyExeModule- MyExeHelperModule- autogen-modules:- MyExeHelperModule--.. pkg-field:: autogen-includes: filename list- :since: 3.0-- A list of header files from this package which are autogenerated- (e.g. by a ``configure`` script). Autogenerated header files are not- packaged by ``sdist`` command.--Accessing data files from package code-----------------------------------------The placement on the target system of files listed in-the :pkg-field:`data-files` field varies between systems, and in some cases-one can even move packages around after installation (see `prefix-independence <installing-packages.html#prefix-independence>`__). To-enable packages to find these files in a portable way, Cabal generates a-module called :file:`Paths_{pkgname}` (with any hyphens in *pkgname*-replaced by underscores) during building, so that it may be imported by-modules of the package. This module defines a function--.. code-block:: haskell-- getDataFileName :: FilePath -> IO FilePath--If the argument is a filename listed in the :pkg-field:`data-files` field, the-result is the name of the corresponding file on the system on which the-program is running.--.. Note::-- If you decide to import the :file:`Paths_{pkgname}` module then it- *must* be listed in the :pkg-field:`other-modules` field just like any other- module in your package and on :pkg-field:`autogen-modules` as the file is- autogenerated.--The :file:`Paths_{pkgname}` module is not platform independent, as any-other autogenerated module, so it does not get included in the source-tarballs generated by ``sdist``.--The :file:`Paths_{pkgname}` module also includes some other useful-functions and values, which record the version of the package and some-other directories which the package has been configured to be installed-into (e.g. data files live in ``getDataDir``):--.. code-block:: haskell-- version :: Version-- getBinDir :: IO FilePath- getLibDir :: IO FilePath- getDynLibDir :: IO FilePath- getDataDir :: IO FilePath- getLibexecDir :: IO FilePath- getSysconfDir :: IO FilePath--The actual location of all these directories can be individually-overridden at runtime using environment variables of the form-``pkg_name_var``, where ``pkg_name`` is the name of the package with all-hyphens converted into underscores, and ``var`` is either ``bindir``,-``libdir``, ``dynlibdir``, ``datadir``, ``libexedir`` or ``sysconfdir``. For example,-the configured data directory for ``pretty-show`` is controlled with the-``pretty_show_datadir`` environment variable.--Accessing the package version-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--The aforementioned auto generated :file:`Paths_{pkgname}` module also-exports the constant ``version ::``-`Version <http://hackage.haskell.org/package/base/docs/Data-Version.html>`__-which is defined as the version of your package as specified in the-``version`` field.--System-dependent parameters------------------------------For some packages, especially those interfacing with C libraries,-implementation details and the build procedure depend on the build-environment. The ``build-type`` ``Configure`` can be used to handle many-such situations. In this case, ``Setup.hs`` should be:--.. code-block:: haskell-- import Distribution.Simple- main = defaultMainWithHooks autoconfUserHooks--Most packages, however, would probably do better using the ``Simple``-build type and `configurations`_.--The :pkg-field:`build-type` ``Configure`` differs from ``Simple`` in two ways:--- The package root directory must contain a shell script called- ``configure``. The configure step will run the script. This- ``configure`` script may be produced by- `autoconf <http://www.gnu.org/software/autoconf/>`__ or may be- hand-written. The ``configure`` script typically discovers- information about the system and records it for later steps, e.g. by- generating system-dependent header files for inclusion in C source- files and preprocessed Haskell source files. (Clearly this won't work- for Windows without MSYS or Cygwin: other ideas are needed.)--- If the package root directory contains a file called- *package*\ ``.buildinfo`` after the configuration step, subsequent- steps will read it to obtain additional settings for `build- information`_ fields,to be merged with the ones- given in the ``.cabal`` file. In particular, this file may be- generated by the ``configure`` script mentioned above, allowing these- settings to vary depending on the build environment.--The build information file should have the following structure:-- *buildinfo*-- ``executable:`` *name* *buildinfo*-- ``executable:`` *name* *buildinfo* ...--where each *buildinfo* consists of settings of fields listed in the-section on `build information`_. The first one (if-present) relates to the library, while each of the others relate to the-named executable. (The names must match the package description, but you-don't have to have entries for all of them.)--Neither of these files is required. If they are absent, this setup-script is equivalent to ``defaultMain``.--Example: Using autoconf-^^^^^^^^^^^^^^^^^^^^^^^--This example is for people familiar with the-`autoconf <http://www.gnu.org/software/autoconf/>`__ tools.--In the X11 package, the file ``configure.ac`` contains:--.. code-block:: shell-- AC_INIT([Haskell X11 package], [1.1], [libraries@haskell.org], [X11])-- # Safety check: Ensure that we are in the correct source directory.- AC_CONFIG_SRCDIR([X11.cabal])-- # Header file to place defines in- AC_CONFIG_HEADERS([include/HsX11Config.h])-- # Check for X11 include paths and libraries- AC_PATH_XTRA- AC_TRY_CPP([#include <X11/Xlib.h>],,[no_x=yes])-- # Build the package if we found X11 stuff- if test "$no_x" = yes- then BUILD_PACKAGE_BOOL=False- else BUILD_PACKAGE_BOOL=True- fi- AC_SUBST([BUILD_PACKAGE_BOOL])-- AC_CONFIG_FILES([X11.buildinfo])- AC_OUTPUT--Then the setup script will run the ``configure`` script, which checks-for the presence of the X11 libraries and substitutes for variables in-the file ``X11.buildinfo.in``:--::-- buildable: @BUILD_PACKAGE_BOOL@- cc-options: @X_CFLAGS@- ld-options: @X_LIBS@--This generates a file ``X11.buildinfo`` supplying the parameters needed-by later stages:--::-- buildable: True- cc-options: -I/usr/X11R6/include- ld-options: -L/usr/X11R6/lib--The ``configure`` script also generates a header file-``include/HsX11Config.h`` containing C preprocessor defines recording-the results of various tests. This file may be included by C source-files and preprocessed Haskell source files in the package.--.. Note::-- Packages using these features will also need to list additional- files such as ``configure``, templates for ``.buildinfo`` files, files- named only in ``.buildinfo`` files, header files and so on in the- :pkg-field:`extra-source-files` field to ensure that they are included in- source distributions. They should also list files and directories generated- by ``configure`` in the :pkg-field:`extra-tmp-files` field to ensure that- they are removed by ``setup clean``.--Quite often the files generated by ``configure`` need to be listed-somewhere in the package description (for example, in the-:pkg-field:`install-includes` field). However, we usually don't want generated-files to be included in the source tarball. The solution is again-provided by the ``.buildinfo`` file. In the above example, the following-line should be added to ``X11.buildinfo``:--::-- install-includes: HsX11Config.h--In this way, the generated ``HsX11Config.h`` file won't be included in-the source tarball in addition to ``HsX11Config.h.in``, but it will be-copied to the right location during the install process. Packages that-use custom ``Setup.hs`` scripts can update the necessary fields-programmatically instead of using the ``.buildinfo`` file.--Conditional compilation--------------------------Sometimes you want to write code that works with more than one version-of a dependency. You can specify a range of versions for the dependency-in the :pkg-field:`build-depends`, but how do you then write the code that can-use different versions of the API?--Haskell lets you preprocess your code using the C preprocessor (either-the real C preprocessor, or ``cpphs``). To enable this, add-``extensions: CPP`` to your package description. When using CPP, Cabal-provides some pre-defined macros to let you test the version of-dependent packages; for example, suppose your package works with either-version 3 or version 4 of the ``base`` package, you could select the-available version in your Haskell modules like this:--.. code-block:: cpp-- #if MIN_VERSION_base(4,0,0)- ... code that works with base-4 ...- #else- ... code that works with base-3 ...- #endif--In general, Cabal supplies a macro-``MIN_VERSION_``\ *``package``*\ ``_(A,B,C)`` for each package depended-on via :pkg-field:`build-depends`. This macro is true if the actual version of-the package in use is greater than or equal to ``A.B.C`` (using the-conventional ordering on version numbers, which is lexicographic on the-sequence, but numeric on each component, so for example 1.2.0 is greater-than 1.0.3).--Since version 1.20, the ``MIN_TOOL_VERSION_``\ *``tool``*-family of macros lets you condition on the version of build tools used to-build the program (e.g. ``hsc2hs``).--Since version 1.24, the macro ``CURRENT_COMPONENT_ID``, which-expands to the string of the component identifier that uniquely-identifies this component. Furthermore, if the package is a library,-the macro ``CURRENT_PACKAGE_KEY`` records the identifier that was passed-to GHC for use in symbols and for type equality.--Since version 2.0, the macro ``CURRENT_PACKAGE_VERSION`` expands-to the string version number of the current package.--Cabal places the definitions of these macros into an-automatically-generated header file, which is included when-preprocessing Haskell source code by passing options to the C-preprocessor.--Cabal also allows to detect when the source code is being used for-generating documentation. The ``__HADDOCK_VERSION__`` macro is defined-only when compiling via Haddock_-instead of a normal Haskell compiler. The value of the-``__HADDOCK_VERSION__`` macro is defined as ``A*1000 + B*10 + C``, where-``A.B.C`` is the Haddock version. This can be useful for working around-bugs in Haddock or generating prettier documentation in some special-cases.--More complex packages------------------------For packages that don't fit the simple schemes described above, you have-a few options:--- By using the :pkg-field:`build-type` ``Custom``, you can supply your own- ``Setup.hs`` file, and customize the simple build infrastructure- using *hooks*. These allow you to perform additional actions before- and after each command is run, and also to specify additional- preprocessors. A typical ``Setup.hs`` may look like this:-- .. code-block:: haskell-- import Distribution.Simple- main = defaultMainWithHooks simpleUserHooks { postHaddock = posthaddock }-- posthaddock args flags desc info = ....-- See ``UserHooks`` in- `Distribution.Simple <../release/cabal-latest/doc/API/Cabal/Distribution-Simple.html>`__- for the details, but note that this interface is experimental, and- likely to change in future releases.-- If you use a custom ``Setup.hs`` file you should strongly consider- adding a :pkg-section:`custom-setup` stanza with a- :pkg-field:`custom-setup:setup-depends` field to ensure that your setup- script does not break with future dependency versions.--- You could delegate all the work to ``make``, though this is unlikely- to be very portable. Cabal supports this with the :pkg-field:`build-type`- ``Make`` and a trivial setup library- `Distribution.Make <../release/cabal-latest/doc/API/Cabal/Distribution-Make.html>`__,- which simply parses the command line arguments and invokes ``make``.- Here ``Setup.hs`` should look like this:-- .. code-block:: haskell-- import Distribution.Make- main = defaultMain-- The root directory of the package should contain a ``configure``- script, and, after that has run, a ``Makefile`` with a default target- that builds the package, plus targets ``install``, ``register``,- ``unregister``, ``clean``, ``dist`` and ``docs``. Some options to- commands are passed through as follows:-- - The ``--with-hc-pkg``, ``--prefix``, ``--bindir``, ``--libdir``,- ``--dynlibdir``, ``--datadir``, ``--libexecdir`` and ``--sysconfdir`` options to- the ``configure`` command are passed on to the ``configure``- script. In addition the value of the ``--with-compiler`` option is- passed in a ``--with-hc`` option and all options specified with- ``--configure-option=`` are passed on.-- - The ``--destdir`` option to the ``copy`` command becomes a setting- of a ``destdir`` variable on the invocation of ``make copy``. The- supplied ``Makefile`` should provide a ``copy`` target, which will- probably look like this:-- .. code-block:: make-- copy :- $(MAKE) install prefix=$(destdir)/$(prefix) \- bindir=$(destdir)/$(bindir) \- libdir=$(destdir)/$(libdir) \- dynlibdir=$(destdir)/$(dynlibdir) \- datadir=$(destdir)/$(datadir) \- libexecdir=$(destdir)/$(libexecdir) \- sysconfdir=$(destdir)/$(sysconfdir) \--- Finally, with the :pkg-field:`build-type` ``Custom``, you can also write your- own setup script from scratch. It must conform to the interface- described in the section on `building and installing- packages <installing-packages.html>`__, and you may use the Cabal- library for all or part of the work. One option is to copy the source- of ``Distribution.Simple``, and alter it for your needs. Good luck.---.. include:: references.inc--.. rubric:: Footnotes--.. [#old-style-build-tool-depends]-- Some packages (ab)use :pkg-field:`build-depends` on old-style builds, but this has a few major drawbacks:-- - using Nix-style builds it's considered an error if you depend on a exe-only package via build-depends: the solver will refuse it.- - it may or may not place the executable on ``$PATH``.- - it does not ensure the correct version of the package is installed, so you might end up overwriting versions with each other.+.. TIP::+ If this is your first time using `cabal` you should check out the `Getting Started guide <getting-started.html>`__.++Let's assume we have created a project directory and already have a+Haskell module or two.++Every project needs a name, we'll call this example "proglet".++.. highlight:: console++::++ $ cd proglet/+ $ ls+ Proglet.hs++It is assumed that (apart from external dependencies) all the files that+make up a package live under a common project root directory. This+simple example has all the project files in one directory, but most+packages will use one or more subdirectories.++To turn this into a Cabal package we need two extra files in the+project's root directory:++- ``proglet.cabal``: containing package metadata and build information.++- ``Setup.hs``: usually containing a few standardized lines of code,+ but can be customized if necessary.++We can create both files manually or we can use ``cabal init`` to create+them for us.++Using "cabal init"+------------------++The ``cabal init --interactive`` command is interactive. If we answer+"no" to using the "sensible defaults" it asks a number of questions.++::++ $ cabal init --interactive+ Should I generate a simple project with sensible defaults? [default: y] n+ What does the package build:+ 1) Executable+ 2) Library+ 3) Library and Executable+ Your choice?+ ...++One of the important questions is whether the package contains a library+and/or an executable. Libraries are collections of Haskell modules that+can be re-used by other Haskell libraries and programs, while executables+are standalone programs.++For the moment these are the only choices. For more complex packages+(e.g. a library and multiple executables or test suites) the ``.cabal``+file can be edited afterwards.++After you make your selection (executable; library; or: library+and executable) cabal asks us a number of questions starting with+which version of the cabal specification to use, our package's name+(for example, "proglet"), and our package's version.++It also asks questions about various other bits of package metadata. For+a package that you never intend to distribute to others, these fields+can be left blank.++Finally, ``cabal init --interactive`` creates the initial ``proglet.cabal``+and ``Setup.hs`` files, and depending on your choice of license, a+``LICENSE`` file as well.++::++ Generating LICENSE...+ Generating Setup.hs...+ Generating proglet.cabal...++ You may want to edit the .cabal file and add a Description field.++At this stage the ``proglet.cabal`` is not quite complete and before you+are able to build the package you will need to edit the file and add+some build information about the library or executable.++Editing the .cabal file+-----------------------++.. highlight:: cabal++Load up the ``.cabal`` file in a text editor. The first part of the+``.cabal`` file has the package metadata and towards the end of the file+you will find the :pkg-section:`executable` or :pkg-section:`library` section.++You will see that the fields that have yet to be filled in are commented+out. Cabal files use "``--``" Haskell-style comment syntax. (Note that+comments are only allowed on lines on their own. Trailing comments on+other lines are not allowed because they could be confused with program+options.)++If you selected earlier to create a library package then your ``.cabal``+file will have a section that looks like this:++::++ library+ exposed-modules: Proglet+ -- other-modules:+ -- build-depends:++Alternatively, if you selected an executable then there will be a+section like:++::++ executable proglet+ -- main-is:+ -- other-modules:+ -- build-depends:++The build information fields listed (but commented out) are just the few+most important and common fields. There are many others that are covered+later in this chapter.++Most of the build information fields are the same between libraries and+executables. The difference is that libraries have a number of "exposed"+modules that make up the public interface of the library, while+executables have a file containing a ``Main`` module.++The name of a library always matches the name of the package, so it is+not specified in the library section. Executables often follow the name+of the package too, but this is not required and the name is given+explicitly.++Modules included in the package+-------------------------------++For a library, ``cabal init`` looks in the project directory for files+that look like Haskell modules and adds all the modules to the+:pkg-field:`library:exposed-modules` field. For modules that do not form part+of your package's public interface, you can move those modules to the+:pkg-field:`other-modules` field. Either way, all modules in the library need+to be listed.++For an executable, ``cabal init`` does not try to guess which file+contains your program's ``Main`` module. You will need to fill in the+:pkg-field:`executable:main-is` field with the file name of your program's+``Main`` module (including ``.hs`` or ``.lhs`` extension). Other modules+included in the executable should be listed in the :pkg-field:`other-modules`+field.++Modules imported from other packages+------------------------------------++While your library or executable may include a number of modules, it+almost certainly also imports a number of external modules from the+standard libraries or other pre-packaged libraries. (These other+libraries are of course just Cabal packages that contain a library.)++You have to list all of the library packages that your library or+executable imports modules from. Or to put it another way: you have to+list all the other packages that your package depends on.++For example, suppose the example ``Proglet`` module imports the module+``Data.Map``. The ``Data.Map`` module comes from the ``containers``+package, so we must list it:++::++ library+ exposed-modules: Proglet+ other-modules:+ build-depends: containers, base == 4.*++In addition, almost every package also depends on the ``base`` library+package because it exports the standard ``Prelude`` module plus other+basic modules like ``Data.List``.++You will notice that we have listed ``base == 4.*``. This gives a+constraint on the version of the base package that our package will work+with. The most common kinds of constraints are:++- ``pkgname >= n``+- ``pkgname ^>= n`` (since Cabal 2.0)+- ``pkgname >= n && < m``+- ``pkgname == n.*`` (since Cabal 1.6)++The last is just shorthand, for example ``base == 4.*`` means exactly+the same thing as ``base >= 4 && < 5``. Please refer to the documentation+on the :pkg-field:`build-depends` field for more information.++Also, you can factor out shared ``build-depends`` (and other fields such+as ``ghc-options``) into a ``common`` stanza which you can ``import`` in+your libraries and executable sections. For example:++::++ common shared-properties+ default-language: Haskell2010+ build-depends:+ base == 4.*+ ghc-options:+ -Wall++ library+ import: shared-properties+ exposed-modules:+ Proglet++Note that the ``import`` **must** be the first thing in the stanza. For more+information see the :ref:`common-stanzas` section.++Building the package+--------------------++For simple packages that's it! We can now try configuring and building+the package:++.. code-block:: console++ $ cabal configure+ $ cabal build++Assuming those two steps worked then you can also install the package:++.. code-block:: console++ $ cabal install++For libraries this makes them available for use in GHCi or to be used by+other packages. For executables it installs the program so that you can+run it (though you may first need to adjust your system's ``$PATH``).++Next steps+----------++What we have covered so far should be enough for very simple packages+that you use on your own system.++The next few sections cover more details needed for more complex+packages and details needed for distributing packages to other people.++The previous chapter covers building and installing packages -- your own+packages or ones developed by other people.++Package concepts+================++Before diving into the details of writing packages it helps to+understand a bit about packages in the Haskell world and the particular+approach that Cabal takes.++The point of packages+---------------------++Packages are a mechanism for organising and distributing code. Packages+are particularly suited for "programming in the large", that is building+big systems by using and re-using code written by different people at+different times.++People organise code into packages based on functionality and+dependencies. Social factors are also important: most packages have a+single author, or a relatively small team of authors.++Packages are also used for distribution: the idea is that a package can+be created in one place and be moved to a different computer and be+usable in that different environment. There are a surprising number of+details that have to be got right for this to work, and a good package+system helps to simplify this process and make it reliable.++Packages come in two main flavours: libraries of reusable code, and+complete programs. Libraries present a code interface, an API, while+programs can be run directly. In the Haskell world, library packages+expose a set of Haskell modules as their public interface. Cabal+packages can contain a library or executables or both.++Some programming languages have packages as a builtin language concept.+For example in Java, a package provides a local namespace for types and+other definitions. In the Haskell world, packages are not a part of the+language itself. Haskell programs consist of a number of modules, and+packages just provide a way to partition the modules into sets of+related functionality. Thus the choice of module names in Haskell is+still important, even when using packages.++Package names and versions+--------------------------++All packages have a name, e.g. "HUnit". Package names are assumed to be+unique. Cabal package names may contain letters, numbers and hyphens,+but not spaces and may also not contain a hyphened section consisting of+only numbers. The namespace for Cabal packages is flat, not+hierarchical.++Packages also have a version, e.g "1.1". This matches the typical way in+which packages are developed. Strictly speaking, each version of a+package is independent, but usually they are very similar. Cabal package+versions follow the conventional numeric style, consisting of a sequence+of digits such as "1.0.1" or "2.0". There are a range of common+conventions for "versioning" packages, that is giving some meaning to+the version number in terms of changes in the package, such as+e.g. `SemVer <http://semver.org>`__; however, for packages intended to be+distributed via Hackage Haskell's `Package Versioning Policy <https://pvp.haskell.org/>`_ applies+(see also the `PVP/SemVer FAQ section <https://pvp.haskell.org/faq/#semver>`__).++The combination of package name and version is called the *package ID*+and is written with a hyphen to separate the name and version, e.g.+"HUnit-1.1".++For Cabal packages, the combination of the package name and version+*uniquely* identifies each package. Or to put it another way: two+packages with the same name and version are considered to *be* the same.++Strictly speaking, the package ID only identifies each Cabal *source*+package; the same Cabal source package can be configured and built in+different ways. There is a separate installed package ID that uniquely+identifies each installed package instance. Most of the time however,+users need not be aware of this detail.++Kinds of package: Cabal vs GHC vs system+----------------------------------------++It can be slightly confusing at first because there are various+different notions of package floating around. Fortunately the details+are not very complicated.++Cabal packages+ Cabal packages are really source packages. That is they contain+ Haskell (and sometimes C) source code.++ Cabal packages can be compiled to produce GHC packages. They can+ also be translated into operating system packages.++GHC packages+ This is GHC's view on packages. GHC only cares about library+ packages, not executables. Library packages have to be registered+ with GHC for them to be available in GHCi or to be used when+ compiling other programs or packages.++ The low-level tool ``ghc-pkg`` is used to register GHC packages and+ to get information on what packages are currently registered.++ You never need to make GHC packages manually. When you build and+ install a Cabal package containing a library then it gets registered+ with GHC automatically.++ Haskell implementations other than GHC have essentially the same+ concept of registered packages. For the most part, Cabal hides the+ slight differences.++Operating system packages+ On operating systems like Linux and Mac OS X, the system has a+ specific notion of a package and there are tools for installing and+ managing packages.++ The Cabal package format is designed to allow Cabal packages to be+ translated, mostly-automatically, into operating system packages.+ They are usually translated 1:1, that is a single Cabal package+ becomes a single system package.++ It is also possible to make Windows installers from Cabal packages,+ though this is typically done for a program together with all of its+ library dependencies, rather than packaging each library separately.++Unit of distribution+--------------------++The Cabal package is the unit of distribution. What this means is that+each Cabal package can be distributed on its own in source or binary+form. Of course there may be dependencies between packages, but there is+usually a degree of flexibility in which versions of packages can work+together so distributing them independently makes sense.++It is perhaps easiest to see what being "the unit of distribution"+means by contrast to an alternative approach. Many projects are made up+of several interdependent packages and during development these might+all be kept under one common directory tree and be built and tested+together. When it comes to distribution however, rather than+distributing them all together in a single tarball, it is required that+they each be distributed independently in their own tarballs.++Cabal's approach is to say that if you can specify a dependency on a+package then that package should be able to be distributed+independently. Or to put it the other way round, if you want to+distribute it as a single unit, then it should be a single package.++Explicit dependencies and automatic package management+------------------------------------------------------++Cabal takes the approach that all packages dependencies are specified+explicitly and specified in a declarative way. The point is to enable+automatic package management. This means tools like ``cabal`` can+resolve dependencies and install a package plus all of its dependencies+automatically. Alternatively, it is possible to mechanically (or mostly+mechanically) translate Cabal packages into system packages and let the+system package manager install dependencies automatically.++It is important to track dependencies accurately so that packages can+reliably be moved from one system to another system and still be able to+build it there. Cabal is therefore relatively strict about specifying+dependencies. For example Cabal's default build system will not even let+code build if it tries to import a module from a package that isn't+listed in the ``.cabal`` file, even if that package is actually+installed. This helps to ensure that there are no "untracked+dependencies" that could cause the code to fail to build on some other+system.++The explicit dependency approach is in contrast to the traditional+"./configure" approach where instead of specifying dependencies+declaratively, the ``./configure`` script checks if the dependencies are+present on the system. Some manual work is required to transform a+``./configure`` based package into a Linux distribution package (or+similar). This conversion work is usually done by people other than the+package author(s). The practical effect of this is that only the most+popular packages will benefit from automatic package management.+Instead, Cabal forces the original author to specify the dependencies+but the advantage is that every package can benefit from automatic+package management.++The "./configure" approach tends to encourage packages that adapt+themselves to the environment in which they are built, for example by+disabling optional features so that they can continue to work when a+particular dependency is not available. This approach makes sense in a+world where installing additional dependencies is a tiresome manual+process and so minimising dependencies is important. The automatic+package management view is that packages should just declare what they+need and the package manager will take responsibility for ensuring that+all the dependencies are installed.++Sometimes of course optional features and optional dependencies do make+sense. Cabal packages can have optional features and varying+dependencies. These conditional dependencies are still specified in a+declarative way however and remain compatible with automatic package+management. The need to remain compatible with automatic package+management means that Cabal's conditional dependencies system is a bit+less flexible than with the "./configure" approach.++.. note::+ `GNU autoconf places restrictions on paths, including the+ path that the user builds a package from.+ <https://www.gnu.org/software/autoconf/manual/autoconf.html#File-System-Conventions>`_+ Package authors using ``build-type: configure`` should be aware of+ these restrictions; because users may be unexpectedly constrained and+ face mysterious errors, it is recommended that ``build-type: configure``+ is only used where strictly necessary.++Portability+-----------++One of the purposes of Cabal is to make it easier to build packages on+different platforms (operating systems and CPU architectures), with+different compiler versions and indeed even with different Haskell+implementations. (Yes, there are Haskell implementations other than+GHC!)++Cabal provides abstractions of features present in different Haskell+implementations and wherever possible it is best to take advantage of+these to increase portability. Where necessary however it is possible to+use specific features of specific implementations.++For example a package author can list in the package's ``.cabal`` what+language extensions the code uses. This allows Cabal to figure out if+the language extension is supported by the Haskell implementation that+the user picks. Additionally, certain language extensions such as+Template Haskell require special handling from the build system and by+listing the extension it provides the build system with enough+information to do the right thing.++Another similar example is linking with foreign libraries. Rather than+specifying GHC flags directly, the package author can list the libraries+that are needed and the build system will take care of using the right+flags for the compiler. Additionally this makes it easier for tools to+discover what system C libraries a package needs, which is useful for+tracking dependencies on system libraries (e.g. when translating into+Linux distribution packages).++In fact both of these examples fall into the category of explicitly+specifying dependencies. Not all dependencies are other Cabal packages.+Foreign libraries are clearly another kind of dependency. It's also+possible to think of language extensions as dependencies: the package+depends on a Haskell implementation that supports all those extensions.++Where compiler-specific options are needed however, there is an "escape+hatch" available. The developer can specify implementation-specific+options and more generally there is a configuration mechanism to+customise many aspects of how a package is built depending on the+Haskell implementation, the operating system, computer architecture and+user-specified configuration flags.
cabal/Cabal/doc/file-format-changelog.rst view
@@ -19,11 +19,26 @@ versions of the ``Cabal`` library denote unreleased development branches which have no stability guarantee. -``cabal-version: 3.2``+``cabal-version: 3.4`` ---------------------- -* Nothing yet +* License fields use identifiers from SPDX License List version+ ``3.9 2020-05-15``++* Dependencies to sublibraries have to be specified explicitly,+ even for current package.+ This way you can have an internal library with the same+ name as some external dependency.++* Remove ``-any`` and ``-none`` syntax for version ranges+ Use ``>=0`` and ``<0`` respectively.++* :pkg-field:`default-language` is optional.+ The Default value is to use the compiler's default language.++* :pkg-field:`mixins` field allow specifying a sublibrary.+ ``cabal-version: 3.0`` ---------------------- @@ -40,7 +55,7 @@ * Remove deprecated ``hs-source-dir``, :pkg-field:`extensions` and :pkg-field:`build-tools` fields. -* Common stanzas are now allowed also in the beginnning of conditional+* Common stanzas are now allowed also in the beginning of conditional sections. In other words, the following is valid ::@@ -52,7 +67,7 @@ import foo-deps * Allow redundant leading or trailing commas in package fields with- optional commas, such as :pkg-field:`exposed-modules`+ optional commas, such as :pkg-field:`library:exposed-modules` * Require fields with optional commas to consistently omit or place commas between elements.@@ -75,11 +90,11 @@ which are autogenerated (e.g. by a ``configure`` script). * New :pkg-field:`asm-sources` and :pkg-field:`asm-options` fields- added for suppporting bundled foreign routines implemented in+ added for supporting bundled foreign routines implemented in assembler. * New :pkg-field:`cmm-sources` and :pkg-field:`cmm-options` fields- added for suppporting bundled foreign primops implemented in+ added for supporting bundled foreign primops implemented in C--. ``cabal-version: 2.4``
+ cabal/Cabal/doc/getting-started.rst view
@@ -0,0 +1,169 @@+Getting Started with Haskell and Cabal+======================================++Installing the Haskell toolchain+--------------------------------++To install the Haskell toolchain follow the `ghcup instructions+<https://www.haskell.org/ghcup/>`__ if you're using Linux or Mac, or follow+`this guide <https://hub.zhox.com/posts/introducing-haskell-dev/>`__ if you're+using Windows.+++Creating a new application+--------------------------++Let's start by creating a simple Haskell application from scratch where we'll+learn about a Haskell package's directory structure, how to run the executable,+and how to add external dependencies.+++Initializing the application+^^^^^^^^^^^^^^^^^^^^^^^^^^^^++Start by creating a ``myfirstapp`` directory to hold the project files, these+instructions work in unix shells and PowerShell (if you're on Windows).++.. code-block:: console++ $ mkdir myfirstapp+ $ cd myfirstapp++Once you have an empty directory we can initialize our package:++.. code-block:: console++ $ cabal init --cabal-version=2.4 --license=NONE -p myfirstapp++This will generate the following files:++.. code-block:: console++ $ ls+ CHANGELOG.md+ Main.hs+ myfirstapp.cabal+ Setup.hs+++``Main.hs`` is where your package's code lives. By default ``cabal init``+creates an executable with the same name as the package ``myfirstapp`` in this+case, you can instruct ``cabal init`` to generate just a library (with+``--lib``) or both a library and executable with (``--libandexe``); for the full+set of options see ``cabal init --help``.++``myfirstapp.cabal`` is Cabal's metadata file which describes your package and+its dependencies. We'll be updating this file in a little bit when we add an+external dependency to our package.+++Running the application+^^^^^^^^^^^^^^^^^^^^^^^++As mentioned above, ``cabal init`` with no arguments generates a package with a+single executable that prints ``"Hello, Haskell!"`` to the terminal. To run the+executable enter the following command:++``cabal run :myfirstapp``++You should see the following output in the terminal:++.. code-block:: console++ $ cabal run :myfirstapp+ ...+ Hello, Haskell!++.. note:: The ``:`` prefix in ``:myfirstapp`` signifies that the+ ``myfirstapp`` target is part of the current package.++Notice that we didn't need to run a `build` command before ``cabal run``, this+is because ``cabal run`` first determines if the code needs to be re-built+before running the executable. If you just want to build a target you can do so+with ``cabal build``:++``cabal build :myfirstapp``+++Adding dependencies+^^^^^^^^^^^^^^^^^^^++Next we'll add an external dependency to our application. `Hackage+<https://hackage.haskell.org/>`__ is the Haskell community's central `package`+archive of open source software.++In our application, we'll use a package called `haskell-say+<https://hackage.haskell.org/package/haskell-say>`__ to print text to the+terminal with some embellishment.++.. TIP::+ If you installed ``cabal`` a while ago but haven't used it recently you may+ need to update the package index, you can do this by running ``cabal+ update``.++In our ``myfirstapp.cabal`` file we'll update the ``build-depends`` attribute of+the ``executable myfirstapp`` section to include ``haskell-say``:++.. code-block:: cabal++ executable myfirstapp+ main-is: Main.hs+ build-depends:+ base >=4.11 && <4.12,+ haskell-say ^>=1.0.0.0++.. NOTE::+ ``^>=1.0.0.0`` means use version 1.0.0.0 of the library or any more recent+ minor release with the same major version.++Next we'll update ``Main.hs`` to use the ``HaskellSay`` library:++.. code-block:: haskell++ module Main where++ import HaskellSay (haskellSay)++ main :: IO ()+ main =+ haskellSay "Hello, Haskell! You're using a function from another package!"++``import HaskellSay (haskellSay)`` brings the ``haskellSay`` function from the+module named ``HaskellSay`` into scope. The ``HaskellSay`` module is defined in+the ``haskell-say`` packages that we added a dependency on above.++Now you can build and re-run your code to see the new output:++.. code-block:: console++ $ cabal run+ ________________________________________________________+ / \+ | Hello, Haskell! You're using a function from another |+ | package! |+ \____ _____________________________________________/+ \ /+ \ /+ \/+ _____ _____+ \ \ \ \+ \ \ \ \+ \ \ \ \+ \ \ \ \ \-----------|+ \ \ \ \ \ |+ \ \ \ \ \---------|+ / / / \+ / / / \ \-------|+ / / / ^ \ \ |+ / / / / \ \ \ ----|+ / / / / \ \+ /____/ /____/ \____\+++What Next?+----------++Now that you know how to set up a simple Haskell package using Cabal, check out+some of thee resources on the Haskell website's `documentation page+<https://www.haskell.org/documentation/>`__ or read more about packages and+Cabal on the `introduction <intro.html>`__ page.
cabal/Cabal/doc/hcar/Cabal-201604.tex view
@@ -94,7 +94,7 @@ \item Further work on nix-style local builds, perhaps making that code path the default. \item Enabling Hackage Security by default.-\item Native suport for+\item Native support for \href{https://github.com/haskell/cabal/pull/2540}{``foreign libraries''}: Haskell libraries that are intended to be used by non-Haskell code. \item New Parsec-based parser for \texttt{.cabal} files.
cabal/Cabal/doc/hcar/Cabal-201611.tex view
@@ -22,7 +22,7 @@ \href{https://mail.haskell.org/pipermail/cabal-devel/2016-December/010384.html}{new point releases} of Cabal/\texttt{cabal-install} from the 1.24 branch. Among other things, Cabal 1.24.2.0 includes a-\href{https://ghc.haskell.org/trac/ghc/ticket/12479}{fix} necessary to+\href{https://gitlab.haskell.org/ghc/ghc/-/issues/12479}{fix} necessary to make soon-to-be-released GHC 8.0.2 work on macOS Sierra. Almost 1500 commits were made to the \texttt{master} branch by
cabal/Cabal/doc/index.rst view
@@ -6,10 +6,16 @@ :maxdepth: 2 :numbered: + getting-started intro config-and-install concepts-and-development- bugs-and-stability nix-local-build-overview- nix-integration+ cabal-commands+ cabal-package+ cabal-project+ setup-commands file-format-changelog+ buildinfo-fields-reference+ bugs-and-stability+ nix-integration
cabal/Cabal/doc/installing-packages.rst view
@@ -41,1738 +41,207 @@ You can also use ``cabal user-config update`` to migrate configuration files created by older versions of ``cabal``. -Repository specification---------------------------An important part of the configuration is the specification of the-repository. When ``cabal`` creates a default config file, it configures-the repository to be the central Hackage server:--::-- repository hackage.haskell.org- url: http://hackage.haskell.org/--The name of the repository is given on the first line, and can be-anything; packages downloaded from this repository will be cached under-``~/.cabal/packages/hackage.haskell.org`` (or whatever name you specify;-you can change the prefix by changing the value of-``remote-repo-cache``). If you want, you can configure multiple-repositories, and ``cabal`` will combine them and be able to download-packages from any of them.--Using secure repositories-^^^^^^^^^^^^^^^^^^^^^^^^^--For repositories that support the TUF security infrastructure (this-includes Hackage), you can enable secure access to the repository by-specifying:--::-- repository hackage.haskell.org- url: http://hackage.haskell.org/- secure: True- root-keys: <root-key-IDs>- key-threshold: <key-threshold>--The ``<root-key-IDs>`` and ``<key-threshold>`` values are used for-bootstrapping. As part of the TUF infrastructure the repository will-contain a file ``root.json`` (for instance,-http://hackage.haskell.org/root.json) which the client needs to do-verification. However, how can ``cabal`` verify the ``root.json`` file-*itself*? This is known as bootstrapping: if you specify a list of root-key IDs and a corresponding threshold, ``cabal`` will verify that the-downloaded ``root.json`` file has been signed with at least-``<key-threshold>`` keys from your set of ``<root-key-IDs>``.--You can, but are not recommended to, omit these two fields. In that case-``cabal`` will download the ``root.json`` field and use it without-verification. Although this bootstrapping step is then unsafe, all-subsequent access is secure (provided that the downloaded ``root.json``-was not tempered with). Of course, adding ``root-keys`` and-``key-threshold`` to your repository specification only shifts the-problem, because now you somehow need to make sure that the key IDs you-received were the right ones. How that is done is however outside the-scope of ``cabal`` proper.--More information about the security infrastructure can be found at-https://github.com/well-typed/hackage-security.--Legacy repositories-^^^^^^^^^^^^^^^^^^^--Currently ``cabal`` supports two kinds of “legacy” repositories. The-first is specified using--::-- remote-repo: hackage.haskell.org:http://hackage.haskell.org/packages/archive--This is just syntactic sugar for--::-- repository hackage.haskell.org- url: hackage.haskell.org:http://hackage.haskell.org/packages/archive--although, in (and only in) the specific case of Hackage, the URL-``http://hackage.haskell.org/packages/archive`` will be silently-translated to ``http://hackage.haskell.org/``.--The second kind of legacy repositories are so-called “local”-repositories:--::-- local-repo: my-local-repo:/path/to/local/repo--This can be used to access repositories on the local file system.-However, the layout of these local repositories is different from the-layout of remote repositories, and usage of these local repositories is-deprecated.--Secure local repositories-^^^^^^^^^^^^^^^^^^^^^^^^^--If you want to use repositories on your local file system, it is-recommended instead to use a *secure* local repository:--::-- repository my-local-repo- url: file:/path/to/local/repo- secure: True- root-keys: <root-key-IDs>- key-threshold: <key-threshold>--The layout of these secure local repos matches the layout of remote-repositories exactly; the :hackage-pkg:`hackage-repo-tool`-can be used to create and manage such repositories.--.. _installing-packages:--Building and installing packages-================================--.. highlight:: console--After you've unpacked a Cabal package, you can build it by moving into-the root directory of the package and running the ``cabal`` tool there:--::-- $ cabal [command] [option...]--The *command* argument selects a particular step in the build/install-process.--You can also get a summary of the command syntax with--::-- $ cabal help--Alternatively, you can also use the ``Setup.hs`` or ``Setup.lhs``-script:--::-- $ runhaskell Setup.hs [command] [option...]--For the summary of the command syntax, run:--::-- $ cabal help--or--::-- $ runhaskell Setup.hs --help--Building and installing a system package-------------------------------------------::-- $ runhaskell Setup.hs configure --ghc- $ runhaskell Setup.hs build- $ runhaskell Setup.hs install--The first line readies the system to build the tool using GHC; for-example, it checks that GHC exists on the system. The second line-performs the actual building, while the last both copies the build-results to some permanent place and registers the package with GHC.--Building and installing a user package-----------------------------------------::-- $ runhaskell Setup.hs configure --user- $ runhaskell Setup.hs build- $ runhaskell Setup.hs install--The package is installed under the user's home directory and is-registered in the user's package database (:option:`setup configure --user`).--Installing packages from Hackage-----------------------------------The ``cabal`` tool also can download, configure, build and install a-Hackage_ package and all of its-dependencies in a single step. To do this, run:--::-- $ cabal install [PACKAGE...]--To browse the list of available packages, visit the-Hackage_ web site.--Developing with sandboxes----------------------------By default, any dependencies of the package are installed into the-global or user package databases (e.g. using-``cabal install --only-dependencies``). If you're building several-different packages that have incompatible dependencies, this can cause-the build to fail. One way to avoid this problem is to build each-package in an isolated environment ("sandbox"), with a sandbox-local-package database. Because sandboxes are per-project, inconsistent-dependencies can be simply disallowed.--For more on sandboxes, see also `this-article <http://coldwa.st/e/blog/2013-08-20-Cabal-sandbox.html>`__.--Sandboxes: basic usage-^^^^^^^^^^^^^^^^^^^^^^--To initialise a fresh sandbox in the current directory, run-``cabal sandbox init``. All subsequent commands (such as ``build`` and-``install``) from this point will use the sandbox.--::-- $ cd /path/to/my/haskell/library- $ cabal sandbox init # Initialise the sandbox- $ cabal install --only-dependencies # Install dependencies into the sandbox- $ cabal build # Build your package inside the sandbox--It can be useful to make a source package available for installation in-the sandbox - for example, if your package depends on a patched or an-unreleased version of a library. This can be done with the-``cabal sandbox add-source`` command - think of it as "local Hackage_".-If an add-source dependency is later modified, it is reinstalled automatically.--::-- $ cabal sandbox add-source /my/patched/library # Add a new add-source dependency- $ cabal install --dependencies-only # Install it into the sandbox- $ cabal build # Build the local package- $ $EDITOR /my/patched/library/Source.hs # Modify the add-source dependency- $ cabal build # Modified dependency is automatically reinstalled--Normally, the sandbox settings (such as optimisation level) are-inherited from the main Cabal config file (``$HOME/cabal/config``).-Sometimes, though, you need to change some settings specifically for a-single sandbox. You can do this by creating a ``cabal.config`` file in-the same directory with your ``cabal.sandbox.config`` (which was created-by ``sandbox init``). This file has the same syntax as the main Cabal-config file.--::-- $ cat cabal.config- documentation: True- constraints: foo == 1.0, bar >= 2.0, baz- $ cabal build # Uses settings from the cabal.config file--When you have decided that you no longer want to build your package-inside a sandbox, just delete it:--::-- $ cabal sandbox delete # Built-in command- $ rm -rf .cabal-sandbox cabal.sandbox.config # Alternative manual method--Sandboxes: advanced usage-^^^^^^^^^^^^^^^^^^^^^^^^^--The default behaviour of the ``add-source`` command is to track-modifications done to the added dependency and reinstall the sandbox-copy of the package when needed. Sometimes this is not desirable: in-these cases you can use ``add-source --snapshot``, which disables the-change tracking. In addition to ``add-source``, there are also-``list-sources`` and ``delete-source`` commands.--Sometimes one wants to share a single sandbox between multiple packages.-This can be easily done with the ``--sandbox`` option:--::-- $ mkdir -p /path/to/shared-sandbox- $ cd /path/to/shared-sandbox- $ cabal sandbox init --sandbox .- $ cd /path/to/package-a- $ cabal sandbox init --sandbox /path/to/shared-sandbox- $ cd /path/to/package-b- $ cabal sandbox init --sandbox /path/to/shared-sandbox--Note that ``cabal sandbox init --sandbox .`` puts all sandbox files into-the current directory. By default, ``cabal sandbox init`` initialises a-new sandbox in a newly-created subdirectory of the current working-directory (``./.cabal-sandbox``).--Using multiple different compiler versions simultaneously is also-supported, via the ``-w`` option:--::-- $ cabal sandbox init- $ cabal install --only-dependencies -w /path/to/ghc-1 # Install dependencies for both compilers- $ cabal install --only-dependencies -w /path/to/ghc-2- $ cabal configure -w /path/to/ghc-1 # Build with the first compiler- $ cabal build- $ cabal configure -w /path/to/ghc-2 # Build with the second compiler- $ cabal build--It can be occasionally useful to run the compiler-specific package-manager tool (e.g. ``ghc-pkg``) on the sandbox package DB directly-(for example, you may need to unregister some packages). The-``cabal sandbox hc-pkg`` command is a convenient wrapper that runs the-compiler-specific package manager tool with the arguments:--::-- $ cabal -v sandbox hc-pkg list- Using a sandbox located at /path/to/.cabal-sandbox- 'ghc-pkg' '--global' '--no-user-package-conf'- '--package-conf=/path/to/.cabal-sandbox/i386-linux-ghc-7.4.2-packages.conf.d'- 'list'- [...]--The ``--require-sandbox`` option makes all sandbox-aware commands-(``install``/``build``/etc.) exit with error if there is no sandbox-present. This makes it harder to accidentally modify the user package-database. The option can be also turned on via the per-user-configuration file (``~/.cabal/config``) or the per-project one-(``$PROJECT_DIR/cabal.config``). The error can be squelched with-``--no-require-sandbox``.--The option ``--sandbox-config-file`` allows to specify the location of-the ``cabal.sandbox.config`` file (by default, ``cabal`` searches for it-in the current directory). This provides the same functionality as-shared sandboxes, but sometimes can be more convenient. Example:--::-- $ mkdir my/sandbox- $ cd my/sandbox- $ cabal sandbox init- $ cd /path/to/my/project- $ cabal --sandbox-config-file=/path/to/my/sandbox/cabal.sandbox.config install- # Uses the sandbox located at /path/to/my/sandbox/.cabal-sandbox- $ cd ~- $ cabal --sandbox-config-file=/path/to/my/sandbox/cabal.sandbox.config install- # Still uses the same sandbox--The sandbox config file can be also specified via the-``CABAL_SANDBOX_CONFIG`` environment variable.--Finally, the flag ``--ignore-sandbox`` lets you temporarily ignore an-existing sandbox:--::-- $ mkdir my/sandbox- $ cd my/sandbox- $ cabal sandbox init- $ cabal --ignore-sandbox install text- # Installs 'text' in the user package database ('~/.cabal').--Creating a binary package----------------------------When creating binary packages (e.g. for Red Hat or Debian) one needs to-create a tarball that can be sent to another system for unpacking in the-root directory:--::-- $ runhaskell Setup.hs configure --prefix=/usr- $ runhaskell Setup.hs build- $ runhaskell Setup.hs copy --destdir=/tmp/mypkg- $ tar -czf mypkg.tar.gz /tmp/mypkg/--If the package contains a library, you need two additional steps:--::-- $ runhaskell Setup.hs register --gen-script- $ runhaskell Setup.hs unregister --gen-script--This creates shell scripts ``register.sh`` and ``unregister.sh``, which-must also be sent to the target system. After unpacking there, the-package must be registered by running the ``register.sh`` script. The-``unregister.sh`` script would be used in the uninstall procedure of the-package. Similar steps may be used for creating binary packages for-Windows.--The following options are understood by all commands:--.. program:: setup--.. option:: --help, -h or -?-- List the available options for the command.--.. option:: --verbose=n or -v n-- Set the verbosity level (0-3). The normal level is 1; a missing *n*- defaults to 2.-- There is also an extended version of this command which can be- used to fine-tune the verbosity of output. It takes the- form ``[silent|normal|verbose|debug]``\ *flags*, where *flags*- is a list of ``+`` flags which toggle various aspects of- output. At the moment, only ``+callsite`` and ``+callstack``- are supported, which respectively toggle call site and call- stack printing (these are only supported if Cabal- is built with a sufficiently recent GHC.)--The various commands and the additional options they support are-described below. In the simple build infrastructure, any other options-will be reported as errors.--.. _setup-configure:--setup configure------------------.. program:: setup configure--Prepare to build the package. Typically, this step checks that the-target platform is capable of building the package, and discovers-platform-specific features that are needed during the build.--The user may also adjust the behaviour of later stages using the options-listed in the following subsections. In the simple build infrastructure,-the values supplied via these options are recorded in a private file-read by later stages.--If a user-supplied ``configure`` script is run (see the section on-`system-dependent-parameters <developing-packages.html#system-dependent-parameters>`__ or-on `complex-packages <developing-packages.html#more-complex-packages>`__), it is-passed the :option:`--with-hc-pkg`, :option:`--prefix`, :option:`--bindir`,-:option:`--libdir`, :option:`--dynlibdir`, :option:`--datadir`, :option:`--libexecdir` and-:option:`--sysconfdir` options. In addition the value of the-:option:`--with-compiler` option is passed in a :option:`--with-hc-pkg` option-and all options specified with :option:`--configure-option` are passed on.--.. note::- `GNU autoconf places restrictions on paths, including the directory- that the package is built from.- <https://www.gnu.org/software/autoconf/manual/autoconf.html#File-System-Conventions>`_- The errors produced when this happens can be obscure; Cabal attempts to- detect and warn in this situation, but it is not perfect.--In Cabal 2.0, support for a single positional argument was added to-``setup configure`` This makes Cabal configure the specific component to-be configured. Specified names can be qualified with ``lib:`` or-``exe:`` in case just a name is ambiguous (as would be the case for a-package named ``p`` which has a library and an executable named ``p``.)-This has the following effects:--- Subsequent invocations of ``cabal build``, ``register``, etc. operate only- on the configured component.--- Cabal requires all "internal" dependencies (e.g., an executable- depending on a library defined in the same package) must be found in- the set of databases via :option:`--package-db` (and related flags): these- dependencies are assumed to be up-to-date. A dependency can be- explicitly specified using :option:`--dependency` simply by giving the name- of the internal library; e.g., the dependency for an internal library- named ``foo`` is given as- ``--dependency=pkg-internal=pkg-1.0-internal-abcd``.--- Only the dependencies needed for the requested component are- required. Similarly, when :option:`--exact-configuration` is specified,- it's only necessary to specify :option:`--dependency` for the component.- (As mentioned previously, you *must* specify internal dependencies as- well.)--- Internal ``build-tool-depends`` and ``build-tools`` dependencies are expected- to be in the ``PATH`` upon subsequent invocations of ``setup``.--Full details can be found in the `Componentized Cabal-proposal <https://github.com/ezyang/ghc-proposals/blob/master/proposals/0000-componentized-cabal.rst>`__.--Programs used for building-^^^^^^^^^^^^^^^^^^^^^^^^^^--The following options govern the programs used to process the source-files of a package:--.. option:: --ghc or -g, --jhc, --lhc, --uhc-- Specify which Haskell implementation to use to build the package. At- most one of these flags may be given. If none is given, the- implementation under which the setup script was compiled or- interpreted is used.--.. option:: --with-compiler=path or -w *path*-- Specify the path to a particular compiler. If given, this must match- the implementation selected above. The default is to search for the- usual name of the selected implementation.-- This flag also sets the default value of the :option:`--with-hc-pkg`- option to the package tool for this compiler. Check the output of- ``setup configure -v`` to ensure that it finds the right package- tool (or use :option:`--with-hc-pkg` explicitly).--.. option:: --with-hc-pkg=path-- Specify the path to the package tool, e.g. ``ghc-pkg``. The package- tool must be compatible with the compiler specified by- :option:`--with-compiler`. If this option is omitted, the default value is- determined from the compiler selected.--.. option:: --with-prog=path-- Specify the path to the program *prog*. Any program known to Cabal- can be used in place of *prog*. It can either be a fully path or the- name of a program that can be found on the program search path. For- example: ``--with-ghc=ghc-6.6.1`` or- ``--with-cpphs=/usr/local/bin/cpphs``. The full list of accepted- programs is not enumerated in this user guide. Rather, run- ``cabal install --help`` to view the list.--.. option:: --prog-options=options-- Specify additional options to the program *prog*. Any program known- to Cabal can be used in place of *prog*. For example:- ``--alex-options="--template=mytemplatedir/"``. The *options* is- split into program options based on spaces. Any options containing- embedded spaced need to be quoted, for example- ``--foo-options='--bar="C:\Program File\Bar"'``. As an alternative- that takes only one option at a time but avoids the need to quote,- use :option:`--prog-option` instead.--.. option:: --prog-option=option-- Specify a single additional option to the program *prog*. For- passing an option that contain embedded spaces, such as a file name- with embedded spaces, using this rather than :option:`--prog-options`- means you do not need an additional level of quoting. Of course if you- are using a command shell you may still need to quote, for example- ``--foo-options="--bar=C:\Program File\Bar"``.--All of the options passed with either :option:`--prog-options`-or :option:`--prog-option` are passed in the order they were-specified on the configure command line.--Installation paths-^^^^^^^^^^^^^^^^^^--The following options govern the location of installed files from a-package:--.. option:: --prefix=dir-- The root of the installation. For example for a global install you- might use ``/usr/local`` on a Unix system, or ``C:\Program Files``- on a Windows system. The other installation paths are usually- subdirectories of *prefix*, but they don't have to be.-- In the simple build system, *dir* may contain the following path- variables: ``$pkgid``, ``$pkg``, ``$version``, ``$compiler``,- ``$os``, ``$arch``, ``$abi``, ``$abitag``--.. option:: --bindir=dir-- Executables that the user might invoke are installed here.-- In the simple build system, *dir* may contain the following path- variables: ``$prefix``, ``$pkgid``, ``$pkg``, ``$version``,- ``$compiler``, ``$os``, ``$arch``, ``$abi``, ``$abitag``--.. option:: --libdir=dir-- Object-code libraries are installed here.-- In the simple build system, *dir* may contain the following path- variables: ``$prefix``, ``$bindir``, ``$pkgid``, ``$pkg``,- ``$version``, ``$compiler``, ``$os``, ``$arch``, ``$abi``,- ``$abitag``--.. option:: --dynlibdir=dir-- Dynamic libraries are installed here.-- By default, this is set to `$libdir/$abi`, which is usually not equal to- `$libdir/$libsubdir`.-- In the simple build system, *dir* may contain the following path- variables: ``$prefix``, ``$bindir``, ``$libdir``, ``$pkgid``, ``$pkg``,- ``$version``, ``$compiler``, ``$os``, ``$arch``, ``$abi``,- ``$abitag``--.. option:: --libexecdir=dir-- Executables that are not expected to be invoked directly by the user- are installed here.-- In the simple build system, *dir* may contain the following path- variables: ``$prefix``, ``$bindir``, ``$libdir``, ``$libsubdir``,- ``$pkgid``, ``$pkg``, ``$version``, ``$compiler``, ``$os``,- ``$arch``, ``$abi``, ``$abitag``--.. option:: --datadir=dir-- Architecture-independent data files are installed here.-- In the simple build system, *dir* may contain the following path- variables: ``$prefix``, ``$bindir``, ``$libdir``, ``$libsubdir``,- ``$pkgid``, ``$pkg``, ``$version``, ``$compiler``, ``$os``,- ``$arch``, ``$abi``, ``$abitag``--.. option:: --sysconfdir=dir-- Installation directory for the configuration files.-- In the simple build system, *dir* may contain the following path- variables: ``$prefix``, ``$bindir``, ``$libdir``, ``$libsubdir``,- ``$pkgid``, ``$pkg``, ``$version``, ``$compiler``, ``$os``,- ``$arch``, ``$abi``, ``$abitag``--In addition the simple build system supports the following installation-path options:--.. option:: --libsubdir=dir-- A subdirectory of *libdir* in which libraries are actually installed. For- example, in the simple build system on Unix, the default *libdir* is- ``/usr/local/lib``, and *libsubdir* contains the compiler ABI and package- identifier,- e.g. ``x86_64-linux-ghc-8.0.2/mypkg-0.1.0-IxQNmCA7qrSEQNkoHSF7A``, so- libraries would be installed in- ``/usr/local/lib/x86_64-linux-ghc-8.0.2/mypkg-0.1.0-IxQNmCA7qrSEQNkoHSF7A/``.-- *dir* may contain the following path variables: ``$pkgid``,- ``$pkg``, ``$version``, ``$compiler``, ``$os``, ``$arch``, ``$abi``,- ``$abitag``--.. option:: --libexecsubdir=dir-- A subdirectory of *libexecdir* in which private executables are- installed. For example, in the simple build system on Unix, the default- *libexecdir* is ``/usr/local/libexec``, and *libsubdir* is- ``x86_64-linux-ghc-8.0.2/mypkg-0.1.0``, so private executables would be- installed in ``/usr/local/libexec/x86_64-linux-ghc-8.0.2/mypkg-0.1.0/``-- *dir* may contain the following path variables: ``$pkgid``,- ``$pkg``, ``$version``, ``$compiler``, ``$os``, ``$arch``, ``$abi``,- ``$abitag``--.. option:: --datasubdir=dir-- A subdirectory of *datadir* in which data files are actually- installed.-- *dir* may contain the following path variables: ``$pkgid``,- ``$pkg``, ``$version``, ``$compiler``, ``$os``, ``$arch``, ``$abi``,- ``$abitag``--.. option:: --docdir=dir-- Documentation files are installed relative to this directory.-- *dir* may contain the following path variables: ``$prefix``,- ``$bindir``, ``$libdir``, ``$libsubdir``, ``$datadir``,- ``$datasubdir``, ``$pkgid``, ``$pkg``, ``$version``, ``$compiler``,- ``$os``, ``$arch``, ``$abi``, ``$abitag``--.. option:: --htmldir=dir-- HTML documentation files are installed relative to this directory.-- *dir* may contain the following path variables: ``$prefix``,- ``$bindir``, ``$libdir``, ``$libsubdir``, ``$datadir``,- ``$datasubdir``, ``$docdir``, ``$pkgid``, ``$pkg``, ``$version``,- ``$compiler``, ``$os``, ``$arch``, ``$abi``, ``$abitag``--.. option:: --program-prefix=prefix-- Prepend *prefix* to installed program names.-- *prefix* may contain the following path variables: ``$pkgid``,- ``$pkg``, ``$version``, ``$compiler``, ``$os``, ``$arch``, ``$abi``,- ``$abitag``--.. option:: --program-suffix=suffix-- Append *suffix* to installed program names. The most obvious use for- this is to append the program's version number to make it possible- to install several versions of a program at once:- ``--program-suffix='$version'``.-- *suffix* may contain the following path variables: ``$pkgid``,- ``$pkg``, ``$version``, ``$compiler``, ``$os``, ``$arch``, ``$abi``,- ``$abitag``--Path variables in the simple build system-"""""""""""""""""""""""""""""""""""""""""--For the simple build system, there are a number of variables that can be-used when specifying installation paths. The defaults are also specified-in terms of these variables. A number of the variables are actually for-other paths, like ``$prefix``. This allows paths to be specified-relative to each other rather than as absolute paths, which is important-for building relocatable packages (see `prefix-independence <#prefix-independence>`__).--$prefix- The path variable that stands for the root of the installation. For- an installation to be relocatable, all other installation paths must- be relative to the ``$prefix`` variable.-$bindir- The path variable that expands to the path given by the :option:`--bindir`- configure option (or the default).-$libdir- As above but for :option:`--libdir`-$libsubdir- As above but for :option:`--libsubdir`-$dynlibdir- As above but for :option:`--dynlibdir`-$datadir- As above but for :option:`--datadir`-$datasubdir- As above but for :option:`--datasubdir`-$docdir- As above but for :option:`--docdir`-$pkgid- The name and version of the package, e.g. ``mypkg-0.2``-$pkg- The name of the package, e.g. ``mypkg``-$version- The version of the package, e.g. ``0.2``-$compiler- The compiler being used to build the package, e.g. ``ghc-6.6.1``-$os- The operating system of the computer being used to build the- package, e.g. ``linux``, ``windows``, ``osx``, ``freebsd`` or- ``solaris``-$arch- The architecture of the computer being used to build the package,- e.g. ``i386``, ``x86_64``, ``ppc`` or ``sparc``-$abitag- An optional tag that a compiler can use for telling incompatible- ABI's on the same architecture apart. GHCJS encodes the underlying- GHC version in the ABI tag.-$abi- A shortcut for getting a path that completely identifies the- platform in terms of binary compatibility. Expands to the same value- as ``$arch-$os-compiler-$abitag`` if the compiler uses an abi tag,- ``$arch-$os-$compiler`` if it doesn't.--Paths in the simple build system-""""""""""""""""""""""""""""""""--For the simple build system, the following defaults apply:--.. list-table:: Default installation paths-- * - Option- - Unix Default- - Windows Default- * - :option:`--prefix` (global)- - ``/usr/local``- - ``%PROGRAMFILES%\Haskell``- * - :option:`--prefix` (per-user)- - ``$HOME/.cabal``- - ``%APPDATA%\cabal``- * - :option:`--bindir`- - ``$prefix/bin``- - ``$prefix\bin``- * - :option:`--libdir`- - ``$prefix/lib``- - ``$prefix``- * - :option:`--libsubdir` (others)- - ``$pkgid/$compiler``- - ``$pkgid\$compiler``- * - :option:`--dynlibdir`- - ``$libdir/$abi``- - ``$libdir\$abi``- * - :option:`--libexecdir`- - ``$prefix/libexec``- - ``$prefix\$pkgid``- * - :option:`--datadir` (executable)- - ``$prefix/share``- - ``$prefix``- * - :option:`--datadir` (library)- - ``$prefix/share``- - ``%PROGRAMFILES%\Haskell``- * - :option:`--datasubdir`- - ``$pkgid``- - ``$pkgid``- * - :option:`--docdir`- - ``$datadir/doc/$pkgid``- - ``$prefix\doc\$pkgid``- * - :option:`--sysconfdir`- - ``$prefix/etc``- - ``$prefix\etc``- * - :option:`--htmldir`- - ``$docdir/html``- - ``$docdir\html``- * - :option:`--program-prefix`- - (empty)- - (empty)- * - :option:`--program-suffix`- - (empty)- - (empty)--Prefix-independence-"""""""""""""""""""--On Windows it is possible to obtain the pathname of the running program.-This means that we can construct an installable executable package that-is independent of its absolute install location. The executable can find-its auxiliary files by finding its own path and knowing the location of-the other files relative to ``$bindir``. Prefix-independence is-particularly useful: it means the user can choose the install location-(i.e. the value of ``$prefix``) at install-time, rather than having to-bake the path into the binary when it is built.--In order to achieve this, we require that for an executable on Windows,-all of ``$bindir``, ``$libdir``, ``$dynlibdir``, ``$datadir`` and ``$libexecdir`` begin-with ``$prefix``. If this is not the case then the compiled executable-will have baked-in all absolute paths.--The application need do nothing special to achieve prefix-independence.-If it finds any files using ``getDataFileName`` and the `other functions-provided for the-purpose <developing-packages.html#accessing-data-files-from-package-code>`__,-the files will be accessed relative to the location of the current-executable.--A library cannot (currently) be prefix-independent, because it will be-linked into an executable whose file system location bears no relation-to the library package.--Controlling Flag Assignments-^^^^^^^^^^^^^^^^^^^^^^^^^^^^--Flag assignments (see the `resolution of conditions and-flags <developing-packages.html#resolution-of-conditions-and-flags>`__)-can be controlled with the following command line options.--.. option:: -f flagname or -f -flagname-- Force the specified flag to ``true`` or ``false`` (if preceded with- a ``-``). Later specifications for the same flags will override- earlier, i.e., specifying ``-fdebug -f-debug`` is equivalent to- ``-f-debug``--.. option:: --flags=flagspecs-- Same as ``-f``, but allows specifying multiple flag assignments at- once. The parameter is a space-separated list of flag names (to- force a flag to ``true``), optionally preceded by a ``-`` (to force- a flag to ``false``). For example,- ``--flags="debug -feature1 feature2"`` is equivalent to- ``-fdebug -f-feature1 -ffeature2``.--Building Test Suites-^^^^^^^^^^^^^^^^^^^^--.. option:: --enable-tests-- Build the test suites defined in the package description file during- the ``build`` stage. Check for dependencies required by the test- suites. If the package is configured with this option, it will be- possible to run the test suites with the ``test`` command after the- package is built.--.. option:: --disable-tests-- (default) Do not build any test suites during the ``build`` stage.- Do not check for dependencies required only by the test suites. It- will not be possible to invoke the ``test`` command without- reconfiguring the package.--.. option:: --enable-coverage-- Build libraries and executables (including test suites) with Haskell- Program Coverage enabled. Running the test suites will automatically- generate coverage reports with HPC.--.. option:: --disable-coverage-- (default) Do not enable Haskell Program Coverage.--Miscellaneous options-^^^^^^^^^^^^^^^^^^^^^--.. option:: --user-- Does a per-user installation. This changes the `default installation- prefix <#paths-in-the-simple-build-system>`__. It also allow- dependencies to be satisfied by the user's package database, in- addition to the global database. This also implies a default of- ``--user`` for any subsequent ``install`` command, as packages- registered in the global database should not depend on packages- registered in a user's database.--.. option:: --global-- (default) Does a global installation. In this case package- dependencies must be satisfied by the global package database. All- packages in the user's package database will be ignored. Typically- the final installation step will require administrative privileges.--.. option:: --package-db=db-- Allows package dependencies to be satisfied from this additional- package database *db* in addition to the global package database.- All packages in the user's package database will be ignored. The- interpretation of *db* is implementation-specific. Typically it will- be a file or directory. Not all implementations support arbitrary- package databases.-- This pushes an extra db onto the db stack. The :option:`--global` and- :option:`--user` mode switches add the respective [Global] and [Global,- User] dbs to the initial stack. There is a compiler-implementation- constraint that the global db must appear first in the stack, and if- the user one appears at all, it must appear immediately after the- global db.-- To reset the stack, use ``--package-db=clear``.--.. option:: --ipid=ipid-- Specifies the *installed package identifier* of the package to be- built; this identifier is passed on to GHC and serves as the basis- for linker symbols and the ``id`` field in a ``ghc-pkg``- registration. When a package has multiple components, the actual- component identifiers are derived off of this identifier (e.g., an- internal library ``foo`` from package ``p-0.1-abcd`` will get the- identifier ``p-0.1-abcd-foo``.--.. option:: --cid=cid-- Specifies the *component identifier* of the component being built;- this is only valid if you are configuring a single component.--.. option:: --default-user-config=file-- Allows a "default" ``cabal.config`` freeze file to be passed in- manually. This file will only be used if one does not exist in the- project directory already. Typically, this can be set from the- global cabal ``config`` file so as to provide a default set of- partial constraints to be used by projects, providing a way for- users to peg themselves to stable package collections.--.. option:: --enable-optimization[=n] or -O [n]-- (default) Build with optimization flags (if available). This is- appropriate for production use, taking more time to build faster- libraries and programs.-- The optional *n* value is the optimisation level. Some compilers- support multiple optimisation levels. The range is 0 to 2. Level 0- is equivalent to :option:`--disable-optimization`, level 1 is the- default if no *n* parameter is given. Level 2 is higher optimisation- if the compiler supports it. Level 2 is likely to lead to longer- compile times and bigger generated code.-- When optimizations are enabled, Cabal passes ``-O2`` to the C compiler.--.. option:: --disable-optimization-- Build without optimization. This is suited for development: building- will be quicker, but the resulting library or programs will be- slower.--.. option:: --enable-profiling-- Build libraries and executables with profiling enabled (for- compilers that support profiling as a separate mode). For this to- work, all libraries used by this package must also have been built- with profiling support. For libraries this involves building an- additional instance of the library in addition to the normal- non-profiling instance. For executables it changes the single- executable to be built in profiling mode.-- This flag covers both libraries and executables, but can be- overridden by the :option:`--enable-library-profiling` flag.-- See also the :option:`--profiling-detail` flag below.--.. option:: --disable-profiling-- (default) Do not enable profiling in generated libraries and- executables.--.. option:: --enable-library-profiling or -p-- As with :option:`--enable-profiling` above, but it applies only for- libraries. So this generates an additional profiling instance of the- library in addition to the normal non-profiling instance.-- The :option:`--enable-profiling` flag controls the profiling mode for both- libraries and executables, but if different modes are desired for- libraries versus executables then use :option:`--enable-library-profiling`- as well.--.. option:: --disable-library-profiling-- (default) Do not generate an additional profiling version of the library.--.. option:: --profiling-detail[=level]-- Some compilers that support profiling, notably GHC, can allocate- costs to different parts of the program and there are different- levels of granularity or detail with which this can be done. In- particular for GHC this concept is called "cost centers", and GHC- can automatically add cost centers, and can do so in different ways.-- This flag covers both libraries and executables, but can be- overridden by the :option:`--library-profiling-detail` flag.-- Currently this setting is ignored for compilers other than GHC. The- levels that cabal currently supports are:-- default- For GHC this uses ``exported-functions`` for libraries and- ``toplevel-functions`` for executables.- none- No costs will be assigned to any code within this component.- exported-functions- Costs will be assigned at the granularity of all top level- functions exported from each module. In GHC specifically, this- is for non-inline functions.- toplevel-functions- Costs will be assigned at the granularity of all top level- functions in each module, whether they are exported from the- module or not. In GHC specifically, this is for non-inline- functions.- all-functions- Costs will be assigned at the granularity of all functions in- each module, whether top level or local. In GHC specifically,- this is for non-inline toplevel or where-bound functions or- values.-- This flag is new in Cabal-1.24. Prior versions used the equivalent- of ``none`` above.--.. option:: --library-profiling-detail[=level]-- As with :option:`--profiling-detail` above, but it applies only for- libraries.-- The level for both libraries and executables is set by the- :option:`--profiling-detail` flag, but if different levels are desired- for libraries versus executables then use- :option:`--library-profiling-detail` as well.--.. option:: --enable-library-vanilla-- (default) Build ordinary libraries (as opposed to profiling- libraries). This is independent of the- :option:`--enable-library-profiling` option. If you enable both, you get- both.--.. option:: --disable-library-vanilla-- Do not build ordinary libraries. This is useful in conjunction with- :option:`--enable-library-profiling` to build only profiling libraries,- rather than profiling and ordinary libraries.--.. option:: --enable-library-for-ghci-- (default) Build libraries suitable for use with GHCi.--.. option:: --disable-library-for-ghci-- Not all platforms support GHCi and indeed on some platforms, trying- to build GHCi libs fails. In such cases this flag can be used as a- workaround.--.. option:: --enable-split-objs-- Use the GHC ``-split-objs`` feature when building the library. This- reduces the final size of the executables that use the library by- allowing them to link with only the bits that they use rather than- the entire library. The downside is that building the library takes- longer and uses considerably more memory.--.. option:: --disable-split-objs-- (default) Do not use the GHC ``-split-objs`` feature. This makes- building the library quicker but the final executables that use the- library will be larger.--.. option:: --enable-executable-stripping-- (default) When installing binary executable programs, run the- ``strip`` program on the binary. This can considerably reduce the- size of the executable binary file. It does this by removing- debugging information and symbols. While such extra information is- useful for debugging C programs with traditional debuggers it is- rarely helpful for debugging binaries produced by Haskell compilers.-- Not all Haskell implementations generate native binaries. For such- implementations this option has no effect.--.. option:: --disable-executable-stripping-- Do not strip binary executables during installation. You might want- to use this option if you need to debug a program using gdb, for- example if you want to debug the C parts of a program containing- both Haskell and C code. Another reason is if your are building a- package for a system which has a policy of managing the stripping- itself (such as some Linux distributions).--.. option:: --enable-shared-- Build shared library. This implies a separate compiler run to- generate position independent code as required on most platforms.--.. option:: --disable-shared-- (default) Do not build shared library.--.. option:: --enable-static-- Build a static library. This passes ``-staticlib`` to GHC (available- for iOS, and with 8.4 more platforms). The result is an archive ``.a``- containing all dependent haskell libararies combined.--.. option:: --disable-static-- (default) Do not build a static library.--.. option:: --enable-executable-dynamic-- Link dependent Haskell libraries into executables dynamically.- The executable's library dependencies must have been- built as shared objects. This implies :option:`--enable-shared`- unless :option:`--disable-shared` is explicitly specified.--.. option:: --disable-executable-dynamic-- (default) Link dependent Haskell libraries into executables statically.- Non-Haskell (C) libraries are still linked dynamically, including libc,- so the result is still not a fully static executable- unless :option:`--enable-executable-static` is given.--.. option:: --enable-executable-static-- Build fully static executables.- This link all dependent libraries into executables statically,- including libc.--.. option:: --disable-executable-static-- (default) Do not build fully static executables.--.. option:: --configure-option=str-- An extra option to an external ``configure`` script, if one is used- (see the section on `system-dependent- parameters <developing-packages.html#system-dependent-parameters>`__).- There can be several of these options.--.. option:: --extra-include-dirs[=dir]-- An extra directory to search for C header files. You can use this- flag multiple times to get a list of directories.-- You might need to use this flag if you have standard system header- files in a non-standard location that is not mentioned in the- package's ``.cabal`` file. Using this option has the same affect as- appending the directory *dir* to the ``include-dirs`` field in each- library and executable in the package's ``.cabal`` file. The- advantage of course is that you do not have to modify the package at- all. These extra directories will be used while building the package- and for libraries it is also saved in the package registration- information and used when compiling modules that use the library.--.. option:: --extra-lib-dirs[=dir]-- An extra directory to search for system libraries files. You can use- this flag multiple times to get a list of directories.--.. option:: --extra-framework-dirs[=dir]-- An extra directory to search for frameworks (OS X only). You can use- this flag multiple times to get a list of directories.-- You might need to use this flag if you have standard system- libraries in a non-standard location that is not mentioned in the- package's ``.cabal`` file. Using this option has the same affect as- appending the directory *dir* to the ``extra-lib-dirs`` field in- each library and executable in the package's ``.cabal`` file. The- advantage of course is that you do not have to modify the package at- all. These extra directories will be used while building the package- and for libraries it is also saved in the package registration- information and used when compiling modules that use the library.--.. option:: --dependency[=pkgname=ipid]-- Specify that a particular dependency should used for a particular- package name. In particular, it declares that any reference to- *pkgname* in a :pkg-field:`build-depends` should be resolved to- *ipid*.--.. option:: --exact-configuration-- This changes Cabal to require every dependency be explicitly- specified using :option:`--dependency`, rather than use Cabal's (very- simple) dependency solver. This is useful for programmatic use of- Cabal's API, where you want to error if you didn't specify enough- :option:`--dependency` flags.--.. option:: --allow-newer[=pkgs], --allow-older[=pkgs]-- Selectively relax upper or lower bounds in dependencies without- editing the package description respectively.-- The following description focuses on upper bounds and the- :option:`--allow-newer` flag, but applies analogously to- :option:`--allow-older` and lower bounds. :option:`--allow-newer`- and :option:`--allow-older` can be used at the same time.-- If you want to install a package A that depends on B >= 1.0 && <- 2.0, but you have the version 2.0 of B installed, you can compile A- against B 2.0 by using ``cabal install --allow-newer=B A``. This- works for the whole package index: if A also depends on C that in- turn depends on B < 2.0, C's dependency on B will be also relaxed.-- Example:-- ::-- $ cd foo- $ cabal configure- Resolving dependencies...- cabal: Could not resolve dependencies:- [...]- $ cabal configure --allow-newer- Resolving dependencies...- Configuring foo...-- Additional examples:-- ::-- # Relax upper bounds in all dependencies.- $ cabal install --allow-newer foo-- # Relax upper bounds only in dependencies on bar, baz and quux.- $ cabal install --allow-newer=bar,baz,quux foo-- # Relax the upper bound on bar and force bar==2.1.- $ cabal install --allow-newer=bar --constraint="bar==2.1" foo-- It's also possible to limit the scope of :option:`--allow-newer` to single- packages with the ``--allow-newer=scope:dep`` syntax. This means- that the dependency on ``dep`` will be relaxed only for the package- ``scope``.-- Example:-- ::-- # Relax upper bound in foo's dependency on base; also relax upper bound in- # every package's dependency on lens.- $ cabal install --allow-newer=foo:base,lens-- # Relax upper bounds in foo's dependency on base and bar's dependency- # on time; also relax the upper bound in the dependency on lens specified by- # any package.- $ cabal install --allow-newer=foo:base,lens --allow-newer=bar:time-- Finally, one can enable :option:`--allow-newer` permanently by setting- ``allow-newer: True`` in the ``~/.cabal/config`` file. Enabling- 'allow-newer' selectively is also supported in the config file- (``allow-newer: foo, bar, baz:base``).--.. option:: --constraint=constraint-- Restrict solutions involving a package to given version- bounds, flag settings, and other properties. For example, to- consider only install plans that use version 2.1 of ``bar``- or do not use ``bar`` at all, write:-- ::-- $ cabal install --constraint="bar == 2.1"-- Version bounds have the same syntax as :pkg-field:`build-depends`.- As a special case, the following prevents ``bar`` from being- used at all:-- ::-- # Note: this is just syntax sugar for '> 1 && < 1', and is- # supported by build-depends.- $ cabal install --constraint="bar -none"-- You can also specify flag assignments:-- ::-- # Require bar to be installed with the foo flag turned on and- # the baz flag turned off.- $ cabal install --constraint="bar +foo -baz"-- To specify multiple constraints, you may pass the- ``constraint`` option multiple times.-- There are also some more specialized constraints, which most people- don't generally need:-- ::-- # Require that a version of bar be used that is already installed in- # the global package database.- $ cabal install --constraint="bar installed"-- # Require the local source copy of bar to be used.- # (Note: By default, if we have a local package we will- # automatically use it, so it will generally not be necessary to- # specify this.)- $ cabal install --constraint="bar source"-- # Require that bar have test suites and benchmarks enabled.- $ cabal install --constraint="bar test" --constraint="bar bench"-- By default, constraints only apply to build dependencies- (:pkg-field:`build-depends`), build dependencies of build- dependencies, and so on. Constraints normally do not apply to- dependencies of the ``Setup.hs`` script of any package- (:pkg-field:`setup-depends`) nor do they apply to build tools- (:pkg-field:`build-tool-depends`) or the dependencies of build- tools. To explicitly apply a constraint to a setup or build- tool dependency, you can add a qualifier to the constraint as- follows:-- ::-- # Example use of the 'any' qualifier. This constraint- # applies to package bar anywhere in the dependency graph.- $ cabal install --constraint="any.bar == 1.0"-- ::-- # Example uses of 'setup' qualifiers.-- # This constraint applies to package bar when it is a- # dependency of any Setup.hs script.- $ cabal install --constraint="setup.bar == 1.0"-- # This constraint applies to package bar when it is a- # dependency of the Setup.hs script of package foo.- $ cabal install --constraint="foo:setup.bar == 1.0"-- .. TODO: Uncomment this example once we decide on a syntax for 'exe'.- .. # Example use of the 'exe' (executable build tool)- # qualifier. This constraint applies to package baz when it- # is a dependency of the build tool bar being used to- # build package foo.- $ cabal install --constraint="foo:bar:exe.baz == 1.0"--.. option:: --preference=preference-- Specify a soft constraint on versions of a package. The solver will- attempt to satisfy these preferences on a "best-effort" basis.--.. option:: --disable-response-files-- Enable workaround for older versions of programs such as ``ar`` or- ``ld`` that do not support response file arguments (i.e. ``@file``- arguments). You may want this flag only if you specify custom ar- executable. For system ``ar`` or the one bundled with ``ghc`` on- Windows the ``cabal`` should do the right thing and hence should- normally not require this flag.--.. _setup-build:--setup build--------------Perform any preprocessing or compilation needed to make this package-ready for installation.--This command takes the following options:--.. program:: setup build--.. option:: --prog-options=options, --prog-option=option-- These are mostly the same as the `options configure- step <#setup-configure>`__. Unlike the options specified at the- configure step, any program options specified at the build step are- not persistent but are used for that invocation only. They options- specified at the build step are in addition not in replacement of- any options specified at the configure step.--.. _setup-haddock:--setup haddock----------------.. program:: setup haddock--Build the documentation for the package using Haddock_.-By default, only the documentation for the exposed modules is generated-(but see the :option:`--executables` and :option:`--internal` flags below).--This command takes the following options:--.. option:: --hoogle-- Generate a file ``dist/doc/html/``\ *pkgid*\ ``.txt``, which can be- converted by Hoogle_ into a- database for searching. This is equivalent to running Haddock_- with the ``--hoogle`` flag.--.. option:: --html-location=url-- Specify a template for the location of HTML documentation for- prerequisite packages. The substitutions (`see- listing <#paths-in-the-simple-build-system>`__) are applied to the- template to obtain a location for each package, which will be used- by hyperlinks in the generated documentation. For example, the- following command generates links pointing at Hackage_ pages:-- setup haddock- --html-location='http://hackage.haskell.org/packages/archive/$pkg/latest/doc/html'-- Here the argument is quoted to prevent substitution by the shell. If- this option is omitted, the location for each package is obtained- using the package tool (e.g. ``ghc-pkg``).--.. option:: --executables-- Also run Haddock_ for the modules of all the executable programs. By default- Haddock_ is run only on the exported modules.--.. option:: --internal-- Run Haddock_ for the all- modules, including unexposed ones, and make- Haddock_ generate documentation- for unexported symbols as well.--.. option:: --css=path-- The argument *path* denotes a CSS file, which is passed to- Haddock_ and used to set the- style of the generated documentation. This is only needed to- override the default style that- Haddock_ uses.--.. option:: --hyperlink-source-- Generate Haddock_ documentation integrated with HsColour_ . First,- HsColour_ is run to generate colourised code. Then Haddock_ is run to- generate HTML documentation. Each entity shown in the documentation is- linked to its definition in the colourised code.--.. option:: --hscolour-css=path-- The argument *path* denotes a CSS file, which is passed to HsColour_ as in-- runhaskell Setup.hs hscolour --css=*path*--.. _setup-hscolour:--setup hscolour-----------------Produce colourised code in HTML format using HsColour_. Colourised code for-exported modules is put in ``dist/doc/html/``\ *pkgid*\ ``/src``.--This command takes the following options:--.. program:: setup hscolour--.. option:: --executables-- Also run HsColour_ on the sources of all executable programs. Colourised- code is put in ``dist/doc/html/``\ *pkgid*/*executable*\ ``/src``.--.. option:: --css=path-- Use the given CSS file for the generated HTML files. The CSS file- defines the colours used to colourise code. Note that this copies- the given CSS file to the directory with the generated HTML files- (renamed to ``hscolour.css``) rather than linking to it.--.. _setup-install:--setup install----------------.. program:: setup install--Copy the files into the install locations and (for library packages)-register the package with the compiler, i.e. make the modules it-contains available to programs.--The `install locations <#installation-paths>`__ are determined by-options to `setup configure`_.--This command takes the following options:--.. option:: --global-- Register this package in the system-wide database. (This is the- default, unless the :option:`setup configure --user` option was supplied- to the ``configure`` command.)--.. option:: --user-- Register this package in the user's local package database. (This is- the default if the :option:`setup configure --user` option was supplied- to the ``configure`` command.)--.. _setup-copy:--setup copy-------------Copy the files without registering them. This command is mainly of use-to those creating binary packages.--This command takes the following option:--.. program:: setup copy--.. option:: --destdir=path-- Specify the directory under which to place installed files. If this is- not given, then the root directory is assumed.--.. _setup-register:--setup register-----------------Register this package with the compiler, i.e. make the modules it-contains available to programs. This only makes sense for library-packages. Note that the ``install`` command incorporates this action.-The main use of this separate command is in the post-installation step-for a binary package.--This command takes the following options:--.. program:: setup register--.. option:: --global-- Register this package in the system-wide database. (This is the- default.)--.. option:: --user-- Register this package in the user's local package database.--.. option:: --gen-script-- Instead of registering the package, generate a script containing- commands to perform the registration. On Unix, this file is called- ``register.sh``, on Windows, ``register.bat``. This script might be- included in a binary bundle, to be run after the bundle is unpacked- on the target system.--.. option:: --gen-pkg-config[=path]-- Instead of registering the package, generate a package registration- file (or directory, in some circumstances). This only applies to- compilers that support package registration files which at the- moment is only GHC. The file should be used with the compiler's- mechanism for registering packages. This option is mainly intended- for packaging systems. If possible use the :option:`--gen-script` option- instead since it is more portable across Haskell implementations.- The *path* is optional and can be used to specify a particular- output file to generate. Otherwise, by default the file is the- package name and version with a ``.conf`` extension.-- This option outputs a directory if the package requires multiple- registrations: this can occur if internal/convenience libraries are- used. These configuration file names are sorted so that they can be- registered in order.--.. option:: --inplace-- Registers the package for use directly from the build tree, without- needing to install it. This can be useful for testing: there's no- need to install the package after modifying it, just recompile and- test.-- This flag does not create a build-tree-local package database. It- still registers the package in one of the user or global databases.-- However, there are some caveats. It only works with GHC (currently).- It only works if your package doesn't depend on having any- supplemental files installed --- plain Haskell libraries should be- fine.--.. _setup-unregister:--setup unregister-------------------.. program:: setup unregister--Deregister this package with the compiler.--This command takes the following options:--.. option:: --global-- Deregister this package in the system-wide database. (This is the- default.)--.. option:: --user-- Deregister this package in the user's local package database.--.. option:: --gen-script-- Instead of deregistering the package, generate a script containing- commands to perform the deregistration. On Unix, this file is called- ``unregister.sh``, on Windows, ``unregister.bat``. This script might- be included in a binary bundle, to be run on the target system.--.. _setup-clean:--setup clean--------------Remove any local files created during the ``configure``, ``build``,-``haddock``, ``register`` or ``unregister`` steps, and also any files-and directories listed in the :pkg-field:`extra-tmp-files` field.--This command takes the following options:--.. program:: setup clean--.. option:: --save-configure, -s-- Keeps the configuration information so it is not necessary to run- the configure step again before building.--.. _setup-test:--setup test-------------Run the test suites specified in the package description file. Aside-from the following flags, Cabal accepts the name of one or more test-suites on the command line after ``test``. When supplied, Cabal will run-only the named test suites, otherwise, Cabal will run all test suites in-the package.--.. program:: setup test--.. option:: --builddir=dir-- The directory where Cabal puts generated build files (default:- ``dist``). Test logs will be located in the ``test`` subdirectory.--.. option:: --human-log=path-- The template used to name human-readable test logs; the path is- relative to ``dist/test``. By default, logs are named according to- the template ``$pkgid-$test-suite.log``, so that each test suite- will be logged to its own human-readable log file. Template- variables allowed are: ``$pkgid``, ``$compiler``, ``$os``,- ``$arch``, ``$abi``, ``$abitag``, ``$test-suite``, and ``$result``.--.. option:: --machine-log=path-- The path to the machine-readable log, relative to ``dist/test``. The- default template is ``$pkgid.log``. Template variables allowed are:- ``$pkgid``, ``$compiler``, ``$os``, ``$arch``, ``$abi``, ``$abitag``- and ``$result``.--.. option:: --show-details=filter-- Determines if the results of individual test cases are shown on the- terminal. May be ``always`` (always show), ``never`` (never show),- ``failures`` (show only failed results), or ``streaming`` (show all- results in real time).--.. option:: --test-options=options- Give extra options to the test executables.--.. option:: --test-option=option-- Give an extra option to the test executables. There is no need to- quote options containing spaces because a single option is assumed,- so options will not be split on spaces.--.. option:: --test-wrapper=path-- The wrapper script/application used to setup and tear down the test- execution context. The text executable path and test arguments are- passed as arguments to the wrapper and it is expected that the wrapper- will return the test's return code, as well as a copy of stdout/stderr.--.. _setup-bench:--setup bench--------------Run the benchmarks specified in the package description file. Aside-from the following flags, Cabal accepts the name of one or more benchmarks-on the command line after ``bench``. When supplied, Cabal will run-only the named benchmarks, otherwise, Cabal will run all benchmarks in-the package.--.. option:: --benchmark-options=options- Give extra options to the benchmark executables.--.. option:: --benchmark-option=option-- Give an extra option to the benchmark executables. There is no need to- quote options containing spaces because a single option is assumed,- so options will not be split on spaces.--.. _setup-sdist:--setup sdist--------------Create a system- and compiler-independent source distribution in a file-*package*-*version*\ ``.tar.gz`` in the ``dist`` subdirectory, for-distribution to package builders. When unpacked, the commands listed in-this section will be available.--The files placed in this distribution are the package description file,-the setup script, the sources of the modules named in the package-description file, and files named in the ``license-file``, ``main-is``,-``c-sources``, ``asm-sources``, ``cmm-sources``, ``js-sources``,-``data-files``, ``extra-source-files`` and ``extra-doc-files`` fields.--This command takes the following option:--.. program:: setup sdist--.. option:: --snapshot-- Append today's date (in "YYYYMMDD" format) to the version number for- the generated source package. The original package is unaffected.---.. include:: references.inc+Environment variables+---------------------++Various environment variables affect ``cabal-install``.++``CABAL_CONFIG``+ The variable to find global configuration file.++``CABAL_DIR``+ Default content directory for ``cabal-install`` files.+ Default value is ``getAppUserDataDirectory "cabal"``, which is+ ``$HOME/.cabal`` on unix systems and ``%APPDATA%\cabal`` in Windows.++ .. note::++ The CABAL_DIR might be dropped in the future, when+ ``cabal-install`` starts to use XDG Directory specification.++``CABAL_BUILDDIR``+ The override for default ``dist`` build directory.+ Note, the nix-style builds build directory (``dist-newstyle``)+ is not affected by this environment variable.++Configuration file discovery+^^^^^^^^^^^^^^^^^^^^^^^^^^^^++1. If ``$CABAL_CONFIG`` is set use it,+2. otherwise if ``$CABAL_DIR`` is set use ``$CABAL_DIR/config``+3. otherwise use ``getAppUserDirectory "cabal"``++If the configuration file doesn't exist ``cabal-install``+will generate the default one, with directories based on+``$CABAL_DIR`` (if set) or ``getAppUserDirectory "cabal"`` prefix.++.. note:++ If ``$CABAL_CONFIG`` is set, but the file doesn't exist,+ one will be generated with ``$CABAL_DIR`` or ``getAppUserDirectory "cabal"``+ based prefixes. In other words not the prefixes based on a+ directory part of ``$CABAL_CONFIG`` path.++Repository specification+------------------------++An important part of the configuration is the specification of the+repository. When ``cabal`` creates a default config file, it configures+the repository to be the central Hackage server:++::++ repository hackage.haskell.org+ url: http://hackage.haskell.org/++The name of the repository is given on the first line, and can be+anything; packages downloaded from this repository will be cached under+``~/.cabal/packages/hackage.haskell.org`` (or whatever name you specify;+you can change the prefix by changing the value of+:cfg-field:`remote-repo-cache`). If you want, you can configure multiple+repositories, and ``cabal`` will combine them and be able to download+packages from any of them.++Using secure repositories+^^^^^^^^^^^^^^^^^^^^^^^^^++For repositories that support the TUF security infrastructure (this+includes Hackage), you can enable secure access to the repository by+specifying:++::++ repository hackage.haskell.org+ url: http://hackage.haskell.org/+ secure: True+ root-keys: <root-key-IDs>+ key-threshold: <key-threshold>++The ``<root-key-IDs>`` and ``<key-threshold>`` values are used for+bootstrapping. As part of the TUF infrastructure the repository will+contain a file ``root.json`` (for instance,+http://hackage.haskell.org/root.json) which the client needs to do+verification. However, how can ``cabal`` verify the ``root.json`` file+*itself*? This is known as bootstrapping: if you specify a list of root+key IDs and a corresponding threshold, ``cabal`` will verify that the+downloaded ``root.json`` file has been signed with at least+``<key-threshold>`` keys from your set of ``<root-key-IDs>``.++You can, but are not recommended to, omit these two fields. In that case+``cabal`` will download the ``root.json`` field and use it without+verification. Although this bootstrapping step is then unsafe, all+subsequent access is secure (provided that the downloaded ``root.json``+was not tampered with). Of course, adding ``root-keys`` and+``key-threshold`` to your repository specification only shifts the+problem, because now you somehow need to make sure that the key IDs you+received were the right ones. How that is done is however outside the+scope of ``cabal`` proper.++More information about the security infrastructure can be found at+https://github.com/haskell/hackage-security.++Local no-index repositories+^^^^^^^^^^^^^^^^^^^^^^^^^^^++It's possible to use a directory of `.tar.gz` package files as a local package+repository.++::++ repository my-local-repository+ url: file+noindex:///absolute/path/to/directory++``cabal`` will construct the index automatically from the+``package-name-version.tar.gz`` files in the directory, and will use optional+corresponding ``package-name-version.cabal`` files as new revisions.++For example, if ``/absolute/path/to/directory`` looks like+::++ /absolute/path/to/directory/+ foo-0.1.0.0.tar.gz+ bar-0.2.0.0.tar.gz+ bar-0.2.0.0.cabal++then ``cabal`` will create an index with two packages:++- ``foo-0.1.0.0`` using the source and ``.cabal`` file inside+ ``foo-0.1.0.0.tar.gz``+- ``bar-0.2.0.0`` using the source inside ``bar-0.2.0.0.tar.gz``+ and ``bar-0.2.0.0.cabal``++The index is cached inside the given directory. If the directory is not+writable, you can append ``#shared-cache`` fragment to the URI,+then the cache will be stored inside the :cfg-field:`remote-repo-cache` directory.+The part of the path will be used to determine the cache key part.++.. note::+ ``cabal-install`` creates a ``.cache`` file, and will aggressively use+ its contents if it exists. Therefore if you change the contents of+ the directory, remember to wipe the cache too.++.. note::+ The URI scheme ``file:`` is interpreted as a remote repository,+ as described in the previous sections, thus requiring manual construction+ of ``01-index.tar`` file.++Legacy repositories+^^^^^^^^^^^^^^^^^^^++Currently ``cabal`` supports single kind of “legacy” repositories.+It is specified using++::++ remote-repo: hackage.haskell.org:http://hackage.haskell.org/packages/archive++This is just syntactic sugar for++::++ repository hackage.haskell.org+ url: http://hackage.haskell.org/packages/archive++although, in (and only in) the specific case of Hackage, the URL+``http://hackage.haskell.org/packages/archive`` will be silently+translated to ``http://hackage.haskell.org/``.++Secure local repositories+^^^^^^^^^^^^^^^^^^^^^^^^^++If you want to use repositories on your local file system, it is+recommended instead to use a *secure* local repository:++::++ repository my-local-repo+ url: file:/path/to/local/repo+ secure: True+ root-keys: <root-key-IDs>+ key-threshold: <key-threshold>++The layout of these secure local repos matches the layout of remote+repositories exactly; the :hackage-pkg:`hackage-repo-tool`+can be used to create and manage such repositories.++.. _installing-packages:++Building and installing packages+================================++To be written++Installing packages from Hackage+--------------------------------++The ``cabal`` tool also can download, configure, build and install a+`Hackage`_ package and all of its+dependencies in a single step. To do this, run:++::++ $ cabal install [PACKAGE...]++To browse the list of available packages, visit the `Hackage`_ web site.++.. _Hackage: https://hackage.haskell.org/
cabal/Cabal/doc/misc.rst view
@@ -60,7 +60,7 @@ example 1.2.3, indicate compatible API additions. The Package Versioning Policy does not require any API guarantees-between major releases, for example between 1.2.x and 1.4.x. In practise+between major releases, for example between 1.2.x and 1.4.x. In practice of course not everything changes between major releases. Some parts of the API are more prone to change than others. The rest of this section gives some informal advice on what level of API stability you can expect
cabal/Cabal/doc/nix-integration.rst view
@@ -1,6 +1,11 @@ Nix Integration =============== +.. note::++ This functionality doesn't work with nix-style builds.+ Nix-style builds are not related to Nix integration.+ `Nix <http://nixos.org/nix/>`_ is a package manager popular with some Haskell developers due to its focus on reliability and reproducibility. ``cabal`` now has the ability to integrate with Nix for dependency management during local package development. Enabling Nix Integration
cabal/Cabal/doc/nix-local-build-overview.rst view
@@ -1,6 +1,8 @@ Nix-style Local Builds ====================== +.. _nix-style-builds:+ Nix-style local builds are a new build system implementation inspired by Nix. The Nix-style local build system is commonly called "v2-build" for short after the ``cabal v2-*`` family of commands that control it. However, those@@ -16,7 +18,7 @@ Nix-style local builds combine the best of non-sandboxed and sandboxed Cabal: -1. Like sandboxed Cabal today, we build sets of independent local+1. Like sandboxed Cabal previously, we build sets of independent local packages deterministically and independent of any global state. v2-build will never tell you that it can't build your package because it would result in a "dangerous reinstall." Given a
cabal/Cabal/doc/nix-local-build.rst view
@@ -51,2122 +51,214 @@ :: - $ cabal v2-build--To build a specific package, you can either run ``v2-build`` from the-directory of the package in question:--::-- $ cd cabal-install- $ cabal v2-build--or you can pass the name of the package as an argument to-``cabal v2-build`` (this works in any subdirectory of the project):--::-- $ cabal v2-build cabal-install--You can also specify a specific component of the package to build. For-example, to build a test suite named ``package-tests``, use the command:--::-- $ cabal v2-build package-tests--Targets can be qualified with package names. So to request-``package-tests`` *from* the ``Cabal`` package, use-``Cabal:package-tests``.--Unlike sandboxes, there is no need to setup a sandbox or ``add-source``-projects; just check in ``cabal.project`` to your repository and-``v2-build`` will just work.--Cookbook-========--How can I profile my library/application?--------------------------------------------Create or edit your ``cabal.project.local``, adding the following-line::-- profiling: True--Now, ``cabal v2-build`` will automatically build all libraries and-executables with profiling. You can fine-tune the profiling settings-for each package using :cfg-field:`profiling-detail`::-- package p- profiling-detail: toplevel-functions--Alternately, you can call ``cabal v2-build --enable-profiling`` to-temporarily build with profiling.--How it works-============--Local versus external packages---------------------------------One of the primary innovations of Nix-style local builds is the-distinction between local packages, which users edit and recompile and-must be built per-project, versus external packages, which can be cached-across projects. To be more precise:--1. A **local package** is one that is listed explicitly in the- ``packages``, ``optional-packages`` or ``extra-packages`` field of a- project. Usually, these refer to packages whose source code lives- directly in a folder in your project (although, you can list an- arbitrary Hackage package in ``extra-packages`` to force it to be- treated as local).--Local packages, as well as the external packages (below) which depend on-them, are built **inplace**, meaning that they are always built-specifically for the project and are not installed globally. Inplace-packages are not cached and not given unique hashes, which makes them-suitable for packages which you want to edit and recompile.--2. An **external package** is any package which is not listed in the- ``packages`` field. The source code for external packages is usually- retrieved from Hackage.--When an external package does not depend on an inplace package, it can-be built and installed to a **global** store, which can be shared across-projects. These build products are identified by a hash that over all of-the inputs which would influence the compilation of a package (flags,-dependency selection, etc.). Just as in Nix, these hashes uniquely-identify the result of a build; if we compute this identifier and we-find that we already have this ID built, we can just use the already-built version.--The global package store is ``~/.cabal/store`` (configurable via-global `store-dir` option); if you need to clear your store for-whatever reason (e.g., to reclaim disk space or because the global-store is corrupted), deleting this directory is safe (``v2-build``-will just rebuild everything it needs on its next invocation).--This split motivates some of the UI choices for Nix-style local build-commands. For example, flags passed to ``cabal v2-build`` are only-applied to *local* packages, so that adding a flag to-``cabal v2-build`` doesn't necessitate a rebuild of *every* transitive-dependency in the global package store.--In cabal-install 2.0 and above, Nix-style local builds also take advantage of a-new Cabal library feature, `per-component-builds <https://github.com/ezyang/ghc-proposals/blob/master/proposals/0000-componentized-cabal.rst>`__,-where each component of a package is configured and built separately.-This can massively speed up rebuilds of packages with lots of components-(e.g., a package that defines multiple executables), as only one-executable needs to be rebuilt. Packages that use Custom setup scripts-are not currently built on a per-component basis.--Where are my build products?-------------------------------A major deficiency in the current implementation of v2-build is that-there is no programmatic way to access the location of build products.-The location of the build products is intended to be an internal-implementation detail of v2-build, but we also understand that many-unimplemented features can only be reasonably worked around by-accessing build products directly.--The location where build products can be found varies depending on the-version of cabal-install:--- In cabal-install-1.24, the dist directory for a package ``p-0.1`` is- stored in ``dist-newstyle/build/p-0.1``. For example, if you built an- executable or test suite named ``pexe``, it would be located at- ``dist-newstyle/build/p-0.1/build/pexe/pexe``.--- In cabal-install-2.0, the dist directory for a package ``p-0.1``- defining a library built with GHC 8.0.1 on 64-bit Linux is- ``dist-newstyle/build/x86_64-linux/ghc-8.0.1/p-0.1``. When- per-component builds are enabled (any non-Custom package), a- subcomponent like an executable or test suite named ``pexe`` will be- stored at- ``dist-newstyle/build/x86_64-linux/ghc-8.0.1/p-0.1/c/pexe``; thus,- the full path of the executable is- ``dist-newstyle/build/x86_64-linux/ghc-8.0.1/p-0.1/c/pexe/build/pexe/pexe``- (you can see why we want this to be an implementation detail!)--- In cabal-install-2.2 and above, the ``/c/`` part of the above path- is replaced with one of ``/l/``, ``/x/``, ``/f/``, ``/t/``, or- ``/b/``, depending on the type of component (sublibrary,- executable, foreign library, test suite, or benchmark- respectively). So the full path to an executable named ``pexe``- compiled with GHC 8.0.1 on a 64-bit Linux is now- ``dist-newstyle/build/x86_64-linux/ghc-8.0.1/p-0.1/x/pexe/build/pexe/pexe``;- for a benchmark named ``pbench`` it now is- ``dist-newstyle/build/x86_64-linux/ghc-8.0.1/p-0.1/b/pbench/build/pbench/pbench``;---The paths are a bit longer in 2.0 and above but the benefit is that you can-transparently have multiple builds with different versions of GHC. We-plan to add the ability to create aliases for certain build-configurations, and more convenient paths to access particularly useful-build products like executables.--Caching----------Nix-style local builds sport a robust caching system which help reduce-the time it takes to execute a rebuild cycle. While the details of how-``cabal-install`` does caching are an implementation detail and may-change in the future, knowing what gets cached is helpful for-understanding the performance characteristics of invocations to-``v2-build``. The cached intermediate results are stored in-``dist-newstyle/cache``; this folder can be safely deleted to clear the-cache.--The following intermediate results are cached in the following files in-this folder (the most important two are first):--``solver-plan`` (binary)- The result of calling the dependency solver, assuming that the- Hackage index, local ``cabal.project`` file, and local ``cabal``- files are unmodified. (Notably, we do NOT have to dependency solve- again if new build products are stored in the global store; the- invocation of the dependency solver is independent of what is- already available in the store.)-``source-hashes`` (binary)- The hashes of all local source files. When all local source files of- a local package are unchanged, ``cabal v2-build`` will skip- invoking ``setup build`` entirely (saving us from a possibly- expensive call to ``ghc --make``). The full list of source files- participating in compilation are determined using- ``setup sdist --list-sources`` (thus, if you do not list all your- source files in a Cabal file, you may fail to recompile when you- edit them.)-``config`` (same format as ``cabal.project``)- The full project configuration, merged from ``cabal.project`` (and- friends) as well as the command line arguments.-``compiler`` (binary)- The configuration of the compiler being used to build the project.-``improved-plan`` (binary)- Like ``solver-plan``, but with all non-inplace packages improved- into pre-existing copies from the store.-``plan.json`` (JSON)- A JSON serialization of the computed install plan intended- for integrating ``cabal`` with external tooling.- The `cabal-plan <http://hackage.haskell.org/package/cabal-plan>`__- package provides a library for parsing ``plan.json`` files into a- Haskell data structure as well as an example tool showing possible- applications.-- .. todo::-- Document JSON schema (including version history of schema)---Note that every package also has a local cache managed by the Cabal-build system, e.g., in ``$distdir/cache``.--There is another useful file in ``dist-newstyle/cache``,-``plan.json``, which is a JSON serialization of the computed install-plan and is intended for integrating with external tooling.-----Commands-========--We now give an in-depth description of all the commands, describing the-arguments and flags they accept.--cabal v2-configure----------------------``cabal v2-configure`` takes a set of arguments and writes a-``cabal.project.local`` file based on the flags passed to this command.-``cabal v2-configure FLAGS; cabal new-build`` is roughly equivalent to-``cabal v2-build FLAGS``, except that with ``new-configure`` the flags-are persisted to all subsequent calls to ``v2-build``.--``cabal v2-configure`` is intended to be a convenient way to write out-a ``cabal.project.local`` for simple configurations; e.g.,-``cabal v2-configure -w ghc-7.8`` would ensure that all subsequent-builds with ``cabal v2-build`` are performed with the compiler-``ghc-7.8``. For more complex configuration, we recommend writing the-``cabal.project.local`` file directly (or placing it in-``cabal.project``!)--``cabal v2-configure`` inherits options from ``Cabal``. semantics:--- Any flag accepted by ``./Setup configure``.--- Any flag accepted by ``cabal configure`` beyond- ``./Setup configure``, namely ``--cabal-lib-version``,- ``--constraint``, ``--preference`` and ``--solver.``--- Any flag accepted by ``cabal install`` beyond ``./Setup configure``.--- Any flag accepted by ``./Setup haddock``.--The options of all of these flags apply only to *local* packages in a-project; this behavior is different than that of ``cabal install``,-which applies flags to every package that would be built. The motivation-for this is to avoid an innocuous addition to the flags of a package-resulting in a rebuild of every package in the store (which might need-to happen if a flag actually applied to every transitive dependency). To-apply options to an external package, use a ``package`` stanza in a-``cabal.project`` file.--cabal v2-update-------------------``cabal v2-update`` updates the state of the package index. If the-project contains multiple remote package repositories it will update-the index of all of them (e.g. when using overlays).--Some examples:--::-- $ cabal v2-update # update all remote repos- $ cabal v2-update head.hackage # update only head.hackage--cabal v2-build------------------``cabal v2-build`` takes a set of targets and builds them. It-automatically handles building and installing any dependencies of these-targets.--A target can take any of the following forms:--- A package target: ``package``, which specifies that all enabled- components of a package to be built. By default, test suites and- benchmarks are *not* enabled, unless they are explicitly requested- (e.g., via ``--enable-tests``.)--- A component target: ``[package:][ctype:]component``, which specifies- a specific component (e.g., a library, executable, test suite or- benchmark) to be built.--- All packages: ``all``, which specifies all packages within the project.--- Components of a particular type: ``package:ctypes``, ``all:ctypes``:- which specifies all components of the given type. Where valid- ``ctypes`` are:- - ``libs``, ``libraries``,- - ``flibs``, ``foreign-libraries``,- - ``exes``, ``executables``,- - ``tests``,- - ``benches``, ``benchmarks``.--In component targets, ``package:`` and ``ctype:`` (valid component types-are ``lib``, ``flib``, ``exe``, ``test`` and ``bench``) can be used to-disambiguate when multiple packages define the same component, or the-same component name is used in a package (e.g., a package ``foo``-defines both an executable and library named ``foo``). We always prefer-interpreting a target as a package name rather than as a component name.--Some example targets:--::-- $ cabal v2-build lib:foo-pkg # build the library named foo-pkg- $ cabal v2-build foo-pkg:foo-tests # build foo-tests in foo-pkg--(There is also syntax for specifying module and file targets, but it-doesn't currently do anything.)--Beyond a list of targets, ``cabal v2-build`` accepts all the flags that-``cabal v2-configure`` takes. Most of these flags are only taken into-consideration when building local packages; however, some flags may-cause extra store packages to be built (for example,-``--enable-profiling`` will automatically make sure profiling libraries-for all transitive dependencies are built and installed.)--In addition ``cabal v2-build`` accepts these flags:--- ``--only-configure``: When given we will forgoe performing a full build and- abort after running the configure phase of each target package.---cabal v2-repl-----------------``cabal v2-repl TARGET`` loads all of the modules of the target into-GHCi as interpreted bytecode. In addition to ``cabal v2-build``'s flags,-it takes an additional ``--repl-options`` flag.--To avoid ``ghci`` specific flags from triggering unneeded global rebuilds these-flags are now stripped from the internal configuration. As a result-``--ghc-options`` will no longer (reliably) work to pass flags to ``ghci`` (or-other repls). Instead, you should use the new ``--repl-options`` flag to-specify these options to the invoked repl. (This flag also works on ``cabal-repl`` and ``Setup repl`` on sufficiently new versions of Cabal.)--Currently, it is not supported to pass multiple targets to ``v2-repl``-(``v2-repl`` will just successively open a separate GHCi session for-each target.)--It also provides a way to experiment with libraries without needing to download-them manually or to install them globally.--This command opens a REPL with the current default target loaded, and a version-of the ``vector`` package matching that specification exposed.--::-- $ cabal v2-repl --build-depends "vector >= 0.12 && < 0.13"--Both of these commands do the same thing as the above, but only exposes ``base``,-``vector``, and the ``vector`` package's transitive dependencies even if the user-is in a project context.--::-- $ cabal v2-repl --ignore-project --build-depends "vector >= 0.12 && < 0.13"- $ cabal v2-repl --project='' --build-depends "vector >= 0.12 && < 0.13"--This command would add ``vector``, but not (for example) ``primitive``, because-it only includes the packages specified on the command line (and ``base``, which-cannot be excluded for technical reasons).--::-- $ cabal v2-repl --build-depends vector --no-transitive-deps--cabal v2-run----------------``cabal v2-run [TARGET [ARGS]]`` runs the executable specified by the-target, which can be a component, a package or can be left blank, as-long as it can uniquely identify an executable within the project.-Tests and benchmarks are also treated as executables.--See `the v2-build section <#cabal-new-build>`__ for the target syntax.--Except in the case of the empty target, the strings after it will be-passed to the executable as arguments.--If one of the arguments starts with ``-`` it will be interpreted as-a cabal flag, so if you need to pass flags to the executable you-have to separate them with ``--``.--::-- $ cabal v2-run target -- -a -bcd --argument--'v2-run' also supports running script files that use a certain format. With-a script that looks like:--::-- #!/usr/bin/env cabal- {- cabal:- build-depends: base ^>= 4.11- , shelly ^>= 1.8.1- -}-- main :: IO ()- main = do- ...--It can either be executed like any other script, using ``cabal`` as an-interpreter, or through this command:--::-- $ cabal v2-run script.hs- $ cabal v2-run script.hs -- --arg1 # args are passed like this--cabal v2-freeze-------------------``cabal v2-freeze`` writes out a **freeze file** which records all of-the versions and flags which that are picked by the solver under the-current index and flags. Default name of this file is-``cabal.project.freeze`` but in combination with a-``--project-file=my.project`` flag (see :ref:`project-file-<cmdoption-project-file>`)-the name will be ``my.project.freeze``.-A freeze file has the same syntax as ``cabal.project`` and looks-something like this:--.. highlight:: cabal--::-- constraints: HTTP ==4000.3.3,- HTTP +warp-tests -warn-as-error -network23 +network-uri -mtl1 -conduit10,- QuickCheck ==2.9.1,- QuickCheck +templatehaskell,- -- etc...---For end-user executables, it is recommended that you distribute the-``cabal.project.freeze`` file in your source repository so that all-users see a consistent set of dependencies. For libraries, this is not-recommended: users often need to build against different versions of-libraries than what you developed against.--cabal v2-bench------------------``cabal v2-bench [TARGETS] [OPTIONS]`` runs the specified benchmarks-(all the benchmarks in the current package by default), first ensuring-they are up to date.--cabal v2-test-----------------``cabal v2-test [TARGETS] [OPTIONS]`` runs the specified test suites-(all the test suites in the current package by default), first ensuring-they are up to date.--cabal v2-haddock--------------------``cabal v2-haddock [FLAGS] [TARGET]`` builds Haddock documentation for-the specified packages within the project.--If a target is not a library :cfg-field:`haddock-benchmarks`,-:cfg-field:`haddock-executables`, :cfg-field:`haddock-internal`,-:cfg-field:`haddock-tests` will be implied as necessary.--cabal v2-exec------------------``cabal v2-exec [FLAGS] [--] COMMAND [--] [ARGS]`` runs the specified command-using the project's environment. That is, passing the right flags to compiler-invocations and bringing the project's executables into scope.--cabal v2-install--------------------``cabal v2-install [FLAGS] PACKAGES`` builds the specified packages and-symlinks/copies their executables in ``installdir`` (usually ``~/.cabal/bin``).--For example this command will build the latest ``cabal-install`` and symlink-its ``cabal`` executable:--::-- $ cabal v2-install cabal-install--In addition, it's possible to use ``cabal v2-install`` to install components-of a local project. For example, with an up-to-date Git clone of the Cabal-repository, this command will build cabal-install HEAD and symlink the-``cabal`` executable:--::-- $ cabal v2-install exe:cabal--Where symlinking is not possible (eg. on Windows), ``--install-method=copy``-can be used:--::-- $ cabal v2-install exe:cabal --install-method=copy --installdir=~/bin--Note that copied executables are not self-contained, since they might use-data-files from the store.--It is also possible to "install" libraries using the ``--lib`` flag. For-example, this command will build the latest Cabal library and install it:--::-- $ cabal v2-install --lib Cabal--This works by managing GHC environments. By default, it is writing to the-global environment in ``~/.ghc/$ARCH-$OS-$GHCVER/environments/default``.-``v2-install`` provides the ``--package-env`` flag to control which of-these environments is modified.--This command will modify the environment file in the current directory:--::-- $ cabal v2-install --lib Cabal --package-env .--This command will modify the environment file in the ``~/foo`` directory:--::-- $ cabal v2-install --lib Cabal --package-env foo/--Do note that the results of the previous two commands will be overwritten by-the use of other v2-style commands, so it is not recommended to use them inside-a project directory.--This command will modify the environment in the "local.env" file in the-current directory:--::-- $ cabal v2-install --lib Cabal --package-env local.env--This command will modify the ``myenv`` named global environment:--::-- $ cabal v2-install --lib Cabal --package-env myenv--If you wish to create a named environment file in the current directory where-the name does not contain an extension, you must reference it as ``./myenv``.--You can learn more about how to use these environments in `this section of the-GHC manual <https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/packages.html#package-environments>`_.--cabal v2-clean------------------``cabal v2-clean [FLAGS]`` cleans up the temporary files and build artifacts-stored in the ``dist-newstyle`` folder.--By default, it removes the entire folder, but it can also spare the configuration-and caches if the ``--save-config`` option is given, in which case it only removes-the build artefacts (``.hi``, ``.o`` along with any other temporary files generated-by the compiler, along with the build output).--cabal v2-sdist------------------``cabal v2-sdist [FLAGS] [TARGETS]`` takes the crucial files needed to build ``TARGETS``-and puts them into an archive format ready for upload to Hackage. These archives are stable-and two archives of the same format built from the same source will hash to the same value.--``cabal v2-sdist`` takes the following flags:--- ``-l``, ``--list-only``: Rather than creating an archive, lists files that would be included.- Output is to ``stdout`` by default. The file paths are relative to the project's root- directory.--- ``-o``, ``--output-dir``: Sets the output dir, if a non-default one is desired. The default is- ``dist-newstyle/sdist/``. ``--output-dir -`` will send output to ``stdout``- unless multiple archives are being created.--- ``-z``, ``--null``: Only used with ``--list-only``. Separates filenames with a NUL- byte instead of newlines.--``v2-sdist`` is inherently incompatible with sdist hooks, not due to implementation but due-to fundamental core invariants (same source code should result in the same tarball, byte for-byte) that must be satisfied for it to function correctly in the larger v2-build ecosystem.-``autogen-modules`` is able to replace uses of the hooks to add generated modules, along with-the custom publishing of Haddock documentation to Hackage.--.. warning::-- Packages that use Backpack will stop working if uploaded to- Hackage, due to `issue #6005 <https://github.com/haskell/cabal/issues/6005>`_.- While this is happening, we recommend not uploading these packages- to Hackage (and instead referencing the package directly- as a ``source-repository-package``).--Configuring builds with cabal.project-=====================================--``cabal.project`` files support a variety of options which configure the-details of your build. The general syntax of a ``cabal.project`` file is-similar to that of a Cabal file: there are a number of fields, some of-which live inside stanzas:--::-- packages: */*.cabal- with-compiler: /opt/ghc/8.0.1/bin/ghc-- package cryptohash- optimization: False--In general, the accepted field names coincide with the accepted command-line flags that ``cabal install`` and other commands take. For example,-``cabal v2-configure --enable-profiling`` will write out a project-file with ``profiling: True``.--The full configuration of a project is determined by combining the-following sources (later entries override earlier ones):--1. ``~/.cabal/config`` (the user-wide global configuration)--2. ``cabal.project`` (the project configuration)--3. ``cabal.project.freeze`` (the output of ``cabal v2-freeze``)--4. ``cabal.project.local`` (the output of ``cabal v2-configure``)---Specifying the local packages--------------------------------The following top-level options specify what the local packages of a-project are:--.. cfg-field:: packages: package location list (space or comma separated)- :synopsis: Project packages.-- :default: ``./*.cabal``-- Specifies the list of package locations which contain the local- packages to be built by this project. Package locations can take the- following forms:-- 1. They can specify a Cabal file, or a directory containing a Cabal- file, e.g., ``packages: Cabal cabal-install/cabal-install.cabal``.-- 2. They can specify a glob-style wildcards, which must match one or- more (a) directories containing a (single) Cabal file, (b) Cabal- files (extension ``.cabal``), or (c) tarballs which contain Cabal- packages (extension ``.tar.gz``).- For example, to match all Cabal files in all- subdirectories, as well as the Cabal projects in the parent- directories ``foo`` and ``bar``, use- ``packages: */*.cabal ../{foo,bar}/``-- 3. They can specify an ``http``, ``https`` or ``file``- URL, representing the path to a remote tarball to be downloaded- and built.-- There is no command line variant of this field; see :issue:`3585`.--.. cfg-field:: optional-packages: package location list (space or comma-separated)- :synopsis: Optional project packages.-- :default: ``./*/*.cabal``-- Like :cfg-field:`packages`, specifies a list of package locations- containing local packages to be built. Unlike :cfg-field:`packages`,- if we glob for a package, it is permissible for the glob to match against- zero packages. The intended use-case for :cfg-field:`optional-packages`- is to make it so that vendored packages can be automatically picked up if- they are placed in a subdirectory, but not error if there aren't any.-- There is no command line variant of this field.--.. cfg-field:: extra-packages: package list with version bounds (comma separated)- :synopsis: Adds external pacakges as local-- [STRIKEOUT:Specifies a list of external packages from Hackage which- should be considered local packages.] (Not implemented)-- There is no command line variant of this field.----All local packages are *vendored*, in the sense that if other packages-(including external ones from Hackage) depend on a package with the name-of a local package, the local package is preferentially used. This-motivates the default settings::-- packages: ./*.cabal- optional-packages: ./*/*.cabal--...any package can be vendored simply by making a checkout in the-top-level project directory, as might be seen in this hypothetical-directory layout::-- foo.cabal- foo-helper/ # local package- unix/ # vendored external package--All of these options support globs. ``cabal v2-build`` has its own glob-format:--- Anywhere in a path, as many times as you like, you can specify an- asterisk ``*`` wildcard. E.g., ``*/*.cabal`` matches all ``.cabal``- files in all immediate subdirectories. Like in glob(7), asterisks do- not match hidden files unless there is an explicit period, e.g.,- ``.*/foo.cabal`` will match ``.private/foo.cabal`` (but- ``*/foo.cabal`` will not).--- You can use braces to specify specific directories; e.g.,- ``{vendor,pkgs}/*.cabal`` matches all Cabal files in the ``vendor``- and ``pkgs`` subdirectories.--Formally, the format described by the following BNF:--.. todo::- convert globbing grammar to proper ABNF_ syntax--.. code-block:: abnf-- FilePathGlob ::= FilePathRoot FilePathGlobRel- FilePathRoot ::= {- empty -} # relative to cabal.project- | "/" # Unix root- | [a-zA-Z] ":" [/\\] # Windows root- | "~" # home directory- FilePathGlobRel ::= Glob "/" FilePathGlobRel # Unix directory- | Glob "\\" FilePathGlobRel # Windows directory- | Glob # file- | {- empty -} # trailing slash- Glob ::= GlobPiece *- GlobPiece ::= "*" # wildcard- | [^*{},/\\] * # literal string- | "\\" [*{},] # escaped reserved character- | "{" Glob "," ... "," Glob "}" # union (match any of these)---Specifying Packages from Remote Version Control Locations-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~--Starting with Cabal 2.4, there is now a stanza-``source-repository-package`` for specifying packages from an external-version control which supports the following fields:--- :pkg-field:`source-repository:type`-- :pkg-field:`source-repository:location`-- :pkg-field:`source-repository:tag`-- :pkg-field:`source-repository:subdir`--A simple example is shown below:--.. code-block:: cabal-- packages: .-- source-repository-package- type: git- location: https://github.com/hvr/HsYAML.git- tag: e70cf0c171c9a586b62b3f75d72f1591e4e6aaa1-- source-repository-package- type: git- location: https://github.com/well-typed/cborg- tag: 3d274c14ca3077c3a081ba7ad57c5182da65c8c1- subdir: cborg--Global configuration options-------------------------------The following top-level configuration options are not specific to any-package, and thus apply globally:---.. cfg-field:: verbose: nat- --verbose=n, -vn- :synopsis: Build verbosity level.-- :default: 1-- Control the verbosity of ``cabal`` commands, valid values are from 0- to 3.-- The command line variant of this field is ``--verbose=2``; a short- form ``-v2`` is also supported.--.. cfg-field:: jobs: nat or $ncpus- --jobs=n, -jn, --jobs=$ncpus- :synopsis: Number of builds running in parallel.-- :default: 1-- Run *nat* jobs simultaneously when building. If ``$ncpus`` is- specified, run the number of jobs equal to the number of CPUs.- Package building is often quite parallel, so turning on parallelism- can speed up build times quite a bit!-- The command line variant of this field is ``--jobs=2``; a short form- ``-j2`` is also supported; a bare ``--jobs`` or ``-j`` is equivalent- to ``--jobs=$ncpus``.--.. cfg-field:: keep-going: boolean- --keep-going- :synopsis: Try to continue building on failure.-- :default: False-- If true, after a build failure, continue to build other unaffected- packages.-- The command line variant of this field is ``--keep-going``.--.. option:: --builddir=DIR-- Specifies the name of the directory where build products for- build will be stored; defaults to ``dist-newstyle``. If a- relative name is specified, this directory is resolved relative- to the root of the project (i.e., where the ``cabal.project``- file lives.)-- This option cannot be specified via a ``cabal.project`` file.--.. _cmdoption-project-file:-.. option:: --project-file=FILE-- Specifies the name of the project file used to specify the- rest of the top-level configuration; defaults to ``cabal.project``.- This name not only specifies the name of the main project file,- but also the auxiliary project files ``cabal.project.freeze``- and ``cabal.project.local``; for example, if you specify- ``--project-file=my.project``, then the other files that will- be probed are ``my.project.freeze`` and ``my.project.local``.-- If the specified project file is a relative path, we will- look for the file relative to the current working directory,- and then for the parent directory, until the project file is- found or we have hit the top of the user's home directory.-- This option cannot be specified via a ``cabal.project`` file.--.. option:: --store-dir=DIR-- Specifies the name of the directory of the global package store.--Solver configuration options-------------------------------The following settings control the behavior of the dependency solver:--.. cfg-field:: constraints: constraints list (comma separated)- --constraint="pkg >= 2.0"- :synopsis: Extra dependencies constraints.-- Add extra constraints to the version bounds, flag settings,- and other properties a solver can pick for a- package. For example:-- ::-- constraints: bar == 2.1-- A package can be specified multiple times in ``constraints``, in- which case the specified constraints are intersected. This is- useful, since the syntax does not allow you to specify multiple- constraints at once. For example, to specify both version bounds and- flag assignments, you would write:-- ::-- constraints: bar == 2.1,- bar +foo -baz-- Valid constraints take the same form as for the `constraint- command line option- <installing-packages.html#cmdoption-setup-configure-constraint>`__.--.. cfg-field:: preferences: preference (comma separated)- --preference="pkg >= 2.0"- :synopsis: Prefered dependency versions.-- Like :cfg-field:`constraints`, but the solver will attempt to satisfy- these preferences on a best-effort basis. The resulting install is locally- optimal with respect to preferences; specifically, no single package- could be replaced with a more preferred version that still satisfies- the hard constraints.-- Operationally, preferences can cause the solver to attempt certain- version choices of a package before others, which can improve- dependency solver runtime.-- One way to use :cfg-field:`preferences` is to take a known working set of- constraints (e.g., via ``cabal v2-freeze``) and record them as- preferences. In this case, the solver will first attempt to use this- configuration, and if this violates hard constraints, it will try to- find the minimal number of upgrades to satisfy the hard constraints- again.-- The command line variant of this field is- ``--preference="pkg >= 2.0"``; to specify multiple preferences, pass- the flag multiple times.--.. cfg-field:: allow-newer: none, all or list of scoped package names (space or comma separated)- --allow-newer, --allow-newer=[none,all,[scope:][^]pkg]- :synopsis: Lift dependencies upper bound constraints.-- :default: ``none``-- Allow the solver to pick an newer version of some packages than- would normally be permitted by than the :pkg-field:`build-depends` bounds- of packages in the install plan. This option may be useful if the- dependency solver cannot otherwise find a valid install plan.-- For example, to relax ``pkg``\ s :pkg-field:`build-depends` upper bound on- ``dep-pkg``, write a scoped package name of the form:-- ::-- allow-newer: pkg:dep-pkg-- If the scope shall be limited to specific releases of ``pkg``, the- extended form as in-- ::-- allow-newer: pkg-1.2.3:dep-pkg, pkg-1.1.2:dep-pkg-- can be used to limit the relaxation of dependencies on- ``dep-pkg`` by the ``pkg-1.2.3`` and ``pkg-1.1.2`` releases only.-- The scoped syntax is recommended, as it is often only a single package- whose upper bound is misbehaving. In this case, the upper bounds of- other packages should still be respected; indeed, relaxing the bound- can break some packages which test the selected version of packages.-- The syntax also allows to prefix the dependee package with a- modifier symbol to modify the scope/semantic of the relaxation- transformation in a additional ways. Currently only one modifier- symbol is defined, i.e. ``^`` (i.e. caret) which causes the- relaxation to be applied only to ``^>=`` operators and leave all other- version operators untouched.-- However, in some situations (e.g., when attempting to build packages- on a new version of GHC), it is useful to disregard *all*- upper-bounds, with respect to a package or all packages. This can be- done by specifying just a package name, or using the keyword ``all``- to specify all packages:-- ::-- -- Disregard upper bounds involving the dependencies on- -- packages bar, baz. For quux only, relax- -- 'quux ^>= ...'-style constraints only.- allow-newer: bar, baz, ^quux-- -- Disregard all upper bounds when dependency solving- allow-newer: all-- -- Disregard all `^>=`-style upper bounds when dependency solving- allow-newer: ^all--- For consistency, there is also the explicit wildcard scope syntax- ``*`` (or its alphabetic synonym ``all``). Consequently, the- examples above are equivalent to the explicitly scoped variants:-- ::-- allow-newer: all:bar, *:baz, *:^quux-- allow-newer: *:*- allow-newer: all:all-- allow-newer: *:^*- allow-newer: all:^all-- In order to ignore all bounds specified by a package ``pkg-1.2.3``- you can combine scoping with a right-hand-side wildcard like so-- ::-- -- Disregard any upper bounds specified by pkg-1.2.3- allow-newer: pkg-1.2.3:*-- -- Disregard only `^>=`-style upper bounds in pkg-1.2.3- allow-newer: pkg-1.2.3:^*--- :cfg-field:`allow-newer` is often used in conjunction with a constraint- (in the cfg-field:`constraints` field) forcing the usage of a specific,- newer version of a package.-- The command line variant of this field is e.g. ``--allow-newer=bar``. A- bare ``--allow-newer`` is equivalent to ``--allow-newer=all``.--.. cfg-field:: allow-older: none, all, list of scoped package names (space or comma separated)- --allow-older, --allow-older=[none,all,[scope:][^]pkg]- :synopsis: Lift dependency lower bound constraints.- :since: 2.0-- :default: ``none``-- Like :cfg-field:`allow-newer`, but applied to lower bounds rather than- upper bounds.-- The command line variant of this field is ``--allow-older=all``. A- bare ``--allow-older`` is equivalent to ``--allow-older=all``.---.. cfg-field:: index-state: HEAD, unix-timestamp, ISO8601 UTC timestamp.- :synopsis: Use source package index state as it existed at a previous time.- :since: 2.0-- :default: ``HEAD``-- This allows to change the source package index state the solver uses- to compute install-plans. This is particularly useful in- combination with freeze-files in order to also freeze the state the- package index was in at the time the install-plan was frozen.-- ::-- -- UNIX timestamp format example- index-state: @1474739268-- -- ISO8601 UTC timestamp format example- -- This format is used by 'cabal v2-configure'- -- for storing `--index-state` values.- index-state: 2016-09-24T17:47:48Z---.. cfg-field:: reject-unconstrained-dependencies: all, none- --reject-unconstrained-dependencies=[all|none]- :synopsis: Restrict the solver to packages that have constraints on them.-- :default: none- :since: 2.6-- By default, the dependency solver can include any package that it's- aware of in a build plan. If you wish to restrict the build plan to- a closed set of packages (e.g., from a freeze file), use this flag.-- When set to `all`, all non-local packages that aren't goals must be- explicitly constrained. When set to `none`, the solver will- consider all packages.---Package configuration options--------------------------------Package options affect the building of specific packages. There are three-ways a package option can be specified:--- They can be specified at the top-level, in which case they apply only- to **local package**, or--- They can be specified inside a ``package`` stanza, in which case they- apply to the build of the package, whether or not it is local or- external.--- They can be specified inside an ``package *`` stanza, in which case they- apply to all packages, local ones from the project and also external- dependencies.---For example, the following options specify that :cfg-field:`optimization`-should be turned off for all local packages, and that ``bytestring`` (possibly-an external dependency) should be built with ``-fno-state-hack``::-- optimization: False-- package bytestring- ghc-options: -fno-state-hack--``ghc-options`` is not specifically described in this documentation,-but is one of many fields for configuring programs. They take the form-``progname-options`` and ``progname-location``, and-can only be set inside package stanzas. (TODO: They are not supported-at top-level, see :issue:`3579`.)--At the moment, there is no way to specify an option to apply to all-external packages or all inplace packages. Additionally, it is only-possible to specify these options on the command line for all local-packages (there is no per-package command line interface.)--Some flags were added by more recent versions of the Cabal library. This-means that they are NOT supported by packages which use Custom setup-scripts that require a version of the Cabal library older than when the-feature was added.--.. cfg-field:: flags: list of +flagname or -flagname (space separated)- --flags="+foo -bar", -ffoo, -f-bar- :synopsis: Enable or disable package flags.-- Force all flags specified as ``+flagname`` to be true, and all flags- specified as ``-flagname`` to be false. For example, to enable the- flag ``foo`` and disable ``bar``, set:-- ::-- flags: +foo -bar-- If there is no leading punctuation, it is assumed that the flag- should be enabled; e.g., this is equivalent:-- ::-- flags: foo -bar-- Flags are *per-package*, so it doesn't make much sense to specify- flags at the top-level, unless you happen to know that *all* of your- local packages support the same named flags. If a flag is not- supported by a package, it is ignored.-- See also the solver configuration field :cfg-field:`constraints`.-- The command line variant of this flag is ``--flags``. There is also- a shortened form ``-ffoo -f-bar``.-- A common mistake is to say ``cabal v2-build -fhans``, where- ``hans`` is a flag for a transitive dependency that is not in the- local package; in this case, the flag will be silently ignored. If- ``haskell-tor`` is the package you want this flag to apply to, try- ``--constraint="haskell-tor +hans"`` instead.--.. cfg-field:: with-compiler: executable- --with-compiler=executable- :synopsis: Path to compiler executable.-- Specify the path to a particular compiler to be used. If not an- absolute path, it will be resolved according to the :envvar:`PATH`- environment. The type of the compiler (GHC, GHCJS, etc) must be- consistent with the setting of the :cfg-field:`compiler` field.-- The most common use of this option is to specify a different version- of your compiler to be used; e.g., if you have ``ghc-7.8`` in your- path, you can specify ``with-compiler: ghc-7.8`` to use it.-- This flag also sets the default value of :cfg-field:`with-hc-pkg`, using- the heuristic that it is named ``ghc-pkg-7.8`` (if your executable name- is suffixed with a version number), or is the executable named- ``ghc-pkg`` in the same directory as the ``ghc`` directory. If this- heuristic does not work, set :cfg-field:`with-hc-pkg` explicitly.-- For inplace packages, ``cabal v2-build`` maintains a separate build- directory for each version of GHC, so you can maintain multiple- build trees for different versions of GHC without clobbering each- other.-- At the moment, it's not possible to set :cfg-field:`with-compiler` on a- per-package basis, but eventually we plan on relaxing this- restriction. If this is something you need, give us a shout.-- The command line variant of this flag is- ``--with-compiler=ghc-7.8``; there is also a short version- ``-w ghc-7.8``.--.. cfg-field:: with-hc-pkg: executable- --with-hc-pkg=executable- :synopsis: Specifies package tool.-- Specify the path to the package tool, e.g., ``ghc-pkg``. This- package tool must be compatible with the compiler specified by- :cfg-field:`with-compiler` (generally speaking, it should be precisely- the tool that was distributed with the compiler). If this option is- omitted, the default value is determined from :cfg-field:`with-compiler`.-- The command line variant of this flag is- ``--with-hc-pkg=ghc-pkg-7.8``.--.. cfg-field:: optimization: nat- --enable-optimization- --disable-optimization- :synopsis: Build with optimization.-- :default: ``1``-- Build with optimization. This is appropriate for production use,- taking more time to build faster libraries and programs.-- The optional *nat* value is the optimisation level. Some compilers- support multiple optimisation levels. The range is 0 to 2. Level 0- disables optimization, level 1 is the default. Level 2 is higher- optimisation if the compiler supports it. Level 2 is likely to lead- to longer compile times and bigger generated code. If you are not- planning to run code, turning off optimization will lead to better- build times and less code to be rebuilt when a module changes.-- When optimizations are enabled, Cabal passes ``-O2`` to the C compiler.-- We also accept ``True`` (equivalent to 1) and ``False`` (equivalent- to 0).-- Note that as of GHC 8.0, GHC does not recompile when optimization- levels change (see :ghc-ticket:`10923`), so if- you change the optimization level for a local package you may need- to blow away your old build products in order to rebuild with the- new optimization level.-- The command line variant of this flag is ``-O2`` (with ``-O1``- equivalent to ``-O``). There are also long-form variants- ``--enable-optimization`` and ``--disable-optimization``.--.. cfg-field:: configure-options: args (space separated)- --configure-option=arg- :synopsis: Options to pass to configure script.-- A list of extra arguments to pass to the external ``./configure``- script, if one is used. This is only useful for packages which have- the ``Configure`` build type. See also the section on- `system-dependent- parameters <developing-packages.html#system-dependent-parameters>`__.-- The command line variant of this flag is ``--configure-option=arg``,- which can be specified multiple times to pass multiple options.--.. cfg-field:: compiler: ghc, ghcjs, jhc, lhc, uhc or haskell-suite- --compiler=compiler- :synopsis: Compiler to build with.-- :default: ``ghc``-- Specify which compiler toolchain to be used. This is independent of- ``with-compiler``, because the choice of toolchain affects Cabal's- build logic.-- The command line variant of this flag is ``--compiler=ghc``.--.. cfg-field:: tests: boolean- --enable-tests- --disable-tests- :synopsis: Build tests.-- :default: ``False``-- Force test suites to be enabled. For most users this should not be- needed, as we always attempt to solve for test suite dependencies,- even when this value is ``False``; furthermore, test suites are- automatically enabled if they are requested as a built target.-- The command line variant of this flag is ``--enable-tests`` and- ``--disable-tests``.--.. cfg-field:: benchmarks: boolean- --enable-benchmarks- --disable-benchmarks- :synopsis: Build benchmarks.-- :default: ``False``-- Force benchmarks to be enabled. For most users this should not be- needed, as we always attempt to solve for benchmark dependencies,- even when this value is ``False``; furthermore, benchmarks are- automatically enabled if they are requested as a built target.-- The command line variant of this flag is ``--enable-benchmarks`` and- ``--disable-benchmarks``.--.. cfg-field:: extra-prog-path: paths (newline or comma separated)- --extra-prog-path=PATH- :synopsis: Add directories to program search path.- :since: 1.18-- A list of directories to search for extra required programs. Most- users should not need this, as programs like ``happy`` and ``alex``- will automatically be installed and added to the path. This can be- useful if a ``Custom`` setup script relies on an exotic extra- program.-- The command line variant of this flag is ``--extra-prog-path=PATH``,- which can be specified multiple times.--.. cfg-field:: run-tests: boolean- --run-tests- :synopsis: Run package test suite upon installation.-- :default: ``False``-- Run the package test suite upon installation. This is useful for- saying "When this package is installed, check that the test suite- passes, terminating the rest of the build if it is broken."-- .. warning::-- One deficiency: the :cfg-field:`run-tests` setting of a package is NOT- recorded as part of the hash, so if you install something without- :cfg-field:`run-tests` and then turn on ``run-tests``, we won't- subsequently test the package. If this is causing you problems, give- us a shout.-- The command line variant of this flag is ``--run-tests``.--Object code options-^^^^^^^^^^^^^^^^^^^--.. cfg-field:: debug-info: integer- --enable-debug-info=<n>- --disable-debug-info- :synopsis: Build with debug info enabled.- :since: 1.22-- :default: False-- If the compiler (e.g., GHC 7.10 and later) supports outputing OS- native debug info (e.g., DWARF), setting ``debug-info: True`` will- instruct it to do so. See the GHC wiki page on :ghc-wiki:`DWARF`- for more information about this feature.-- (This field also accepts numeric syntax, but until GHC 8.2 this didn't- do anything.)-- The command line variant of this flag is ``--enable-debug-info`` and- ``--disable-debug-info``.--.. cfg-field:: split-sections: boolean- --enable-split-sections- --disable-split-sections- :synopsis: Use GHC's split sections feature.- :since: 2.2-- :default: False-- Use the GHC ``-split-sections`` feature when building the library. This- reduces the final size of the executables that use the library by- allowing them to link with only the bits that they use rather than- the entire library. The downside is that building the library takes- longer and uses a bit more memory.-- This feature is supported by GHC 8.0 and later.-- The command line variant of this flag is ``--enable-split-sections`` and- ``--disable-split-sections``.--.. cfg-field:: split-objs: boolean- --enable-split-objs- --disable-split-objs- :synopsis: Use GHC's split objects feature.-- :default: False-- Use the GHC ``-split-objs`` feature when building the library. This- reduces the final size of the executables that use the library by- allowing them to link with only the bits that they use rather than- the entire library. The downside is that building the library takes- longer and uses considerably more memory.-- It is generally recommend that you use ``split-sections`` instead- of ``split-objs`` where possible.-- The command line variant of this flag is ``--enable-split-objs`` and- ``--disable-split-objs``.--.. cfg-field:: executable-stripping: boolean- --enable-executable-stripping- --disable-executable-stripping- :synopsis: Strip installed programs.-- :default: True-- When installing binary executable programs, run the ``strip``- program on the binary. This can considerably reduce the size of the- executable binary file. It does this by removing debugging- information and symbols.-- Not all Haskell implementations generate native binaries. For such- implementations this option has no effect.-- If ``debug-info`` is set explicitly then ``executable-stripping`` is set- to ``False`` as otherwise all the debug symbols will be stripped.-- The command line variant of this flag is- ``--enable-executable-stripping`` and- ``--disable-executable-stripping``.--.. cfg-field:: library-stripping: boolean- --enable-library-stripping- --disable-library-stripping- :synopsis: Strip installed libraries.- :since: 1.20-- When installing binary libraries, run the ``strip`` program on the- binary, saving space on the file system. See also- ``executable-stripping``.-- If ``debug-info`` is set explicitly then ``library-stripping`` is set- to ``False`` as otherwise all the debug symbols will be stripped.-- The command line variant of this flag is- ``--enable-library-stripping`` and ``--disable-library-stripping``.--Executable options-^^^^^^^^^^^^^^^^^^--.. cfg-field:: program-prefix: prefix- --program-prefix=prefix- :synopsis: Prepend prefix to program names.-- [STRIKEOUT:Prepend *prefix* to installed program names.] (Currently- implemented in a silly and not useful way. If you need this to work- give us a shout.)-- *prefix* may contain the following path variables: ``$pkgid``,- ``$pkg``, ``$version``, ``$compiler``, ``$os``, ``$arch``, ``$abi``,- ``$abitag``-- The command line variant of this flag is ``--program-prefix=foo-``.--.. cfg-field:: program-suffix: suffix- --program-suffix=suffix- :synopsis: Append refix to program names.-- [STRIKEOUT:Append *suffix* to installed program names.] (Currently- implemented in a silly and not useful way. If you need this to work- give us a shout.)-- The most obvious use for this is to append the program's version- number to make it possible to install several versions of a program- at once: ``program-suffix: $version``.-- *suffix* may contain the following path variables: ``$pkgid``,- ``$pkg``, ``$version``, ``$compiler``, ``$os``, ``$arch``, ``$abi``,- ``$abitag``-- The command line variant of this flag is- ``--program-suffix='$version'``.--Dynamic linking options-^^^^^^^^^^^^^^^^^^^^^^^--.. cfg-field:: shared: boolean- --enable-shared- --disable-shared- :synopsis: Build shared library.-- :default: False-- Build shared library. This implies a separate compiler run to- generate position independent code as required on most platforms.-- The command line variant of this flag is ``--enable-shared`` and- ``--disable-shared``.--.. cfg-field:: executable-dynamic: boolean- --enable-executable-dynamic- --disable-executable-dynamic- :synopsis: Link executables dynamically.-- :default: False-- Link executables dynamically. The executable's library dependencies- should be built as shared objects. This implies ``shared: True``- unless ``shared: False`` is explicitly specified.-- The command line variant of this flag is- ``--enable-executable-dynamic`` and- ``--disable-executable-dynamic``.--.. cfg-field:: library-for-ghci: boolean- --enable-library-for-ghci- --disable-library-for-ghci- :synopsis: Build libraries suitable for use with GHCi.-- :default: True-- Build libraries suitable for use with GHCi. This involves an extra- linking step after the build.-- Not all platforms support GHCi and indeed on some platforms, trying- to build GHCi libs fails. In such cases, consider setting- ``library-for-ghci: False``.-- The command line variant of this flag is- ``--enable-library-for-ghci`` and ``--disable-library-for-ghci``.--.. cfg-field:: relocatable:- --relocatable- :synopsis: Build relocatable package.- :since: 1.22-- :default: False-- [STRIKEOUT:Build a package which is relocatable.] (TODO: It is not- clear what this actually does, or if it works at all.)-- The command line variant of this flag is ``--relocatable``.--Static linking options-^^^^^^^^^^^^^^^^^^^^^^--.. cfg-field:: static: boolean- --enable-static- --disable-static- :synopsis: Build static library.--- :default: False-- Roll this and all dependent libraries into a combined ``.a`` archive.- This uses GHCs ``-staticlib`` flag, which is available for iOS and with- GHC 8.4 and later for other platforms as well.--.. cfg-field:: executable-static: boolean- --enable-executable-static- --disable-executable-static- :synopsis: Build fully static executables.--- :default: False-- Build fully static executables.- This link all dependent libraries into executables statically,- including libc.- This passes ``-static`` and ``-optl=-static`` to GHC.--Foreign function interface options-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--.. cfg-field:: extra-include-dirs: directories (comma or newline separated list)- --extra-include-dirs=DIR- :synopsis: Adds C header search path.-- An extra directory to search for C header files. You can use this- flag multiple times to get a list of directories.-- You might need to use this flag if you have standard system header- files in a non-standard location that is not mentioned in the- package's ``.cabal`` file. Using this option has the same affect as- appending the directory *dir* to the :pkg-field:`include-dirs` field in each- library and executable in the package's ``.cabal`` file. The- advantage of course is that you do not have to modify the package at- all. These extra directories will be used while building the package- and for libraries it is also saved in the package registration- information and used when compiling modules that use the library.-- The command line variant of this flag is- ``--extra-include-dirs=DIR``, which can be specified multiple times.--.. cfg-field:: extra-lib-dirs: directories (comma or newline separated list)- --extra-lib-dirs=DIR- :synopsis: Adds library search directory.-- An extra directory to search for system libraries files.-- The command line variant of this flag is ``--extra-lib-dirs=DIR``,- which can be specified multiple times.--.. cfg-field:: extra-framework-dirs: directories (comma or newline separated list)- --extra-framework-dirs=DIR- :synopsis: Adds framework search directory (OS X only).-- An extra directory to search for frameworks (OS X only).-- You might need to use this flag if you have standard system- libraries in a non-standard location that is not mentioned in the- package's ``.cabal`` file. Using this option has the same affect as- appending the directory *dir* to the :cfg-field:`extra-lib-dirs` field in- each library and executable in the package's ``.cabal`` file. The- advantage of course is that you do not have to modify the package at- all. These extra directories will be used while building the package- and for libraries it is also saved in the package registration- information and used when compiling modules that use the library.-- The command line variant of this flag is- ``--extra-framework-dirs=DIR``, which can be specified multiple- times.--Profiling options-^^^^^^^^^^^^^^^^^--.. cfg-field:: profiling: boolean- --enable-profiling- --disable-profiling- :synopsis: Enable profiling builds.- :since: 1.22-- :default: False-- Build libraries and executables with profiling enabled (for- compilers that support profiling as a separate mode). It is only- necessary to specify :cfg-field:`profiling` for the specific package you- want to profile; ``cabal v2-build`` will ensure that all of its- transitive dependencies are built with profiling enabled.-- To enable profiling for only libraries or executables, see- :cfg-field:`library-profiling` and :cfg-field:`executable-profiling`.-- For useful profiling, it can be important to control precisely what- cost centers are allocated; see :cfg-field:`profiling-detail`.-- The command line variant of this flag is ``--enable-profiling`` and- ``--disable-profiling``.--.. cfg-field:: profiling-detail: level- --profiling-detail=level- :synopsis: Profiling detail level.- :since: 1.24-- Some compilers that support profiling, notably GHC, can allocate- costs to different parts of the program and there are different- levels of granularity or detail with which this can be done. In- particular for GHC this concept is called "cost centers", and GHC- can automatically add cost centers, and can do so in different ways.-- This flag covers both libraries and executables, but can be- overridden by the ``library-profiling-detail`` field.-- Currently this setting is ignored for compilers other than GHC. The- levels that cabal currently supports are:-- default- For GHC this uses ``exported-functions`` for libraries and- ``toplevel-functions`` for executables.- none- No costs will be assigned to any code within this component.- exported-functions- Costs will be assigned at the granularity of all top level- functions exported from each module. In GHC, this- is for non-inline functions. Corresponds to ``-fprof-auto-exported``.- toplevel-functions- Costs will be assigned at the granularity of all top level- functions in each module, whether they are exported from the- module or not. In GHC specifically, this is for non-inline- functions. Corresponds to ``-fprof-auto-top``.- all-functions- Costs will be assigned at the granularity of all functions in- each module, whether top level or local. In GHC specifically,- this is for non-inline toplevel or where-bound functions or- values. Corresponds to ``-fprof-auto``.-- The command line variant of this flag is- ``--profiling-detail=none``.--.. cfg-field:: library-profiling-detail: level- --library-profiling-detail=level- :synopsis: Libraries profiling detail level.- :since: 1.24-- Like :cfg-field:`profiling-detail`, but applied only to libraries-- The command line variant of this flag is- ``--library-profiling-detail=none``.--.. cfg-field:: library-vanilla: boolean- --enable-library-vanilla- --disable-library-vanilla- :synopsis: Build libraries without profiling.-- :default: True-- Build ordinary libraries (as opposed to profiling libraries).- Mostly, you can set this to False to avoid building ordinary- libraries when you are profiling.-- The command line variant of this flag is- ``--enable-library-vanilla`` and ``--disable-library-vanilla``.--.. cfg-field:: library-profiling: boolean- --enable-library-profiling- --disable-library-profiling- :synopsis: Build libraries with profiling enabled.- :since: 1.22-- :default: False-- Build libraries with profiling enabled. You probably want- to use :cfg-field:`profiling` instead.-- The command line variant of this flag is- ``--enable-library-profiling`` and ``--disable-library-profiling``.--.. cfg-field:: executable-profiling: boolean- --enable-executable-profiling- --disable-executable-profiling- :synopsis: Build executables with profiling enabled.- :since: 1.22-- :default: False-- Build executables with profiling enabled. You probably want- to use :cfg-field:`profiling` instead.-- The command line variant of this flag is- ``--enable-executable-profiling`` and- ``--disable-executable-profiling``.--Coverage options-^^^^^^^^^^^^^^^^--.. cfg-field:: coverage: boolean- --enable-coverage- --disable-coverage- :synopsis: Build with coverage enabled.- :since: 1.22-- :default: False-- Build libraries and executables (including test suites) with Haskell- Program Coverage enabled. Running the test suites will automatically- generate coverage reports with HPC.-- The command line variant of this flag is ``--enable-coverage`` and- ``--disable-coverage``.--.. cfg-field:: library-coverage: boolean- --enable-library-coverage- --disable-library-coverage- :since: 1.22- :deprecated:-- :default: False-- Deprecated, use :cfg-field:`coverage`.-- The command line variant of this flag is- ``--enable-library-coverage`` and ``--disable-library-coverage``.--Haddock options-^^^^^^^^^^^^^^^--.. cfg-field:: documentation: boolean- --enable-documentation- --disable-documentation- :synopsis: Enable building of documentation.-- :default: False-- Enables building of Haddock documentation-- The command line variant of this flag is ``--enable-documentation``- and ``--disable-documentation``.-- `documentation: true` does not imply :cfg-field:`haddock-benchmarks`,- :cfg-field:`haddock-executables`, :cfg-field:`haddock-internal` or- :cfg-field:`haddock-tests`. These need to be enabled separately if- desired.--.. cfg-field:: doc-index-file: templated path- --doc-index-file=TEMPLATE- :synopsis: Path to haddock templates.-- A central index of Haddock API documentation (template cannot use- ``$pkgid``), which should be updated as documentation is built.-- The command line variant of this flag is- ``--doc-index-file=TEMPLATE``--The following commands are equivalent to ones that would be passed when-running ``setup haddock``. (TODO: Where does the documentation get put.)--.. cfg-field:: haddock-hoogle: boolean- :synopsis: Generate Hoogle file.-- :default: False-- Generate a text file which can be converted by Hoogle_- into a database for searching. This is equivalent to running ``haddock``- with the ``--hoogle`` flag.-- The command line variant of this flag is ``--hoogle`` (for the- ``haddock`` command).--.. cfg-field:: haddock-html: boolean- :synopsis: Build HTML documentation.-- :default: True-- Build HTML documentation.-- The command line variant of this flag is ``--html`` (for the- ``haddock`` command).--.. cfg-field:: haddock-html-location: templated path- --html-location=TEMPLATE- :synopsis: Haddock HTML templates location.-- Specify a template for the location of HTML documentation for- prerequisite packages. The substitutions are applied to the template- to obtain a location for each package, which will be used by- hyperlinks in the generated documentation. For example, the- following command generates links pointing at [Hackage] pages:-- ::-- html-location: http://hackage.haskell.org/packages/archive/$pkg/latest/doc/html-- The command line variant of this flag is ``--html-location`` (for- the ``haddock`` subcommand).-- ::-- --html-location='http://hackage.haskell.org/packages/archive/$pkg/latest/doc/html'-- Here the argument is quoted to prevent substitution by the shell. If- this option is omitted, the location for each package is obtained- using the package tool (e.g. ``ghc-pkg``).--.. cfg-field:: haddock-executables: boolean- :synopsis: Generate documentation for executables.-- :default: False-- Run haddock on all executable programs.-- The command line variant of this flag is ``--executables`` (for the- ``haddock`` subcommand).--.. cfg-field:: haddock-tests: boolean- :synopsis: Generate documentation for tests.-- :default: False-- Run haddock on all test suites.-- The command line variant of this flag is ``--tests`` (for the- ``haddock`` subcommand).--.. cfg-field:: haddock-benchmarks: boolean- :synopsis: Generate documentation for benchmarks.-- :default: False-- Run haddock on all benchmarks.-- The command line variant of this flag is ``--benchmarks`` (for the- ``haddock`` subcommand).--.. cfg-field:: haddock-all: boolean- :synopsis: Generate documentation for everything-- :default: False-- Run haddock on all components.-- The command line variant of this flag is ``--all`` (for the- ``haddock`` subcommand).--.. cfg-field:: haddock-internal: boolean- :synopsis: Generate documentation for internal modules-- :default: False-- Build haddock documentation which includes unexposed modules and- symbols.-- The command line variant of this flag is ``--internal`` (for the- ``haddock`` subcommand).--.. cfg-field:: haddock-css: path- :synopsis: Location of Haddoc CSS file.-- The CSS file that should be used to style the generated- documentation (overriding haddock's default.)-- The command line variant of this flag is ``--css`` (for the- ``haddock`` subcommand).--.. cfg-field:: haddock-hyperlink-source: boolean- :synopsis: Generate hyperlinked source code for documentation-- :default: False-- Generated hyperlinked source code using `HsColour`_, and have- Haddock documentation link to it.-- The command line variant of this flag is ``--hyperlink-source`` (for- the ``haddock`` subcommand).--.. cfg-field:: haddock-hscolour-css: path- :synopsis: Location of CSS file for HsColour-- The CSS file that should be used to style the generated hyperlinked- source code (from `HsColour`_).-- The command line variant of this flag is ``--hscolour-css`` (for the- ``haddock`` subcommand).--.. cfg-field:: haddock-contents-location: URL- :synopsis: URL for contents page.-- A baked-in URL to be used as the location for the contents page.-- The command line variant of this flag is ``--contents-location``- (for the ``haddock`` subcommand).--.. cfg-field:: haddock-keep-temp-files: boolean- :synopsis: Keep temporary Haddock files.-- Keep temporary files.-- The command line variant of this flag is ``--keep-temp-files`` (for- the ``haddock`` subcommand).--Advanced global configuration options----------------------------------------.. cfg-field:: write-ghc-environment-files: always, never, or ghc8.4.4+- --write-ghc-environment-files=policy- :synopsis: Whether a ``.ghc.environment`` should be created after a successful build.-- :default: ``never``-- Whether a `GHC package environment file <https://downloads.haskell.org/~ghc/master/users-guide/packages.html#package-environments>`_- should be created after a successful build.-- Since Cabal 3.0, defaults to ``never``. Before that, defaulted to- creating them only when compiling with GHC 8.4.4 and older (GHC- 8.4.4 `is the first version- <https://ghc.haskell.org/trac/ghc/ticket/13753>`_ that supports- the ``-package-env -`` option that allows ignoring the package- environment files).---.. cfg-field:: http-transport: curl, wget, powershell, or plain-http- --http-transport=transport- :synopsis: Transport to use with http(s) requests.-- :default: ``curl``-- Set a transport to be used when making http(s) requests.-- The command line variant of this field is ``--http-transport=curl``.--.. cfg-field:: ignore-expiry: boolean- --ignore-expiry- :synopsis: Ignore Hackage expiration dates.-- :default: False-- If ``True``, we will ignore expiry dates on metadata from Hackage.-- In general, you should not set this to ``True`` as it will leave you- vulnerable to stale cache attacks. However, it may be temporarily- useful if the main Hackage server is down, and we need to rely on- mirrors which have not been updated for longer than the expiry- period on the timestamp.-- The command line variant of this field is ``--ignore-expiry``.--.. cfg-field:: remote-repo-cache: directory- --remote-repo-cache=DIR- :synopsis: Location of packages cache.-- :default: ``~/.cabal/packages``-- [STRIKEOUT:The location where packages downloaded from remote- repositories will be cached.] Not implemented yet.-- The command line variant of this flag is- ``--remote-repo-cache=DIR``.--.. cfg-field:: logs-dir: directory- --logs-dir=DIR- :synopsis: Directory to store build logs.-- :default: ``~/.cabal/logs``-- [STRIKEOUT:The location where build logs for packages are stored.]- Not implemented yet.-- The command line variant of this flag is ``--logs-dir=DIR``.--.. cfg-field:: build-summary: template filepath- --build-summary=TEMPLATE- :synopsis: Build summaries location.-- :default: ``~/.cabal/logs/build.log``-- [STRIKEOUT:The file to save build summaries. Valid variables which- can be used in the path are ``$pkgid``, ``$compiler``, ``$os`` and- ``$arch``.] Not implemented yet.-- The command line variant of this flag is- ``--build-summary=TEMPLATE``.--.. cfg-field:: local-repo: directory- --local-repo=DIR- :deprecated:-- [STRIKEOUT:The location of a local repository.] Deprecated. See- "Legacy repositories."-- The command line variant of this flag is ``--local-repo=DIR``.--.. cfg-field:: world-file: path- --world-file=FILE- :deprecated:-- [STRIKEOUT:The location of the world file.] Deprecated.-- The command line variant of this flag is ``--world-file=FILE``.--Undocumented fields: ``root-cmd``, ``symlink-bindir``, ``build-log``,-``remote-build-reporting``, ``report-planned-failure``, ``one-shot``,-``offline``.--Advanced solver options-^^^^^^^^^^^^^^^^^^^^^^^--Most users generally won't need these.--.. cfg-field:: solver: modular- --solver=modular- :synopsis: Which solver to use.-- This field is reserved to allow the specification of alternative- dependency solvers. At the moment, the only accepted option is- ``modular``.-- The command line variant of this field is ``--solver=modular``.--.. cfg-field:: max-backjumps: nat- --max-backjumps=N- :synopsis: Maximum number of solver backjumps.-- :default: 4000-- Maximum number of backjumps (backtracking multiple steps) allowed- while solving. Set -1 to allow unlimited backtracking, and 0 to- disable backtracking completely.-- The command line variant of this field is ``--max-backjumps=4000``.--.. cfg-field:: reorder-goals: boolean- --reorder-goals- --no-reorder-goals- :synopsis: Allow solver to reorder goals.-- :default: False-- When enabled, the solver will reorder goals according to certain- heuristics. Slows things down on average, but may make backtracking- faster for some packages. It's unlikely to help for small projects,- but for big install plans it may help you find a plan when otherwise- this is not possible. See :issue:`1780` for more commentary.-- The command line variant of this field is ``--(no-)reorder-goals``.--.. cfg-field:: count-conflicts: boolean- --count-conflicts- --no-count-conflicts- :synopsis: Solver prefers versions with less conflicts.-- :default: True-- Try to speed up solving by preferring goals that are involved in a- lot of conflicts.-- The command line variant of this field is- ``--(no-)count-conflicts``.--.. cfg-field:: minimize-conflict-set: boolean- --minimize-conflict-set- --no-minimize-conflict-set- :synopsis: Try to improve the solver error message when there is no- solution.-- :default: False-- When there is no solution, try to improve the solver error message- by finding a minimal conflict set. This option may increase run- time significantly, so it is off by default.-- The command line variant of this field is- ``--(no-)minimize-conflict-set``.--.. cfg-field:: strong-flags: boolean- --strong-flags- --no-strong-flags- :synopsis: Do not defer flag choices when solving.-- :default: False-- Do not defer flag choices. (TODO: Better documentation.)-- The command line variant of this field is ``--(no-)strong-flags``.--.. cfg-field:: allow-boot-library-installs: boolean- --allow-boot-library-installs- --no-allow-boot-library-installs- :synopsis: Allow cabal to install or upgrade any package.-- :default: False-- By default, the dependency solver doesn't allow ``base``,- ``ghc-prim``, ``integer-simple``, ``integer-gmp``, and- ``template-haskell`` to be installed or upgraded. This flag- removes the restriction.-- The command line variant of this field is- ``--(no-)allow-boot-library-installs``.--.. cfg-field:: cabal-lib-version: version- --cabal-lib-version=version- :synopsis: Version of Cabal library used to build package.-- This field selects the version of the Cabal library which should be- used to build packages. This option is intended primarily for- internal development use (e.g., forcing a package to build with a- newer version of Cabal, to test a new version of Cabal.) (TODO:- Specify its semantics more clearly.)-- The command line variant of this field is- ``--cabal-lib-version=1.24.0.1``.--.. include:: references.inc+ $ cabal v2-build all++To build a specific package, you can either run ``v2-build`` from the+directory of the package in question:++::++ $ cd cabal-install+ $ cabal v2-build++or you can pass the name of the package as an argument to+``cabal v2-build`` (this works in any subdirectory of the project):++::++ $ cabal v2-build cabal-install++You can also specify a specific component of the package to build. For+example, to build a test suite named ``package-tests``, use the command:++::++ $ cabal v2-build package-tests++Targets can be qualified with package names. So to request+``package-tests`` *from* the ``Cabal`` package, use+``Cabal:package-tests``.++Unlike sandboxes, there is no need to setup a sandbox or ``add-source``+projects; just check in ``cabal.project`` to your repository and+``v2-build`` will just work.++Cookbook+========++How can I profile my library/application?+-----------------------------------------++Create or edit your ``cabal.project.local``, adding the following+line::++ profiling: True++Now, ``cabal v2-build`` will automatically build all libraries and+executables with profiling. You can fine-tune the profiling settings+for each package using :cfg-field:`profiling-detail`::++ package p+ profiling-detail: toplevel-functions++Alternately, you can call ``cabal v2-build --enable-profiling`` to+temporarily build with profiling.++How it works+============++Local versus external packages+------------------------------++One of the primary innovations of Nix-style local builds is the+distinction between local packages, which users edit and recompile and+must be built per-project, versus external packages, which can be cached+across projects. To be more precise:++1. A **local package** is one that is listed explicitly in the+ ``packages``, ``optional-packages`` or ``extra-packages`` field of a+ project. Usually, these refer to packages whose source code lives+ directly in a folder in your project. But you can list an+ arbitrary Hackage package in :cfg-field:`packages`+ to force it to be treated as local.++Local packages, as well as the external packages (below) which depend on+them, are built **inplace**, meaning that they are always built+specifically for the project and are not installed globally. Inplace+packages are not cached and not given unique hashes, which makes them+suitable for packages which you want to edit and recompile.++2. An **external package** is any package which is not listed in the+ ``packages`` field. The source code for external packages is usually+ retrieved from Hackage.++When an external package does not depend on an inplace package, it can+be built and installed to a **global** store, which can be shared across+projects. These build products are identified by a hash based on all of+the inputs which influence the compilation of a package (flags,+dependency selection, etc.). Just as in Nix, these hashes uniquely+identify the result of a build; if we compute this identifier and we+find that we already have this ID built, we can just use the already+built version.++The global package store is ``~/.cabal/store`` (configurable via+global `store-dir` option); if you need to clear your store for+whatever reason (e.g., to reclaim disk space or because the global+store is corrupted), deleting this directory is safe (``v2-build``+will just rebuild everything it needs on its next invocation).++This split motivates some of the UI choices for Nix-style local build+commands. For example, flags passed to ``cabal v2-build`` are only+applied to *local* packages, so that adding a flag to+``cabal v2-build`` doesn't necessitate a rebuild of *every* transitive+dependency in the global package store.++In cabal-install 2.0 and above, Nix-style local builds also take advantage of a+new Cabal library feature, `per-component+builds <https://github.com/ezyang/ghc-proposals/blob/master/proposals/0000-componentized-cabal.rst>`__,+where each component of a package is configured and built separately.+This can massively speed up rebuilds of packages with lots of components+(e.g., a package that defines multiple executables), as only one+executable needs to be rebuilt. Packages that use Custom setup scripts+are not currently built on a per-component basis.++Where are my build products?+----------------------------++A major deficiency in the current implementation of v2-build is that+there is no programmatic way to access the location of build products.+The location of the build products is intended to be an internal+implementation detail of v2-build, but we also understand that many+unimplemented features can only be reasonably worked around by+accessing build products directly.++The location where build products can be found varies depending on the+version of cabal-install:++- In cabal-install-1.24, the dist directory for a package ``p-0.1`` is+ stored in ``dist-newstyle/build/p-0.1``. For example, if you built an+ executable or test suite named ``pexe``, it would be located at+ ``dist-newstyle/build/p-0.1/build/pexe/pexe``.++- In cabal-install-2.0, the dist directory for a package ``p-0.1``+ defining a library built with GHC 8.0.1 on 64-bit Linux is+ ``dist-newstyle/build/x86_64-linux/ghc-8.0.1/p-0.1``. When+ per-component builds are enabled (any non-Custom package), a+ subcomponent like an executable or test suite named ``pexe`` will be+ stored at+ ``dist-newstyle/build/x86_64-linux/ghc-8.0.1/p-0.1/c/pexe``; thus,+ the full path of the executable is+ ``dist-newstyle/build/x86_64-linux/ghc-8.0.1/p-0.1/c/pexe/build/pexe/pexe``+ (you can see why we want this to be an implementation detail!)++- In cabal-install-2.2 and above, the ``/c/`` part of the above path+ is replaced with one of ``/l/``, ``/x/``, ``/f/``, ``/t/``, or+ ``/b/``, depending on the type of component (sublibrary,+ executable, foreign library, test suite, or benchmark+ respectively). So the full path to an executable named ``pexe``+ compiled with GHC 8.0.1 on a 64-bit Linux is now+ ``dist-newstyle/build/x86_64-linux/ghc-8.0.1/p-0.1/x/pexe/build/pexe/pexe``;+ for a benchmark named ``pbench`` it now is+ ``dist-newstyle/build/x86_64-linux/ghc-8.0.1/p-0.1/b/pbench/build/pbench/pbench``;+++The paths are a bit longer in 2.0 and above but the benefit is that you can+transparently have multiple builds with different versions of GHC. We+plan to add the ability to create aliases for certain build+configurations, and more convenient paths to access particularly useful+build products like executables.++Caching+-------++Nix-style local builds sport a robust caching system which helps to reduce+the time it takes to execute a rebuild cycle. While the details of how+``cabal-install`` does caching are an implementation detail and may+change in the future, knowing what gets cached is helpful for+understanding the performance characteristics of invocations to+``v2-build``. The cached intermediate results are stored in+``dist-newstyle/cache``; this folder can be safely deleted to clear the+cache.++The following intermediate results are cached in the following files in+this folder (the most important two are first):++``solver-plan`` (binary)+ The result of calling the dependency solver, assuming that the+ Hackage index, local ``cabal.project`` file, and local ``cabal``+ files are unmodified. (Notably, we do NOT have to dependency solve+ again if new build products are stored in the global store; the+ invocation of the dependency solver is independent of what is+ already available in the store.)+``source-hashes`` (binary)+ The hashes of all local source files. When all local source files of+ a local package are unchanged, ``cabal v2-build`` will skip+ invoking ``setup build`` entirely (saving us from a possibly+ expensive call to ``ghc --make``). The full list of source files+ participating in compilation is determined using+ ``cabal sdist --list-only``. Thus if you do not list all your+ source files in a Cabal file, Cabal may fail to recompile when you+ edit them.+``config`` (same format as ``cabal.project``)+ The full project configuration, merged from ``cabal.project`` (and+ friends) as well as the command line arguments.+``compiler`` (binary)+ The configuration of the compiler being used to build the project.+``improved-plan`` (binary)+ Like ``solver-plan``, but with all non-inplace packages improved+ into pre-existing copies from the store.+``plan.json`` (JSON)+ A JSON serialization of the computed install plan intended+ for integrating ``cabal`` with external tooling.+ The `cabal-plan <http://hackage.haskell.org/package/cabal-plan>`__+ package provides a library for parsing ``plan.json`` files into a+ Haskell data structure as well as an example tool showing possible+ applications.++ .. todo::++ Document JSON schema (including version history of schema)+++Note that every package also has a local cache managed by the Cabal+build system, e.g., in ``$distdir/cache``.
cabal/Cabal/doc/references.inc view
@@ -23,4 +23,4 @@ .. _ABNF: https://tools.ietf.org/html/rfc5234 -.. _Backpack: https://ghc.haskell.org/trac/ghc/wiki/Backpack+.. _Backpack: https://gitlab.haskell.org/ghc/ghc/-/wikis/backpack
+ cabal/Cabal/doc/requirements.txt view
@@ -0,0 +1,2 @@+sphinx == 3.1.*+sphinx_rtd_theme
+ cabal/Cabal/doc/setup-commands.rst view
@@ -0,0 +1,1422 @@+Setup.hs Commands+=================++.. highlight:: console++The low-level Cabal interface is implemented using ``Setup.hs`` scripts.+You should prefer using higher level interface provided by+nix-style builds.++::++ $ runhaskell Setup.hs [command] [option...]++For the summary of the command syntax, run:++::++ $ runhaskell Setup.hs --help++Building and installing a system package+----------------------------------------++::++ $ runhaskell Setup.hs configure --ghc+ $ runhaskell Setup.hs build+ $ runhaskell Setup.hs install++The first line readies the system to build the tool using GHC; for+example, it checks that GHC exists on the system. The second line+performs the actual building, while the last both copies the build+results to some permanent place and registers the package with GHC.++.. note ::+ + Global installing of packages is not recommended.+ The :ref:`Nix-style builds<nix-style-builds>` is the preferred way of building and installing+ packages.++Creating a binary package+-------------------------++When creating binary packages (e.g. for Red Hat or Debian) one needs to+create a tarball that can be sent to another system for unpacking in the+root directory:++::++ $ runhaskell Setup.hs configure --prefix=/usr+ $ runhaskell Setup.hs build+ $ runhaskell Setup.hs copy --destdir=/tmp/mypkg+ $ tar -czf mypkg.tar.gz /tmp/mypkg/++If the package contains a library, you need two additional steps:++::++ $ runhaskell Setup.hs register --gen-script+ $ runhaskell Setup.hs unregister --gen-script++This creates shell scripts ``register.sh`` and ``unregister.sh``, which+must also be sent to the target system. After unpacking there, the+package must be registered by running the ``register.sh`` script. The+``unregister.sh`` script would be used in the uninstall procedure of the+package. Similar steps may be used for creating binary packages for+Windows.++The following options are understood by all commands:++.. program:: setup++.. option:: --help, -h or -?++ List the available options for the command.++.. option:: --verbose=n or -v n++ Set the verbosity level (0-3). The normal level is 1; a missing *n*+ defaults to 2.++ There is also an extended version of this command which can be+ used to fine-tune the verbosity of output. It takes the+ form ``[silent|normal|verbose|debug]``\ *flags*, where *flags*+ is a list of ``+`` flags which toggle various aspects of+ output. At the moment, only ``+callsite`` and ``+callstack``+ are supported, which respectively toggle call site and call+ stack printing (these are only supported if Cabal+ is built with a sufficiently recent GHC.)++The various commands and the additional options they support are+described below. In the simple build infrastructure, any other options+will be reported as errors.++.. _setup-configure:++runhaskell Setup.hs configure+-----------------------------++.. program:: runhaskell Setup.hs configure++Prepare to build the package. Typically, this step checks that the+target platform is capable of building the package, and discovers+platform-specific features that are needed during the build.++The user may also adjust the behaviour of later stages using the options+listed in the following subsections. In the simple build infrastructure,+the values supplied via these options are recorded in a private file+read by later stages.++If a user-supplied ``configure`` script is run (see the section on+`system-dependent+parameters <developing-packages.html#system-dependent-parameters>`__ or+on `complex+packages <developing-packages.html#more-complex-packages>`__), it is+passed the :option:`--with-hc-pkg`, :option:`--prefix`, :option:`--bindir`,+:option:`--libdir`, :option:`--dynlibdir`, :option:`--datadir`, :option:`--libexecdir` and+:option:`--sysconfdir` options. In addition the value of the+:option:`--with-compiler` option is passed in a :option:`--with-hc-pkg` option+and all options specified with :option:`--configure-option` are passed on.++.. note::+ `GNU autoconf places restrictions on paths, including the directory+ that the package is built from.+ <https://www.gnu.org/software/autoconf/manual/autoconf.html#File-System-Conventions>`_+ The errors produced when this happens can be obscure; Cabal attempts to+ detect and warn in this situation, but it is not perfect.++In Cabal 2.0, support for a single positional argument was added to+``runhaskell Setup.hs configure`` This makes Cabal configure the specific component to+be configured. Specified names can be qualified with ``lib:`` or+``exe:`` in case just a name is ambiguous (as would be the case for a+package named ``p`` which has a library and an executable named ``p``.)+This has the following effects:++- Subsequent invocations of ``cabal build``, ``register``, etc. operate only+ on the configured component.++- Cabal requires all "internal" dependencies (e.g., an executable+ depending on a library defined in the same package) must be found in+ the set of databases via :option:`--package-db` (and related flags): these+ dependencies are assumed to be up-to-date. A dependency can be+ explicitly specified using :option:`--dependency` simply by giving the name+ of the internal library; e.g., the dependency for an internal library+ named ``foo`` is given as+ ``--dependency=pkg-internal=pkg-1.0-internal-abcd``.++- Only the dependencies needed for the requested component are+ required. Similarly, when :option:`--exact-configuration` is specified,+ it's only necessary to specify :option:`--dependency` for the component.+ (As mentioned previously, you *must* specify internal dependencies as+ well.)++- Internal ``build-tool-depends`` and ``build-tools`` dependencies are expected+ to be in the ``PATH`` upon subsequent invocations of ``setup``.++Full details can be found in the `Componentized Cabal+proposal <https://github.com/ezyang/ghc-proposals/blob/master/proposals/0000-componentized-cabal.rst>`__.++Programs used for building+^^^^^^^^^^^^^^^^^^^^^^^^^^++The following options govern the programs used to process the source+files of a package:++.. option:: --ghc or -g, --jhc, --lhc, --uhc++ Specify which Haskell implementation to use to build the package. At+ most one of these flags may be given. If none is given, the+ implementation under which the setup script was compiled or+ interpreted is used.++.. option:: --with-compiler=path or -w *path*++ Specify the path to a particular compiler. If given, this must match+ the implementation selected above. The default is to search for the+ usual name of the selected implementation.++ This flag also sets the default value of the :option:`--with-hc-pkg`+ option to the package tool for this compiler. Check the output of+ ``runhaskell Setup.hs configure -v`` to ensure that it finds the right package+ tool (or use :option:`--with-hc-pkg` explicitly).++.. option:: --with-hc-pkg=path++ Specify the path to the package tool, e.g. ``ghc-pkg``. The package+ tool must be compatible with the compiler specified by+ :option:`--with-compiler`. If this option is omitted, the default value is+ determined from the compiler selected.++.. option:: --with-prog=path++ Specify the path to the program *prog*. Any program known to Cabal+ can be used in place of *prog*. It can either be a fully path or the+ name of a program that can be found on the program search path. For+ example: ``--with-ghc=ghc-6.6.1`` or+ ``--with-cpphs=/usr/local/bin/cpphs``. The full list of accepted+ programs is not enumerated in this user guide. Rather, run+ ``cabal install --help`` to view the list.++.. option:: --prog-options=options++ Specify additional options to the program *prog*. Any program known+ to Cabal can be used in place of *prog*. For example:+ ``--alex-options="--template=mytemplatedir/"``. The *options* is+ split into program options based on spaces. Any options containing+ embedded spaced need to be quoted, for example+ ``--foo-options='--bar="C:\Program File\Bar"'``. As an alternative+ that takes only one option at a time but avoids the need to quote,+ use :option:`--prog-option` instead.++.. option:: --prog-option=option++ Specify a single additional option to the program *prog*. For+ passing an option that contain embedded spaces, such as a file name+ with embedded spaces, using this rather than :option:`--prog-options`+ means you do not need an additional level of quoting. Of course if you+ are using a command shell you may still need to quote, for example+ ``--foo-options="--bar=C:\Program File\Bar"``.++All of the options passed with either :option:`--prog-options`+or :option:`--prog-option` are passed in the order they were+specified on the configure command line.++Installation paths+^^^^^^^^^^^^^^^^^^++The following options govern the location of installed files from a+package:++.. option:: --prefix=dir++ The root of the installation. For example for a global install you+ might use ``/usr/local`` on a Unix system, or ``C:\Program Files``+ on a Windows system. The other installation paths are usually+ subdirectories of *prefix*, but they don't have to be.++ In the simple build system, *dir* may contain the following path+ variables: ``$pkgid``, ``$pkg``, ``$version``, ``$compiler``,+ ``$os``, ``$arch``, ``$abi``, ``$abitag``++.. option:: --bindir=dir++ Executables that the user might invoke are installed here.++ In the simple build system, *dir* may contain the following path+ variables: ``$prefix``, ``$pkgid``, ``$pkg``, ``$version``,+ ``$compiler``, ``$os``, ``$arch``, ``$abi``, ``$abitag``++.. option:: --libdir=dir++ Object-code libraries are installed here.++ In the simple build system, *dir* may contain the following path+ variables: ``$prefix``, ``$bindir``, ``$pkgid``, ``$pkg``,+ ``$version``, ``$compiler``, ``$os``, ``$arch``, ``$abi``,+ ``$abitag``++.. option:: --dynlibdir=dir++ Dynamic libraries are installed here.++ By default, this is set to `$libdir/$abi`, which is usually not equal to+ `$libdir/$libsubdir`.++ In the simple build system, *dir* may contain the following path+ variables: ``$prefix``, ``$bindir``, ``$libdir``, ``$pkgid``, ``$pkg``,+ ``$version``, ``$compiler``, ``$os``, ``$arch``, ``$abi``,+ ``$abitag``++.. option:: --libexecdir=dir++ Executables that are not expected to be invoked directly by the user+ are installed here.++ In the simple build system, *dir* may contain the following path+ variables: ``$prefix``, ``$bindir``, ``$libdir``, ``$libsubdir``,+ ``$pkgid``, ``$pkg``, ``$version``, ``$compiler``, ``$os``,+ ``$arch``, ``$abi``, ``$abitag``++.. option:: --datadir=dir++ Architecture-independent data files are installed here.++ In the simple build system, *dir* may contain the following path+ variables: ``$prefix``, ``$bindir``, ``$libdir``, ``$libsubdir``,+ ``$pkgid``, ``$pkg``, ``$version``, ``$compiler``, ``$os``,+ ``$arch``, ``$abi``, ``$abitag``++.. option:: --sysconfdir=dir++ Installation directory for the configuration files.++ In the simple build system, *dir* may contain the following path+ variables: ``$prefix``, ``$bindir``, ``$libdir``, ``$libsubdir``,+ ``$pkgid``, ``$pkg``, ``$version``, ``$compiler``, ``$os``,+ ``$arch``, ``$abi``, ``$abitag``++In addition the simple build system supports the following installation+path options:++.. option:: --libsubdir=dir++ A subdirectory of *libdir* in which libraries are actually installed. For+ example, in the simple build system on Unix, the default *libdir* is+ ``/usr/local/lib``, and *libsubdir* contains the compiler ABI and package+ identifier,+ e.g. ``x86_64-linux-ghc-8.0.2/mypkg-0.1.0-IxQNmCA7qrSEQNkoHSF7A``, so+ libraries would be installed in+ ``/usr/local/lib/x86_64-linux-ghc-8.0.2/mypkg-0.1.0-IxQNmCA7qrSEQNkoHSF7A/``.++ *dir* may contain the following path variables: ``$pkgid``,+ ``$pkg``, ``$version``, ``$compiler``, ``$os``, ``$arch``, ``$abi``,+ ``$abitag``++.. option:: --libexecsubdir=dir++ A subdirectory of *libexecdir* in which private executables are+ installed. For example, in the simple build system on Unix, the default+ *libexecdir* is ``/usr/local/libexec``, and *libsubdir* is+ ``x86_64-linux-ghc-8.0.2/mypkg-0.1.0``, so private executables would be+ installed in ``/usr/local/libexec/x86_64-linux-ghc-8.0.2/mypkg-0.1.0/``++ *dir* may contain the following path variables: ``$pkgid``,+ ``$pkg``, ``$version``, ``$compiler``, ``$os``, ``$arch``, ``$abi``,+ ``$abitag``++.. option:: --datasubdir=dir++ A subdirectory of *datadir* in which data files are actually+ installed.++ *dir* may contain the following path variables: ``$pkgid``,+ ``$pkg``, ``$version``, ``$compiler``, ``$os``, ``$arch``, ``$abi``,+ ``$abitag``++.. option:: --docdir=dir++ Documentation files are installed relative to this directory.++ *dir* may contain the following path variables: ``$prefix``,+ ``$bindir``, ``$libdir``, ``$libsubdir``, ``$datadir``,+ ``$datasubdir``, ``$pkgid``, ``$pkg``, ``$version``, ``$compiler``,+ ``$os``, ``$arch``, ``$abi``, ``$abitag``++.. option:: --htmldir=dir++ HTML documentation files are installed relative to this directory.++ *dir* may contain the following path variables: ``$prefix``,+ ``$bindir``, ``$libdir``, ``$libsubdir``, ``$datadir``,+ ``$datasubdir``, ``$docdir``, ``$pkgid``, ``$pkg``, ``$version``,+ ``$compiler``, ``$os``, ``$arch``, ``$abi``, ``$abitag``++.. option:: --program-prefix=prefix++ Prepend *prefix* to installed program names.++ *prefix* may contain the following path variables: ``$pkgid``,+ ``$pkg``, ``$version``, ``$compiler``, ``$os``, ``$arch``, ``$abi``,+ ``$abitag``++.. option:: --program-suffix=suffix++ Append *suffix* to installed program names. The most obvious use for+ this is to append the program's version number to make it possible+ to install several versions of a program at once:+ ``--program-suffix='$version'``.++ *suffix* may contain the following path variables: ``$pkgid``,+ ``$pkg``, ``$version``, ``$compiler``, ``$os``, ``$arch``, ``$abi``,+ ``$abitag``++Path variables in the simple build system+"""""""""""""""""""""""""""""""""""""""""++For the simple build system, there are a number of variables that can be+used when specifying installation paths. The defaults are also specified+in terms of these variables. A number of the variables are actually for+other paths, like ``$prefix``. This allows paths to be specified+relative to each other rather than as absolute paths, which is important+for building relocatable packages (see `prefix+independence <#prefix-independence>`__).++$prefix+ The path variable that stands for the root of the installation. For+ an installation to be relocatable, all other installation paths must+ be relative to the ``$prefix`` variable.+$bindir+ The path variable that expands to the path given by the :option:`--bindir`+ configure option (or the default).+$libdir+ As above but for :option:`--libdir`+$libsubdir+ As above but for :option:`--libsubdir`+$dynlibdir+ As above but for :option:`--dynlibdir`+$datadir+ As above but for :option:`--datadir`+$datasubdir+ As above but for :option:`--datasubdir`+$docdir+ As above but for :option:`--docdir`+$pkgid+ The name and version of the package, e.g. ``mypkg-0.2``+$pkg+ The name of the package, e.g. ``mypkg``+$version+ The version of the package, e.g. ``0.2``+$compiler+ The compiler being used to build the package, e.g. ``ghc-6.6.1``+$os+ The operating system of the computer being used to build the+ package, e.g. ``linux``, ``windows``, ``osx``, ``freebsd`` or+ ``solaris``+$arch+ The architecture of the computer being used to build the package,+ e.g. ``i386``, ``x86_64``, ``ppc`` or ``sparc``+$abitag+ An optional tag that a compiler can use for telling incompatible+ ABI's on the same architecture apart. GHCJS encodes the underlying+ GHC version in the ABI tag.+$abi+ A shortcut for getting a path that completely identifies the+ platform in terms of binary compatibility. Expands to the same value+ as ``$arch-$os-compiler-$abitag`` if the compiler uses an abi tag,+ ``$arch-$os-$compiler`` if it doesn't.++Paths in the simple build system+""""""""""""""""""""""""""""""""++For the simple build system, the following defaults apply:++.. list-table:: Default installation paths++ * - Option+ - Unix Default+ - Windows Default+ * - :option:`--prefix` (global)+ - ``/usr/local``+ - ``%PROGRAMFILES%\Haskell``+ * - :option:`--prefix` (per-user)+ - ``$HOME/.cabal``+ - ``%APPDATA%\cabal``+ * - :option:`--bindir`+ - ``$prefix/bin``+ - ``$prefix\bin``+ * - :option:`--libdir`+ - ``$prefix/lib``+ - ``$prefix``+ * - :option:`--libsubdir` (others)+ - ``$pkgid/$compiler``+ - ``$pkgid\$compiler``+ * - :option:`--dynlibdir`+ - ``$libdir/$abi``+ - ``$libdir\$abi``+ * - :option:`--libexecdir`+ - ``$prefix/libexec``+ - ``$prefix\$pkgid``+ * - :option:`--datadir` (executable)+ - ``$prefix/share``+ - ``$prefix``+ * - :option:`--datadir` (library)+ - ``$prefix/share``+ - ``%PROGRAMFILES%\Haskell``+ * - :option:`--datasubdir`+ - ``$pkgid``+ - ``$pkgid``+ * - :option:`--docdir`+ - ``$datadir/doc/$pkgid``+ - ``$prefix\doc\$pkgid``+ * - :option:`--sysconfdir`+ - ``$prefix/etc``+ - ``$prefix\etc``+ * - :option:`--htmldir`+ - ``$docdir/html``+ - ``$docdir\html``+ * - :option:`--program-prefix`+ - (empty)+ - (empty)+ * - :option:`--program-suffix`+ - (empty)+ - (empty)++Prefix-independence+"""""""""""""""""""++On Windows it is possible to obtain the pathname of the running program.+This means that we can construct an installable executable package that+is independent of its absolute install location. The executable can find+its auxiliary files by finding its own path and knowing the location of+the other files relative to ``$bindir``. Prefix-independence is+particularly useful: it means the user can choose the install location+(i.e. the value of ``$prefix``) at install-time, rather than having to+bake the path into the binary when it is built.++In order to achieve this, we require that for an executable on Windows,+all of ``$bindir``, ``$libdir``, ``$dynlibdir``, ``$datadir`` and ``$libexecdir`` begin+with ``$prefix``. If this is not the case then the compiled executable+will have baked-in all absolute paths.++The application need do nothing special to achieve prefix-independence.+If it finds any files using ``getDataFileName`` and the `other functions+provided for the+purpose <developing-packages.html#accessing-data-files-from-package-code>`__,+the files will be accessed relative to the location of the current+executable.++A library cannot (currently) be prefix-independent, because it will be+linked into an executable whose file system location bears no relation+to the library package.++Controlling Flag Assignments+^^^^^^^^^^^^^^^^^^^^^^^^^^^^++Flag assignments (see the `resolution of conditions and+flags <developing-packages.html#resolution-of-conditions-and-flags>`__)+can be controlled with the following command line options.++.. option:: -f flagname or -f -flagname++ Force the specified flag to ``true`` or ``false`` (if preceded with+ a ``-``). Later specifications for the same flags will override+ earlier, i.e., specifying ``-fdebug -f-debug`` is equivalent to+ ``-f-debug``++.. option:: --flags=flagspecs++ Same as ``-f``, but allows specifying multiple flag assignments at+ once. The parameter is a space-separated list of flag names (to+ force a flag to ``true``), optionally preceded by a ``-`` (to force+ a flag to ``false``). For example,+ ``--flags="debug -feature1 feature2"`` is equivalent to+ ``-fdebug -f-feature1 -ffeature2``.++Building Test Suites+^^^^^^^^^^^^^^^^^^^^++.. option:: --enable-tests++ Build the test suites defined in the package description file during+ the ``build`` stage. Check for dependencies required by the test+ suites. If the package is configured with this option, it will be+ possible to run the test suites with the ``test`` command after the+ package is built.++.. option:: --disable-tests++ (default) Do not build any test suites during the ``build`` stage.+ Do not check for dependencies required only by the test suites. It+ will not be possible to invoke the ``test`` command without+ reconfiguring the package.++.. option:: --enable-coverage++ Build libraries and executables (including test suites) with Haskell+ Program Coverage enabled. Running the test suites will automatically+ generate coverage reports with HPC.++.. option:: --disable-coverage++ (default) Do not enable Haskell Program Coverage.++Miscellaneous options+^^^^^^^^^^^^^^^^^^^^^++.. option:: --user++ Does a per-user installation. This changes the `default installation+ prefix <#paths-in-the-simple-build-system>`__. It also allow+ dependencies to be satisfied by the user's package database, in+ addition to the global database. This also implies a default of+ ``--user`` for any subsequent ``install`` command, as packages+ registered in the global database should not depend on packages+ registered in a user's database.++.. option:: --global++ (default) Does a global installation. In this case package+ dependencies must be satisfied by the global package database. All+ packages in the user's package database will be ignored. Typically+ the final installation step will require administrative privileges.++.. option:: --package-db=db++ Allows package dependencies to be satisfied from this additional+ package database *db* in addition to the global package database.+ All packages in the user's package database will be ignored. The+ interpretation of *db* is implementation-specific. Typically it will+ be a file or directory. Not all implementations support arbitrary+ package databases.++ This pushes an extra db onto the db stack. The :option:`--global` and+ :option:`--user` mode switches add the respective [Global] and [Global,+ User] dbs to the initial stack. There is a compiler-implementation+ constraint that the global db must appear first in the stack, and if+ the user one appears at all, it must appear immediately after the+ global db.++ To reset the stack, use ``--package-db=clear``.++.. option:: --ipid=ipid++ Specifies the *installed package identifier* of the package to be+ built; this identifier is passed on to GHC and serves as the basis+ for linker symbols and the ``id`` field in a ``ghc-pkg``+ registration. When a package has multiple components, the actual+ component identifiers are derived off of this identifier (e.g., an+ internal library ``foo`` from package ``p-0.1-abcd`` will get the+ identifier ``p-0.1-abcd-foo``.++.. option:: --cid=cid++ Specifies the *component identifier* of the component being built;+ this is only valid if you are configuring a single component.++.. option:: --default-user-config=file++ Allows a "default" ``cabal.config`` freeze file to be passed in+ manually. This file will only be used if one does not exist in the+ project directory already. Typically, this can be set from the+ global cabal ``config`` file so as to provide a default set of+ partial constraints to be used by projects, providing a way for+ users to peg themselves to stable package collections.++.. option:: --enable-optimization[=n] or -O [n]++ (default) Build with optimization flags (if available). This is+ appropriate for production use, taking more time to build faster+ libraries and programs.++ The optional *n* value is the optimisation level. Some compilers+ support multiple optimisation levels. The range is 0 to 2. Level 0+ is equivalent to :option:`--disable-optimization`, level 1 is the+ default if no *n* parameter is given. Level 2 is higher optimisation+ if the compiler supports it. Level 2 is likely to lead to longer+ compile times and bigger generated code.++ When optimizations are enabled, Cabal passes ``-O2`` to the C compiler.++.. option:: --disable-optimization++ Build without optimization. This is suited for development: building+ will be quicker, but the resulting library or programs will be+ slower.++.. option:: --enable-profiling++ Build libraries and executables with profiling enabled (for+ compilers that support profiling as a separate mode). For this to+ work, all libraries used by this package must also have been built+ with profiling support. For libraries this involves building an+ additional instance of the library in addition to the normal+ non-profiling instance. For executables it changes the single+ executable to be built in profiling mode.++ This flag covers both libraries and executables, but can be+ overridden by the :option:`--enable-library-profiling` flag.++ See also the :option:`--profiling-detail` flag below.++.. option:: --disable-profiling++ (default) Do not enable profiling in generated libraries and+ executables.++.. option:: --enable-library-profiling or -p++ As with :option:`--enable-profiling` above, but it applies only for+ libraries. So this generates an additional profiling instance of the+ library in addition to the normal non-profiling instance.++ The :option:`--enable-profiling` flag controls the profiling mode for both+ libraries and executables, but if different modes are desired for+ libraries versus executables then use :option:`--enable-library-profiling`+ as well.++.. option:: --disable-library-profiling++ (default) Do not generate an additional profiling version of the library.++.. option:: --profiling-detail[=level]++ Some compilers that support profiling, notably GHC, can allocate+ costs to different parts of the program and there are different+ levels of granularity or detail with which this can be done. In+ particular for GHC this concept is called "cost centers", and GHC+ can automatically add cost centers, and can do so in different ways.++ This flag covers both libraries and executables, but can be+ overridden by the :option:`--library-profiling-detail` flag.++ Currently this setting is ignored for compilers other than GHC. The+ levels that cabal currently supports are:++ default+ For GHC this uses ``exported-functions`` for libraries and+ ``toplevel-functions`` for executables.+ none+ No costs will be assigned to any code within this component.+ exported-functions+ Costs will be assigned at the granularity of all top level+ functions exported from each module. In GHC specifically, this+ is for non-inline functions.+ toplevel-functions+ Costs will be assigned at the granularity of all top level+ functions in each module, whether they are exported from the+ module or not. In GHC specifically, this is for non-inline+ functions.+ all-functions+ Costs will be assigned at the granularity of all functions in+ each module, whether top level or local. In GHC specifically,+ this is for non-inline toplevel or where-bound functions or+ values.++ This flag is new in Cabal-1.24. Prior versions used the equivalent+ of ``none`` above.++.. option:: --library-profiling-detail[=level]++ As with :option:`--profiling-detail` above, but it applies only for+ libraries.++ The level for both libraries and executables is set by the+ :option:`--profiling-detail` flag, but if different levels are desired+ for libraries versus executables then use+ :option:`--library-profiling-detail` as well.++.. option:: --enable-library-vanilla++ (default) Build ordinary libraries (as opposed to profiling+ libraries). This is independent of the+ :option:`--enable-library-profiling` option. If you enable both, you get+ both.++.. option:: --disable-library-vanilla++ Do not build ordinary libraries. This is useful in conjunction with+ :option:`--enable-library-profiling` to build only profiling libraries,+ rather than profiling and ordinary libraries.++.. option:: --enable-library-for-ghci++ (default) Build libraries suitable for use with GHCi.++.. option:: --disable-library-for-ghci++ Not all platforms support GHCi and indeed on some platforms, trying+ to build GHCi libs fails. In such cases this flag can be used as a+ workaround.++.. option:: --enable-split-objs++ Use the GHC ``-split-objs`` feature when building the library. This+ reduces the final size of the executables that use the library by+ allowing them to link with only the bits that they use rather than+ the entire library. The downside is that building the library takes+ longer and uses considerably more memory.++.. option:: --disable-split-objs++ (default) Do not use the GHC ``-split-objs`` feature. This makes+ building the library quicker but the final executables that use the+ library will be larger.++.. option:: --enable-executable-stripping++ (default) When installing binary executable programs, run the+ ``strip`` program on the binary. This can considerably reduce the+ size of the executable binary file. It does this by removing+ debugging information and symbols. While such extra information is+ useful for debugging C programs with traditional debuggers it is+ rarely helpful for debugging binaries produced by Haskell compilers.++ Not all Haskell implementations generate native binaries. For such+ implementations this option has no effect.++.. option:: --disable-executable-stripping++ Do not strip binary executables during installation. You might want+ to use this option if you need to debug a program using gdb, for+ example if you want to debug the C parts of a program containing+ both Haskell and C code. Another reason is if your are building a+ package for a system which has a policy of managing the stripping+ itself (such as some Linux distributions).++.. option:: --enable-shared++ Build shared library. This implies a separate compiler run to+ generate position independent code as required on most platforms.++.. option:: --disable-shared++ (default) Do not build shared library.++.. option:: --enable-static++ Build a static library. This passes ``-staticlib`` to GHC (available+ for iOS, and with 8.4 more platforms). The result is an archive ``.a``+ containing all dependent haskell libararies combined.++.. option:: --disable-static++ (default) Do not build a static library.++.. option:: --enable-executable-dynamic++ Link dependent Haskell libraries into executables dynamically.+ The executable's library dependencies must have been+ built as shared objects. This implies :option:`--enable-shared`+ unless :option:`--disable-shared` is explicitly specified.++.. option:: --disable-executable-dynamic++ (default) Link dependent Haskell libraries into executables statically.+ Non-Haskell (C) libraries are still linked dynamically, including libc,+ so the result is still not a fully static executable+ unless :option:`--enable-executable-static` is given.++.. option:: --enable-executable-static++ Build fully static executables.+ This link all dependent libraries into executables statically,+ including libc.++.. option:: --disable-executable-static++ (default) Do not build fully static executables.++.. option:: --configure-option=str++ An extra option to an external ``configure`` script, if one is used+ (see the section on `system-dependent+ parameters <developing-packages.html#system-dependent-parameters>`__).+ There can be several of these options.++.. option:: --extra-include-dirs[=dir]++ An extra directory to search for C header files. You can use this+ flag multiple times to get a list of directories.++ You might need to use this flag if you have standard system header+ files in a non-standard location that is not mentioned in the+ package's ``.cabal`` file. Using this option has the same affect as+ appending the directory *dir* to the ``include-dirs`` field in each+ library and executable in the package's ``.cabal`` file. The+ advantage of course is that you do not have to modify the package at+ all. These extra directories will be used while building the package+ and for libraries it is also saved in the package registration+ information and used when compiling modules that use the library.++.. option:: --extra-lib-dirs[=dir]++ An extra directory to search for system libraries files. You can use+ this flag multiple times to get a list of directories.++.. option:: --extra-framework-dirs[=dir]++ An extra directory to search for frameworks (OS X only). You can use+ this flag multiple times to get a list of directories.++ You might need to use this flag if you have standard system+ libraries in a non-standard location that is not mentioned in the+ package's ``.cabal`` file. Using this option has the same affect as+ appending the directory *dir* to the ``extra-lib-dirs`` field in+ each library and executable in the package's ``.cabal`` file. The+ advantage of course is that you do not have to modify the package at+ all. These extra directories will be used while building the package+ and for libraries it is also saved in the package registration+ information and used when compiling modules that use the library.++.. option:: --dependency[=pkgname=ipid]++ Specify that a particular dependency should used for a particular+ package name. In particular, it declares that any reference to+ *pkgname* in a :pkg-field:`build-depends` should be resolved to+ *ipid*.++.. option:: --exact-configuration++ This changes Cabal to require every dependency be explicitly+ specified using :option:`--dependency`, rather than use Cabal's (very+ simple) dependency solver. This is useful for programmatic use of+ Cabal's API, where you want to error if you didn't specify enough+ :option:`--dependency` flags.++.. option:: --allow-newer[=pkgs], --allow-older[=pkgs]++ Selectively relax upper or lower bounds in dependencies without+ editing the package description respectively.++ The following description focuses on upper bounds and the+ :option:`--allow-newer` flag, but applies analogously to+ :option:`--allow-older` and lower bounds. :option:`--allow-newer`+ and :option:`--allow-older` can be used at the same time.++ If you want to install a package A that depends on B >= 1.0 && <+ 2.0, but you have the version 2.0 of B installed, you can compile A+ against B 2.0 by using ``cabal install --allow-newer=B A``. This+ works for the whole package index: if A also depends on C that in+ turn depends on B < 2.0, C's dependency on B will be also relaxed.++ Example:++ ::++ $ cd foo+ $ cabal configure+ Resolving dependencies...+ cabal: Could not resolve dependencies:+ [...]+ $ cabal configure --allow-newer+ Resolving dependencies...+ Configuring foo...++ Additional examples:++ ::++ # Relax upper bounds in all dependencies.+ $ cabal install --allow-newer foo++ # Relax upper bounds only in dependencies on bar, baz and quux.+ $ cabal install --allow-newer=bar,baz,quux foo++ # Relax the upper bound on bar and force bar==2.1.+ $ cabal install --allow-newer=bar --constraint="bar==2.1" foo++ It's also possible to limit the scope of :option:`--allow-newer` to single+ packages with the ``--allow-newer=scope:dep`` syntax. This means+ that the dependency on ``dep`` will be relaxed only for the package+ ``scope``.++ Example:++ ::++ # Relax upper bound in foo's dependency on base; also relax upper bound in+ # every package's dependency on lens.+ $ cabal install --allow-newer=foo:base,lens++ # Relax upper bounds in foo's dependency on base and bar's dependency+ # on time; also relax the upper bound in the dependency on lens specified by+ # any package.+ $ cabal install --allow-newer=foo:base,lens --allow-newer=bar:time++ Finally, one can enable :option:`--allow-newer` permanently by setting+ ``allow-newer: True`` in the ``~/.cabal/config`` file. Enabling+ 'allow-newer' selectively is also supported in the config file+ (``allow-newer: foo, bar, baz:base``).++.. option:: --constraint=constraint++ Restrict solutions involving a package to given version+ bounds, flag settings, and other properties. For example, to+ consider only install plans that use version 2.1 of ``bar``+ or do not use ``bar`` at all, write:++ ::++ $ cabal install --constraint="bar == 2.1"++ Version bounds have the same syntax as :pkg-field:`build-depends`.+ As a special case, the following prevents ``bar`` from being+ used at all:++ ::++ # Note: this is just syntax sugar for '> 1 && < 1', and is+ # supported by build-depends.+ $ cabal install --constraint="bar -none"++ You can also specify flag assignments:++ ::++ # Require bar to be installed with the foo flag turned on and+ # the baz flag turned off.+ $ cabal install --constraint="bar +foo -baz"++ To specify multiple constraints, you may pass the+ ``constraint`` option multiple times.++ There are also some more specialized constraints, which most people+ don't generally need:++ ::++ # Require that a version of bar be used that is already installed in+ # the global package database.+ $ cabal install --constraint="bar installed"++ # Require the local source copy of bar to be used.+ # (Note: By default, if we have a local package we will+ # automatically use it, so it will generally not be necessary to+ # specify this.)+ $ cabal install --constraint="bar source"++ # Require that bar have test suites and benchmarks enabled.+ $ cabal install --constraint="bar test" --constraint="bar bench"++ By default, constraints only apply to build dependencies+ (:pkg-field:`build-depends`), build dependencies of build+ dependencies, and so on. Constraints normally do not apply to+ dependencies of the ``Setup.hs`` script of any package+ (:pkg-field:`custom-setup:setup-depends`) nor do they apply to build tools+ (:pkg-field:`build-tool-depends`) or the dependencies of build+ tools. To explicitly apply a constraint to a setup or build+ tool dependency, you can add a qualifier to the constraint as+ follows:++ ::++ # Example use of the 'any' qualifier. This constraint+ # applies to package bar anywhere in the dependency graph.+ $ cabal install --constraint="any.bar == 1.0"++ ::++ # Example uses of 'setup' qualifiers.++ # This constraint applies to package bar when it is a+ # dependency of any Setup.hs script.+ $ cabal install --constraint="setup.bar == 1.0"++ # This constraint applies to package bar when it is a+ # dependency of the Setup.hs script of package foo.+ $ cabal install --constraint="foo:setup.bar == 1.0"++ .. TODO: Uncomment this example once we decide on a syntax for 'exe'.+ .. # Example use of the 'exe' (executable build tool)+ # qualifier. This constraint applies to package baz when it+ # is a dependency of the build tool bar being used to+ # build package foo.+ $ cabal install --constraint="foo:bar:exe.baz == 1.0"++.. option:: --preference=preference++ Specify a soft constraint on versions of a package. The solver will+ attempt to satisfy these preferences on a "best-effort" basis.++.. option:: --disable-response-files++ Enable workaround for older versions of programs such as ``ar`` or+ ``ld`` that do not support response file arguments (i.e. ``@file``+ arguments). You may want this flag only if you specify custom ar+ executable. For system ``ar`` or the one bundled with ``ghc`` on+ Windows the ``cabal`` should do the right thing and hence should+ normally not require this flag.++.. _setup-build:++runhaskell Setup.hs build+-------------------------++Perform any preprocessing or compilation needed to make this package+ready for installation.++This command takes the following options:++.. program:: runhaskell Setup.hs build++.. option:: --prog-options=options, --prog-option=option++ These are mostly the same as the `options configure+ step <#setup-configure>`__. Unlike the options specified at the+ configure step, any program options specified at the build step are+ not persistent but are used for that invocation only. They options+ specified at the build step are in addition not in replacement of+ any options specified at the configure step.++.. _setup-haddock:++runhaskell Setup.hs haddock+---------------------------++.. program:: runhaskell Setup.hs haddock++Build the documentation for the package using Haddock_.+By default, only the documentation for the exposed modules is generated+(but see the :option:`--executables` and :option:`--internal` flags below).++This command takes the following options:++.. option:: --hoogle++ Generate a file ``dist/doc/html/``\ *pkgid*\ ``.txt``, which can be+ converted by Hoogle_ into a+ database for searching. This is equivalent to running Haddock_+ with the ``--hoogle`` flag.++.. option:: --html-location=url++ Specify a template for the location of HTML documentation for+ prerequisite packages. The substitutions (`see+ listing <#paths-in-the-simple-build-system>`__) are applied to the+ template to obtain a location for each package, which will be used+ by hyperlinks in the generated documentation. For example, the+ following command generates links pointing at Hackage_ pages:++ runhaskell Setup.hs haddock+ --html-location='http://hackage.haskell.org/packages/archive/$pkg/latest/doc/html'++ Here the argument is quoted to prevent substitution by the shell. If+ this option is omitted, the location for each package is obtained+ using the package tool (e.g. ``ghc-pkg``).++.. option:: --executables++ Also run Haddock_ for the modules of all the executable programs. By default+ Haddock_ is run only on the exported modules.++.. option:: --internal++ Run Haddock_ for the all+ modules, including unexposed ones, and make+ Haddock_ generate documentation+ for unexported symbols as well.++.. option:: --css=path++ The argument *path* denotes a CSS file, which is passed to+ Haddock_ and used to set the+ style of the generated documentation. This is only needed to+ override the default style that+ Haddock_ uses.++.. option:: --hyperlink-source++ Generate Haddock_ documentation integrated with HsColour_ . First,+ HsColour_ is run to generate colourised code. Then Haddock_ is run to+ generate HTML documentation. Each entity shown in the documentation is+ linked to its definition in the colourised code.++.. option:: --hscolour-css=path++ The argument *path* denotes a CSS file, which is passed to HsColour_ as in++ runhaskell Setup.hs hscolour --css=*path*++.. _setup-hscolour:++runhaskell Setup.hs hscolour+----------------------------++Produce colourised code in HTML format using HsColour_. Colourised code for+exported modules is put in ``dist/doc/html/``\ *pkgid*\ ``/src``.++This command takes the following options:++.. program:: runhaskell Setup.hs hscolour++.. option:: --executables++ Also run HsColour_ on the sources of all executable programs. Colourised+ code is put in ``dist/doc/html/``\ *pkgid*/*executable*\ ``/src``.++.. option:: --css=path++ Use the given CSS file for the generated HTML files. The CSS file+ defines the colours used to colourise code. Note that this copies+ the given CSS file to the directory with the generated HTML files+ (renamed to ``hscolour.css``) rather than linking to it.++.. _setup-install:++runhaskell Setup.hs install+---------------------------++.. program:: runhaskell Setup.hs install++Copy the files into the install locations and (for library packages)+register the package with the compiler, i.e. make the modules it+contains available to programs.++The `install locations <#installation-paths>`__ are determined by+options to `runhaskell Setup.hs configure`_.++This command takes the following options:++.. option:: --global++ Register this package in the system-wide database. (This is the+ default, unless the :option:`runhaskell Setup.hs configure --user` option was supplied+ to the ``configure`` command.)++.. option:: --user++ Register this package in the user's local package database. (This is+ the default if the :option:`runhaskell Setup.hs configure --user` option was supplied+ to the ``configure`` command.)++.. _setup-copy:++runhaskell Setup.hs copy+------------------------++Copy the files without registering them. This command is mainly of use+to those creating binary packages.++This command takes the following option:++.. program:: runhaskell Setup.hs copy++.. option:: --destdir=path++ Specify the directory under which to place installed files. If this is+ not given, then the root directory is assumed.++.. _setup-register:++runhaskell Setup.hs register+----------------------------++Register this package with the compiler, i.e. make the modules it+contains available to programs. This only makes sense for library+packages. Note that the ``install`` command incorporates this action.+The main use of this separate command is in the post-installation step+for a binary package.++This command takes the following options:++.. program:: runhaskell Setup.hs register++.. option:: --global++ Register this package in the system-wide database. (This is the+ default.)++.. option:: --user++ Register this package in the user's local package database.++.. option:: --gen-script++ Instead of registering the package, generate a script containing+ commands to perform the registration. On Unix, this file is called+ ``register.sh``, on Windows, ``register.bat``. This script might be+ included in a binary bundle, to be run after the bundle is unpacked+ on the target system.++.. option:: --gen-pkg-config[=path]++ Instead of registering the package, generate a package registration+ file (or directory, in some circumstances). This only applies to+ compilers that support package registration files which at the+ moment is only GHC. The file should be used with the compiler's+ mechanism for registering packages. This option is mainly intended+ for packaging systems. If possible use the :option:`--gen-script` option+ instead since it is more portable across Haskell implementations.+ The *path* is optional and can be used to specify a particular+ output file to generate. Otherwise, by default the file is the+ package name and version with a ``.conf`` extension.++ This option outputs a directory if the package requires multiple+ registrations: this can occur if internal/convenience libraries are+ used. These configuration file names are sorted so that they can be+ registered in order.++.. option:: --inplace++ Registers the package for use directly from the build tree, without+ needing to install it. This can be useful for testing: there's no+ need to install the package after modifying it, just recompile and+ test.++ This flag does not create a build-tree-local package database. It+ still registers the package in one of the user or global databases.++ However, there are some caveats. It only works with GHC (currently).+ It only works if your package doesn't depend on having any+ supplemental files installed --- plain Haskell libraries should be+ fine.++.. _setup-unregister:++runhaskell Setup.hs unregister+------------------------------++.. program:: runhaskell Setup.hs unregister++Deregister this package with the compiler.++This command takes the following options:++.. option:: --global++ Deregister this package in the system-wide database. (This is the+ default.)++.. option:: --user++ Deregister this package in the user's local package database.++.. option:: --gen-script++ Instead of deregistering the package, generate a script containing+ commands to perform the deregistration. On Unix, this file is called+ ``unregister.sh``, on Windows, ``unregister.bat``. This script might+ be included in a binary bundle, to be run on the target system.++.. _setup-clean:++runhaskell Setup.hs clean+-------------------------++Remove any local files created during the ``configure``, ``build``,+``haddock``, ``register`` or ``unregister`` steps, and also any files+and directories listed in the :pkg-field:`extra-tmp-files` field.++This command takes the following options:++.. program:: runhaskell Setup.hs clean++.. option:: --save-configure, -s++ Keeps the configuration information so it is not necessary to run+ the configure step again before building.++.. _setup-test:++runhaskell Setup.hs test+------------------------++Run the test suites specified in the package description file. Aside+from the following flags, Cabal accepts the name of one or more test+suites on the command line after ``test``. When supplied, Cabal will run+only the named test suites, otherwise, Cabal will run all test suites in+the package.++.. program:: runhaskell Setup.hs test++.. option:: --builddir=dir++ The directory where Cabal puts generated build files (default:+ ``dist``). Test logs will be located in the ``test`` subdirectory.++.. option:: --human-log=path++ The template used to name human-readable test logs; the path is+ relative to ``dist/test``. By default, logs are named according to+ the template ``$pkgid-$test-suite.log``, so that each test suite+ will be logged to its own human-readable log file. Template+ variables allowed are: ``$pkgid``, ``$compiler``, ``$os``,+ ``$arch``, ``$abi``, ``$abitag``, ``$test-suite``, and ``$result``.++.. option:: --machine-log=path++ The path to the machine-readable log, relative to ``dist/test``. The+ default template is ``$pkgid.log``. Template variables allowed are:+ ``$pkgid``, ``$compiler``, ``$os``, ``$arch``, ``$abi``, ``$abitag``+ and ``$result``.++.. option:: --show-details=filter++ Determines if the results of individual test cases are shown on the+ terminal. May be ``always`` (always show), ``never`` (never show),+ ``failures`` (show only failed results), or ``streaming`` (show all+ results in real time).++.. option:: --test-options=options+ Give extra options to the test executables.++.. option:: --test-option=option++ Give an extra option to the test executables. There is no need to+ quote options containing spaces because a single option is assumed,+ so options will not be split on spaces.++.. option:: --test-wrapper=path++ The wrapper script/application used to setup and tear down the test+ execution context. The text executable path and test arguments are+ passed as arguments to the wrapper and it is expected that the wrapper+ will return the test's return code, as well as a copy of stdout/stderr.++.. _setup-bench:++runhaskell Setup.hs bench+-------------------------++Run the benchmarks specified in the package description file. Aside+from the following flags, Cabal accepts the name of one or more benchmarks+on the command line after ``bench``. When supplied, Cabal will run+only the named benchmarks, otherwise, Cabal will run all benchmarks in+the package.++.. option:: --benchmark-options=options+ Give extra options to the benchmark executables.++.. option:: --benchmark-option=option++ Give an extra option to the benchmark executables. There is no need to+ quote options containing spaces because a single option is assumed,+ so options will not be split on spaces.++.. _setup-sdist:++runhaskell Setup.hs sdist+-------------------------++Create a system- and compiler-independent source distribution in a file+*package*-*version*\ ``.tar.gz`` in the ``dist`` subdirectory, for+distribution to package builders. When unpacked, the commands listed in+this section will be available.++The files placed in this distribution are the package description file,+the setup script, the sources of the modules named in the package+description file, and files named in the ``license-file``, ``main-is``,+``c-sources``, ``asm-sources``, ``cmm-sources``, ``js-sources``,+``data-files``, ``extra-source-files`` and ``extra-doc-files`` fields.++This command takes the following option:++.. program:: runhaskell Setup.hs sdist++.. option:: --snapshot++ Append today's date (in "YYYYMMDD" format) to the version number for+ the generated source package. The original package is unaffected.+++.. include:: references.inc
cabal/LICENSE view
@@ -1,4 +1,4 @@-Copyright (c) 2003-2017, Cabal Development Team.+Copyright (c) 2003-2020, Cabal Development Team. See the AUTHORS file for the full list of copyright holders. See */LICENSE for the copyright holders of the subcomponents.
cabal/Makefile view
@@ -1,10 +1,7 @@ .PHONY : all lexer sdpx lib exe doctest .PHONY : gen-extra-source-files gen-extra-source-files-lib gen-extra-source-files-cli .PHONY : cabal-install-dev cabal-install-prod--LEXER_HS:=Cabal/Distribution/Fields/Lexer.hs-SPDX_LICENSE_HS:=Cabal/Distribution/SPDX/LicenseId.hs-SPDX_EXCEPTION_HS:=Cabal/Distribution/SPDX/LicenseExceptionId.hs+.PHONY : phony CABALBUILD := cabal v2-build CABALRUN := cabal v2-run@@ -23,8 +20,13 @@ lib-ghc-7.6 : $(CABALBUILD) --project-file=cabal.project.libonly --with-compiler=ghc-7.6.3 Cabal:libs +lib-ghc-7.8 :+ $(CABALBUILD) --project-file=cabal.project.libonly --with-compiler=ghc-7.8.4 Cabal:libs+ # source generation: Lexer +LEXER_HS:=Cabal/Distribution/Fields/Lexer.hs+ lexer : $(LEXER_HS) $(LEXER_HS) : boot/Lexer.x@@ -34,27 +36,47 @@ # source generation: SPDX +SPDX_LICENSE_HS:=Cabal/Distribution/SPDX/LicenseId.hs+SPDX_EXCEPTION_HS:=Cabal/Distribution/SPDX/LicenseExceptionId.hs+ spdx : $(SPDX_LICENSE_HS) $(SPDX_EXCEPTION_HS) $(SPDX_LICENSE_HS) : boot/SPDX.LicenseId.template.hs cabal-dev-scripts/src/GenUtils.hs cabal-dev-scripts/src/GenSPDX.hs license-list-data/licenses-3.0.json license-list-data/licenses-3.2.json- cabal v2-run --builddir=dist-newstyle-meta --project-file=cabal.project.meta gen-spdx -- boot/SPDX.LicenseId.template.hs license-list-data/licenses-3.0.json license-list-data/licenses-3.2.json license-list-data/licenses-3.6.json $(SPDX_LICENSE_HS)+ cabal v2-run --builddir=dist-newstyle-meta --project-file=cabal.project.meta gen-spdx -- boot/SPDX.LicenseId.template.hs license-list-data/licenses-3.0.json license-list-data/licenses-3.2.json license-list-data/licenses-3.6.json license-list-data/licenses-3.9.json $(SPDX_LICENSE_HS) $(SPDX_EXCEPTION_HS) : boot/SPDX.LicenseExceptionId.template.hs cabal-dev-scripts/src/GenUtils.hs cabal-dev-scripts/src/GenSPDXExc.hs license-list-data/exceptions-3.0.json license-list-data/exceptions-3.2.json- cabal v2-run --builddir=dist-newstyle-meta --project-file=cabal.project.meta gen-spdx-exc -- boot/SPDX.LicenseExceptionId.template.hs license-list-data/exceptions-3.0.json license-list-data/exceptions-3.2.json license-list-data/exceptions-3.6.json $(SPDX_EXCEPTION_HS)+ cabal v2-run --builddir=dist-newstyle-meta --project-file=cabal.project.meta gen-spdx-exc -- boot/SPDX.LicenseExceptionId.template.hs license-list-data/exceptions-3.0.json license-list-data/exceptions-3.2.json license-list-data/exceptions-3.6.json license-list-data/exceptions-3.9.json $(SPDX_EXCEPTION_HS) +# source generation: templates++TEMPLATE_MACROS:=Cabal/Distribution/Simple/Build/Macros/Z.hs++templates : $(TEMPLATE_MACROS)++$(TEMPLATE_MACROS) : boot/cabal_macros.template.h cabal-dev-scripts/src/GenCabalMacros.hs+ cabal v2-run --builddir=dist-newstyle-meta --project-file=cabal.project.meta gen-cabal-macros -- $< $@++# generated docs++Cabal/doc/buildinfo-fields-reference.rst : phony+ cabal build --builddir=dist-newstyle-bi --project-file=cabal.project.buildinfo buildinfo-reference-generator+ $$(cabal-plan list-bin --builddir=dist-newstyle-bi buildinfo-reference-generator) buildinfo-reference-generator/template.zinza | tee $@+ # cabal-install.cabal file generation -cabal-install-prod : cabal-install/cabal-install.cabal.pp- runghc cabal-dev-scripts/src/Preprocessor.hs -o cabal-install/cabal-install.cabal cabal-install/cabal-install.cabal.pp- git update-index --no-assume-unchanged cabal-install/cabal-install.cabal+cabal-install-cabal : phony cabal-install/cabal-install.cabal.dev cabal-install/cabal-install.cabal.prod -cabal-install-dev : cabal-install/cabal-install.cabal.pp- runghc cabal-dev-scripts/src/Preprocessor.hs -o cabal-install/cabal-install.cabal -f CABAL_FLAG_LIB cabal-install/cabal-install.cabal.pp- @echo "tell git to ignore changes to cabal-install.cabal:"- @echo "git update-index --assume-unchanged cabal-install/cabal-install.cabal"+cabal-install/cabal-install.cabal.dev : cabal-install/cabal-install.cabal.zinza+ cabal v2-run --builddir=dist-newstyle-meta --project-file=cabal.project.meta gen-cabal-install-cabal -- True cabal-install/cabal-install.cabal.zinza cabal-install/cabal-install.cabal.dev -cabal-install-monolithic : cabal-install/cabal-install.cabal.pp- runghc cabal-dev-scripts/src/Preprocessor.hs -o cabal-install/cabal-install.cabal -f CABAL_FLAG_LIB -f CABAL_FLAG_MONOLITHIC cabal-install/cabal-install.cabal.pp+cabal-install/cabal-install.cabal.prod : cabal-install/cabal-install.cabal.zinza+ cabal v2-run --builddir=dist-newstyle-meta --project-file=cabal.project.meta gen-cabal-install-cabal -- False cabal-install/cabal-install.cabal.zinza cabal-install/cabal-install.cabal.prod++cabal-install-prod : cabal-install/cabal-install.cabal.prod+ cp cabal-install/cabal-install.cabal.prod cabal-install/cabal-install.cabal++cabal-install-dev : cabal-install/cabal-install.cabal.dev+ cp cabal-install/cabal-install.cabal.dev cabal-install/cabal-install.cabal @echo "tell git to ignore changes to cabal-install.cabal:" @echo "git update-index --assume-unchanged cabal-install/cabal-install.cabal" @@ -65,10 +87,25 @@ gen-extra-source-files-lib : cabal v2-run --builddir=dist-newstyle-meta --project-file=cabal.project.meta gen-extra-source-files -- $$(pwd)/Cabal/Cabal.cabal +# analyse-imports+analyse-imports : phony+ find Cabal/Distribution cabal-install/Distribution -type f -name '*.hs' | xargs cabal v2-run --builddir=dist-newstyle-meta --project-file=cabal.project.meta analyse-imports --++# github actions+github-actions : .github/workflows/artifacts.yml+github-actions : .github/workflows/quick-jobs.yml+github-actions : .github/workflows/bootstrap.yml+github-actions : .github/workflows/linux.yml+github-actions : .github/workflows/macos.yml+github-actions : .github/workflows/windows.yml++.github/workflows/%.yml : boot/ci-%.template.yml cabal-dev-scripts/src/GenValidate.hs+ cabal v2-run --builddir=dist-newstyle-meta --project-file=cabal.project.meta gen-validate -- $< $@+ # We need to generate cabal-install-dev so the test modules are in .cabal file! gen-extra-source-files-cli : $(MAKE) cabal-install-dev- cabal v2-run --builddir=dist-newstyle-meta --project-file=cabal.project.meta gen-extra-source-files -- $$(pwd)/cabal-install/cabal-install.cabal.pp $$(pwd)/cabal-install/cabal-install.cabal+ cabal v2-run --builddir=dist-newstyle-meta --project-file=cabal.project.meta gen-extra-source-files -- $$(pwd)/cabal-install/cabal-install.cabal.zinza $$(pwd)/cabal-install/cabal-install.cabal $(MAKE) cabal-install-prod # ghcid@@ -84,6 +121,10 @@ doctest : doctest --fast Cabal/Distribution Cabal/Language +# This is not run as part of validate.sh (we need hackage-security, which is tricky to get).+doctest-cli :+ doctest -D__DOCTEST__ --fast cabal-install/Distribution+ # tests check-tests :@@ -110,5 +151,78 @@ rm -rf .ghc.environment.* cd cabal-testsuite && `cabal-plan list-bin cabal-tests` --with-cabal=`cabal-plan list-bin cabal` --hide-successes -j3 ${TEST} -validate-via-docker:- docker build -t cabal-validate -f validate.dockerfile .+# This doesn't run build, as you first need to test with cabal-install-test :)+cabal-install-test-accept:+ @which cabal-plan+ rm -rf .ghc.environment.*+ cd cabal-testsuite && `cabal-plan list-bin cabal-tests` --with-cabal=`cabal-plan list-bin cabal` --hide-successes -j3 --accept ${TEST}++# Docker validation++# Use this carefully, on big machine you can say+#+# make validate-via-docker-all -j4 -O+#+validate-via-docker-all : validate-via-docker-7.6.3+validate-via-docker-all : validate-via-docker-7.8.4+validate-via-docker-all : validate-via-docker-7.10.3+validate-via-docker-all : validate-via-docker-8.0.2+validate-via-docker-all : validate-via-docker-8.2.2+validate-via-docker-all : validate-via-docker-8.4.4+validate-via-docker-all : validate-via-docker-8.6.5+validate-via-docker-all : validate-via-docker-8.8.3+validate-via-docker-all : validate-via-docker-8.10.1++validate-dockerfiles : .docker/validate-8.10.1.dockerfile+validate-dockerfiles : .docker/validate-8.8.3.dockerfile+validate-dockerfiles : .docker/validate-8.6.5.dockerfile+validate-dockerfiles : .docker/validate-8.4.4.dockerfile+validate-dockerfiles : .docker/validate-8.2.2.dockerfile+validate-dockerfiles : .docker/validate-8.6.5.dockerfile+validate-dockerfiles : .docker/validate-7.10.3.dockerfile+validate-dockerfiles : .docker/validate-7.8.4.dockerfile+validate-dockerfiles : .docker/validate-7.6.3.dockerfile++.docker/validate-%.dockerfile : .docker/validate.dockerfile.zinza cabal-dev-scripts/src/GenValidateDockerfile.hs+ cabal v2-run --builddir=dist-newstyle-meta --project-file=cabal.project.meta gen-validate-dockerfile -- $* $< $@++validate-via-docker-7.6.3:+ docker build -t cabal-validate -f .docker/validate-7.6.3.dockerfile .++validate-via-docker-7.8.4:+ docker build -t cabal-validate -f .docker/validate-7.8.4.dockerfile .++validate-via-docker-7.10.3:+ docker build -t cabal-validate -f .docker/validate-7.10.3.dockerfile .++validate-via-docker-8.0.2:+ docker build -t cabal-validate -f .docker/validate-8.0.2.dockerfile .++validate-via-docker-8.2.2:+ docker build -t cabal-validate -f .docker/validate-8.2.2.dockerfile .++validate-via-docker-8.4.4:+ docker build -t cabal-validate -f .docker/validate-8.4.4.dockerfile .++validate-via-docker-8.6.5:+ docker build -t cabal-validate -f .docker/validate-8.6.5.dockerfile .++validate-via-docker-8.8.3:+ docker build -t cabal-validate -f .docker/validate-8.8.3.dockerfile .++# Only library ATM+validate-via-docker-8.10.1:+ docker build -t cabal-validate -f .docker/validate-8.10.1.dockerfile .++validate-via-docker-old:+ docker build -t cabal-validate -f .docker/validate-old.dockerfile .++# Weeder+weeder :+ cabal build all --project-file=cabal.project.weeder+ weeder | less++# tags+.PHONY : tags+tags :+ hasktags -b Cabal/Distribution Cabal/Cabal-described/src Cabal/Language cabal-install/Distribution cabal-testsuite/src
cabal/appveyor.yml view
@@ -47,7 +47,7 @@ - "C:\\sr" build_script:- - runghc cabal-dev-scripts/src/Preprocessor.hs -o cabal-install/cabal-install.cabal -f CABAL_FLAG_LIB cabal-install/cabal-install.cabal.pp+ - cp cabal-install/cabal-install.cabal.dev cabal-install/cabal-install.cabal - cabal %CABOPTS% v2-configure --enable-tests - appveyor-retry cabal %CABOPTS% v2-build lib:Cabal --only-dependencies - cabal %CABOPTS% v2-build lib:Cabal@@ -55,7 +55,7 @@ - cabal %CABOPTS% v2-test Cabal - appveyor-retry cabal %CABOPTS% v2-build exe:cabal exe:cabal-tests --only-dependencies - cabal %CABOPTS% v2-build exe:cabal- - cabal %CABOPTS% v2-run cabal-tests -- -j3 --with-cabal=dist-newstyle\build\x86_64-windows\ghc-8.6.5\cabal-install-3.1.0.0\x\cabal\build\cabal\cabal.exe+ - cabal %CABOPTS% v2-run cabal-tests -- -j3 --with-cabal=dist-newstyle\build\x86_64-windows\ghc-8.6.5\cabal-install-3.3.0.0\x\cabal\build\cabal\cabal.exe - appveyor-retry cabal %CABOPTS% v2-build cabal-install:tests --only-dependencies - cd cabal-install - cabal %CABOPTS% v2-run cabal-install:memory-usage-tests
cabal/boot/SPDX.LicenseExceptionId.template.hs view
@@ -11,9 +11,11 @@ import Distribution.Compat.Prelude import Prelude () +import Distribution.Compat.Lens (set) import Distribution.Pretty import Distribution.Parsec import Distribution.Utils.Generic (isAsciiAlphaNum)+import Distribution.Utils.Structured (Structured (..), nominalStructure, typeVersion) import Distribution.SPDX.LicenseListVersion import qualified Data.Binary.Get as Binary@@ -39,6 +41,10 @@ then fail "Too large LicenseExceptionId tag" else return (toEnum (fromIntegral i)) +-- note: remember to bump version each time the definition changes+instance Structured LicenseExceptionId where+ structure p = set typeVersion 306 $ nominalStructure p+ instance Pretty LicenseExceptionId where pretty = Disp.text . licenseExceptionId @@ -82,12 +88,16 @@ licenseExceptionIdList LicenseListVersion_3_6 = {{licenseList_3_6}} ++ bulkOfLicenses+licenseExceptionIdList LicenseListVersion_3_9 =+{{licenseList_3_9}}+ ++ bulkOfLicenses -- | Create a 'LicenseExceptionId' from a 'String'. mkLicenseExceptionId :: LicenseListVersion -> String -> Maybe LicenseExceptionId mkLicenseExceptionId LicenseListVersion_3_0 s = Map.lookup s stringLookup_3_0 mkLicenseExceptionId LicenseListVersion_3_2 s = Map.lookup s stringLookup_3_2 mkLicenseExceptionId LicenseListVersion_3_6 s = Map.lookup s stringLookup_3_6+mkLicenseExceptionId LicenseListVersion_3_9 s = Map.lookup s stringLookup_3_9 stringLookup_3_0 :: Map String LicenseExceptionId stringLookup_3_0 = Map.fromList $ map (\i -> (licenseExceptionId i, i)) $@@ -100,6 +110,10 @@ stringLookup_3_6 :: Map String LicenseExceptionId stringLookup_3_6 = Map.fromList $ map (\i -> (licenseExceptionId i, i)) $ licenseExceptionIdList LicenseListVersion_3_6++stringLookup_3_9 :: Map String LicenseExceptionId+stringLookup_3_9 = Map.fromList $ map (\i -> (licenseExceptionId i, i)) $+ licenseExceptionIdList LicenseListVersion_3_9 -- | License exceptions in all SPDX License lists bulkOfLicenses :: [LicenseExceptionId]
cabal/boot/SPDX.LicenseId.template.hs view
@@ -5,6 +5,7 @@ licenseId, licenseName, licenseIsOsiApproved,+ licenseIsFsfLibre, mkLicenseId, licenseIdList, -- * Helpers@@ -14,9 +15,11 @@ import Distribution.Compat.Prelude import Prelude () +import Distribution.Compat.Lens (set) import Distribution.Pretty import Distribution.Parsec import Distribution.Utils.Generic (isAsciiAlphaNum)+import Distribution.Utils.Structured (Structured (..), nominalStructure, typeVersion) import Distribution.SPDX.LicenseListVersion import qualified Data.Binary.Get as Binary@@ -44,6 +47,10 @@ then fail "Too large LicenseId tag" else return (toEnum (fromIntegral i)) +-- note: remember to bump version each time the definition changes+instance Structured LicenseId where+ structure p = set typeVersion 306 $ nominalStructure p+ instance Pretty LicenseId where pretty = Disp.text . licenseId @@ -125,9 +132,26 @@ -- See <https://opensource.org/licenses/alphabetical>. licenseIsOsiApproved :: LicenseId -> Bool {% for l in licenses %}-licenseIsOsiApproved {{l.constructor}} = {% if l.isOsiApproved %}True{% else %}False{% endif %}+{% if l.isOsiApproved %}+licenseIsOsiApproved {{l.constructor}} = True+{% endif %} {% endfor %}+licenseIsOsiApproved _ = False +-- | Whether the license is considered libre by Free Software Foundation (FSF).+--+-- See <https://www.gnu.org/licenses/license-list.en.html>+--+-- @since 3.4.0.0+--+licenseIsFsfLibre :: LicenseId -> Bool+{% for l in licenses %}+{% if l.isFsfLibre %}+licenseIsFsfLibre {{l.constructor}} = True+{% endif %}+{% endfor %}+licenseIsFsfLibre _ = False+ ------------------------------------------------------------------------------- -- Creation -------------------------------------------------------------------------------@@ -142,12 +166,16 @@ licenseIdList LicenseListVersion_3_6 = {{licenseList_3_6}} ++ bulkOfLicenses+licenseIdList LicenseListVersion_3_9 =+{{licenseList_3_9}}+ ++ bulkOfLicenses -- | Create a 'LicenseId' from a 'String'. mkLicenseId :: LicenseListVersion -> String -> Maybe LicenseId mkLicenseId LicenseListVersion_3_0 s = Map.lookup s stringLookup_3_0 mkLicenseId LicenseListVersion_3_2 s = Map.lookup s stringLookup_3_2 mkLicenseId LicenseListVersion_3_6 s = Map.lookup s stringLookup_3_6+mkLicenseId LicenseListVersion_3_9 s = Map.lookup s stringLookup_3_9 stringLookup_3_0 :: Map String LicenseId stringLookup_3_0 = Map.fromList $ map (\i -> (licenseId i, i)) $@@ -160,6 +188,10 @@ stringLookup_3_6 :: Map String LicenseId stringLookup_3_6 = Map.fromList $ map (\i -> (licenseId i, i)) $ licenseIdList LicenseListVersion_3_6++stringLookup_3_9 :: Map String LicenseId+stringLookup_3_9 = Map.fromList $ map (\i -> (licenseId i, i)) $+ licenseIdList LicenseListVersion_3_9 -- | Licenses in all SPDX License lists bulkOfLicenses :: [LicenseId]
+ cabal/boot/cabal_macros.template.h view
@@ -0,0 +1,41 @@+/* DO NOT EDIT: This file is automatically generated by Cabal */++{% for pkg in packages %}+/* package {{ pkg.name }}-{{ pkg.version }} */+#ifndef VERSION_{{ manglePkgName pkg.name }}+#define VERSION_{{ manglePkgName pkg.name }} "{{ pkg.version }}"+#endif /* VERSION_{{ manglePkgName pkg.name }} */+#ifndef MIN_VERSION_{{ manglePkgName pkg.name }}+#define MIN_VERSION_{{ manglePkgName pkg.name }}(major1,major2,minor) (\+ (major1) < {{ pkg.x }} || \+ (major1) == {{ pkg.x }} && (major2) < {{ pkg.y }} || \+ (major1) == {{ pkg.x }} && (major2) == {{ pkg.y }} && (minor) <= {{ pkg.z }})+#endif /* MIN_VERSION_{{ manglePkgName pkg.name }} */+{% endfor %}++{% for tool in tools %}+/* tool {{ tool.name }}-{{ tool.version }} */+#ifndef TOOL_VERSION_{{ mangleStr tool.name }}+#define TOOL_VERSION_{{ mangleStr tool.name }} "{{ tool.version }}"+#endif /* TOOL_VERSION_{{ mangleStr tool.name }} */+#ifndef MIN_TOOL_VERSION_{{ mangleStr tool.name }}+#define MIN_TOOL_VERSION_{{ mangleStr tool.name }}(major1,major2,minor) (\+ (major1) < {{ tool.x }} || \+ (major1) == {{ tool.x }} && (major2) < {{ tool.y }} || \+ (major1) == {{ tool.x }} && (major2) == {{ tool.y }} && (minor) <= {{ tool.z }})+#endif /* MIN_TOOL_VERSION_{{ mangleStr tool.name }} */+{% endfor %}++{% if notNull packageKey %}+#ifndef CURRENT_PACKAGE_KEY+#define CURRENT_PACKAGE_KEY "{{ packageKey }}"+#endif /* CURRENT_packageKey */+{% endif %}+{% if notNull componentId %}+#ifndef CURRENT_COMPONENT_ID+#define CURRENT_COMPONENT_ID "{{ componentId }}"+#endif /* CURRENT_COMPONENT_ID */+{% endif %}+#ifndef CURRENT_PACKAGE_VERSION+#define CURRENT_PACKAGE_VERSION "{{ packageVersion }}"+#endif /* CURRENT_PACKAGE_VERSION */
+ cabal/boot/ci-artifacts.template.yml view
@@ -0,0 +1,136 @@+name: Artifacts+on:+ push:+ branches:+ - master+ - "3.2"+ pull_request:+ branches:+ - master+ release:+ types:+ - created++jobs:+ artifact-linux:+ name: Artifact on Linux+ runs-on: ubuntu-18.04+ container:+ # Older Ubuntu for older glibc+ image: phadej/ghc:8.6.5-xenial+ steps:+ - name: Set PATH+ run: |+ echo "::add-path::$HOME/.cabal/bin"+ - name: Update Hackage index+ run: cabal v2-update+ - uses: actions/checkout@v2+ - name: Release project+ run: |+ cp cabal.project.release cabal.project+ rm -rf cabal.project.local cabal.project.freeze+ - name: Build+ run: |+ cabal v2-build cabal-install:exe:cabal+ cp $(find dist-newstyle -type f -executable -name cabal) cabal.exe+ - name: Smoke test+ run: |+ ./cabal.exe --version+ - name: Prepare for upload+ run: xz -c < cabal.exe > cabal-artifact.xz+ - uses: actions/upload-artifact@v1+ with:+ name: cabal-linux-x86_64.xz+ path: cabal-artifact.xz++ artifact-macos:+ name: Artifact on macOS+ runs-on: macos-latest+ steps:+ - name: Install GHC+ run: |+ cd $(mktemp -d)+ curl -sLO "https://downloads.haskell.org/~ghc/8.6.5/ghc-8.6.5-x86_64-apple-darwin.tar.xz"+ tar -xJf ghc-*.tar.xz+ cd ghc-*+ ./configure --prefix=/opt/ghc/8.6.5+ sudo make install+ - name: Install Cabal+ run: |+ cd $(mktemp -d)+ curl -sLO https://downloads.haskell.org/~cabal/cabal-install-3.0.0.0/cabal-install-3.0.0.0-x86_64-apple-darwin17.7.0.tar.xz+ tar -xJf cabal-install-*.tar.xz+ sudo mkdir -p /opt/cabal/3.0/bin+ sudo cp cabal /opt/cabal/3.0/bin/cabal+ sudo chmod 755 /opt/cabal/3.0/bin/cabal+ - name: Set PATH+ run: |+ echo "::add-path::/opt/ghc/8.6.5/bin"+ echo "::add-path::/opt/cabal/3.0/bin"+ echo "::add-path::$HOME/.cabal/bin"+ - name: Update Hackage index+ run: cabal v2-update+ - uses: actions/checkout@v2+ - name: Release project+ run: |+ cp cabal.project.release cabal.project+ rm -rf cabal.project.local cabal.project.freeze+ - name: Build+ run: |+ cabal v2-build cabal-install:exe:cabal+ # macOS find doesn't know -executable+ cp $(find dist-newstyle -type f -name cabal) cabal.exe+ - name: Smoke test+ run: |+ ./cabal.exe --version+ - name: Prepare for upload+ run: xz -c < cabal.exe > cabal-artifact.xz+ - uses: actions/upload-artifact@v1+ with:+ name: cabal-macos-x86_64.xz+ path: cabal-artifact.xz++ artifact-windows:+ name: Artifact on Windows+ runs-on: windows-latest+ steps:+ - name: Install Cabal+ run: choco install -fy cabal --version 3.0.0.0+ - name: Install GHC+ run: |+ choco uninstall -y ghc+ choco install -y ghc --version 8.6.5+ - name: Set PATH+ run: |+ [Environment]::GetEnvironmentVariable("Path")+ Write-Host "::add-path::C:\ProgramData\chocolatey\lib\cabal\tools\cabal-3.0.0.0"+ Write-Host "::add-path::C:\ProgramData\chocolatey\lib\ghc\tools\ghc-8.6.5\bin"+ - name: Print versions+ run: |+ ghc --version+ cabal --version+ cabal user-config init -a "http-transport: plain-http" -a "store-dir: C:\SR" -f -v3+ - name: Update Hackage index+ run: cabal v2-update+ - uses: actions/checkout@v2+ - name: Release project+ shell: bash+ run: |+ cp cabal.project.release cabal.project+ rm -rf cabal.project.local cabal.project.freeze+ - name: Build+ shell: bash+ run: |+ cabal v2-build cabal-install:exe:cabal+ cp dist-newstyle/build/x86_64-windows/ghc-8.6.5/cabal-install-3.3.0.0/x/cabal/build/cabal/cabal.exe cabal.exe+ - name: Smoke test+ shell: bash+ run: |+ ./cabal.exe --version+ - name: Prepare for upload+ shell: bash+ run: xz -c < cabal.exe > cabal-artifact.xz+ - uses: actions/upload-artifact@v1+ with:+ name: cabal-windows-x86_64.xz+ path: cabal-artifact.xz
+ cabal/boot/ci-bootstrap.template.yml view
@@ -0,0 +1,64 @@+# This file is auto-generated+#+# To regenerate it run+#+# make github-actions+#+name: Bootstrap+on:+ push:+ branches:+ - master+ - "3.2"+ pull_request:+ branches:+ - master+ release:+ types:+ - created++jobs:+ boostrap-linux:+ name: Bootstrap on Linux+ runs-on: ubuntu-18.04+ steps:+ - name: Set PATH+ run: |+ echo "::add-path::/opt/ghc/8.6.5/bin"+ - uses: actions/checkout@v2+ - name: bootstrap.sh+ env:+ EXTRA_CONFIGURE_OPTS: ""+ run: |+ cd cabal-install+ sh ./bootstrap.sh --no-doc+ - name: Smoke test+ run: |+ $HOME/.cabal/bin/cabal --version++ boostrap-macos:+ name: Bootstrap on macOS+ runs-on: macos-latest+ steps:+ - name: Install GHC+ run: |+ cd $(mktemp -d)+ curl -sLO "https://downloads.haskell.org/~ghc/8.6.5/ghc-8.6.5-x86_64-apple-darwin.tar.xz"+ tar -xJf ghc-*.tar.xz+ cd ghc-*+ ./configure --prefix=/opt/ghc/8.6.5+ sudo make install+ - name: Set PATH+ run: |+ echo "::add-path::/opt/ghc/8.6.5/bin"+ echo "::add-path::$HOME/.cabal/bin"+ - uses: actions/checkout@v2+ - name: bootstrap.sh+ env:+ EXTRA_CONFIGURE_OPTS: ""+ run: |+ cd cabal-install+ sh ./bootstrap.sh --no-doc+ - name: Smoke test+ run: |+ $HOME/.cabal/bin/cabal --version
+ cabal/boot/ci-linux.template.yml view
@@ -0,0 +1,72 @@+# This file is auto-generated+#+# To regenerate it run+#+# make github-actions+#+name: Linux+on:+ push:+ branches:+ - master+ - "3.2"+ pull_request:+ branches:+ - master+ release:+ types:+ - created++jobs:+{% for job in jobs %}+ validate-{{ mangleVersion job.version }}{% if job.old %}-old{% endif %}:+ name: validate.sh {%if job.old %}old GHCs{% else %}ghc-{{job.version}}{% endif %}+ runs-on: ubuntu-18.04+{% for needs in job.needs %}+ needs: validate-{{ mangleVersion needs }}+{% endfor %}+ container:+ image: phadej/ghc:{{job.version}}-{% if job.xenial %}xenial{% else %}bionic{% endif %}+ steps:+ - name: System info+ run: |+ uname -a+ # https://help.github.com/en/actions/automating-your-workflow-with-github-actions/development-tools-for-github-actions#add-a-system-path-add-path+ - name: Set PATH+ run: |+ echo "::add-path::$HOME/.cabal/bin"+ - name: Install cabal-plan+ run: |+ mkdir -p $HOME/.cabal/bin+ curl -sL https://github.com/haskell-hvr/cabal-plan/releases/download/v0.6.2.0/cabal-plan-0.6.2.0-x86_64-linux.xz > cabal-plan.xz+ echo "de73600b1836d3f55e32d80385acc055fd97f60eaa0ab68a755302685f5d81bc cabal-plan.xz" | sha256sum -c -+ xz -d < cabal-plan.xz > $HOME/.cabal/bin/cabal-plan+ rm -f cabal-plan.xz+ chmod a+x $HOME/.cabal/bin/cabal-plan+{% if or job.xenial job.old %}+ - name: apt-get update+ run: apt-get update+{% endif %}+{% if job.xenial %}+ - name: Install dynamic libraries+ run: apt-get install -y ghc-{{job.version}}-dyn+{% endif %}+{% if job.old %}+ - name: Install extra compilers+ run: apt-get install -y ghc-7.0.4-dyn ghc-7.2.2-dyn ghc-7.4.2-dyn+{% endif %}+ - name: Update Hackage index+ run: cabal v2-update+ # https://github.com/actions/checkout/issues/170+ # - uses: actions/checkout@v2+ - name: Checkout+ run: |+ echo $GITHUB_REF $GITHUB_SHA+ git clone --depth 1 https://github.com/$GITHUB_REPOSITORY.git .+ git fetch origin $GITHUB_SHA:temporary-ci-branch+ git checkout $GITHUB_SHA || (git fetch && git checkout $GITHUB_SHA)+{% for step in job.steps %}+ - name: Validate {{step}}+ run: sh validate.sh -j 2 -w ghc-{{job.version}} -v {{job.flags}} -s {{step}}+{% endfor %}+{% endfor %}
+ cabal/boot/ci-macos.template.yml view
@@ -0,0 +1,68 @@+# This file is auto-generated+#+# To regenerate it run+#+# make github-actions+#+name: MacOS+on:+ push:+ branches:+ - master+ - "3.2"+ pull_request:+ branches:+ - master+ release:+ types:+ - created++jobs:+{% for job in macosJobs %}+ validate-macos-{{ mangleVersion job.version }}:+ name: validate.sh macos ghc-{{job.version}}+ runs-on: macos-latest+{% for needs in job.needs %}+ needs: validate-macos-{{ mangleVersion needs }}+{% endfor %}+ steps:+ - name: System info+ run: |+ uname -a+ - name: Install Autotools+ run: |+ brew install automake+ - name: Install GHC+ run: |+ cd $(mktemp -d)+ curl -sLO {{job.ghcUrl}}+ tar -xJf ghc-*.tar.xz+ cd ghc-*+ ./configure --prefix=/opt/ghc/{{job.version}}+ sudo make install+ - name: Install Cabal+ run: |+ cd $(mktemp -d)+ curl -sLO https://downloads.haskell.org/~cabal/cabal-install-3.0.0.0/cabal-install-3.0.0.0-x86_64-apple-darwin17.7.0.tar.xz+ tar -xJf cabal-install-*.tar.xz+ sudo mkdir -p /opt/cabal/3.0/bin+ sudo cp cabal /opt/cabal/3.0/bin/cabal+ sudo chmod 755 /opt/cabal/3.0/bin/cabal+ - name: Set PATH+ run: |+ echo "::add-path::/opt/ghc/{{job.version}}/bin"+ echo "::add-path::/opt/cabal/3.0/bin"+ echo "::add-path::$HOME/.cabal/bin"+ - name: Update Hackage index+ run: cabal v2-update+ - name: Install cabal-plan+ run: |+ cd $(mktemp -d)+{# aeson +fast, so we don't wait for -O2 #}+ cabal v2-install cabal-plan --constraint='cabal-plan ^>=0.6.2.0' --constraint='aeson +fast'+ - uses: actions/checkout@v2+{% for step in job.steps %}+ - name: Validate {{step}}+ run: sh validate.sh -j 2 -w ghc-{{job.version}} -v {{job.flags}} -s {{step}}+{% endfor %}+{% endfor %}
+ cabal/boot/ci-quick-jobs.template.yml view
@@ -0,0 +1,84 @@+# This file is auto-generated+#+# To regenerate it run+#+# make github-actions+#+name: Quick jobs+on:+ push:+ branches:+ - master+ - "3.2"+ pull_request:+ branches:+ - master+ release:+ types:+ - created++jobs:+ meta:+ name: Meta checks+ runs-on: ubuntu-18.04+ # This job is not run in a container, any recent GHC should be fine+ steps:+ - name: Set PATH+ run: |+ echo "::add-path::$HOME/.cabal/bin"+ echo "::add-path::/opt/cabal/3.2/bin"+ echo "::add-path::/opt/ghc/8.6.5/bin"+ - uses: actions/cache@v1+ with:+ path: ~/.cabal/store+ key: linux-store-meta+ - name: Update Hackage index+ run: cabal v2-update+ - name: Install alex+ run: cabal v2-install alex+ - uses: actions/checkout@v2+ - name: Regenerate files+ run: |+ make lexer+ make gen-extra-source-files+ make spdx+ make templates+ make github-actions+ make cabal-install-cabal+ - name: Check that diff is clean+ run: |+ git status > /dev/null+ git diff-files -p --exit-code+ doctest:+ name: Doctest Cabal+ runs-on: ubuntu-18.04+ steps:+ - name: Set PATH+ run: |+ echo "::add-path::$HOME/.cabal/bin"+ echo "::add-path::/opt/cabal/3.2/bin"+ echo "::add-path::/opt/ghc/8.6.5/bin"+ - name: Install cabal-env+ run: |+ mkdir -p $HOME/.cabal/bin+ curl -sL https://github.com/phadej/cabal-extras/releases/download/preview-20191225/cabal-env-snapshot-20191225-x86_64-linux.xz > cabal-env.xz+ echo "1b567d529c5f627fd8c956e57ae8f0d9f11ee66d6db34b7fb0cb1c370b4edf01 cabal-env.xz" | sha256sum -c -+ xz -d < cabal-env.xz > $HOME/.cabal/bin/cabal-env+ rm -f cabal-env.xz+ chmod a+x $HOME/.cabal/bin/cabal-env+ - uses: actions/cache@v1+ with:+ path: ~/.cabal/store+ key: linux-store-doctest+ - name: Update Hackage index+ run: cabal v2-update+ - name: Install doctest+ run: cabal v2-install doctest+ - name: Install libraries+ run: |+ cabal-env --transitive QuickCheck+ cabal-env array bytestring containers deepseq directory filepath pretty process time binary unix text parsec mtl+ cat $HOME/.ghc/*/environments/default+ - uses: actions/checkout@v2+ - name: Doctest+ run: make doctest
+ cabal/boot/ci-windows.template.yml view
@@ -0,0 +1,84 @@+# This file is auto-generated+#+# To regenerate it run+#+# make github-actions+#+name: Windows+on:+ push:+ branches:+ - master+ - "3.2"+ pull_request:+ branches:+ - master+ release:+ types:+ - created++jobs:++{############################################################################}+{# Windows jobs #}+{############################################################################}+{% for job in winJobs %}+ test-windows-{{ mangleVersion job.version }}:+ name: test ghc-{{job.version}}+ runs-on: windows-latest+{% for needs in job.needs %}+ needs: test-windows-{{ mangleVersion needs }}+{% endfor %}+ steps:+ - name: Install Cabal+ run: choco install -fy cabal --version 3.2.0.0+ - name: Install GHC+ run: |+ choco uninstall -y ghc --all-versions+ choco install -y ghc --version {{ job.version }}+ - name: Set PATH+ run: |+ [Environment]::GetEnvironmentVariable("Path")+ Write-Host "::add-path::C:\ProgramData\Chocolatey\lib\cabal\tools\cabal-3.2.0.0"+ Write-Host "::add-path::C:\ProgramData\Chocolatey\lib\ghc\tools\ghc-{{ job.version }}\bin"+ [Environment]::GetEnvironmentVariable("Path")+ - name: Print versions+ run: |+ [Environment]::GetEnvironmentVariable("Path")+ cabal --version+ ghc --version+ cabal user-config init -a "http-transport: plain-http" -a "store-dir: C:\SR" -f -v3+ - uses: actions/cache@v1+ with:+ path: C:\SR+ key: windows-store-meta+ - name: Update Hackage index+ run: cabal v2-update+ - uses: actions/checkout@v2+ - name: make cabal-install-dev+ run: cp cabal-install/cabal-install.cabal.dev cabal-install/cabal-install.cabal+ # We cannot ask for all dependencies, but we can for Cabal.+ - name: cabal v2-build Cabal --only-dependencies+ run: cabal v2-build Cabal --only-dependencies+ - name: cabal v2-build+ run: cabal v2-build all+ - name: cabal-install memory-usage-tests+ run: |+ cd cabal-install+ cabal v2-run cabal-install:memory-usage-tests+ - name: cabal-install solver-quickcheck+ run: |+ cd cabal-install+ cabal v2-run cabal-install:solver-quickcheck+ - name: cabal-install integration-tests2+ run: |+ cd cabal-install+ cabal v2-run cabal-install:integration-tests2+ - name: cabal-install unit-tests+ run: |+ cd cabal-install+ cabal v2-run cabal-install:unit-tests -- --pattern "! (/FileMonitor/ || /VCS/ || /Get/)"+ - name: cabal-tests+ # Using only one job, -j1, to fail less.+ run: cabal v2-run cabal-tests -- -j1 --with-cabal=dist-newstyle\build\x86_64-windows\ghc-{{ job.version }}\cabal-install-3.3.0.0\x\cabal\build\cabal\cabal.exe+{% endfor %}
+ cabal/buildinfo-reference-generator/buildinfo-reference-generator.cabal view
@@ -0,0 +1,16 @@+cabal-version: 2.2+name: buildinfo-reference-generator+version: 0++executable buildinfo-reference-generator+ default-language: Haskell2010+ hs-source-dirs: src+ ghc-options: -Wall+ main-is: Main.hs+ build-depends:+ , base ^>=4.12 || ^>=4.13+ , Cabal+ , Cabal-described+ , containers+ , pretty+ , zinza ^>=0.2
+ cabal/buildinfo-reference-generator/src/Main.hs view
@@ -0,0 +1,274 @@+{-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE MultiParamTypeClasses #-}+module Main (main) where++import Data.Map.Strict (Map)++import Data.Bifunctor (first)+import Data.Proxy (Proxy (..))+import Data.Void (Void)+import Distribution.CabalSpecVersion (CabalSpecVersion, showCabalSpecVersion)+import Distribution.Compat.Newtype (pack')+import Distribution.FieldGrammar.Class (FieldGrammar (..))+import Distribution.Fields.Field (FieldName)+import Distribution.Pretty (pretty)+import Distribution.Simple.Utils (fromUTF8BS)+import GHC.Generics (Generic)+import System.Environment (getArgs)+import System.Exit (exitFailure)++import Distribution.PackageDescription.FieldGrammar (buildInfoFieldGrammar, packageDescriptionFieldGrammar, testSuiteFieldGrammar)++import qualified Data.Map.Strict as Map+import qualified Text.PrettyPrint as PP++import qualified Zinza as Z++import Distribution.Described+import Distribution.Utils.GrammarRegex++import Distribution.ModuleName (ModuleName)+import Distribution.Types.Version (Version)+import Distribution.Types.VersionRange (VersionRange)++-------------------------------------------------------------------------------+-- Main+-------------------------------------------------------------------------------++main :: IO ()+main = do+ args <- getArgs+ case args of+ [tmpl] -> do+ -- TODO: getArgs+ run <- Z.parseAndCompileTemplateIO tmpl+ contents <- run $ Z+ { zBuildInfoFields = fromReference buildInfoFieldGrammar+ , zPackageDescriptionFields = fromReference packageDescriptionFieldGrammar+ , zTestSuiteFields = fromReference $ testSuiteFieldGrammar // buildInfoFieldGrammar+ , zProductions =+ [ zproduction "hs-string" reHsString+ "String as in Haskell; it's recommended to avoid using Haskell-specific escapes."+ , zproduction "unqual-name" reUnqualComponent $ unwords+ [ "Unqualified component names are used for package names, component names etc. but not flag names."+ , "Unqualified component name consist of components separated by dash, each component is non-empty alphanumeric string, with at least one alphabetic character."+ , "In other words, component may not look like a number."+ ]++ , zproduction "module-name" (describe (Proxy :: Proxy ModuleName))+ "Haskell module name as recognized by Cabal parser."+ , zproduction "version" (describe (Proxy :: Proxy Version))+ "Version is to first approximation numbers separated by dots, where leading zero is not allowed and each version digit is consists at most of nine characters."+ , zproduction "version-range" (describe (Proxy :: Proxy VersionRange))+ "Version range syntax is recursive. Also note the set syntax added in ``cabal-version: 3.0``, set cannot be empty."+ ]+ , zSpaceList = show $ regexDoc $+ REMunch RESpaces1 (RENamed "element" RETodo)+ , zCommaList = show $ regexDoc $+ expandedCommaList (RENamed "element" RETodo)+ , zOptCommaList = show $ regexDoc $+ expandedOptCommaList (RENamed "element" RETodo)++ , zNull = null+ , zNotNull = not . null+ }++ putStrLn contents+ _ -> do+ putStrLn "Usage: generator <tmpl>"+ exitFailure++zproduction :: String -> GrammarRegex Void -> String -> ZProduction+zproduction name re desc = ZProduction+ { zprodName = name+ , zprodSyntax = show (regexDoc re')+ , zprodDescription = desc+ }+ where+ re' = case re of+ RENamed _ r -> r+ _ -> re++-- also in UnitTests.Distribution.Described+expandedCommaList :: GrammarRegex a -> GrammarRegex a+expandedCommaList = REUnion . expandedCommaList'++expandedCommaList' :: GrammarRegex a -> [GrammarRegex a]+expandedCommaList' r =+ [ REMunch reSpacedComma r+ , reComma <> RESpaces <> REMunch1 reSpacedComma r+ , REMunch1 reSpacedComma r <> RESpaces <> reComma+ ]++expandedOptCommaList :: GrammarRegex a -> GrammarRegex a+expandedOptCommaList r = REUnion $ reSpacedList r : expandedCommaList' r++-------------------------------------------------------------------------------+-- Template Inputs+-------------------------------------------------------------------------------++data Z = Z+ { zBuildInfoFields :: [ZField]+ , zPackageDescriptionFields :: [ZField]+ , zTestSuiteFields :: [ZField]+ , zProductions :: [ZProduction]+ , zSpaceList :: String+ , zCommaList :: String+ , zOptCommaList :: String+ , zNull :: String -> Bool+ , zNotNull :: String -> Bool+ }+ deriving (Generic)++data ZField = ZField+ { zfieldName :: String+ , zfieldAvailableSince :: String+ , zfieldDeprecatedSince :: (String, String)+ , zfieldRemovedIn :: (String, String)+ , zfieldFormat :: String+ , zfieldDefault :: String+ , zfieldSyntax :: String+ }+ deriving (Generic)++data ZProduction = ZProduction+ { zprodName :: String+ , zprodSyntax :: String+ , zprodDescription :: String+ }+ deriving (Generic)++instance Z.Zinza Z where+ toType = Z.genericToTypeSFP+ toValue = Z.genericToValueSFP+ fromValue = Z.genericFromValueSFP++instance Z.Zinza ZField where+ toType = Z.genericToTypeSFP+ toValue = Z.genericToValueSFP+ fromValue = Z.genericFromValueSFP++instance Z.Zinza ZProduction where+ toType = Z.genericToTypeSFP+ toValue = Z.genericToValueSFP+ fromValue = Z.genericFromValueSFP++-------------------------------------------------------------------------------+-- From reference+-------------------------------------------------------------------------------++-- TODO: produce ZField+fromReference :: Reference a a -> [ZField]+fromReference (Reference m) =+ [ ZField+ { zfieldName = fromUTF8BS n+ , zfieldAvailableSince = maybe "" showCabalSpecVersion (fdAvailableSince desc)+ , zfieldDeprecatedSince = maybe ("", "") (first showCabalSpecVersion) (fdDeprecatedSince desc)+ , zfieldRemovedIn = maybe ("", "") (first showCabalSpecVersion) (fdRemovedIn desc)+ , zfieldFormat = fmt+ , zfieldDefault = def+ , zfieldSyntax = syntax+ }+ | (n, desc) <- Map.toList m+ , let (fmt, def, syntax) = fromFieldDesc' (fdDescription desc)+ ]++fromFieldDesc' :: FieldDesc' -> (String, String, String)+fromFieldDesc' (MonoidalFieldAla s) = ("Monoidal field", "", show s)+fromFieldDesc' (BooleanFieldDesc def) = ("Boolean field", show def, show $ describeDoc ([] :: [Bool]))+fromFieldDesc' (OptionalFieldAla s) = ("Optional field", "", show s)+fromFieldDesc' (OptionalFieldDefAla s def) = ("Optional field", show def, show s)+fromFieldDesc' FreeTextField = ("Free text field", "", "")+fromFieldDesc' (UniqueField s) = ("Required field", "", show s)++-------------------------------------------------------------------------------+-- Reference+-------------------------------------------------------------------------------++newtype Reference a b = Reference (Map FieldName FieldDesc)+ deriving (Functor)++referenceAvailableSince :: CabalSpecVersion -> Reference a b -> Reference a b+referenceAvailableSince v (Reference m) =+ Reference (fmap (fieldDescAvailableSince v) m)++referenceRemovedIn :: CabalSpecVersion -> String -> Reference a b -> Reference a b+referenceRemovedIn v desc (Reference m) =+ Reference (fmap (fieldDescRemovedIn v desc) m)++referenceDeprecatedSince :: CabalSpecVersion -> String -> Reference a b -> Reference a b+referenceDeprecatedSince v desc (Reference m) =+ Reference (fmap (fieldDescDeprecatedSince v desc) m)++(//) :: Reference a b -> Reference c d -> Reference a b+Reference ab // Reference cd = Reference $ Map.difference ab cd++fieldDescAvailableSince :: CabalSpecVersion -> FieldDesc -> FieldDesc+fieldDescAvailableSince v d = d { fdAvailableSince = Just v }++fieldDescRemovedIn :: CabalSpecVersion -> String -> FieldDesc -> FieldDesc+fieldDescRemovedIn v desc d = d { fdRemovedIn = Just (v, desc) }++fieldDescDeprecatedSince :: CabalSpecVersion -> String -> FieldDesc -> FieldDesc+fieldDescDeprecatedSince v desc d = d { fdDeprecatedSince = Just (v, desc) }++data FieldDesc = FieldDesc+ { fdAvailableSince :: Maybe CabalSpecVersion+ , fdRemovedIn :: Maybe (CabalSpecVersion, String)+ , fdDeprecatedSince :: Maybe (CabalSpecVersion, String)+ , fdDescription :: FieldDesc'+ }+ deriving Show++reference :: FieldName -> FieldDesc' -> Reference a b+reference fn d = Reference $ Map.singleton fn $ FieldDesc Nothing Nothing Nothing d++data FieldDesc'+ = BooleanFieldDesc Bool+ | UniqueField PP.Doc -- ^ not used in BuildInfo+ | FreeTextField -- ^ not user in BuildInfo+ | OptionalFieldAla PP.Doc+ | OptionalFieldDefAla PP.Doc PP.Doc+ | MonoidalFieldAla PP.Doc+ deriving Show++instance Applicative (Reference a) where+ pure _ = Reference Map.empty+ Reference f <*> Reference x = Reference (Map.union f x)++instance FieldGrammar Described Reference where+ blurFieldGrammar _ (Reference xs) = Reference xs++ uniqueFieldAla fn pack _l =+ reference fn $ UniqueField (describeDoc pack)++ booleanFieldDef fn _l def =+ reference fn $ BooleanFieldDesc def++ optionalFieldAla fn pack _l =+ reference fn $ OptionalFieldAla (describeDoc pack)++ optionalFieldDefAla fn pack _l def =+ reference fn $ OptionalFieldDefAla+ (describeDoc pack)+ (pretty $ pack' pack def)++ freeTextField fn _l = reference fn FreeTextField++ freeTextFieldDef fn _l = reference fn FreeTextField+ freeTextFieldDefST fn _l = reference fn FreeTextField++ monoidalFieldAla fn pack _l =+ reference fn (MonoidalFieldAla (describeDoc pack))++ prefixedFields _pfx _l = Reference Map.empty++ knownField _fn = Reference Map.empty -- TODO++ -- hidden fields are hidden from the reference.+ hiddenField _ = Reference Map.empty++ deprecatedSince = referenceDeprecatedSince+ removedIn = referenceRemovedIn+ availableSince v _ r = referenceAvailableSince v r
+ cabal/buildinfo-reference-generator/template.zinza view
@@ -0,0 +1,233 @@+.. _buildinfo-field-reference:++Field Syntax Reference+======================++Notation+---------------++Field syntax is described as they are in the latest cabal file format version.++* terminals are enclosed in quotes and type set in typewriter script:++ .. math::++ \mathord{"}\mathtt{example}\mathord{"}++* non-terminals are type set in italic:++ .. math::++ \mathit{version\text-range}++* character sets are type set resembling regular expression notation:+++ .. math::++ [ \mathord{"}\mathtt{1}\mathord{"} \cdots \mathord{"}\mathtt{9}\mathord{"} ]++ Character set complements have :math:`c` superscript:++ .. math::++ [ \mathord{"}\mathtt{1}\mathord{"} \cdots \mathord{"}\mathtt{9}\mathord{"} ]^c++* repetition is type set using regular expression inspired notation.+ Superscripts tell how many time to repeat:+ The generic notation is :math:`\in[n\ldots5]`, however there+ are common shorthands:+ :math:`\ast` for :math:`\in[0\ldots\infty]` (``many``),+ :math:`+` for :math:`\in[1\ldots\infty]` (``some``),+ :math:`?` for :math:`\in[0\ldots1]` (``optional``).++ Subscripts tell the used separator:++ .. math::++ \mathit{digit}^+_{\mathord{"}\mathtt{.}\mathord{"}}++ Would be ``digit(\.digit)*`` in common regex syntax.++* alternatives are listed in braces separated by vertical bar:++ .. math::++ \{ \mathit{foo} \mid \mathit{bar} \}++ In case of multiple alternatives, the stacked notation is used++ .. math::++ \left\{\begin{gathered}+ \mathit{one} \\+ \mathit{two} \\+ \mathit{three} \\+ \mathit{four} \\+ \mathit{five}+ \end{gathered}\right\}++* parenthesis are used only for grouping:++ .. math::++ \left(\mathit{foo} \mid \mathit{bar}\right)^+++* any amount of spaces, and at least single space are type set using+ :math:`\circ` and :math:`\bullet` respectively.+ They may appear standalone, not only as binary operators.++ .. math::++ \mathit{module} \bullet \mathord{``}\mathtt{as}\mathord{"} \bullet \mathit{module}++* While notation is heavily regular expression inspired, there+ are also fixed points, which allow represent recursive grammars+++ .. math::+ + \mathbf{fix}\; \mathit{expr}\; \mathbf{in}\; \mathit{digit}+ \mid \mathit{expr} \circ \mathord{``}\mathtt{+}\mathord{"} \circ \mathit{expr}+ \mid \mathord{``}\mathtt{(} \mathord{"} \circ \mathit{expr} \circ \mathord{``}\mathtt{)}\mathord{"} ++Lists+-----++Many fields in cabal file format are lists. There are three variations:++Space separated+ Are used for lists of things with simple grammars, for example :pkg-field:`ghc-options`++ .. math::+ {{spaceList}}++Comma separated+ Are used for lists of things with complicated grammars, for example :pkg-field:`build-depends`+ There can be leading or trailing comma (but not both) since ``cabal-version: 2.2``.+ Note, the comma cannot exist alone.++ .. math::+ \mathrm{commalist}(\mathit{element}) =+ {{commaList}}++Optional comma separated+ Surprisingly many fields can have optional comma separator.+ Since ``cabal-version: 3.0`` comma usage have to be consistent,+ in other words either used everywhere or nowhere.+ It's recommended to avoid using comma in these fields,+ an example field is :pkg-field:`default-extensions`.++ .. math::+ \mathrm{optcommalist}(\mathit{element}) =+ {{optCommaList}}++Non-terminals+-------------++In the syntax definitions below the following non-terminal symbols are used:++{% for production in productions %}+{{ production.name }}+ {{ production.description }}++ .. math::+ {{ production.syntax }}++{% endfor %}++Build info fields+-----------------++{% for field in buildInfoFields %}+{{ field.name }}+ * {{field.format}}+{% if notNull field.default %}+ * Default: ``{{field.default}}``+{% endif %}+{% if notNull field.availableSince %}+ * Available since ``cabal-version: {{field.availableSince}}``.+{% endif %}+{% if notNull field.deprecatedSince.fst %}+ * Deprecated since ``cabal-version: {{field.deprecatedSince.fst}}``: {{field.deprecatedSince.snd}}+{% endif %}+{% if notNull field.removedIn.fst %}+ * Removed in ``cabal-version: {{field.removedIn.fst}}``: {{field.removedIn.snd}}+{% endif %}+{# We show documentation link only for non deprecated fields #}+{% if null field.deprecatedSince.fst %}+{% if null field.removedIn.fst %}+ * Documentation of :pkg-field:`{{field.name}}`+{% endif %}+{% endif %}+{% if notNull field.syntax %}++ .. math::+ {{field.syntax}}+{% endif %}++{% endfor %}++Package description fields+--------------------------++{% for field in packageDescriptionFields %}+{{ field.name }}+ * {{field.format}}+{% if notNull field.default %}+ * Default: ``{{field.default}}``+{% endif %}+{% if notNull field.availableSince %}+ * Available since ``cabal-version: {{field.availableSince}}``.+{% endif %}+{% if notNull field.deprecatedSince.fst %}+ * Deprecated since ``cabal-version: {{field.deprecatedSince.fst}}``: {{field.deprecatedSince.snd}}+{% endif %}+{% if notNull field.removedIn.fst %}+ * Removed in ``cabal-version: {{field.removedIn.fst}}``: {{field.removedIn.snd}}+{% endif %}+{# We show documentation link only for non deprecated fields #}+{% if null field.deprecatedSince.fst %}+{% if null field.removedIn.fst %}+ * Documentation of :pkg-field:`{{field.name}}`+{% endif %}+{% endif %}+{% if notNull field.syntax %}++ .. math::+ {{field.syntax}}+{% endif %}++{% endfor %}++Test-suite fields+-----------------++{% for field in testSuiteFields %}+{{ field.name }}+ * {{field.format}}+{% if notNull field.default %}+ * Default: ``{{field.default}}``+{% endif %}+{% if notNull field.availableSince %}+ * Available since ``cabal-version: {{field.availableSince}}``.+{% endif %}+{% if notNull field.deprecatedSince.fst %}+ * Deprecated since ``cabal-version: {{field.deprecatedSince.fst}}``: {{field.deprecatedSince.snd}}+{% endif %}+{% if notNull field.removedIn.fst %}+ * Removed in ``cabal-version: {{field.removedIn.fst}}``: {{field.removedIn.snd}}+{% endif %}+{# We show documentation link only for non deprecated fields #}+{% if null field.deprecatedSince.fst %}+{% if null field.removedIn.fst %}+ * Documentation of :pkg-field:`test-suite:{{field.name}}`+{% endif %}+{% endif %}+{% if notNull field.syntax %}++ .. math::+ {{field.syntax}}+{% endif %}++{% endfor %}
+ cabal/cabal-benchmarks/LICENSE view
@@ -0,0 +1,34 @@+Copyright (c) 2003-2020, Cabal Development Team.+See the AUTHORS file for the full list of copyright holders.++See */LICENSE for the copyright holders of the subcomponents.++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are+met:++ * Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ * Redistributions in binary form must reproduce the above+ copyright notice, this list of conditions and the following+ disclaimer in the documentation and/or other materials provided+ with the distribution.++ * Neither the name of Isaac Jones nor the names of other+ contributors may be used to endorse or promote products derived+ from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ cabal/cabal-benchmarks/README.md view
@@ -0,0 +1,3 @@+# cabal-benchmarks++TBW
+ cabal/cabal-benchmarks/bench/CabalBenchmarks.hs view
@@ -0,0 +1,14 @@+module Main where++import Criterion.Main (bench, defaultMain, env, whnf)+import Distribution.PackageDescription.Parsec (parseGenericPackageDescriptionMaybe)++import qualified Data.ByteString as BS++main :: IO ()+main = defaultMain+ [ env (BS.readFile "Cabal/Cabal.cabal") $ \bs ->+ bench "Cabal" $ whnf parseGenericPackageDescriptionMaybe bs+ , env (BS.readFile "cabal-benchmarks/cabal-benchmarks.cabal") $ \bs ->+ bench "cabal-benchmarks" $ whnf parseGenericPackageDescriptionMaybe bs+ ]
+ cabal/cabal-benchmarks/cabal-benchmarks.cabal view
@@ -0,0 +1,34 @@+name: cabal-benchmarks+version: 3+copyright: 2003-2020, Cabal Development Team (see AUTHORS file)+license: BSD3+license-file: LICENSE+author: Cabal Development Team <cabal-devel@haskell.org>+maintainer: cabal-devel@haskell.org+homepage: http://www.haskell.org/cabal/+bug-reports: https://github.com/haskell/cabal/issues+synopsis: Benchmarks for the cabal dependency solver+description:+ This package contains benchmarks that test cabal's dependency solver by running the cabal executable.++category: Distribution+cabal-version: >=1.10+build-type: Simple+extra-source-files: README.md++source-repository head+ type: git+ location: https://github.com/haskell/cabal/+ subdir: solver-benchmarks++test-suite cabal-benchmarks+ default-language: Haskell2010+ type: exitcode-stdio-1.0+ main-is: CabalBenchmarks.hs+ hs-source-dirs: bench+ ghc-options: -threaded -Wall -fwarn-tabs+ build-depends:+ base+ , bytestring+ , Cabal+ , criterion >=1.5.6.2 && <1.6
cabal/cabal-dev-scripts/LICENSE view
@@ -1,9 +1,13 @@-opyright (c) 2017, Cabal Development Team+Copyright (c) 2003-2020, Cabal Development Team.+See the AUTHORS file for the full list of copyright holders. +See */LICENSE for the copyright holders of the subcomponents.+ All rights reserved. Redistribution and use in source and binary forms, with or without-modification, are permitted provided that the following conditions are met:+modification, are permitted provided that the following conditions are+met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.@@ -13,7 +17,7 @@ disclaimer in the documentation and/or other materials provided with the distribution. - * Neither the name of Cabal Development Team nor the names of other+ * Neither the name of Isaac Jones nor the names of other contributors may be used to endorse or promote products derived from this software without specific prior written permission.
cabal/cabal-dev-scripts/cabal-dev-scripts.cabal view
@@ -15,9 +15,9 @@ main-is: GenExtraSourceFiles.hs hs-source-dirs: src build-depends:- , base >=4.10 && <4.13+ , base >=4.10 && <4.15 , bytestring- , Cabal >=2.2 && <2.6+ , Cabal >=2.2 && <3.3 , directory , filepath , process@@ -29,15 +29,15 @@ hs-source-dirs: src ghc-options: -Wall build-depends:- , aeson ^>=1.4.1.0- , base >=4.10 && <4.13+ , aeson ^>=1.4.1.0 || ^>=1.5.2.0+ , base >=4.10 && <4.15 , bytestring , containers , Diff ^>=0.4- , lens ^>=4.18.1+ , lens ^>=4.18.1 || ^>=4.19.1 , optparse-applicative ^>=0.15.1.0 , text- , zinza ^>=0.1+ , zinza ^>=0.2 executable gen-spdx-exc default-language: Haskell2010@@ -46,12 +46,71 @@ hs-source-dirs: src ghc-options: -Wall build-depends:- , aeson ^>=1.4.1.0- , base >=4.10 && <4.13+ , aeson ^>=1.4.1.0 || ^>=1.5.2.0+ , base >=4.10 && <4.15 , bytestring , containers , Diff ^>=0.4- , lens ^>=4.18.1+ , lens ^>=4.18.1 || ^>=4.19.1 , optparse-applicative ^>=0.15.1.0 , text- , zinza ^>=0.1+ , zinza ^>=0.2++executable gen-validate+ default-language: Haskell2010+ main-is: GenValidate.hs+ hs-source-dirs: src+ ghc-options: -Wall+ build-depends:+ , base+ , bytestring+ , HsYAML ^>=0.2.1.0+ , zinza ^>=0.2++executable gen-validate-dockerfile+ default-language: Haskell2010+ main-is: GenValidateDockerfile.hs+ hs-source-dirs: src+ ghc-options: -Wall+ build-depends:+ , base+ , bytestring+ , containers+ , HsYAML ^>=0.2.1.0+ , zinza ^>=0.2++executable gen-cabal-macros+ default-language: Haskell2010+ main-is: GenCabalMacros.hs+ other-modules: Capture+ hs-source-dirs: src+ ghc-options: -Wall+ build-depends:+ , base+ , bytestring+ , Cabal+ , syb ^>=0.7.1+ , template-haskell+ , zinza ^>=0.2++executable gen-cabal-install-cabal+ default-language: Haskell2010+ main-is: GenCabalInstallCabal.hs+ hs-source-dirs: src+ ghc-options: -Wall+ build-depends:+ , base+ , bytestring+ , Cabal+ , zinza ^>=0.2++executable analyse-imports+ default-language: Haskell2010+ main-is: AnalyseImports.hs+ hs-source-dirs: src+ ghc-options: -Wall+ build-depends:+ , base+ , containers+ , regex-applicative+ , haskell-lexer ^>=1.1
+ cabal/cabal-dev-scripts/src/AnalyseImports.hs view
@@ -0,0 +1,106 @@+{-# LANGUAGE LambdaCase #-}+module Main (main) where++import Control.Applicative (liftA2, many, (<|>))+import Control.Monad (void)+import Data.Foldable (for_)+import Data.List (sortBy)+import Data.Maybe (fromMaybe)+import Data.Ord (comparing)+import Language.Haskell.Lexer (PosToken, Token (..), lexerPass0)+import System.Environment (getArgs)+import Text.Regex.Applicative (RE)++import qualified Data.Map.Strict as Map+import qualified Text.Regex.Applicative as RE++main :: IO ()+main = do+ args <- getArgs++ data_ <- traverse processFile args++ putStrLn "Modules"+ let modules = sortBy (flip $ comparing snd) $ Map.toList $ Map.fromListWith (+)+ [ (mn, 1 :: Int)+ | xs <- data_+ , (mn, _) <- xs+ ]++ for_ (take 30 modules) $ \(mn, n) ->+ putStrLn $ mn ++ " " ++ show n++ putStrLn ""++ putStrLn "Symbols"+ let symbols = sortBy (flip $ comparing snd) $ Map.toList $ Map.fromListWith (+)+ [ ((mn,sym), 1 :: Int)+ | xs <- data_+ , (mn, syms) <- xs+ , sym <- syms+ ]++ for_ (take 50 symbols) $ \((mn,sym), n) ->+ putStrLn $ mn ++ "." ++ sym ++ " " ++ show n++processFile :: FilePath -> IO [(String, [String])]+processFile fp = do+ contents <- readFile fp+ let tokens = filter (\(t, _) -> t `notElem` [Whitespace, Comment, Commentstart, NestedComment])+ $ lexerPass0 contents++ return $ fromMaybe [] $ RE.match (somewhere imports) tokens++imports :: RE PosToken (String, [String])+imports = (,)+ <$ reservedid "import" <*> (conid <|> qconid) <*> msymbols+ where+ msymbols :: RE PosToken [String]+ msymbols =special "(" *> symbols <* special ")" <|> pure []++ symbols :: RE PosToken [String]+ symbols = liftA2 (:) symbol $ many (special "," *> symbol)++ symbol :: RE PosToken String+ symbol = varid <|> special "(" *> varsym <* special ")"+++-------------------------------------------------------------------------------+-- regex-applicative + haskell-lexer+-------------------------------------------------------------------------------++anything :: RE s ()+anything = void $ RE.few RE.anySym++somewhere :: RE s a -> RE s [a]+somewhere re = anything *> RE.few (re <* anything)++reservedid :: String -> RE PosToken ()+reservedid k = RE.msym $ \case+ (Reservedid, (_, k')) | k == k' -> Just ()+ _ -> Nothing++special :: String -> RE PosToken ()+special k = RE.msym $ \case+ (Special, (_, k')) | k == k' -> Just ()+ _ -> Nothing++conid :: RE PosToken String+conid = RE.msym $ \case+ (Conid, (_, k)) -> Just k+ _ -> Nothing++qconid :: RE PosToken String+qconid = RE.msym $ \case+ (Qconid, (_, k)) -> Just k+ _ -> Nothing++varid :: RE PosToken String+varid = RE.msym $ \case+ (Varid, (_, k)) -> Just k+ _ -> Nothing++varsym :: RE PosToken String+varsym = RE.msym $ \case+ (Varsym, (_, k)) -> Just k+ _ -> Nothing
+ cabal/cabal-dev-scripts/src/Capture.hs view
@@ -0,0 +1,31 @@+module Capture (capture) where++import Language.Haskell.TH+import Language.Haskell.TH.Syntax (NameFlavour (..), Name (..))+import Control.Monad.IO.Class++import Data.Generics as SYB++-- | Capture the source code of declarations in the variable+capture+ :: String -- ^ variable name+ -> Q [Dec] -- ^ definitions+ -> Q [Dec]+capture name decls = do+ decls1 <- decls++ -- mangle all names to drop unique suffixes and module prefixes+ let decls2 = SYB.everywhere (SYB.mkT mangleName) decls1+ let declsStr = pprint decls2+ -- liftIO (putStrLn declsStr)++ let nameTyDecl :: Dec+ nameTyDecl = SigD (mkName name) (ConT (mkName "String"))++ nameDecl :: Dec+ nameDecl = ValD (VarP $ mkName name) (NormalB (LitE (StringL declsStr))) []++ return $ nameTyDecl : nameDecl : decls1+ where+ mangleName :: Name -> Name+ mangleName (Name occ _) = Name occ NameS
+ cabal/cabal-dev-scripts/src/GenCabalInstallCabal.hs view
@@ -0,0 +1,49 @@+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE ScopedTypeVariables #-}+module Main (main) where++import Control.Exception (SomeException (..), catch, displayException)+import GHC.Generics (Generic)+import System.Environment (getArgs)+import System.Exit (exitFailure)++import qualified Zinza as Z++withIO :: (Bool -> FilePath -> FilePath -> IO a) -> IO a+withIO k = do+ args <- getArgs+ case args of+ [dev',src,tgt]+ | Just dev <- parseBool dev'+ -> k dev src tgt `catch` \(SomeException e) -> do+ putStrLn $ "Exception: " ++ displayException e+ exitFailure+ _ -> do+ putStrLn "Usage cabal v2-run ... source.temeplate.ext target.ext"+ exitFailure+ where+ parseBool "True" = Just True+ parseBool "False" = Just False+ parseBool _ = Nothing+ ++main :: IO ()+main = withIO $ \dev src tgt -> do+ render <- Z.parseAndCompileTemplateIO src+ contents <- render $ Z dev ()+ writeFile tgt contents++-------------------------------------------------------------------------------+-- Data+-------------------------------------------------------------------------------++data Z = Z+ { zDev :: Bool+ , zUnused :: ()+ }+ deriving (Generic)++instance Z.Zinza Z where+ toType = Z.genericToTypeSFP+ toValue = Z.genericToValueSFP+ fromValue = Z.genericFromValueSFP
+ cabal/cabal-dev-scripts/src/GenCabalMacros.hs view
@@ -0,0 +1,119 @@+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell #-}+{-# OPTIONS_GHC -Wno-orphans #-}+module Main (main) where++import Control.Exception (SomeException (..), catch, displayException)+import Distribution.Types.PackageName (PackageName)+import Distribution.Types.Version (Version)+import GHC.Generics (Generic)+import System.Environment (getArgs)+import System.Exit (exitFailure)+import Zinza+ (ModuleConfig (..), Ty (..), Zinza (..), genericFromValueSFP, genericToTypeSFP,+ genericToValueSFP, parseAndCompileModuleIO)++import Capture++-------------------------------------------------------------------------------+-- Inputs+-------------------------------------------------------------------------------++$(capture "decls" [d|+ data Z = Z+ { zPackages :: [ZPackage]+ , zTools :: [ZTool]+ , zPackageKey :: String+ , zComponentId :: String+ , zPackageVersion :: Version+ , zNotNull :: String -> Bool+ , zManglePkgName :: PackageName -> String+ , zMangleStr :: String -> String+ }+ deriving (Generic)++ data ZPackage = ZPackage+ { zpkgName :: PackageName+ , zpkgVersion :: Version+ , zpkgX :: String+ , zpkgY :: String+ , zpkgZ :: String+ }+ deriving (Generic)++ data ZTool = ZTool+ { ztoolName :: String+ , ztoolVersion :: Version+ , ztoolX :: String+ , ztoolY :: String+ , ztoolZ :: String+ }+ deriving (Generic)+ |])++-------------------------------------------------------------------------------+-- Main+-------------------------------------------------------------------------------++withIO :: (FilePath -> FilePath -> IO a) -> IO a+withIO k = do+ args <- getArgs+ case args of+ [src,tgt] -> k src tgt `catch` \(SomeException e) -> do+ putStrLn $ "Exception: " ++ displayException e+ exitFailure+ _ -> do+ putStrLn "Usage cabal v2-run ... source.temeplate.ext target.ext"+ exitFailure++main :: IO ()+main = withIO $ \src tgt -> do+ mdl <- parseAndCompileModuleIO config src+ writeFile tgt mdl++config :: ModuleConfig Z+config = ModuleConfig+ { mcRender = "render"+ , mcHeader =+ [ "{-# LANGUAGE DeriveGeneric #-}"+ , "module Distribution.Simple.Build.Macros.Z (render, Z(..), ZPackage (..), ZTool (..)) where"+ , "import Distribution.ZinzaPrelude"+ , decls+ , "render :: Z -> String"+ ]+ }++-------------------------------------------------------------------------------+-- Zinza instances+-------------------------------------------------------------------------------++instance Zinza Z where+ toType = genericToTypeSFP+ toValue = genericToValueSFP+ fromValue = genericFromValueSFP++instance Zinza ZPackage where+ toType = genericToTypeSFP+ toValue = genericToValueSFP+ fromValue = genericFromValueSFP++instance Zinza ZTool where+ toType = genericToTypeSFP+ toValue = genericToValueSFP+ fromValue = genericFromValueSFP++-------------------------------------------------------------------------------+-- Orphans+-------------------------------------------------------------------------------++instance Zinza PackageName where+ toType _ = TyString (Just "prettyShow")+ toValue _ = error "not needed"+ fromValue _ = error "not needed"++instance Zinza Version where+ toType _ = TyString (Just "prettyShow")+ toValue _ = error "not needed"+ fromValue _ = error "not needed"
cabal/cabal-dev-scripts/src/GenSPDX.hs view
@@ -3,12 +3,11 @@ module Main (main) where import Control.Lens (imap)-import Data.Aeson (FromJSON (..), eitherDecode, withObject, (.:))+import Data.Aeson (FromJSON (..), eitherDecode, withObject, (.!=), (.:), (.:?)) import Data.List (sortOn) import Data.Semigroup ((<>)) import Data.Text (Text) import Data.Traversable (for)-import GHC.Generics (Generic) import qualified Data.ByteString.Lazy as LBS import qualified Data.Set as Set@@ -34,6 +33,7 @@ <$> licenses "3.0" <*> licenses "3.2" <*> licenses "3.6"+ <*> licenses "3.8" template = O.strArgument $ mconcat [ O.metavar "SPDX.LicenseId.template.hs"@@ -72,14 +72,17 @@ (\vers -> vers /= allVers && Set.member SPDXLicenseListVersion_3_2 vers) , inputLicenseList_3_6 = mkLicenseList (\vers -> vers /= allVers && Set.member SPDXLicenseListVersion_3_6 vers)+ , inputLicenseList_3_9 = mkLicenseList+ (\vers -> vers /= allVers && Set.member SPDXLicenseListVersion_3_9 vers) } where- PerV (LL ls_3_0) (LL ls_3_2) (LL ls_3_6) = lss+ PerV (LL ls_3_0) (LL ls_3_2) (LL ls_3_6) (LL ls_3_9) = lss constructorNames :: [(Text, License, Set.Set SPDXLicenseListVersion)] constructorNames = map (\(l, tags) -> (toConstructorName $ licenseId l, l, tags)) $ combine licenseId $ \ver -> case ver of+ SPDXLicenseListVersion_3_9 -> filterDeprecated ls_3_9 SPDXLicenseListVersion_3_6 -> filterDeprecated ls_3_6 SPDXLicenseListVersion_3_2 -> filterDeprecated ls_3_2 SPDXLicenseListVersion_3_0 -> filterDeprecated ls_3_0@@ -92,6 +95,7 @@ , ilId = textShow (licenseId l) , ilName = textShow (licenseName l) , ilIsOsiApproved = licenseOsiApproved l+ , ilIsFsfLibre = licenseFsfLibre l } licenseIds :: Text@@ -113,6 +117,7 @@ { licenseId :: !Text , licenseName :: !Text , licenseOsiApproved :: !Bool+ , licenseFsfLibre :: !Bool , licenseDeprecated :: !Bool } deriving (Show)@@ -125,6 +130,7 @@ <$> obj .: "licenseId" <*> obj .: "name" <*> obj .: "isOsiApproved"+ <*> obj .:? "isFsfLibre" .!= False <*> obj .: "isDeprecatedLicenseId" instance FromJSON LicenseList where
cabal/cabal-dev-scripts/src/GenSPDXExc.hs view
@@ -32,6 +32,7 @@ <$> licenses "3.0" <*> licenses "3.2" <*> licenses "3.6"+ <*> licenses "3.8" template = O.strArgument $ mconcat [ O.metavar "SPDX.LicenseExceptionId.template.hs"@@ -70,14 +71,17 @@ (\vers -> vers /= allVers && Set.member SPDXLicenseListVersion_3_2 vers) , inputLicenseList_3_6 = mkLicenseList (\vers -> vers /= allVers && Set.member SPDXLicenseListVersion_3_6 vers)+ , inputLicenseList_3_9 = mkLicenseList+ (\vers -> vers /= allVers && Set.member SPDXLicenseListVersion_3_9 vers) } where- PerV (LL ls_3_0) (LL ls_3_2) (LL ls_3_6) = lss+ PerV (LL ls_3_0) (LL ls_3_2) (LL ls_3_6) (LL ls_3_9) = lss constructorNames :: [(Text, License, Set.Set SPDXLicenseListVersion)] constructorNames = map (\(l, tags) -> (toConstructorName $ licenseId l, l, tags)) $ combine licenseId $ \ver -> case ver of+ SPDXLicenseListVersion_3_9 -> filterDeprecated ls_3_9 SPDXLicenseListVersion_3_6 -> filterDeprecated ls_3_6 SPDXLicenseListVersion_3_2 -> filterDeprecated ls_3_2 SPDXLicenseListVersion_3_0 -> filterDeprecated ls_3_0@@ -90,6 +94,7 @@ , ilId = textShow (licenseId l) , ilName = textShow (licenseName l) , ilIsOsiApproved = False -- not used in exceptions+ , ilIsFsfLibre = False -- not used in exceptions } licenseIds :: Text
cabal/cabal-dev-scripts/src/GenUtils.hs view
@@ -27,12 +27,14 @@ = SPDXLicenseListVersion_3_0 | SPDXLicenseListVersion_3_2 | SPDXLicenseListVersion_3_6+ | SPDXLicenseListVersion_3_9 deriving (Eq, Ord, Show, Enum, Bounded) allVers :: Set.Set SPDXLicenseListVersion allVers = Set.fromList [minBound .. maxBound] prettyVer :: SPDXLicenseListVersion -> Text+prettyVer SPDXLicenseListVersion_3_9 = "SPDX License List 3.9" prettyVer SPDXLicenseListVersion_3_6 = "SPDX License List 3.6" prettyVer SPDXLicenseListVersion_3_2 = "SPDX License List 3.2" prettyVer SPDXLicenseListVersion_3_0 = "SPDX License List 3.0"@@ -41,7 +43,7 @@ -- Per version ------------------------------------------------------------------------------- -data PerV a = PerV a a a+data PerV a = PerV a a a a deriving (Functor, Foldable, Traversable) -------------------------------------------------------------------------------@@ -141,21 +143,25 @@ , inputLicenseList_3_0 :: Text , inputLicenseList_3_2 :: Text , inputLicenseList_3_6 :: Text+ , inputLicenseList_3_9 :: Text } deriving (Show, Generic) instance Z.Zinza Input where- toType = Z.genericToTypeSFP- toValue = Z.genericToValueSFP+ toType = Z.genericToTypeSFP+ toValue = Z.genericToValueSFP+ fromValue = Z.genericFromValueSFP data InputLicense = InputLicense { ilConstructor :: Text , ilId :: Text , ilName :: Text , ilIsOsiApproved :: Bool+ , ilIsFsfLibre :: Bool } deriving (Show, Generic) instance Z.Zinza InputLicense where- toType = Z.genericToTypeSFP- toValue = Z.genericToValueSFP+ toType = Z.genericToTypeSFP+ toValue = Z.genericToValueSFP+ fromValue = Z.genericFromValueSFP
+ cabal/cabal-dev-scripts/src/GenValidate.hs view
@@ -0,0 +1,157 @@+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE ScopedTypeVariables #-}+-- runghc -package-env=default Validate.hs validate.yml.zinza .github/workflows/validate.yml+module Main (main) where++import Data.List (isPrefixOf)+import GHC.Generics (Generic)+import System.Environment (getArgs)+import System.Exit (exitFailure)+import Zinza (Zinza (..), genericFromValueSFP, genericToTypeSFP, genericToValueSFP, parseAndCompileTemplateIO)++import qualified Data.ByteString.Lazy.Char8 as LBS8+import qualified Data.YAML as YAML++main :: IO ()+main = do+ args <- getArgs+ case args of+ [src,tgt] -> do+ run <- parseAndCompileTemplateIO src+ -- this shouldn't fail (run-time errors are due bugs in zinza)+ w <- run Z+ { zJobs =+ [ GhcJob "8.10.1" False "" False ["8.8.3"] defSteps+ , GhcJob "8.8.3" False "--solver-benchmarks" False [] defSteps+ , GhcJob "8.6.5" False "--complete-hackage-tests" False ["8.8.3"] defSteps+ , GhcJob "8.4.4" False "" False ["8.8.3"] defSteps+ , GhcJob "8.2.2" False "" False ["8.8.3"] defSteps+ , GhcJob "8.0.2" False "" False ["8.8.3"] defSteps+ , GhcJob "7.10.3" False "" False ["8.8.3"] defSteps+ , GhcJob "7.8.4" False "--lib-only" False ["8.8.3"] libSteps+ , GhcJob "7.6.3" True "--lib-only" False ["8.8.3"] libSteps+ , GhcJob "8.8.3" True "--lib-only" True ["8.8.3"] $+ libSteps +++ [ "lib-suite-extras --extra-hc /opt/ghc/7.0.4/bin/ghc-7.0.4"+ , "lib-suite-extras --extra-hc /opt/ghc/7.2.2/bin/ghc-7.2.2"+ , "lib-suite-extras --extra-hc /opt/ghc/7.4.2/bin/ghc-7.4.2"+ ]+ ]+ , zMacosJobs =+ [ mkMacGhcJob "8.8.3" "https://downloads.haskell.org/~ghc/8.8.3/ghc-8.8.3-x86_64-apple-darwin.tar.xz"+ , mkMacGhcJob "8.6.5" "https://downloads.haskell.org/~ghc/8.6.5/ghc-8.6.5-x86_64-apple-darwin.tar.xz"+ ]+ , zWinJobs =+ -- 8.8.1 fails atm,+ -- Shutting down GHCi sessions (please be patient)...+ -- Unexpected failure on GHCi exit: fd:10: hClose: resource vanished (Broken pipe)+ -- cabal-tests: fd:10: hClose: resource vanished (Broken pipe)+ -- [ WinGhcJob "8.8.1" ["8.6.5"]+ [ WinGhcJob "8.6.5" []+ ]+ , zMangleVersion = map mangleChar+ , zOr = (||)+ , zNotNull = not . null+ , zFalse = False+ }++ -- check that YAML is syntactically valid+ let bs = LBS8.pack w+ case YAML.decode1 bs of+ Right (_ :: YAML.Node YAML.Pos) -> return ()+ Left (pos, err) -> do+ putStrLn $ "ERROR:" ++ YAML.prettyPosWithSource pos bs err+ exitFailure++ writeFile tgt w+ _ -> putStrLn "Usage source.yml.zinza target.yml"++mangleChar :: Char -> Char+mangleChar '.' = '_'+mangleChar c = c++defSteps :: [String]+defSteps =+ [ "print-config"+ , "print-tool-versions"+ , "make-cabal-install-dev"+ , "build"+ , "lib-tests"+ , "lib-suite"+ , "cli-tests"+ , "cli-suite"+ ]++libSteps :: [String]+libSteps =+ [ "print-config"+ , "print-tool-versions"+ , "build"+ , "lib-tests"+ , "lib-suite"+ ]++data Z = Z+ { zJobs :: [GhcJob]+ , zMacosJobs :: [MacGhcJob]+ , zWinJobs :: [WinGhcJob]+ , zMangleVersion :: String -> String+ , zOr :: Bool -> Bool -> Bool+ , zNotNull :: [String] -> Bool+ , zFalse :: Bool+ }+ deriving (Generic)++data GhcJob = GhcJob+ { gjVersion :: String+ , gjXenial :: Bool+ , gjFlags :: String+ , gjOld :: Bool+ , gjNeeds :: [String]+ , gjSteps :: [String]+ }+ deriving (Generic)++data MacGhcJob = MacGhcJob+ { mgjVersion :: String+ , mgjGhcUrl :: String+ , mgjFlags :: String+ , mgjNeeds :: [String]+ , mgjSteps :: [String]+ }+ deriving (Generic)++data WinGhcJob = WinGhcJob+ { wgjVersion :: String+ , wgjNeeds :: [String]+ }+ deriving (Generic)++mkMacGhcJob :: String -> String -> MacGhcJob+mkMacGhcJob v u = MacGhcJob+ { mgjVersion = v+ , mgjGhcUrl = u+ , mgjFlags = ""+ , mgjNeeds = ["8.8.3" | not $ "8.8" `isPrefixOf` v ]+ , mgjSteps = defSteps+ }++instance Zinza Z where+ toType = genericToTypeSFP+ toValue = genericToValueSFP+ fromValue = genericFromValueSFP++instance Zinza GhcJob where+ toType = genericToTypeSFP+ toValue = genericToValueSFP+ fromValue = genericFromValueSFP++instance Zinza MacGhcJob where+ toType = genericToTypeSFP+ toValue = genericToValueSFP+ fromValue = genericFromValueSFP++instance Zinza WinGhcJob where+ toType = genericToTypeSFP+ toValue = genericToValueSFP+ fromValue = genericFromValueSFP
+ cabal/cabal-dev-scripts/src/GenValidateDockerfile.hs view
@@ -0,0 +1,74 @@+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE ScopedTypeVariables #-}+module Main (main) where++import Control.Exception (SomeException (..), catch, displayException)+import GHC.Generics (Generic)+import System.Environment (getArgs)+import System.Exit (exitFailure)++import qualified Data.Map as Map+import qualified Zinza as Z++withIO :: (String -> FilePath -> FilePath -> IO a) -> IO a+withIO k = do+ args <- getArgs+ case args of+ [version,src,tgt]+ -> k version src tgt `catch` \(SomeException e) -> do+ putStrLn $ "Exception: " ++ displayException e+ exitFailure+ _ -> do+ putStrLn "Usage cabal v2-run ... version"+ exitFailure++main :: IO ()+main = withIO $ \version src tgt -> do+ render <- Z.parseAndCompileTemplateIO src+ case Map.lookup version params of+ Just z -> do+ contents <- render z+ writeFile tgt contents++ Nothing -> do+ putStrLn $ "Unknown version " ++ version+ exitFailure++-------------------------------------------------------------------------------+-- Params+-------------------------------------------------------------------------------++params :: Map.Map String Z+params = Map.fromList+ [ pair "8.10.1" $ Z "ghc-8.10.1" "8.10.1-bionic" False True False True ""+ , pair "8.8.3" $ Z "ghc-8.8.3" "8.8.3-bionic" False True False True "--doctest --solver-benchmarks --complete-hackage"+ , pair "8.6.5" $ Z "ghc-8.6.5" "8.6.5-bionic" False True False True ""+ , pair "8.4.4" $ Z "ghc-8.4.4" "8.4.4-bionic" False True False True ""+ , pair "8.2.2" $ Z "ghc-8.2.2" "8.2.2-bionic" True True False True ""+ , pair "8.0.2" $ Z "ghc-8.0.2" "8.0.2-bionic" True True False True ""+ , pair "7.10.3" $ Z "ghc-7.10.3" "7.10.3-bionic" True True False True ""+ , pair "7.8.4" $ Z "ghc-7.8.4" "7.8.4-xenial" True True True False "--lib-only"+ , pair "7.6.3" $ Z "ghc-7.6.3" "7.6.3-xenial" True False True False "--lib-only"+ ]+ where+ pair = (,)++-------------------------------------------------------------------------------+-- Data+-------------------------------------------------------------------------------++data Z = Z+ { zGhc :: String+ , zImage :: String+ , zParsecCompat :: Bool+ , zHasTransformers :: Bool+ , zNeedsDynamic :: Bool+ , zClient :: Bool+ , zArgs :: String+ }+ deriving (Generic)++instance Z.Zinza Z where+ toType = Z.genericToTypeSFP+ toValue = Z.genericToValueSFP+ fromValue = Z.genericFromValueSFP
− cabal/cabal-dev-scripts/src/Preprocessor.hs
@@ -1,222 +0,0 @@-{-# LANGUAGE DeriveFunctor #-}-module Main (main) where--import Control.Applicative-import Control.Monad (ap, unless)-import Data.Char (isSpace)-import System.Environment (getArgs)-import System.IO (hPutStrLn, stderr)--import qualified Data.Map as Map-import qualified System.Console.GetOpt as O------------------------------------------------------------------------------------ Types----------------------------------------------------------------------------------type Flag = String-type Var = String--data Token- = Raw String- | Var Int Var- | If Flag- | Else- | Endif- | Def Var- | Enddef- | Comment- | Error String- deriving Show--data Tree- = TRaw String- | TVar Int Var- | TDef Var Forest- | TIf Flag Forest Forest- deriving Show--type Forest = [Tree]------------------------------------------------------------------------------------ Lex----------------------------------------------------------------------------------tokens :: String -> [Token]-tokens = map classify . lines where- classify :: String -> Token- classify s0 = case s1 of- [] -> Raw ""- ('#' : _) -> Comment- ('$' : s) -> Var (length ws) s- ('%' : s)- | Just s' <- "if" `isPrefixOf'` s -> If $ dropWhile isSpace s'- | Just _ <- "else" `isPrefixOf'` s -> Else- | Just _ <- "endif" `isPrefixOf'` s -> Endif- | Just s' <- "def" `isPrefixOf'` s -> Def $ dropWhile isSpace s'- | Just _ <- "enddef" `isPrefixOf'` s -> Enddef- | otherwise -> Error $ "Unknown command: " ++ s- _ -> Raw s0- where- (ws, s1) = span isSpace s0---- | 'isPrefixOf' returning the rest of the string-isPrefixOf' :: String -> String -> Maybe String-isPrefixOf' [] ys = Just ys-isPrefixOf' (_:_) [] = Nothing-isPrefixOf' (x:xs) (y:ys) | x == y = isPrefixOf' xs ys- | otherwise = Nothing------------------------------------------------------------------------------------ Parse----------------------------------------------------------------------------------newtype P a = P { unP :: [Token] -> Either String ([Token], a) }- deriving Functor--instance Applicative P where- pure x = P $ \toks -> Right (toks, x)- (<*>) = ap--instance Alternative P where- empty = P $ \_ -> Left "empty"- x <|> y = P $ \toks -> case unP x toks of- Right res -> Right res- Left _ -> unP y toks--instance Monad P where- return = pure- m >>= k = P $ \toks0 -> do- (toks1, x) <- unP m toks0- unP (k x) toks1--runP :: P a -> [Token] -> Either String a-runP (P p) = fmap snd . p--forest :: [Token] -> Either String Forest-forest = runP (forestP <* eof) where- forestP = many tree- tree = rawP <|> varP <|> ifP <|> defP-- ifP :: P Tree- ifP = do- f <- if_- c <- forestP- a <- else_ *> forestP <|> pure []- endif_- return (TIf f c a)-- defP :: P Tree- defP = do- v <- def_- t <- forestP- enddef_- return (TDef v t)-- rawP :: P Tree- rawP = token "Raw " $ \tok -> case tok of- Raw s -> Just (TRaw s)- _ -> Nothing-- varP :: P Tree- varP = token "Var" $ \toks -> case toks of- Var n v -> Just (TVar n v)- _ -> Nothing-- if_ :: P Flag- if_ = token "If" $ \toks -> case toks of- If f -> Just f- _ -> Nothing-- def_ :: P Var- def_ = token "Def" $ \toks -> case toks of- Def v -> Just v- _ -> Nothing-- else_ :: P ()- else_ = token "Else" $ \toks -> case toks of- Else -> Just ()- _ -> Nothing-- enddef_ :: P ()- enddef_ = token "Enddef" $ \toks -> case toks of- Enddef -> Just ()- _ -> Nothing-- endif_ :: P ()- endif_ = token "Endif" $ \toks -> case toks of- Endif -> Just ()- _ -> Nothing-- token :: String -> (Token -> Maybe a) -> P a- token name f = P $ \toks -> case toks of- (tok : toks') | Just x <- f tok -> Right (toks', x)- _ -> Left $ "Expected " ++ name-- eof :: P ()- eof = P $ \toks ->- if null toks- then Right (toks, ())- else Left $ "expected end-of-input, got: " ++ show (take 1 toks)------------------------------------------------------------------------------------- Process----------------------------------------------------------------------------------process :: [Flag] -> String -> String-process flags- = either error (unlines . go Map.empty)- . forest- . filter (not . isComment)- . tokens- where- isComment Comment = True- isComment _ = False-- go :: Map.Map Var Forest -> Forest -> [String]- go _ [] = []- go vars (TRaw s : toks) = s : go vars toks- go vars (TVar _ v : toks) = case Map.lookup v vars of- Nothing -> go vars toks- Just f -> go vars (f ++ toks)- go vars (TIf f c a : toks)- | f `elem` flags = go vars (c ++ toks)- | otherwise = go vars (a ++ toks)- go vars (TDef n f : toks) = go (Map.insert n f vars) toks------------------------------------------------------------------------------------ Main----------------------------------------------------------------------------------data Opts = Opts- { optsFlags :: [Flag]- , optsOutput :: Maybe FilePath- }--emptyOpts :: Opts-emptyOpts = Opts [] Nothing--optDescrs :: [O.OptDescr (Opts -> Opts)]-optDescrs =- [ O.Option "o" []- (O.ReqArg (\arg opts -> opts { optsOutput = Just arg }) "OUTPUT")- "Output"- , O.Option "f" []- (O.ReqArg (\arg opts -> opts { optsFlags = arg : optsFlags opts }) "FLAG")- "Flag"- ]--main :: IO ()-main = do- (optEndos, args, errs) <- O.getOpt O.RequireOrder optDescrs <$> getArgs- let opts = foldr ($) emptyOpts optEndos :: Opts- unless (null errs) $ do- mapM_ (hPutStrLn stderr) errs- fail "errors"- case args of- [fp] -> do- contents <- readFile fp- let output = process (optsFlags opts) contents- maybe putStr writeFile (optsOutput opts) output- _ -> fail "Expecting exactly one argument"
cabal/cabal-install/Distribution/Client/BuildReports/Anonymous.hs view
@@ -1,3 +1,5 @@+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE OverloadedStrings #-} ----------------------------------------------------------------------------- -- | -- Module : Distribution.Client.Reporting@@ -17,111 +19,44 @@ Outcome(..), -- * Constructing and writing reports- new,+ newBuildReport, -- * parsing and pretty printing- parse,- parseList,- show,+ parseBuildReport,+ parseBuildReportList,+ showBuildReport, -- showList, ) where +import Distribution.Client.Compat.Prelude import Prelude ()-import Distribution.Client.Compat.Prelude hiding (show) -import qualified Distribution.Client.Types as BR- ( BuildOutcome, BuildFailure(..), BuildResult(..)- , DocsResult(..), TestsResult(..) )-import Distribution.Client.Utils- ( mergeBy, MergeResult(..) )-import qualified Paths_cabal_install (version)+import Distribution.CabalSpecVersion+import Distribution.Client.BuildReports.Types+import Distribution.Client.Utils (cabalInstallVersion)+import Distribution.Compiler (CompilerId (..))+import Distribution.FieldGrammar+import Distribution.Fields (readFields, showFields)+import Distribution.Fields.ParseResult (ParseResult, parseFatalFailure, runParseResult)+import Distribution.Package (PackageIdentifier (..), mkPackageName)+import Distribution.PackageDescription (FlagAssignment)+import Distribution.Parsec (PError (..), zeroPos)+import Distribution.System (Arch, OS) -import Distribution.Package- ( PackageIdentifier(..), mkPackageName )-import Distribution.PackageDescription- ( FlagName, mkFlagName, unFlagName- , FlagAssignment, mkFlagAssignment, unFlagAssignment )-import Distribution.Version- ( mkVersion' )-import Distribution.System- ( OS, Arch )-import Distribution.Compiler- ( CompilerId(..) )-import qualified Distribution.Deprecated.Text as Text- ( Text(disp, parse) )-import Distribution.Deprecated.ParseUtils- ( FieldDescr(..), ParseResult(..), Field(..)- , simpleField, listField, ppFields, readFields- , syntaxError, locatedErrorMsg )-import Distribution.Simple.Utils- ( comparing )+import qualified Distribution.Client.BuildReports.Lens as L+import qualified Distribution.Client.Types as BR (BuildFailure (..), BuildOutcome, BuildResult (..), DocsResult (..), TestsResult (..)) -import qualified Distribution.Deprecated.ReadP as Parse- ( ReadP, pfail, munch1, skipSpaces )-import qualified Text.PrettyPrint as Disp- ( Doc, render, char, text )-import Text.PrettyPrint- ( (<+>) )+import qualified Data.ByteString as BS+import qualified Data.ByteString.Char8 as BS8 -import Data.Char as Char- ( isAlpha, isAlphaNum ) -data BuildReport- = BuildReport {- -- | The package this build report is about- package :: PackageIdentifier,-- -- | The OS and Arch the package was built on- os :: OS,- arch :: Arch,-- -- | The Haskell compiler (and hopefully version) used- compiler :: CompilerId,-- -- | The uploading client, ie cabal-install-x.y.z- client :: PackageIdentifier,-- -- | Which configurations flags we used- flagAssignment :: FlagAssignment,-- -- | Which dependent packages we were using exactly- dependencies :: [PackageIdentifier],-- -- | Did installing work ok?- installOutcome :: InstallOutcome,-- -- Which version of the Cabal library was used to compile the Setup.hs--- cabalVersion :: Version,-- -- Which build tools we were using (with versions)--- tools :: [PackageIdentifier],-- -- | Configure outcome, did configure work ok?- docsOutcome :: Outcome,-- -- | Configure outcome, did configure work ok?- testsOutcome :: Outcome- }--data InstallOutcome- = PlanningFailed- | DependencyFailed PackageIdentifier- | DownloadFailed- | UnpackFailed- | SetupFailed- | ConfigureFailed- | BuildFailed- | TestsFailed- | InstallFailed- | InstallOk- deriving Eq--data Outcome = NotTried | Failed | Ok- deriving Eq+-------------------------------------------------------------------------------+-- New+------------------------------------------------------------------------------- -new :: OS -> Arch -> CompilerId -> PackageIdentifier -> FlagAssignment+newBuildReport :: OS -> Arch -> CompilerId -> PackageIdentifier -> FlagAssignment -> [PackageIdentifier] -> BR.BuildOutcome -> BuildReport-new os' arch' comp pkgid flags deps result =+newBuildReport os' arch' comp pkgid flags deps result = BuildReport { package = pkgid, os = os',@@ -159,159 +94,64 @@ cabalInstallID :: PackageIdentifier cabalInstallID =- PackageIdentifier (mkPackageName "cabal-install")- (mkVersion' Paths_cabal_install.version)+ PackageIdentifier (mkPackageName "cabal-install") cabalInstallVersion --- --------------------------------------------------------------- * External format--- ------------------------------------------------------------+-------------------------------------------------------------------------------+-- FieldGrammar+------------------------------------------------------------------------------- -initialBuildReport :: BuildReport-initialBuildReport = BuildReport {- package = requiredField "package",- os = requiredField "os",- arch = requiredField "arch",- compiler = requiredField "compiler",- client = requiredField "client",- flagAssignment = mempty,- dependencies = [],- installOutcome = requiredField "install-outcome",--- cabalVersion = Nothing,--- tools = [],- docsOutcome = NotTried,- testsOutcome = NotTried- }- where- requiredField fname = error ("required field: " ++ fname)+fieldDescrs+ :: ( Applicative (g BuildReport), FieldGrammar c g+ , c (Identity Arch)+ , c (Identity CompilerId)+ , c (Identity FlagAssignment)+ , c (Identity InstallOutcome)+ , c (Identity OS)+ , c (Identity Outcome)+ , c (Identity PackageIdentifier)+ , c (List VCat (Identity PackageIdentifier) PackageIdentifier)+ )+ => g BuildReport BuildReport+fieldDescrs = BuildReport+ <$> uniqueField "package" L.package+ <*> uniqueField "os" L.os+ <*> uniqueField "arch" L.arch+ <*> uniqueField "compiler" L.compiler+ <*> uniqueField "client" L.client+ <*> monoidalField "flags" L.flagAssignment+ <*> monoidalFieldAla "dependencies" (alaList VCat) L.dependencies+ <*> uniqueField "install-outcome" L.installOutcome+ <*> uniqueField "docs-outcome" L.docsOutcome+ <*> uniqueField "tests-outcome" L.testsOutcome -- ----------------------------------------------------------------------------- -- Parsing -parse :: String -> Either String BuildReport-parse s = case parseFields s of- ParseFailed perror -> Left msg where (_, msg) = locatedErrorMsg perror- ParseOk _ report -> Right report+parseBuildReport :: BS.ByteString -> Either String BuildReport+parseBuildReport s = case snd $ runParseResult $ parseFields s of+ Left (_, perrors) -> Left $ unlines [ err | PError _ err <- toList perrors ]+ Right report -> Right report -parseFields :: String -> ParseResult BuildReport+parseFields :: BS.ByteString -> ParseResult BuildReport parseFields input = do- fields <- traverse extractField =<< readFields input- let merged = mergeBy (\desc (_,name,_) -> compare (fieldName desc) name)- sortedFieldDescrs- (sortBy (comparing (\(_,name,_) -> name)) fields)- checkMerged initialBuildReport merged-- where- extractField :: Field -> ParseResult (Int, String, String)- extractField (F line name value) = return (line, name, value)- extractField (Section line _ _ _) = syntaxError line "Unrecognized stanza"- extractField (IfBlock line _ _ _) = syntaxError line "Unrecognized stanza"-- checkMerged report [] = return report- checkMerged report (merged:remaining) = case merged of- InBoth fieldDescr (line, _name, value) -> do- report' <- fieldSet fieldDescr line value report- checkMerged report' remaining- OnlyInRight (line, name, _) ->- syntaxError line ("Unrecognized field " ++ name)- OnlyInLeft fieldDescr ->- fail ("Missing field " ++ fieldName fieldDescr)+ fields <- either (parseFatalFailure zeroPos . show) pure $ readFields input+ case partitionFields fields of+ (fields', []) -> parseFieldGrammar CabalSpecV2_4 fields' fieldDescrs+ _otherwise -> parseFatalFailure zeroPos "found sections in BuildReport" -parseList :: String -> [BuildReport]-parseList str =- [ report | Right report <- map parse (split str) ]+parseBuildReportList :: BS.ByteString -> [BuildReport]+parseBuildReportList str =+ [ report | Right report <- map parseBuildReport (split str) ] where- split :: String -> [String]- split = filter (not . null) . unfoldr chunk . lines+ split :: BS.ByteString -> [BS.ByteString]+ split = filter (not . BS.null) . unfoldr chunk . BS8.lines chunk [] = Nothing- chunk ls = case break null ls of- (r, rs) -> Just (unlines r, dropWhile null rs)+ chunk ls = case break BS.null ls of+ (r, rs) -> Just (BS8.unlines r, dropWhile BS.null rs) -- ----------------------------------------------------------------------------- -- Pretty-printing -show :: BuildReport -> String-show = Disp.render . ppFields fieldDescrs---- -------------------------------------------------------------------------------- Description of the fields, for parsing/printing--fieldDescrs :: [FieldDescr BuildReport]-fieldDescrs =- [ simpleField "package" Text.disp Text.parse- package (\v r -> r { package = v })- , simpleField "os" Text.disp Text.parse- os (\v r -> r { os = v })- , simpleField "arch" Text.disp Text.parse- arch (\v r -> r { arch = v })- , simpleField "compiler" Text.disp Text.parse- compiler (\v r -> r { compiler = v })- , simpleField "client" Text.disp Text.parse- client (\v r -> r { client = v })- , listField "flags" dispFlag parseFlag- (unFlagAssignment . flagAssignment)- (\v r -> r { flagAssignment = mkFlagAssignment v })- , listField "dependencies" Text.disp Text.parse- dependencies (\v r -> r { dependencies = v })- , simpleField "install-outcome" Text.disp Text.parse- installOutcome (\v r -> r { installOutcome = v })- , simpleField "docs-outcome" Text.disp Text.parse- docsOutcome (\v r -> r { docsOutcome = v })- , simpleField "tests-outcome" Text.disp Text.parse- testsOutcome (\v r -> r { testsOutcome = v })- ]--sortedFieldDescrs :: [FieldDescr BuildReport]-sortedFieldDescrs = sortBy (comparing fieldName) fieldDescrs--dispFlag :: (FlagName, Bool) -> Disp.Doc-dispFlag (fname, True) = Disp.text (unFlagName fname)-dispFlag (fname, False) = Disp.char '-' <<>> Disp.text (unFlagName fname)--parseFlag :: Parse.ReadP r (FlagName, Bool)-parseFlag = do- name <- Parse.munch1 (\c -> Char.isAlphaNum c || c == '_' || c == '-')- case name of- ('-':flag) -> return (mkFlagName flag, False)- flag -> return (mkFlagName flag, True)--instance Text.Text InstallOutcome where- disp PlanningFailed = Disp.text "PlanningFailed"- disp (DependencyFailed pkgid) = Disp.text "DependencyFailed" <+> Text.disp pkgid- disp DownloadFailed = Disp.text "DownloadFailed"- disp UnpackFailed = Disp.text "UnpackFailed"- disp SetupFailed = Disp.text "SetupFailed"- disp ConfigureFailed = Disp.text "ConfigureFailed"- disp BuildFailed = Disp.text "BuildFailed"- disp TestsFailed = Disp.text "TestsFailed"- disp InstallFailed = Disp.text "InstallFailed"- disp InstallOk = Disp.text "InstallOk"-- parse = do- name <- Parse.munch1 Char.isAlphaNum- case name of- "PlanningFailed" -> return PlanningFailed- "DependencyFailed" -> do Parse.skipSpaces- pkgid <- Text.parse- return (DependencyFailed pkgid)- "DownloadFailed" -> return DownloadFailed- "UnpackFailed" -> return UnpackFailed- "SetupFailed" -> return SetupFailed- "ConfigureFailed" -> return ConfigureFailed- "BuildFailed" -> return BuildFailed- "TestsFailed" -> return TestsFailed- "InstallFailed" -> return InstallFailed- "InstallOk" -> return InstallOk- _ -> Parse.pfail--instance Text.Text Outcome where- disp NotTried = Disp.text "NotTried"- disp Failed = Disp.text "Failed"- disp Ok = Disp.text "Ok"- parse = do- name <- Parse.munch1 Char.isAlpha- case name of- "NotTried" -> return NotTried- "Failed" -> return Failed- "Ok" -> return Ok- _ -> Parse.pfail+showBuildReport :: BuildReport -> String+showBuildReport = showFields (const []) . prettyFieldGrammar CabalSpecV2_4 fieldDescrs
+ cabal/cabal-install/Distribution/Client/BuildReports/Lens.hs view
@@ -0,0 +1,46 @@+module Distribution.Client.BuildReports.Lens (+ BuildReport,+ module Distribution.Client.BuildReports.Lens,+) where++import Distribution.Client.Compat.Prelude+import Distribution.Compat.Lens+import Prelude ()++import Distribution.Client.BuildReports.Types (BuildReport, InstallOutcome, Outcome)+import Distribution.Compiler (CompilerId)+import Distribution.System (Arch, OS)+import Distribution.Types.Flag (FlagAssignment)+import Distribution.Types.PackageId (PackageIdentifier)++import qualified Distribution.Client.BuildReports.Types as T++package :: Lens' BuildReport PackageIdentifier+package f s = fmap (\x -> s { T.package = x }) (f (T.package s))++os :: Lens' BuildReport OS+os f s = fmap (\x -> s { T.os = x }) (f (T.os s))++arch :: Lens' BuildReport Arch+arch f s = fmap (\x -> s { T.arch = x }) (f (T.arch s))++compiler :: Lens' BuildReport CompilerId+compiler f s = fmap (\x -> s { T.compiler = x }) (f (T.compiler s))++client :: Lens' BuildReport PackageIdentifier+client f s = fmap (\x -> s { T.client = x }) (f (T.client s))++flagAssignment :: Lens' BuildReport FlagAssignment+flagAssignment f s = fmap (\x -> s { T.flagAssignment = x }) (f (T.flagAssignment s))++dependencies :: Lens' BuildReport [PackageIdentifier]+dependencies f s = fmap (\x -> s { T.dependencies = x }) (f (T.dependencies s))++installOutcome :: Lens' BuildReport InstallOutcome+installOutcome f s = fmap (\x -> s { T.installOutcome = x }) (f (T.installOutcome s))++docsOutcome :: Lens' BuildReport Outcome+docsOutcome f s = fmap (\x -> s { T.docsOutcome = x }) (f (T.docsOutcome s))++testsOutcome :: Lens' BuildReport Outcome+testsOutcome f s = fmap (\x -> s { T.testsOutcome = x }) (f (T.testsOutcome s))
cabal/cabal-install/Distribution/Client/BuildReports/Storage.hs view
@@ -1,3 +1,4 @@+{-# OPTIONS_GHC -fno-warn-incomplete-uni-patterns #-} ----------------------------------------------------------------------------- -- | -- Module : Distribution.Client.Reporting@@ -23,8 +24,11 @@ fromPlanningFailure, ) where +import Distribution.Client.Compat.Prelude+import Prelude ()++import Distribution.Client.BuildReports.Anonymous (BuildReport, showBuildReport, newBuildReport) import qualified Distribution.Client.BuildReports.Anonymous as BuildReport-import Distribution.Client.BuildReports.Anonymous (BuildReport) import Distribution.Client.Types import qualified Distribution.Client.InstallPlan as InstallPlan@@ -46,12 +50,11 @@ import Distribution.Compiler ( CompilerId(..), CompilerInfo(..) ) import Distribution.Simple.Utils- ( comparing, equating )+ ( equating ) -import Data.List- ( groupBy, sortBy )-import Data.Maybe- ( mapMaybe )+import Data.List.NonEmpty+ ( groupBy )+import qualified Data.List as L import System.FilePath ( (</>), takeDirectory ) import System.Directory@@ -66,12 +69,12 @@ -- the writes for each report are atomic (under 4k and flush at boundaries) where- format r = '\n' : BuildReport.show r ++ "\n"+ format r = '\n' : showBuildReport r ++ "\n" separate :: [(BuildReport, Maybe Repo)] -> [(Repo, [BuildReport])] separate = map (\rs@((_,repo,_):_) -> (repo, [ r | (r,_,_) <- rs ]))- . map concat- . groupBy (equating (repoName . head))+ . map (concatMap toList)+ . L.groupBy (equating (repoName . head)) . sortBy (comparing (repoName . head)) . groupBy (equating repoName) . onlyRemote@@ -99,7 +102,7 @@ , let output = concatMap format reports' ] where- format r = '\n' : BuildReport.show r ++ "\n"+ format r = '\n' : showBuildReport r ++ "\n" reportFileName template report = fromPathTemplate (substPathTemplate env template)@@ -114,7 +117,7 @@ platform groupByFileName = map (\grp@((filename,_):_) -> (filename, map snd grp))- . groupBy (equating fst)+ . L.groupBy (equating fst) . sortBy (comparing fst) -- ------------------------------------------------------------@@ -139,13 +142,13 @@ fromPlanPackage (Platform arch os) comp (InstallPlan.Configured (ConfiguredPackage _ srcPkg flags _ deps)) (Just buildResult) =- Just ( BuildReport.new os arch comp+ Just ( newBuildReport os arch comp (packageId srcPkg) flags (map packageId (CD.nonSetupDeps deps)) buildResult , extractRepo srcPkg) where- extractRepo (SourcePackage { packageSource = RepoTarballPackage repo _ _ })+ extractRepo (SourcePackage { srcpkgSource = RepoTarballPackage repo _ _ }) = Just repo extractRepo _ = Nothing @@ -155,5 +158,5 @@ fromPlanningFailure :: Platform -> CompilerId -> [PackageId] -> FlagAssignment -> [(BuildReport, Maybe Repo)] fromPlanningFailure (Platform arch os) comp pkgids flags =- [ (BuildReport.new os arch comp pkgid flags [] (Left PlanningFailed), Nothing)+ [ (newBuildReport os arch comp pkgid flags [] (Left PlanningFailed), Nothing) | pkgid <- pkgids ]
cabal/cabal-install/Distribution/Client/BuildReports/Types.hs view
@@ -13,38 +13,154 @@ ----------------------------------------------------------------------------- module Distribution.Client.BuildReports.Types ( ReportLevel(..),- ) where+ BuildReport (..),+ InstallOutcome(..),+ Outcome(..),+) where -import qualified Distribution.Deprecated.Text as Text- ( Text(..) )+import Distribution.Client.Compat.Prelude+import Prelude () -import qualified Distribution.Deprecated.ReadP as Parse- ( pfail, munch1 )-import qualified Text.PrettyPrint as Disp- ( text )+import qualified Distribution.Compat.CharParsing as P+import qualified Text.PrettyPrint as Disp -import Data.Char as Char- ( isAlpha, toLower )-import GHC.Generics (Generic)-import Distribution.Compat.Binary (Binary)+import Distribution.Compiler (CompilerId (..))+import Distribution.PackageDescription (FlagAssignment)+import Distribution.System (Arch, OS)+import Distribution.Types.PackageId (PackageIdentifier) +-------------------------------------------------------------------------------+-- ReportLevel+------------------------------------------------------------------------------- data ReportLevel = NoReports | AnonymousReports | DetailedReports- deriving (Eq, Ord, Enum, Show, Generic)+ deriving (Eq, Ord, Enum, Bounded, Show, Generic) instance Binary ReportLevel+instance Structured ReportLevel -instance Text.Text ReportLevel where- disp NoReports = Disp.text "none"- disp AnonymousReports = Disp.text "anonymous"- disp DetailedReports = Disp.text "detailed"- parse = do- name <- Parse.munch1 Char.isAlpha+instance Pretty ReportLevel where+ pretty NoReports = Disp.text "none"+ pretty AnonymousReports = Disp.text "anonymous"+ pretty DetailedReports = Disp.text "detailed"++instance Parsec ReportLevel where+ parsec = do+ name <- P.munch1 isAlpha case lowercase name of "none" -> return NoReports "anonymous" -> return AnonymousReports "detailed" -> return DetailedReports- _ -> Parse.pfail+ _ -> P.unexpected $ "ReportLevel: " ++ name lowercase :: String -> String-lowercase = map Char.toLower+lowercase = map toLower++-------------------------------------------------------------------------------+-- BuildReport+-------------------------------------------------------------------------------++data BuildReport = BuildReport {+ -- | The package this build report is about+ package :: PackageIdentifier,++ -- | The OS and Arch the package was built on+ os :: OS,+ arch :: Arch,++ -- | The Haskell compiler (and hopefully version) used+ compiler :: CompilerId,++ -- | The uploading client, ie cabal-install-x.y.z+ client :: PackageIdentifier,++ -- | Which configurations flags we used+ flagAssignment :: FlagAssignment,++ -- | Which dependent packages we were using exactly+ dependencies :: [PackageIdentifier],++ -- | Did installing work ok?+ installOutcome :: InstallOutcome,++ -- Which version of the Cabal library was used to compile the Setup.hs+-- cabalVersion :: Version,++ -- Which build tools we were using (with versions)+-- tools :: [PackageIdentifier],++ -- | Configure outcome, did configure work ok?+ docsOutcome :: Outcome,++ -- | Configure outcome, did configure work ok?+ testsOutcome :: Outcome+ }+ deriving (Eq, Show, Generic)++++-------------------------------------------------------------------------------+-- InstallOutcome+-------------------------------------------------------------------------------++data InstallOutcome+ = PlanningFailed+ | DependencyFailed PackageIdentifier+ | DownloadFailed+ | UnpackFailed+ | SetupFailed+ | ConfigureFailed+ | BuildFailed+ | TestsFailed+ | InstallFailed+ | InstallOk+ deriving (Eq, Show, Generic)++instance Pretty InstallOutcome where+ pretty PlanningFailed = Disp.text "PlanningFailed"+ pretty (DependencyFailed pkgid) = Disp.text "DependencyFailed" <+> pretty pkgid+ pretty DownloadFailed = Disp.text "DownloadFailed"+ pretty UnpackFailed = Disp.text "UnpackFailed"+ pretty SetupFailed = Disp.text "SetupFailed"+ pretty ConfigureFailed = Disp.text "ConfigureFailed"+ pretty BuildFailed = Disp.text "BuildFailed"+ pretty TestsFailed = Disp.text "TestsFailed"+ pretty InstallFailed = Disp.text "InstallFailed"+ pretty InstallOk = Disp.text "InstallOk"++instance Parsec InstallOutcome where+ parsec = do+ name <- P.munch1 isAlpha+ case name of+ "PlanningFailed" -> return PlanningFailed+ "DependencyFailed" -> DependencyFailed <$ P.spaces <*> parsec+ "DownloadFailed" -> return DownloadFailed+ "UnpackFailed" -> return UnpackFailed+ "SetupFailed" -> return SetupFailed+ "ConfigureFailed" -> return ConfigureFailed+ "BuildFailed" -> return BuildFailed+ "TestsFailed" -> return TestsFailed+ "InstallFailed" -> return InstallFailed+ "InstallOk" -> return InstallOk+ _ -> P.unexpected $ "InstallOutcome: " ++ name++-------------------------------------------------------------------------------+-- Outcome+-------------------------------------------------------------------------------++data Outcome = NotTried | Failed | Ok+ deriving (Eq, Show, Enum, Bounded, Generic)++instance Pretty Outcome where+ pretty NotTried = Disp.text "NotTried"+ pretty Failed = Disp.text "Failed"+ pretty Ok = Disp.text "Ok"++instance Parsec Outcome where+ parsec = do+ name <- P.munch1 isAlpha+ case name of+ "NotTried" -> return NotTried+ "Failed" -> return Failed+ "Ok" -> return Ok+ _ -> P.unexpected $ "Outcome: " ++ name
cabal/cabal-install/Distribution/Client/BuildReports/Upload.hs view
@@ -7,6 +7,9 @@ , uploadReports ) where +import Distribution.Client.Compat.Prelude+import Prelude ()+ {- import Network.Browser ( BrowserAction, request, setAllowRedirects )@@ -17,14 +20,10 @@ -} import Network.URI (URI, uriPath) --parseRelativeReference, relativeTo) -import Control.Monad- ( forM_ ) import System.FilePath.Posix ( (</>) ) import qualified Distribution.Client.BuildReports.Anonymous as BuildReport-import Distribution.Client.BuildReports.Anonymous (BuildReport)-import Distribution.Deprecated.Text (display)-import Distribution.Verbosity (Verbosity)+import Distribution.Client.BuildReports.Anonymous (BuildReport, showBuildReport) import Distribution.Simple.Utils (die') import Distribution.Client.HttpUtils import Distribution.Client.Setup@@ -35,7 +34,7 @@ uploadReports :: Verbosity -> RepoContext -> (String, String) -> URI -> [(BuildReport, Maybe BuildLog)] -> IO () uploadReports verbosity repoCtxt auth uri reports = do- forM_ reports $ \(report, mbBuildLog) -> do+ for_ reports $ \(report, mbBuildLog) -> do buildId <- postBuildReport verbosity repoCtxt auth uri report case mbBuildLog of Just buildLog -> putBuildLog verbosity repoCtxt auth buildId buildLog@@ -43,9 +42,9 @@ postBuildReport :: Verbosity -> RepoContext -> (String, String) -> URI -> BuildReport -> IO BuildReportId postBuildReport verbosity repoCtxt auth uri buildReport = do- let fullURI = uri { uriPath = "/package" </> display (BuildReport.package buildReport) </> "reports" }+ let fullURI = uri { uriPath = "/package" </> prettyShow (BuildReport.package buildReport) </> "reports" } transport <- repoContextGetTransport repoCtxt- res <- postHttp transport verbosity fullURI (BuildReport.show buildReport) (Just auth)+ res <- postHttp transport verbosity fullURI (showBuildReport buildReport) (Just auth) case res of (303, redir) -> return $ undefined redir --TODO parse redir _ -> die' verbosity "unrecognized response" -- give response@@ -53,7 +52,7 @@ {- setAllowRedirects False (_, response) <- request Request {- rqURI = uri { uriPath = "/package" </> display (BuildReport.package buildReport) </> "reports" },+ rqURI = uri { uriPath = "/package" </> prettyShow (BuildReport.package buildReport) </> "reports" }, rqMethod = POST, rqHeaders = [Header HdrContentType ("text/plain"), Header HdrContentLength (show (length body)),
cabal/cabal-install/Distribution/Client/Check.hs view
@@ -28,7 +28,6 @@ (parseGenericPackageDescription, runParseResult) import Distribution.Parsec (PWarning (..), showPError, showPWarning) import Distribution.Simple.Utils (defaultPackageDesc, die', notice, warn)-import Distribution.Verbosity (Verbosity) import System.IO (hPutStr, stderr) import qualified Data.ByteString as BS
cabal/cabal-install/Distribution/Client/CmdBench.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE RecordWildCards #-} -- | cabal-install CLI command: bench --@@ -8,35 +8,38 @@ benchAction, -- * Internals exposed for testing- TargetProblem(..),+ componentNotBenchmarkProblem,+ isSubComponentProblem,+ noBenchmarksProblem, selectPackageTargets, selectComponentTarget ) where +import Distribution.Client.Compat.Prelude+import Prelude ()+ import Distribution.Client.ProjectOrchestration import Distribution.Client.CmdErrorMessages-+ ( renderTargetSelector, showTargetSelector, renderTargetProblem,+ renderTargetProblemNoTargets, plural, targetSelectorPluralPkgs,+ targetSelectorFilter )+import Distribution.Client.TargetProblem+ ( TargetProblem (..) )+import Distribution.Client.NixStyleOptions+ ( NixStyleFlags (..), nixStyleOptions, defaultNixStyleFlags ) import Distribution.Client.Setup- ( GlobalFlags, ConfigFlags(..), ConfigExFlags, InstallFlags )-import qualified Distribution.Client.Setup as Client-import Distribution.Simple.Setup- ( HaddockFlags, TestFlags, BenchmarkFlags, fromFlagOrDefault )+ ( GlobalFlags, ConfigFlags(..) )+import Distribution.Simple.Flag+ ( fromFlagOrDefault ) import Distribution.Simple.Command ( CommandUI(..), usageAlternatives )-import Distribution.Deprecated.Text- ( display ) import Distribution.Verbosity- ( Verbosity, normal )+ ( normal ) import Distribution.Simple.Utils ( wrapText, die' ) -import Control.Monad (when)---benchCommand :: CommandUI ( ConfigFlags, ConfigExFlags, InstallFlags- , HaddockFlags, TestFlags, BenchmarkFlags- )-benchCommand = Client.installCommand {+benchCommand :: CommandUI (NixStyleFlags ())+benchCommand = CommandUI { commandName = "v2-bench", commandSynopsis = "Run benchmarks", commandUsage = usageAlternatives "v2-bench" [ "[TARGETS] [FLAGS]" ],@@ -65,6 +68,9 @@ ++ " Run the benchmark built with '-O2' (including local libs used)\n\n" ++ cmdCommonHelpTextNewBuildBeta++ , commandDefaultFlags = defaultNixStyleFlags ()+ , commandOptions = nixStyleOptions (const []) } @@ -75,12 +81,8 @@ -- For more details on how this works, see the module -- "Distribution.Client.ProjectOrchestration" ---benchAction :: ( ConfigFlags, ConfigExFlags, InstallFlags- , HaddockFlags, TestFlags, BenchmarkFlags )- -> [String] -> GlobalFlags -> IO ()-benchAction ( configFlags, configExFlags, installFlags- , haddockFlags, testFlags, benchmarkFlags )- targetStrings globalFlags = do+benchAction :: NixStyleFlags () -> [String] -> GlobalFlags -> IO ()+benchAction flags@NixStyleFlags {..} targetStrings globalFlags = do baseCtx <- establishProjectBaseContext verbosity cliConfig OtherCommand @@ -102,7 +104,6 @@ $ resolveTargets selectPackageTargets selectComponentTarget- TargetProblemCommon elaboratedPlan Nothing targetSelectors@@ -119,11 +120,8 @@ runProjectPostBuildPhase verbosity baseCtx buildCtx buildOutcomes where verbosity = fromFlagOrDefault normal (configVerbosity configFlags)- cliConfig = commandLineFlagsToProjectConfig- globalFlags configFlags configExFlags- installFlags+ cliConfig = commandLineFlagsToProjectConfig globalFlags flags mempty -- ClientInstallFlags, not needed here- haddockFlags testFlags benchmarkFlags -- | This defines what a 'TargetSelector' means for the @bench@ command. -- It selects the 'AvailableTarget's that the 'TargetSelector' refers to,@@ -133,7 +131,7 @@ -- or fail if there are no benchmarks or no buildable benchmarks. -- selectPackageTargets :: TargetSelector- -> [AvailableTarget k] -> Either TargetProblem [k]+ -> [AvailableTarget k] -> Either BenchTargetProblem [k] selectPackageTargets targetSelector targets -- If there are any buildable benchmark targets then we select those@@ -146,7 +144,7 @@ -- If there are no benchmarks but some other targets then we report that | not (null targets)- = Left (TargetProblemNoBenchmarks targetSelector)+ = Left (noBenchmarksProblem targetSelector) -- If there are no targets at all then we report that | otherwise@@ -168,34 +166,27 @@ -- to the basic checks on being buildable etc. -- selectComponentTarget :: SubComponentTarget- -> AvailableTarget k -> Either TargetProblem k+ -> AvailableTarget k -> Either BenchTargetProblem k selectComponentTarget subtarget@WholeComponent t | CBenchName _ <- availableTargetComponentName t- = either (Left . TargetProblemCommon) return $- selectComponentTargetBasic subtarget t+ = selectComponentTargetBasic subtarget t | otherwise- = Left (TargetProblemComponentNotBenchmark (availableTargetPackageId t)- (availableTargetComponentName t))+ = Left (componentNotBenchmarkProblem+ (availableTargetPackageId t)+ (availableTargetComponentName t)) selectComponentTarget subtarget t- = Left (TargetProblemIsSubComponent (availableTargetPackageId t)- (availableTargetComponentName t)- subtarget)+ = Left (isSubComponentProblem+ (availableTargetPackageId t)+ (availableTargetComponentName t)+ subtarget) -- | The various error conditions that can occur when matching a -- 'TargetSelector' against 'AvailableTarget's for the @bench@ command. ---data TargetProblem =- TargetProblemCommon TargetProblemCommon-- -- | The 'TargetSelector' matches benchmarks but none are buildable- | TargetProblemNoneEnabled TargetSelector [AvailableTarget ()]-- -- | There are no targets at all- | TargetProblemNoTargets TargetSelector-+data BenchProblem = -- | The 'TargetSelector' matches targets but no benchmarks- | TargetProblemNoBenchmarks TargetSelector+ TargetProblemNoBenchmarks TargetSelector -- | The 'TargetSelector' refers to a component that is not a benchmark | TargetProblemComponentNotBenchmark PackageId ComponentName@@ -204,25 +195,30 @@ | TargetProblemIsSubComponent PackageId ComponentName SubComponentTarget deriving (Eq, Show) -reportTargetProblems :: Verbosity -> [TargetProblem] -> IO a-reportTargetProblems verbosity =- die' verbosity . unlines . map renderTargetProblem -renderTargetProblem :: TargetProblem -> String-renderTargetProblem (TargetProblemCommon problem) =- renderTargetProblemCommon "run" problem+type BenchTargetProblem = TargetProblem BenchProblem -renderTargetProblem (TargetProblemNoneEnabled targetSelector targets) =- renderTargetProblemNoneEnabled "benchmark" targetSelector targets+noBenchmarksProblem :: TargetSelector -> TargetProblem BenchProblem+noBenchmarksProblem = CustomTargetProblem . TargetProblemNoBenchmarks -renderTargetProblem (TargetProblemNoBenchmarks targetSelector) =- "Cannot run benchmarks for the target '" ++ showTargetSelector targetSelector- ++ "' which refers to " ++ renderTargetSelector targetSelector- ++ " because "- ++ plural (targetSelectorPluralPkgs targetSelector) "it does" "they do"- ++ " not contain any benchmarks."+componentNotBenchmarkProblem :: PackageId -> ComponentName -> TargetProblem BenchProblem+componentNotBenchmarkProblem pkgid name = CustomTargetProblem $+ TargetProblemComponentNotBenchmark pkgid name -renderTargetProblem (TargetProblemNoTargets targetSelector) =+isSubComponentProblem+ :: PackageId+ -> ComponentName+ -> SubComponentTarget+ -> TargetProblem BenchProblem+isSubComponentProblem pkgid name subcomponent = CustomTargetProblem $+ TargetProblemIsSubComponent pkgid name subcomponent++reportTargetProblems :: Verbosity -> [BenchTargetProblem] -> IO a+reportTargetProblems verbosity =+ die' verbosity . unlines . map renderBenchTargetProblem++renderBenchTargetProblem :: BenchTargetProblem -> String+renderBenchTargetProblem (TargetProblemNoTargets targetSelector) = case targetSelectorFilter targetSelector of Just kind | kind /= BenchKind -> "The bench command is for running benchmarks, but the target '"@@ -230,16 +226,26 @@ ++ renderTargetSelector targetSelector ++ "." _ -> renderTargetProblemNoTargets "benchmark" targetSelector+renderBenchTargetProblem problem =+ renderTargetProblem "benchmark" renderBenchProblem problem -renderTargetProblem (TargetProblemComponentNotBenchmark pkgid cname) =+renderBenchProblem :: BenchProblem -> String+renderBenchProblem (TargetProblemNoBenchmarks targetSelector) =+ "Cannot run benchmarks for the target '" ++ showTargetSelector targetSelector+ ++ "' which refers to " ++ renderTargetSelector targetSelector+ ++ " because "+ ++ plural (targetSelectorPluralPkgs targetSelector) "it does" "they do"+ ++ " not contain any benchmarks."++renderBenchProblem (TargetProblemComponentNotBenchmark pkgid cname) = "The bench command is for running benchmarks, but the target '" ++ showTargetSelector targetSelector ++ "' refers to " ++ renderTargetSelector targetSelector ++ " from the package "- ++ display pkgid ++ "."+ ++ prettyShow pkgid ++ "." where targetSelector = TargetComponent pkgid cname WholeComponent -renderTargetProblem (TargetProblemIsSubComponent pkgid cname subtarget) =+renderBenchProblem (TargetProblemIsSubComponent pkgid cname subtarget) = "The bench command can only run benchmarks as a whole, " ++ "not files or modules within them, but the target '" ++ showTargetSelector targetSelector ++ "' refers to "
cabal/cabal-install/Distribution/Client/CmdBuild.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE RecordWildCards #-} -- | cabal-install CLI command: build -- module Distribution.Client.CmdBuild (@@ -6,37 +7,34 @@ buildAction, -- * Internals exposed for testing- TargetProblem(..), selectPackageTargets, selectComponentTarget ) where +import Prelude ()+import Distribution.Client.Compat.Prelude+ import Distribution.Client.ProjectOrchestration+import Distribution.Client.TargetProblem+ ( TargetProblem (..), TargetProblem' ) import Distribution.Client.CmdErrorMessages -import Distribution.Compat.Semigroup ((<>))+import Distribution.Client.NixStyleOptions+ ( NixStyleFlags (..), nixStyleOptions, defaultNixStyleFlags ) import Distribution.Client.Setup- ( GlobalFlags, ConfigFlags(..), ConfigExFlags, InstallFlags- , liftOptions, yesNoOpt )-import qualified Distribution.Client.Setup as Client-import Distribution.Simple.Setup- ( HaddockFlags, TestFlags, BenchmarkFlags- , Flag(..), toFlag, fromFlag, fromFlagOrDefault )+ ( GlobalFlags, ConfigFlags(..), yesNoOpt )+import Distribution.Simple.Flag ( Flag(..), toFlag, fromFlag, fromFlagOrDefault ) import Distribution.Simple.Command- ( CommandUI(..), usageAlternatives, option )+ ( CommandUI(..), usageAlternatives, option, optionName ) import Distribution.Verbosity- ( Verbosity, normal )+ ( normal ) import Distribution.Simple.Utils ( wrapText, die' ) import qualified Data.Map as Map -buildCommand ::- CommandUI- (BuildFlags, ( ConfigFlags, ConfigExFlags- , InstallFlags, HaddockFlags- , TestFlags, BenchmarkFlags ))+buildCommand :: CommandUI (NixStyleFlags BuildFlags) buildCommand = CommandUI { commandName = "v2-build", commandSynopsis = "Compile targets within the project.",@@ -68,24 +66,17 @@ ++ " Build the component in profiling mode " ++ "(including dependencies as needed)\n\n" - ++ cmdCommonHelpTextNewBuildBeta,- commandDefaultFlags =- (defaultBuildFlags, commandDefaultFlags Client.installCommand),- commandOptions = \ showOrParseArgs ->- liftOptions snd setSnd- (commandOptions Client.installCommand showOrParseArgs) ++- liftOptions fst setFst- [ option [] ["only-configure"]- "Instead of performing a full build just run the configure step"- buildOnlyConfigure (\v flags -> flags { buildOnlyConfigure = v })- (yesNoOpt showOrParseArgs)- ]+ ++ cmdCommonHelpTextNewBuildBeta+ , commandDefaultFlags = defaultNixStyleFlags defaultBuildFlags+ , commandOptions = filter (\o -> optionName o /= "ignore-project")+ . nixStyleOptions (\showOrParseArgs ->+ [ option [] ["only-configure"]+ "Instead of performing a full build just run the configure step"+ buildOnlyConfigure (\v flags -> flags { buildOnlyConfigure = v })+ (yesNoOpt showOrParseArgs)+ ]) } - where- setFst a (_,b) = (a,b)- setSnd b (a,_) = (a,b)- data BuildFlags = BuildFlags { buildOnlyConfigure :: Flag Bool }@@ -102,16 +93,8 @@ -- For more details on how this works, see the module -- "Distribution.Client.ProjectOrchestration" ---buildAction ::- ( BuildFlags- , ( ConfigFlags, ConfigExFlags, InstallFlags- , HaddockFlags, TestFlags, BenchmarkFlags ))- -> [String] -> GlobalFlags -> IO ()-buildAction- ( buildFlags- , ( configFlags, configExFlags, installFlags- , haddockFlags, testFlags, benchmarkFlags ))- targetStrings globalFlags = do+buildAction :: NixStyleFlags BuildFlags -> [String] -> GlobalFlags -> IO ()+buildAction flags@NixStyleFlags { extraFlags = buildFlags, ..} targetStrings globalFlags = do -- TODO: This flags defaults business is ugly let onlyConfigure = fromFlag (buildOnlyConfigure defaultBuildFlags <> buildOnlyConfigure buildFlags)@@ -130,11 +113,10 @@ -- Interpret the targets on the command line as build targets -- (as opposed to say repl or haddock targets).- targets <- either (reportTargetProblems verbosity) return+ targets <- either (reportBuildTargetProblems verbosity) return $ resolveTargets selectPackageTargets selectComponentTarget- TargetProblemCommon elaboratedPlan Nothing targetSelectors@@ -158,11 +140,8 @@ runProjectPostBuildPhase verbosity baseCtx buildCtx buildOutcomes where verbosity = fromFlagOrDefault normal (configVerbosity configFlags)- cliConfig = commandLineFlagsToProjectConfig- globalFlags configFlags configExFlags- installFlags+ cliConfig = commandLineFlagsToProjectConfig globalFlags flags mempty -- ClientInstallFlags, not needed here- haddockFlags testFlags benchmarkFlags -- | This defines what a 'TargetSelector' means for the @bench@ command. -- It selects the 'AvailableTarget's that the 'TargetSelector' refers to,@@ -173,7 +152,7 @@ -- components -- selectPackageTargets :: TargetSelector- -> [AvailableTarget k] -> Either TargetProblem [k]+ -> [AvailableTarget k] -> Either TargetProblem' [k] selectPackageTargets targetSelector targets -- If there are any buildable targets then we select those@@ -206,36 +185,12 @@ -- For the @build@ command we just need the basic checks on being buildable etc. -- selectComponentTarget :: SubComponentTarget- -> AvailableTarget k -> Either TargetProblem k-selectComponentTarget subtarget =- either (Left . TargetProblemCommon) Right- . selectComponentTargetBasic subtarget----- | The various error conditions that can occur when matching a--- 'TargetSelector' against 'AvailableTarget's for the @build@ command.----data TargetProblem =- TargetProblemCommon TargetProblemCommon-- -- | The 'TargetSelector' matches targets but none are buildable- | TargetProblemNoneEnabled TargetSelector [AvailableTarget ()]-- -- | There are no targets at all- | TargetProblemNoTargets TargetSelector- deriving (Eq, Show)--reportTargetProblems :: Verbosity -> [TargetProblem] -> IO a-reportTargetProblems verbosity =- die' verbosity . unlines . map renderTargetProblem+ -> AvailableTarget k -> Either TargetProblem' k+selectComponentTarget = selectComponentTargetBasic -renderTargetProblem :: TargetProblem -> String-renderTargetProblem (TargetProblemCommon problem) =- renderTargetProblemCommon "build" problem-renderTargetProblem (TargetProblemNoneEnabled targetSelector targets) =- renderTargetProblemNoneEnabled "build" targetSelector targets-renderTargetProblem(TargetProblemNoTargets targetSelector) =- renderTargetProblemNoTargets "build" targetSelector+reportBuildTargetProblems :: Verbosity -> [TargetProblem'] -> IO a+reportBuildTargetProblems verbosity problems =+ reportTargetProblems verbosity "build" problems reportCannotPruneDependencies :: Verbosity -> CannotPruneDependencies -> IO a reportCannotPruneDependencies verbosity =
cabal/cabal-install/Distribution/Client/CmdClean.hs view
@@ -20,12 +20,8 @@ import Distribution.Simple.Utils ( info, die', wrapText, handleDoesNotExist ) import Distribution.Verbosity- ( Verbosity, normal )+ ( normal ) -import Control.Monad- ( mapM_ )-import Control.Exception- ( throwIO ) import System.Directory ( removeDirectoryRecursive, removeFile , doesDirectoryExist, getDirectoryContents )@@ -111,5 +107,5 @@ removeEnvFiles :: FilePath -> IO () removeEnvFiles dir =- (mapM_ (removeFile . (dir </>)) . filter ((".ghc.environment" ==) . take 16))+ (traverse_ (removeFile . (dir </>)) . filter ((".ghc.environment" ==) . take 16)) =<< getDirectoryContents dir
cabal/cabal-install/Distribution/Client/CmdConfigure.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE RecordWildCards #-} -- | cabal-install CLI command: configure -- module Distribution.Client.CmdConfigure (@@ -5,31 +6,36 @@ configureAction, ) where +import Distribution.Client.Compat.Prelude+import Prelude ()+ import System.Directory-import Control.Monad+import System.FilePath import qualified Data.Map as Map import Distribution.Client.ProjectOrchestration import Distribution.Client.ProjectConfig ( writeProjectLocalExtraConfig ) +import Distribution.Client.NixStyleOptions+ ( NixStyleFlags (..), nixStyleOptions, defaultNixStyleFlags ) import Distribution.Client.Setup- ( GlobalFlags, ConfigFlags(..), ConfigExFlags, InstallFlags )-import Distribution.Simple.Setup- ( HaddockFlags, TestFlags, BenchmarkFlags, fromFlagOrDefault )+ ( GlobalFlags, ConfigFlags(..) )+import Distribution.Simple.Flag+ ( fromFlagOrDefault ) import Distribution.Verbosity ( normal ) import Distribution.Simple.Command- ( CommandUI(..), usageAlternatives )+ ( CommandUI(..), usageAlternatives, optionName ) import Distribution.Simple.Utils ( wrapText, notice )-import qualified Distribution.Client.Setup as Client -configureCommand :: CommandUI ( ConfigFlags, ConfigExFlags, InstallFlags- , HaddockFlags, TestFlags, BenchmarkFlags- )-configureCommand = Client.installCommand {+import Distribution.Client.DistDirLayout+ ( DistDirLayout(..) )++configureCommand :: CommandUI (NixStyleFlags ())+configureCommand = CommandUI { commandName = "v2-configure", commandSynopsis = "Add extra project configuration", commandUsage = usageAlternatives "v2-configure" [ "[FLAGS]" ],@@ -67,7 +73,10 @@ ++ " project configuration works.\n\n" ++ cmdCommonHelpTextNewBuildBeta- }+ , commandDefaultFlags = defaultNixStyleFlags ()+ , commandOptions = filter (\o -> optionName o /= "ignore-project")+ . nixStyleOptions (const [])+ } -- | To a first approximation, the @configure@ just runs the first phase of -- the @build@ command where we bring the install plan up to date (thus@@ -79,12 +88,8 @@ -- For more details on how this works, see the module -- "Distribution.Client.ProjectOrchestration" ---configureAction :: ( ConfigFlags, ConfigExFlags, InstallFlags- , HaddockFlags, TestFlags, BenchmarkFlags )- -> [String] -> GlobalFlags -> IO ()-configureAction ( configFlags, configExFlags, installFlags- , haddockFlags, testFlags, benchmarkFlags )- _extraArgs globalFlags = do+configureAction :: NixStyleFlags () -> [String] -> GlobalFlags -> IO ()+configureAction flags@NixStyleFlags {..} _extraArgs globalFlags = do --TODO: deal with _extraArgs, since flags with wrong syntax end up there baseCtx <- establishProjectBaseContext verbosity cliConfig OtherCommand@@ -92,10 +97,26 @@ -- Write out the @cabal.project.local@ so it gets picked up by the -- planning phase. If old config exists, then print the contents -- before overwriting- exists <- doesFileExist "cabal.project.local"++ let localFile = distProjectFile (distDirLayout baseCtx) "local"+ -- | Chooses cabal.project.local~, or if it already exists+ -- cabal.project.local~0, cabal.project.local~1 etc.+ firstFreeBackup = firstFreeBackup' (0 :: Int)+ firstFreeBackup' i = do+ let backup = localFile <> "~" <> (if i <= 0 then "" else show (i - 1))+ exists <- doesFileExist backup+ if exists+ then firstFreeBackup' (i + 1)+ else return backup++ -- If cabal.project.local already exists, back up to cabal.project.local~[n]+ exists <- doesFileExist localFile when exists $ do- notice verbosity "'cabal.project.local' file already exists. Now overwriting it."- copyFile "cabal.project.local" "cabal.project.local~"+ backup <- firstFreeBackup+ notice verbosity $+ quote (takeFileName localFile) <> " already exists, backing it up to "+ <> quote (takeFileName backup) <> "."+ copyFile localFile backup writeProjectLocalExtraConfig (distDirLayout baseCtx) cliConfig @@ -122,9 +143,7 @@ printPlan verbosity baseCtx' buildCtx where verbosity = fromFlagOrDefault normal (configVerbosity configFlags)- cliConfig = commandLineFlagsToProjectConfig- globalFlags configFlags configExFlags- installFlags+ cliConfig = commandLineFlagsToProjectConfig globalFlags flags mempty -- ClientInstallFlags, not needed here- haddockFlags testFlags benchmarkFlags+ quote s = "'" <> s <> "'"
cabal/cabal-install/Distribution/Client/CmdErrorMessages.hs view
@@ -1,5 +1,8 @@-{-# LANGUAGE RecordWildCards, NamedFieldPuns #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE RecordWildCards #-} + -- | Utilities to help format error messages for the various CLI commands. -- module Distribution.Client.CmdErrorMessages (@@ -7,24 +10,32 @@ module Distribution.Client.TargetSelector, ) where -import Distribution.Client.ProjectOrchestration+import Distribution.Client.Compat.Prelude+import Prelude ()++import Distribution.Client.ProjectPlanning+ ( AvailableTarget(..), AvailableTargetStatus(..),+ CannotPruneDependencies(..), TargetRequested(..) ) import Distribution.Client.TargetSelector- ( ComponentKindFilter, componentKind, showTargetSelector )+ ( SubComponentTarget(..) )+import Distribution.Client.TargetProblem+ ( TargetProblem(..), TargetProblem' )+import Distribution.Client.TargetSelector+ ( ComponentKind(..), ComponentKindFilter, TargetSelector(..),+ componentKind, showTargetSelector ) import Distribution.Package- ( packageId, PackageName, packageName )+ ( PackageId, packageId, PackageName, packageName )+import Distribution.Simple.Utils+ ( die' ) import Distribution.Types.ComponentName- ( showComponentName )+ ( ComponentName(..), showComponentName ) import Distribution.Types.LibraryName ( LibraryName(..) ) import Distribution.Solver.Types.OptionalStanza ( OptionalStanza(..) )-import Distribution.Deprecated.Text- ( display ) -import Data.Maybe (isNothing)-import Data.List (sortBy, groupBy, nub)-import Data.Function (on)+import qualified Data.List.NonEmpty as NE -----------------------@@ -72,13 +83,13 @@ -- things, e.g. grouping components by package name -- -- > renderListSemiAnd--- > [ "the package " ++ display pkgname ++ " components "+-- > [ "the package " ++ prettyShow pkgname ++ " components " -- > ++ renderListCommaAnd showComponentName components -- > | (pkgname, components) <- sortGroupOn packageName allcomponents ] -- sortGroupOn :: Ord b => (a -> b) -> [a] -> [(b, [a])]-sortGroupOn key = map (\xs@(x:_) -> (key x, xs))- . groupBy ((==) `on` key)+sortGroupOn key = map (\(x:|xs) -> (key x, x:xs))+ . NE.groupBy ((==) `on` key) . sortBy (compare `on` key) @@ -89,19 +100,19 @@ renderTargetSelector :: TargetSelector -> String renderTargetSelector (TargetPackage _ pkgids Nothing) = "the " ++ plural (listPlural pkgids) "package" "packages" ++ " "- ++ renderListCommaAnd (map display pkgids)+ ++ renderListCommaAnd (map prettyShow pkgids) renderTargetSelector (TargetPackage _ pkgids (Just kfilter)) = "the " ++ renderComponentKind Plural kfilter ++ " in the " ++ plural (listPlural pkgids) "package" "packages" ++ " "- ++ renderListCommaAnd (map display pkgids)+ ++ renderListCommaAnd (map prettyShow pkgids) renderTargetSelector (TargetPackageNamed pkgname Nothing) =- "the package " ++ display pkgname+ "the package " ++ prettyShow pkgname renderTargetSelector (TargetPackageNamed pkgname (Just kfilter)) = "the " ++ renderComponentKind Plural kfilter- ++ " in the package " ++ display pkgname+ ++ " in the package " ++ prettyShow pkgname renderTargetSelector (TargetAllPackages Nothing) = "all the packages in the project"@@ -115,8 +126,8 @@ ++ renderComponentName (packageName pkgid) cname renderTargetSelector (TargetComponentUnknown pkgname (Left ucname) subtarget) =- renderSubComponentTarget subtarget ++ "the component " ++ display ucname- ++ " in the package " ++ display pkgname+ renderSubComponentTarget subtarget ++ "the component " ++ prettyShow ucname+ ++ " in the package " ++ prettyShow pkgname renderTargetSelector (TargetComponentUnknown pkgname (Right cname) subtarget) = renderSubComponentTarget subtarget ++ "the "@@ -127,7 +138,7 @@ renderSubComponentTarget (FileTarget filename) = "the file " ++ filename ++ "in " renderSubComponentTarget (ModuleTarget modname) =- "the module" ++ display modname ++ "in "+ "the module" ++ prettyShow modname ++ "in " renderOptionalStanza :: Plural -> OptionalStanza -> String@@ -167,12 +178,12 @@ targetSelectorFilter TargetComponentUnknown{} = Nothing renderComponentName :: PackageName -> ComponentName -> String-renderComponentName pkgname (CLibName LMainLibName) = "library " ++ display pkgname-renderComponentName _ (CLibName (LSubLibName name)) = "library " ++ display name-renderComponentName _ (CFLibName name) = "foreign library " ++ display name-renderComponentName _ (CExeName name) = "executable " ++ display name-renderComponentName _ (CTestName name) = "test suite " ++ display name-renderComponentName _ (CBenchName name) = "benchmark " ++ display name+renderComponentName pkgname (CLibName LMainLibName) = "library " ++ prettyShow pkgname+renderComponentName _ (CLibName (LSubLibName name)) = "library " ++ prettyShow name+renderComponentName _ (CFLibName name) = "foreign library " ++ prettyShow name+renderComponentName _ (CExeName name) = "executable " ++ prettyShow name+renderComponentName _ (CTestName name) = "test suite " ++ prettyShow name+renderComponentName _ (CBenchName name) = "benchmark " ++ prettyShow name renderComponentKind :: Plural -> ComponentKind -> String renderComponentKind Singular ckind = case ckind of@@ -190,39 +201,55 @@ ---------------------------------------------------------- Renderering error messages for TargetProblemCommon+-- Renderering error messages for TargetProblem -- -renderTargetProblemCommon :: String -> TargetProblemCommon -> String-renderTargetProblemCommon verb (TargetNotInProject pkgname) =- "Cannot " ++ verb ++ " the package " ++ display pkgname ++ ", it is not "+-- | Default implementation of 'reportTargetProblems' simply renders one problem per line.+reportTargetProblems :: Verbosity -> String -> [TargetProblem'] -> IO a+reportTargetProblems verbosity verb =+ die' verbosity . unlines . map (renderTargetProblem verb absurd)++-- | Default implementation of 'renderTargetProblem'.+renderTargetProblem+ :: String -- ^ verb+ -> (a -> String) -- ^ how to render custom problems+ -> TargetProblem a+ -> String+renderTargetProblem _verb f (CustomTargetProblem x) = f x+renderTargetProblem verb _ (TargetProblemNoneEnabled targetSelector targets) =+ renderTargetProblemNoneEnabled verb targetSelector targets+renderTargetProblem verb _ (TargetProblemNoTargets targetSelector) =+ renderTargetProblemNoTargets verb targetSelector++renderTargetProblem verb _ (TargetNotInProject pkgname) =+ "Cannot " ++ verb ++ " the package " ++ prettyShow pkgname ++ ", it is not " ++ "in this project (either directly or indirectly). If you want to add it " ++ "to the project then edit the cabal.project file." -renderTargetProblemCommon verb (TargetAvailableInIndex pkgname) =- "Cannot " ++ verb ++ " the package " ++ display pkgname ++ ", it is not "+renderTargetProblem verb _ (TargetAvailableInIndex pkgname) =+ "Cannot " ++ verb ++ " the package " ++ prettyShow pkgname ++ ", it is not " ++ "in this project (either directly or indirectly), but it is in the current " ++ "package index. If you want to add it to the project then edit the " ++ "cabal.project file." -renderTargetProblemCommon verb (TargetComponentNotProjectLocal pkgid cname _) =+renderTargetProblem verb _ (TargetComponentNotProjectLocal pkgid cname _) = "Cannot " ++ verb ++ " the " ++ showComponentName cname ++ " because the "- ++ "package " ++ display pkgid ++ " is not local to the project, and cabal "+ ++ "package " ++ prettyShow pkgid ++ " is not local to the project, and cabal " ++ "does not currently support building test suites or benchmarks of " ++ "non-local dependencies. To run test suites or benchmarks from " ++ "dependencies you can unpack the package locally and adjust the " ++ "cabal.project file to include that package directory." -renderTargetProblemCommon verb (TargetComponentNotBuildable pkgid cname _) =+renderTargetProblem verb _ (TargetComponentNotBuildable pkgid cname _) = "Cannot " ++ verb ++ " the " ++ showComponentName cname ++ " because it is "- ++ "marked as 'buildable: False' within the '" ++ display (packageName pkgid)+ ++ "marked as 'buildable: False' within the '" ++ prettyShow (packageName pkgid) ++ ".cabal' file (at least for the current configuration). If you believe it " ++ "should be buildable then check the .cabal file to see if the buildable " ++ "property is conditional on flags. Alternatively you may simply have to " ++ "edit the .cabal file to declare it as buildable and fix any resulting " ++ "build problems." -renderTargetProblemCommon verb (TargetOptionalStanzaDisabledByUser _ cname _) =+renderTargetProblem verb _ (TargetOptionalStanzaDisabledByUser _ cname _) = "Cannot " ++ verb ++ " the " ++ showComponentName cname ++ " because " ++ "building " ++ compkinds ++ " has been explicitly disabled in the " ++ "configuration. You can adjust this configuration in the "@@ -235,10 +262,10 @@ where compkinds = renderComponentKind Plural (componentKind cname) -renderTargetProblemCommon verb (TargetOptionalStanzaDisabledBySolver pkgid cname _) =+renderTargetProblem verb _ (TargetOptionalStanzaDisabledBySolver pkgid cname _) = "Cannot " ++ verb ++ " the " ++ showComponentName cname ++ " because the " ++ "solver did not find a plan that included the " ++ compkinds- ++ " for " ++ display pkgid ++ ". It is probably worth trying again with "+ ++ " for " ++ prettyShow pkgid ++ ". It is probably worth trying again with " ++ compkinds ++ " explicitly enabled in the configuration in the " ++ "cabal.project{.local} file. This will ask the solver to find a plan with " ++ "the " ++ compkinds ++ " available. It will either fail with an "@@ -248,27 +275,27 @@ where compkinds = renderComponentKind Plural (componentKind cname) -renderTargetProblemCommon verb (TargetProblemUnknownComponent pkgname ecname) =+renderTargetProblem verb _ (TargetProblemUnknownComponent pkgname ecname) = "Cannot " ++ verb ++ " the " ++ (case ecname of- Left ucname -> "component " ++ display ucname+ Left ucname -> "component " ++ prettyShow ucname Right cname -> renderComponentName pkgname cname)- ++ " from the package " ++ display pkgname+ ++ " from the package " ++ prettyShow pkgname ++ ", because the package does not contain a " ++ (case ecname of Left _ -> "component" Right cname -> renderComponentKind Singular (componentKind cname)) ++ " with that name." -renderTargetProblemCommon verb (TargetProblemNoSuchPackage pkgid) =+renderTargetProblem verb _ (TargetProblemNoSuchPackage pkgid) = "Internal error when trying to " ++ verb ++ " the package "- ++ display pkgid ++ ". The package is not in the set of available targets "+ ++ prettyShow pkgid ++ ". The package is not in the set of available targets " ++ "for the project plan, which would suggest an inconsistency " ++ "between readTargetSelectors and resolveTargets." -renderTargetProblemCommon verb (TargetProblemNoSuchComponent pkgid cname) =+renderTargetProblem verb _ (TargetProblemNoSuchComponent pkgid cname) = "Internal error when trying to " ++ verb ++ " the "- ++ showComponentName cname ++ " from the package " ++ display pkgid+ ++ showComponentName cname ++ " from the package " ++ prettyShow pkgid ++ ". The package,component pair is not in the set of available targets " ++ "for the project plan, which would suggest an inconsistency " ++ "between readTargetSelectors and resolveTargets."@@ -383,9 +410,9 @@ "Cannot select only the dependencies (as requested by the " ++ "'--only-dependencies' flag), " ++ (case pkgids of- [pkgid] -> "the package " ++ display pkgid ++ " is "+ [pkgid] -> "the package " ++ prettyShow pkgid ++ " is " _ -> "the packages "- ++ renderListCommaAnd (map display pkgids) ++ " are ")+ ++ renderListCommaAnd (map prettyShow pkgids) ++ " are ") ++ "required by a dependency of one of the other targets." where -- throw away the details and just list the deps that are needed
cabal/cabal-install/Distribution/Client/CmdExec.hs view
@@ -21,13 +21,12 @@ ( GenericPlanPackage(..) , toGraph )+import Distribution.Client.NixStyleOptions+ ( NixStyleFlags (..), nixStyleOptions, defaultNixStyleFlags ) import Distribution.Client.Setup- ( ConfigExFlags- , ConfigFlags(configVerbosity)+ ( ConfigFlags(configVerbosity) , GlobalFlags- , InstallFlags )-import qualified Distribution.Client.Setup as Client import Distribution.Client.ProjectOrchestration ( ProjectBuildContext(..) , runProjectPreBuildPhase@@ -49,7 +48,7 @@ , ElaboratedSharedConfig(..) ) import Distribution.Simple.Command- ( CommandUI(..)+ ( CommandUI(..), optionName ) import Distribution.Simple.Program.Db ( modifyProgramSearchPath@@ -73,21 +72,18 @@ import Distribution.Simple.GHC ( getImplInfo , GhcImplInfo(supportsPkgEnvFiles) )-import Distribution.Simple.Setup- ( HaddockFlags- , TestFlags- , BenchmarkFlags- , fromFlagOrDefault+import Distribution.Simple.Flag+ ( fromFlagOrDefault ) import Distribution.Simple.Utils ( die' , info+ , createDirectoryIfMissingVerbose , withTempDirectory , wrapText ) import Distribution.Verbosity- ( Verbosity- , normal+ ( normal ) import Prelude ()@@ -96,9 +92,7 @@ import qualified Data.Set as S import qualified Data.Map as M -execCommand :: CommandUI ( ConfigFlags, ConfigExFlags, InstallFlags- , HaddockFlags, TestFlags, BenchmarkFlags- )+execCommand :: CommandUI (NixStyleFlags ()) execCommand = CommandUI { commandName = "v2-exec" , commandSynopsis = "Give a command access to the store."@@ -119,16 +113,13 @@ ++ " to choose an appropriate version of ghc and to include any" ++ " ghc-specific flags requested." , commandNotes = Nothing- , commandOptions = commandOptions Client.installCommand- , commandDefaultFlags = commandDefaultFlags Client.installCommand+ , commandOptions = filter (\o -> optionName o /= "ignore-project")+ . nixStyleOptions (const [])+ , commandDefaultFlags = defaultNixStyleFlags () } -execAction :: ( ConfigFlags, ConfigExFlags, InstallFlags- , HaddockFlags, TestFlags, BenchmarkFlags )- -> [String] -> GlobalFlags -> IO ()-execAction ( configFlags, configExFlags, installFlags- , haddockFlags, testFlags, benchmarkFlags )- extraArgs globalFlags = do+execAction :: NixStyleFlags () -> [String] -> GlobalFlags -> IO ()+execAction flags@NixStyleFlags {..} extraArgs globalFlags = do baseCtx <- establishProjectBaseContext verbosity cliConfig OtherCommand @@ -197,11 +188,8 @@ runProgramInvocation verbosity invocation where verbosity = fromFlagOrDefault normal (configVerbosity configFlags)- cliConfig = commandLineFlagsToProjectConfig- globalFlags configFlags configExFlags- installFlags+ cliConfig = commandLineFlagsToProjectConfig globalFlags flags mempty -- ClientInstallFlags, not needed here- haddockFlags testFlags benchmarkFlags withOverrides env args program = program { programOverrideEnv = programOverrideEnv program ++ env , programDefaultArgs = programDefaultArgs program ++ args}@@ -223,11 +211,8 @@ -> PostBuildProjectStatus -> ([(String, Maybe String)] -> IO a) -> IO a-withTempEnvFile verbosity- baseCtx- buildCtx- buildStatus- action =+withTempEnvFile verbosity baseCtx buildCtx buildStatus action = do+ createDirectoryIfMissingVerbose verbosity True (distTempDirectory (distDirLayout baseCtx)) withTempDirectory verbosity (distTempDirectory (distDirLayout baseCtx))
cabal/cabal-install/Distribution/Client/CmdFreeze.hs view
@@ -7,11 +7,17 @@ freezeAction, ) where +import Distribution.Client.Compat.Prelude+import Prelude ()++import Distribution.Client.NixStyleOptions+ ( NixStyleFlags (..), nixStyleOptions, defaultNixStyleFlags ) import Distribution.Client.ProjectOrchestration import Distribution.Client.ProjectPlanning import Distribution.Client.ProjectConfig ( ProjectConfig(..), ProjectConfigShared(..) , writeProjectLocalFreezeConfig )+import Distribution.Client.IndexUtils (TotalIndexState, ActiveRepos) import Distribution.Client.Targets ( UserQualifier(..), UserConstraintScope(..), UserConstraint(..) ) import Distribution.Solver.Types.PackageConstraint@@ -31,28 +37,22 @@ import Distribution.PackageDescription ( FlagAssignment, nullFlagAssignment ) import Distribution.Client.Setup- ( GlobalFlags, ConfigFlags(..), ConfigExFlags, InstallFlags )-import Distribution.Simple.Setup- ( HaddockFlags, TestFlags, BenchmarkFlags, fromFlagOrDefault )+ ( GlobalFlags, ConfigFlags(..) )+import Distribution.Simple.Flag+ ( fromFlagOrDefault )+import Distribution.Simple.Flag (Flag (..)) import Distribution.Simple.Utils ( die', notice, wrapText ) import Distribution.Verbosity ( normal ) -import Data.Monoid as Monoid import qualified Data.Map as Map-import Data.Map (Map)-import Control.Monad (unless) import Distribution.Simple.Command ( CommandUI(..), usageAlternatives )-import qualified Distribution.Client.Setup as Client --freezeCommand :: CommandUI ( ConfigFlags, ConfigExFlags, InstallFlags- , HaddockFlags, TestFlags, BenchmarkFlags- )-freezeCommand = Client.installCommand {+freezeCommand :: CommandUI (NixStyleFlags ())+freezeCommand = CommandUI { commandName = "v2-freeze", commandSynopsis = "Freeze dependencies.", commandUsage = usageAlternatives "v2-freeze" [ "[FLAGS]" ],@@ -92,6 +92,8 @@ ++ "https://github.com/haskell/cabal/issues and if you\nhave any time " ++ "to get involved and help with testing, fixing bugs etc then\nthat " ++ "is very much appreciated.\n"+ , commandDefaultFlags = defaultNixStyleFlags ()+ , commandOptions = nixStyleOptions (const []) } -- | To a first approximation, the @freeze@ command runs the first phase of@@ -101,12 +103,8 @@ -- For more details on how this works, see the module -- "Distribution.Client.ProjectOrchestration" ---freezeAction :: ( ConfigFlags, ConfigExFlags, InstallFlags- , HaddockFlags, TestFlags, BenchmarkFlags )- -> [String] -> GlobalFlags -> IO ()-freezeAction ( configFlags, configExFlags, installFlags- , haddockFlags, testFlags, benchmarkFlags )- extraArgs globalFlags = do+freezeAction :: NixStyleFlags () -> [String] -> GlobalFlags -> IO ()+freezeAction flags@NixStyleFlags {..} extraArgs globalFlags = do unless (null extraArgs) $ die' verbosity $ "'freeze' doesn't take any extra arguments: "@@ -119,37 +117,39 @@ localPackages } <- establishProjectBaseContext verbosity cliConfig OtherCommand - (_, elaboratedPlan, _) <-+ (_, elaboratedPlan, _, totalIndexState, activeRepos) <- rebuildInstallPlan verbosity distDirLayout cabalDirLayout projectConfig localPackages - let freezeConfig = projectFreezeConfig elaboratedPlan+ let freezeConfig = projectFreezeConfig elaboratedPlan totalIndexState activeRepos writeProjectLocalFreezeConfig distDirLayout freezeConfig notice verbosity $ "Wrote freeze file: " ++ distProjectFile distDirLayout "freeze" where verbosity = fromFlagOrDefault normal (configVerbosity configFlags)- cliConfig = commandLineFlagsToProjectConfig- globalFlags configFlags configExFlags- installFlags+ cliConfig = commandLineFlagsToProjectConfig globalFlags flags mempty -- ClientInstallFlags, not needed here- haddockFlags testFlags benchmarkFlags -- | Given the install plan, produce a config value with constraints that -- freezes the versions of packages used in the plan. ---projectFreezeConfig :: ElaboratedInstallPlan -> ProjectConfig-projectFreezeConfig elaboratedPlan =- Monoid.mempty {- projectConfigShared = Monoid.mempty {- projectConfigConstraints =+projectFreezeConfig+ :: ElaboratedInstallPlan+ -> TotalIndexState+ -> ActiveRepos+ -> ProjectConfig+projectFreezeConfig elaboratedPlan totalIndexState activeRepos = mempty+ { projectConfigShared = mempty+ { projectConfigConstraints = concat (Map.elems (projectFreezeConstraints elaboratedPlan))- }+ , projectConfigIndexState = Flag totalIndexState+ , projectConfigActiveRepos = Flag activeRepos+ } } -- | Given the install plan, produce solver constraints that will ensure the
cabal/cabal-install/Distribution/Client/CmdHaddock.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE RecordWildCards #-} -- | cabal-install CLI command: haddock --@@ -8,33 +8,32 @@ haddockAction, -- * Internals exposed for testing- TargetProblem(..), selectPackageTargets, selectComponentTarget ) where +import Distribution.Client.Compat.Prelude+import Prelude ()+ import Distribution.Client.ProjectOrchestration import Distribution.Client.CmdErrorMessages-+import Distribution.Client.TargetProblem+ ( TargetProblem (..), TargetProblem' )+import Distribution.Client.NixStyleOptions+ ( NixStyleFlags (..), nixStyleOptions, defaultNixStyleFlags ) import Distribution.Client.Setup- ( GlobalFlags, ConfigFlags(..), ConfigExFlags, InstallFlags )-import qualified Distribution.Client.Setup as Client+ ( GlobalFlags, ConfigFlags(..) ) import Distribution.Simple.Setup- ( HaddockFlags(..), TestFlags, BenchmarkFlags(..), fromFlagOrDefault )+ ( HaddockFlags(..), fromFlagOrDefault ) import Distribution.Simple.Command ( CommandUI(..), usageAlternatives ) import Distribution.Verbosity- ( Verbosity, normal )+ ( normal ) import Distribution.Simple.Utils ( wrapText, die' ) -import Control.Monad (when)---haddockCommand :: CommandUI ( ConfigFlags, ConfigExFlags, InstallFlags- , HaddockFlags, TestFlags, BenchmarkFlags- )-haddockCommand = Client.installCommand {+haddockCommand :: CommandUI (NixStyleFlags ())+haddockCommand = CommandUI { commandName = "v2-haddock", commandSynopsis = "Build Haddock documentation", commandUsage = usageAlternatives "v2-haddock" [ "[FLAGS] TARGET" ],@@ -61,7 +60,9 @@ ++ " Build documentation for the package named pkgname\n\n" ++ cmdCommonHelpTextNewBuildBeta- }+ , commandOptions = nixStyleOptions (const [])+ , commandDefaultFlags = defaultNixStyleFlags ()+ } --TODO: [nice to have] support haddock on specific components, not just -- whole packages and the silly --executables etc modifiers. @@ -70,13 +71,8 @@ -- For more details on how this works, see the module -- "Distribution.Client.ProjectOrchestration" ---haddockAction :: ( ConfigFlags, ConfigExFlags, InstallFlags- , HaddockFlags, TestFlags, BenchmarkFlags )- -> [String] -> GlobalFlags -> IO ()-haddockAction ( configFlags, configExFlags, installFlags- , haddockFlags, testFlags, benchmarkFlags )- targetStrings globalFlags = do-+haddockAction :: NixStyleFlags () -> [String] -> GlobalFlags -> IO ()+haddockAction flags@NixStyleFlags {..} targetStrings globalFlags = do baseCtx <- establishProjectBaseContext verbosity cliConfig HaddockCommand targetSelectors <- either (reportTargetSelectorProblems verbosity) return@@ -91,11 +87,10 @@ -- When we interpret the targets on the command line, interpret them as -- haddock targets- targets <- either (reportTargetProblems verbosity) return+ targets <- either (reportBuildDocumentationTargetProblems verbosity) return $ resolveTargets (selectPackageTargets haddockFlags) selectComponentTarget- TargetProblemCommon elaboratedPlan Nothing targetSelectors@@ -112,11 +107,7 @@ runProjectPostBuildPhase verbosity baseCtx buildCtx buildOutcomes where verbosity = fromFlagOrDefault normal (configVerbosity configFlags)- cliConfig = commandLineFlagsToProjectConfig- globalFlags configFlags configExFlags- installFlags- mempty -- ClientInstallFlags, not needed here- haddockFlags testFlags benchmarkFlags+ cliConfig = commandLineFlagsToProjectConfig globalFlags flags mempty -- ClientInstallFlags, not needed here -- | This defines what a 'TargetSelector' means for the @haddock@ command. -- It selects the 'AvailableTarget's that the 'TargetSelector' refers to,@@ -127,7 +118,7 @@ -- We do similarly for test-suites, benchmarks and foreign libs. -- selectPackageTargets :: HaddockFlags -> TargetSelector- -> [AvailableTarget k] -> Either TargetProblem [k]+ -> [AvailableTarget k] -> Either TargetProblem' [k] selectPackageTargets haddockFlags targetSelector targets -- If there are any buildable targets then we select those@@ -177,35 +168,9 @@ -- etc. -- selectComponentTarget :: SubComponentTarget- -> AvailableTarget k -> Either TargetProblem k-selectComponentTarget subtarget =- either (Left . TargetProblemCommon) Right- . selectComponentTargetBasic subtarget----- | The various error conditions that can occur when matching a--- 'TargetSelector' against 'AvailableTarget's for the @haddock@ command.----data TargetProblem =- TargetProblemCommon TargetProblemCommon-- -- | The 'TargetSelector' matches targets but none are buildable- | TargetProblemNoneEnabled TargetSelector [AvailableTarget ()]-- -- | There are no targets at all- | TargetProblemNoTargets TargetSelector- deriving (Eq, Show)--reportTargetProblems :: Verbosity -> [TargetProblem] -> IO a-reportTargetProblems verbosity =- die' verbosity . unlines . map renderTargetProblem--renderTargetProblem :: TargetProblem -> String-renderTargetProblem (TargetProblemCommon problem) =- renderTargetProblemCommon "build documentation for" problem--renderTargetProblem (TargetProblemNoneEnabled targetSelector targets) =- renderTargetProblemNoneEnabled "build documentation for" targetSelector targets+ -> AvailableTarget k -> Either TargetProblem' k+selectComponentTarget = selectComponentTargetBasic -renderTargetProblem(TargetProblemNoTargets targetSelector) =- renderTargetProblemNoTargets "build documentation for" targetSelector+reportBuildDocumentationTargetProblems :: Verbosity -> [TargetProblem'] -> IO a+reportBuildDocumentationTargetProblems verbosity problems =+ reportTargetProblems verbosity "build documentation for" problems
cabal/cabal-install/Distribution/Client/CmdInstall.hs view
@@ -12,9 +12,10 @@ installAction, -- * Internals exposed for testing- TargetProblem(..), selectPackageTargets, selectComponentTarget,+ -- * Internals exposed for CmdRepl + CmdRun+ establishDummyDistDirLayout, establishDummyProjectBaseContext ) where @@ -26,15 +27,14 @@ import Distribution.Client.ProjectOrchestration import Distribution.Client.CmdErrorMessages import Distribution.Client.CmdSdist+import Distribution.Client.TargetProblem+ ( TargetProblem', TargetProblem (..) ) import Distribution.Client.CmdInstall.ClientInstallFlags+import Distribution.Client.CmdInstall.ClientInstallTargetSelector import Distribution.Client.Setup- ( GlobalFlags(..), ConfigFlags(..), ConfigExFlags, InstallFlags(..)- , configureExOptions, haddockOptions, installOptions, testOptions- , benchmarkOptions, configureOptions, liftOptions )-import Distribution.Solver.Types.ConstraintSource- ( ConstraintSource(..) )+ ( GlobalFlags(..), ConfigFlags(..) ) import Distribution.Client.Types ( PackageSpecifier(..), PackageLocation(..), UnresolvedSourcePackage , SourcePackageDb(..) )@@ -43,12 +43,19 @@ ( Package(..), PackageName, mkPackageName, unPackageName ) import Distribution.Types.PackageId ( PackageIdentifier(..) )+import Distribution.Client.ProjectConfig+ ( ProjectPackageLocation(..)+ , fetchAndReadSourcePackages+ )+import Distribution.Client.NixStyleOptions+ ( NixStyleFlags (..), nixStyleOptions, defaultNixStyleFlags )+import Distribution.Client.ProjectFlags (ProjectFlags (..)) import Distribution.Client.ProjectConfig.Types ( ProjectConfig(..), ProjectConfigShared(..) , ProjectConfigBuildOnly(..), PackageConfig(..) , getMapLast, getMapMappend, projectConfigLogsDir , projectConfigStoreDir, projectConfigBuildOnly- , projectConfigDistDir, projectConfigConfigFile )+ , projectConfigConfigFile ) import Distribution.Simple.Program.Db ( userSpecifyPaths, userSpecifyArgss, defaultProgramDb , modifyProgramSearchPath, ProgramDb )@@ -57,14 +64,14 @@ import Distribution.Simple.Program.Find ( ProgramSearchPathEntry(..) ) import Distribution.Client.Config- ( getCabalDir, loadConfig, SavedConfig(..) )+ ( defaultInstallPath, getCabalDir, loadConfig, SavedConfig(..) ) import qualified Distribution.Simple.PackageIndex as PI import Distribution.Solver.Types.PackageIndex ( lookupPackageName, searchByName ) import Distribution.Types.InstalledPackageInfo ( InstalledPackageInfo(..) ) import Distribution.Types.Version- ( nullVersion )+ ( Version, nullVersion ) import Distribution.Types.VersionRange ( thisVersion ) import Distribution.Solver.Types.PackageConstraint@@ -72,80 +79,71 @@ import Distribution.Client.IndexUtils ( getSourcePackages, getInstalledPackages ) import Distribution.Client.ProjectConfig- ( readGlobalConfig, projectConfigWithBuilderRepoContext+ ( projectConfigWithBuilderRepoContext , resolveBuildTimeSettings, withProjectOrGlobalConfig ) import Distribution.Client.ProjectPlanning ( storePackageInstallDirs' )+import Distribution.Client.ProjectPlanning.Types+ ( ElaboratedInstallPlan ) import qualified Distribution.Simple.InstallDirs as InstallDirs import Distribution.Client.DistDirLayout- ( defaultDistDirLayout, DistDirLayout(..), mkCabalDirLayout- , ProjectRoot(ProjectRootImplicit)+ ( DistDirLayout(..), mkCabalDirLayout , cabalStoreDirLayout , CabalDirLayout(..), StoreDirLayout(..) ) import Distribution.Client.RebuildMonad ( runRebuild ) import Distribution.Client.InstallSymlink- ( OverwritePolicy(..), symlinkBinary )+ ( symlinkBinary, trySymlink )+import Distribution.Client.Types.OverwritePolicy+ ( OverwritePolicy (..) )+import Distribution.Simple.Flag+ ( fromFlagOrDefault, flagToMaybe, flagElim ) import Distribution.Simple.Setup- ( Flag(..), HaddockFlags, TestFlags, BenchmarkFlags- , fromFlagOrDefault, flagToMaybe )+ ( Flag(..) ) import Distribution.Solver.Types.SourcePackage ( SourcePackage(..) ) import Distribution.Simple.Command- ( CommandUI(..), OptionField(..), usageAlternatives )+ ( CommandUI(..), usageAlternatives ) import Distribution.Simple.Configure ( configCompilerEx ) import Distribution.Simple.Compiler ( Compiler(..), CompilerId(..), CompilerFlavor(..) , PackageDBStack ) import Distribution.Simple.GHC- ( ghcPlatformAndVersionString+ ( ghcPlatformAndVersionString, getGhcAppDir , GhcImplInfo(..), getImplInfo , GhcEnvironmentFileEntry(..) , renderGhcEnvironmentFile, readGhcEnvironmentFile, ParseErrorExc ) import Distribution.System- ( Platform )+ ( Platform , buildOS, OS (Windows) ) import Distribution.Types.UnitId ( UnitId ) import Distribution.Types.UnqualComponentName ( UnqualComponentName, unUnqualComponentName ) import Distribution.Verbosity- ( Verbosity, normal, lessVerbose )+ ( normal, lessVerbose ) import Distribution.Simple.Utils ( wrapText, die', notice, warn , withTempDirectory, createDirectoryIfMissingVerbose , ordNub ) import Distribution.Utils.Generic ( safeHead, writeFileAtomic )-import Distribution.Deprecated.Text- ( simpleParse )-import Distribution.Pretty- ( prettyShow ) -import Control.Exception- ( catch )-import Control.Monad- ( mapM, mapM_ ) import qualified Data.ByteString.Lazy.Char8 as BS-import Data.Either- ( partitionEithers ) import Data.Ord- ( comparing, Down(..) )+ ( Down(..) ) import qualified Data.Map as Map import Distribution.Utils.NubList ( fromNubList )+import Network.URI (URI) import System.Directory- ( getHomeDirectory, doesFileExist, createDirectoryIfMissing+ ( doesFileExist, createDirectoryIfMissing , getTemporaryDirectory, makeAbsolute, doesDirectoryExist , removeFile, removeDirectory, copyFile ) import System.FilePath ( (</>), (<.>), takeDirectory, takeBaseName ) --installCommand :: CommandUI ( ConfigFlags, ConfigExFlags, InstallFlags- , HaddockFlags, TestFlags, BenchmarkFlags- , ClientInstallFlags- )+installCommand :: CommandUI (NixStyleFlags ClientInstallFlags) installCommand = CommandUI { commandName = "v2-install" , commandSynopsis = "Install packages."@@ -172,45 +170,10 @@ ++ " Install the package in the ./pkgfoo directory\n" ++ cmdCommonHelpTextNewBuildBeta- , commandOptions = \showOrParseArgs ->- liftOptions get1 set1- -- Note: [Hidden Flags]- -- hide "constraint", "dependency", and- -- "exact-configuration" from the configure options.- (filter ((`notElem` ["constraint", "dependency"- , "exact-configuration"])- . optionName) $ configureOptions showOrParseArgs)- ++ liftOptions get2 set2 (configureExOptions showOrParseArgs- ConstraintSourceCommandlineFlag)- ++ liftOptions get3 set3- -- hide "target-package-db" and "symlink-bindir" flags from the- -- install options.- -- "symlink-bindir" is obsoleted by "installdir" in ClientInstallFlags- (filter ((`notElem` ["target-package-db", "symlink-bindir"])- . optionName) $- installOptions showOrParseArgs)- ++ liftOptions get4 set4- -- hide "verbose" and "builddir" flags from the- -- haddock options.- (filter ((`notElem` ["v", "verbose", "builddir"])- . optionName) $- haddockOptions showOrParseArgs)- ++ liftOptions get5 set5 (testOptions showOrParseArgs)- ++ liftOptions get6 set6 (benchmarkOptions showOrParseArgs)- ++ liftOptions get7 set7 (clientInstallOptions showOrParseArgs)- , commandDefaultFlags = ( mempty, mempty, mempty, mempty, mempty, mempty- , defaultClientInstallFlags )+ , commandOptions = nixStyleOptions clientInstallOptions+ , commandDefaultFlags = defaultNixStyleFlags defaultClientInstallFlags }- where- get1 (a,_,_,_,_,_,_) = a; set1 a (_,b,c,d,e,f,g) = (a,b,c,d,e,f,g)- get2 (_,b,_,_,_,_,_) = b; set2 b (a,_,c,d,e,f,g) = (a,b,c,d,e,f,g)- get3 (_,_,c,_,_,_,_) = c; set3 c (a,b,_,d,e,f,g) = (a,b,c,d,e,f,g)- get4 (_,_,_,d,_,_,_) = d; set4 d (a,b,c,_,e,f,g) = (a,b,c,d,e,f,g)- get5 (_,_,_,_,e,_,_) = e; set5 e (a,b,c,d,_,f,g) = (a,b,c,d,e,f,g)- get6 (_,_,_,_,_,f,_) = f; set6 f (a,b,c,d,e,_,g) = (a,b,c,d,e,f,g)- get7 (_,_,_,_,_,_,g) = g; set7 g (a,b,c,d,e,f,_) = (a,b,c,d,e,f,g) - -- | The @install@ command actually serves four different needs. It installs: -- * exes: -- For example a program from hackage. The behavior is similar to the old@@ -228,54 +191,37 @@ -- For more details on how this works, see the module -- "Distribution.Client.ProjectOrchestration" ---installAction- :: ( ConfigFlags, ConfigExFlags, InstallFlags- , HaddockFlags, TestFlags, BenchmarkFlags- , ClientInstallFlags)- -> [String] -> GlobalFlags- -> IO ()-installAction ( configFlags, configExFlags, installFlags- , haddockFlags, testFlags, benchmarkFlags- , clientInstallFlags' )- targetStrings globalFlags = do- -- We never try to build tests/benchmarks for remote packages.- -- So we set them as disabled by default and error if they are explicitly- -- enabled.- when (configTests configFlags' == Flag True) $- die' verbosity $ "--enable-tests was specified, but tests can't "- ++ "be enabled in a remote package"- when (configBenchmarks configFlags' == Flag True) $- die' verbosity $ "--enable-benchmarks was specified, but benchmarks can't "- ++ "be enabled in a remote package"+installAction :: NixStyleFlags ClientInstallFlags -> [String] -> GlobalFlags -> IO ()+installAction flags@NixStyleFlags { extraFlags = clientInstallFlags', .. } targetStrings globalFlags = do+ -- Ensure there were no invalid configuration options specified.+ verifyPreconditionsOrDie verbosity configFlags' -- We cannot use establishDummyProjectBaseContext to get these flags, since -- it requires one of them as an argument. Normal establishProjectBaseContext -- does not, and this is why this is done only for the install command- clientInstallFlags <- do- let configFileFlag = globalConfigFile globalFlags- savedConfig <- loadConfig verbosity configFileFlag- pure $ savedClientInstallFlags savedConfig `mappend` clientInstallFlags'+ clientInstallFlags <- getClientInstallFlags verbosity globalFlags clientInstallFlags' let installLibs = fromFlagOrDefault False (cinstInstallLibs clientInstallFlags) targetFilter = if installLibs then Just LibKind else Just ExeKind targetStrings' = if null targetStrings then ["."] else targetStrings + withProject :: IO ([PackageSpecifier UnresolvedSourcePackage], [URI], [TargetSelector], ProjectConfig) withProject = do- let verbosity' = lessVerbose verbosity+ let reducedVerbosity = lessVerbose verbosity -- First, we need to learn about what's available to be installed.- localBaseCtx <- establishProjectBaseContext verbosity'- cliConfig InstallCommand+ localBaseCtx <-+ establishProjectBaseContext reducedVerbosity cliConfig InstallCommand let localDistDirLayout = distDirLayout localBaseCtx- pkgDb <- projectConfigWithBuilderRepoContext verbosity'+ pkgDb <- projectConfigWithBuilderRepoContext reducedVerbosity (buildSettings localBaseCtx) (getSourcePackages verbosity) let (targetStrings'', packageIds) = partitionEithers . flip fmap targetStrings' $- \str -> case simpleParse str of+ \str -> case simpleParsec str of Just (pkgId :: PackageId) | pkgVersion pkgId /= nullVersion -> Right pkgId _ -> Left str@@ -290,7 +236,7 @@ flip TargetPackageNamed targetFilter . pkgName <$> packageIds if null targetStrings'- then return (packageSpecifiers, packageTargets, projectConfig localBaseCtx)+ then return (packageSpecifiers, [], packageTargets, projectConfig localBaseCtx) else do targetSelectors <- either (reportTargetSelectorProblems verbosity) return@@ -298,113 +244,17 @@ Nothing targetStrings'' (specs, selectors) <-- withInstallPlan verbosity' localBaseCtx $ \elaboratedPlan _ -> do- -- Split into known targets and hackage packages.- (targets, hackageNames) <- case- resolveTargets- selectPackageTargets- selectComponentTarget- TargetProblemCommon- elaboratedPlan- (Just pkgDb)- targetSelectors of- Right targets ->- -- Everything is a local dependency.- return (targets, [])- Left errs -> do- -- Not everything is local.- let- (errs', hackageNames) = partitionEithers . flip fmap errs $ \case- TargetProblemCommon (TargetAvailableInIndex name) -> Right name- err -> Left err-- -- report incorrect case for known package.- for_ errs' $ \case- TargetProblemCommon (TargetNotInProject hn) ->- case searchByName (packageIndex pkgDb) (unPackageName hn) of- [] -> return ()- xs -> die' verbosity . concat $- [ "Unknown package \"", unPackageName hn, "\". "- , "Did you mean any of the following?\n"- , unlines (("- " ++) . unPackageName . fst <$> xs)- ]- _ -> return ()-- when (not . null $ errs') $ reportTargetProblems verbosity errs'-- let- targetSelectors' = flip filter targetSelectors $ \case- TargetComponentUnknown name _ _- | name `elem` hackageNames -> False- TargetPackageNamed name _- | name `elem` hackageNames -> False- _ -> True-- -- This can't fail, because all of the errors are- -- removed (or we've given up).- targets <-- either (reportTargetProblems verbosity) return $- resolveTargets- selectPackageTargets- selectComponentTarget- TargetProblemCommon- elaboratedPlan- Nothing- targetSelectors'-- return (targets, hackageNames)-- let- planMap = InstallPlan.toMap elaboratedPlan- targetIds = Map.keys targets-- sdistize (SpecificSourcePackage spkg@SourcePackage{..}) =- SpecificSourcePackage spkg'- where- sdistPath = distSdistFile localDistDirLayout packageInfoId- spkg' = spkg { packageSource = LocalTarballPackage sdistPath }- sdistize named = named-- local = sdistize <$> localPackages localBaseCtx-- gatherTargets :: UnitId -> TargetSelector- gatherTargets targetId = TargetPackageNamed pkgName targetFilter- where- Just targetUnit = Map.lookup targetId planMap- PackageIdentifier{..} = packageId targetUnit-- targets' = fmap gatherTargets targetIds-- hackagePkgs :: [PackageSpecifier UnresolvedSourcePackage]- hackagePkgs = flip NamedPackage [] <$> hackageNames-- hackageTargets :: [TargetSelector]- hackageTargets =- flip TargetPackageNamed targetFilter <$> hackageNames-- createDirectoryIfMissing True (distSdistDirectory localDistDirLayout)-- unless (Map.null targets) $- mapM_- (\(SpecificSourcePackage pkg) -> packageToSdist verbosity- (distProjectRootDirectory localDistDirLayout) TarGzArchive- (distSdistFile localDistDirLayout (packageId pkg)) pkg- ) (localPackages localBaseCtx)-- if null targets- then return (hackagePkgs, hackageTargets)- else return (local ++ hackagePkgs, targets' ++ hackageTargets)+ getSpecsAndTargetSelectors+ verbosity reducedVerbosity pkgDb targetSelectors localDistDirLayout localBaseCtx targetFilter return ( specs ++ packageSpecifiers+ , [] , selectors ++ packageTargets , projectConfig localBaseCtx ) + withoutProject :: ProjectConfig -> IO ([PackageSpecifier pkg], [URI], [TargetSelector], ProjectConfig) withoutProject globalConfig = do- let- parsePkg pkgName- | Just (pkg :: PackageId) <- simpleParse pkgName = return pkg- | otherwise = die' verbosity ("Invalid package ID: " ++ pkgName)- packageIds <- mapM parsePkg targetStrings'+ tss <- traverse (parseWithoutProjectTargetSelector verbosity) targetStrings' cabalDir <- getCabalDir let@@ -430,32 +280,27 @@ verbosity buildSettings (getSourcePackages verbosity) - for_ targetStrings' $ \case- name- | null (lookupPackageName packageIndex (mkPackageName name))- , xs@(_:_) <- searchByName packageIndex name ->- die' verbosity . concat $- [ "Unknown package \"", name, "\". "- , "Did you mean any of the following?\n"- , unlines (("- " ++) . unPackageName . fst <$> xs)- ]- _ -> return ()+ for_ (concatMap woPackageNames tss) $ \name -> do+ when (null (lookupPackageName packageIndex name)) $ do+ let xs = searchByName packageIndex (unPackageName name)+ let emptyIf True _ = []+ emptyIf False zs = zs+ die' verbosity $ concat $+ [ "Unknown package \"", unPackageName name, "\". "+ ] ++ emptyIf (null xs)+ [ "Did you mean any of the following?\n"+ , unlines (("- " ++) . unPackageName . fst <$> xs)+ ] let- packageSpecifiers = flip fmap packageIds $ \case- PackageIdentifier{..}- | pkgVersion == nullVersion -> NamedPackage pkgName []- | otherwise -> NamedPackage pkgName- [PackagePropertyVersion- (thisVersion pkgVersion)]- packageTargets = flip TargetPackageNamed Nothing . pkgName <$> packageIds- return (packageSpecifiers, packageTargets, projectConfig)+ (uris, packageSpecifiers) = partitionEithers $ map woPackageSpecifiers tss+ packageTargets = map woPackageTargets tss - (specs, selectors, config) <-- withProjectOrGlobalConfig verbosity globalConfigFlag- withProject withoutProject+ return (packageSpecifiers, uris, packageTargets, projectConfig) - home <- getHomeDirectory+ (specs, uris, targetSelectors, config) <-+ withProjectOrGlobalConfig verbosity ignoreProject globalConfigFlag withProject withoutProject+ let ProjectConfig { projectConfigBuildOnly = ProjectConfigBuildOnly {@@ -493,98 +338,41 @@ configCompilerEx hcFlavor hcPath hcPkg preProgDb verbosity let- globalEnv name =- home </> ".ghc" </> ghcPlatformAndVersionString platform compilerVersion- </> "environments" </> name- localEnv dir =- dir </>- ".ghc.environment." <> ghcPlatformAndVersionString platform compilerVersion- GhcImplInfo{ supportsPkgEnvFiles } = getImplInfo compiler- -- Why? We know what the first part will be, we only care about the packages.- filterEnvEntries = filter $ \case- GhcEnvFilePackageId _ -> True- _ -> False - envFile <- case flagToMaybe (cinstEnvironmentPath clientInstallFlags) of- Just spec- -- Is spec a bare word without any "pathy" content, then it refers to- -- a named global environment.- | takeBaseName spec == spec -> return (globalEnv spec)- | otherwise -> do- spec' <- makeAbsolute spec- isDir <- doesDirectoryExist spec'- if isDir- -- If spec is a directory, then make an ambient environment inside- -- that directory.- then return (localEnv spec')- -- Otherwise, treat it like a literal file path.- else return spec'- Nothing -> return (globalEnv "default")-- envFileExists <- doesFileExist envFile- envEntries <- filterEnvEntries <$> if- (compilerFlavor == GHC || compilerFlavor == GHCJS)- && supportsPkgEnvFiles && envFileExists- then catch (readGhcEnvironmentFile envFile) $ \(_ :: ParseErrorExc) ->- warn verbosity ("The environment file " ++ envFile ++- " is unparsable. Libraries cannot be installed.") >> return []- else return []-- cabalDir <- getCabalDir- mstoreDir <-- sequenceA $ makeAbsolute <$> flagToMaybe projectConfigStoreDir- let- mlogsDir = flagToMaybe projectConfigLogsDir- cabalLayout = mkCabalDirLayout cabalDir mstoreDir mlogsDir- packageDbs = storePackageDBStack (cabalStoreDirLayout cabalLayout) compilerId-+ envFile <- getEnvFile clientInstallFlags platform compilerVersion+ existingEnvEntries <-+ getExistingEnvEntries verbosity compilerFlavor supportsPkgEnvFiles envFile+ packageDbs <- getPackageDbStack compilerId projectConfigStoreDir projectConfigLogsDir installedIndex <- getInstalledPackages verbosity compiler packageDbs progDb - let (envSpecs, envEntries') =- environmentFileToSpecifiers installedIndex envEntries+ let+ (envSpecs, nonGlobalEnvEntries) =+ getEnvSpecsAndNonGlobalEntries installedIndex existingEnvEntries installLibs -- Second, we need to use a fake project to let Cabal build the -- installables correctly. For that, we need a place to put a -- temporary dist directory. globalTmp <- getTemporaryDirectory- withTempDirectory- verbosity- globalTmp- "cabal-install."- $ \tmpDir -> do++ withTempDirectory verbosity globalTmp "cabal-install." $ \tmpDir -> do+ distDirLayout <- establishDummyDistDirLayout verbosity config tmpDir++ uriSpecs <- runRebuild tmpDir $ fetchAndReadSourcePackages+ verbosity+ distDirLayout+ (projectConfigShared config)+ (projectConfigBuildOnly config)+ [ ProjectPackageRemoteTarball uri | uri <- uris ]+ baseCtx <- establishDummyProjectBaseContext verbosity config- tmpDir- (envSpecs ++ specs)+ distDirLayout+ (envSpecs ++ specs ++ uriSpecs) InstallCommand - buildCtx <-- runProjectPreBuildPhase verbosity baseCtx $ \elaboratedPlan -> do-- -- Interpret the targets on the command line as build targets- targets <- either (reportTargetProblems verbosity) return- $ resolveTargets- selectPackageTargets- selectComponentTarget- TargetProblemCommon- elaboratedPlan- Nothing- selectors-- let elaboratedPlan' = pruneInstallPlanToTargets- TargetActionBuild- targets- elaboratedPlan- elaboratedPlan'' <-- if buildSettingOnlyDeps (buildSettings baseCtx)- then either (reportCannotPruneDependencies verbosity) return $- pruneInstallPlanToDependencies (Map.keysSet targets)- elaboratedPlan'- else return elaboratedPlan'-- return (elaboratedPlan'', targets)+ buildCtx <- constructProjectBuildContext verbosity baseCtx targetSelectors printPlan verbosity baseCtx buildCtx @@ -600,18 +388,188 @@ when (not dryRun) $ if installLibs then installLibraries verbosity- buildCtx compiler packageDbs progDb envFile envEntries'+ buildCtx compiler packageDbs progDb envFile nonGlobalEnvEntries else installExes verbosity baseCtx buildCtx platform compiler configFlags clientInstallFlags where configFlags' = disableTestsBenchsByDefault configFlags verbosity = fromFlagOrDefault normal (configVerbosity configFlags')+ ignoreProject = flagIgnoreProject projectFlags cliConfig = commandLineFlagsToProjectConfig- globalFlags configFlags' configExFlags- installFlags clientInstallFlags'- haddockFlags testFlags benchmarkFlags+ globalFlags+ flags { configFlags = configFlags' }+ clientInstallFlags' globalConfigFlag = projectConfigConfigFile (projectConfigShared cliConfig) +-- | Verify that invalid config options were not passed to the install command.+--+-- If an invalid configuration is found the command will @die'@.+verifyPreconditionsOrDie :: Verbosity -> ConfigFlags -> IO ()+verifyPreconditionsOrDie verbosity configFlags = do+ -- We never try to build tests/benchmarks for remote packages.+ -- So we set them as disabled by default and error if they are explicitly+ -- enabled.+ when (configTests configFlags == Flag True) $+ die' verbosity $ "--enable-tests was specified, but tests can't "+ ++ "be enabled in a remote package"+ when (configBenchmarks configFlags == Flag True) $+ die' verbosity $ "--enable-benchmarks was specified, but benchmarks can't "+ ++ "be enabled in a remote package"++getClientInstallFlags :: Verbosity -> GlobalFlags -> ClientInstallFlags -> IO ClientInstallFlags+getClientInstallFlags verbosity globalFlags existingClientInstallFlags = do+ let configFileFlag = globalConfigFile globalFlags+ savedConfig <- loadConfig verbosity configFileFlag+ pure $ savedClientInstallFlags savedConfig `mappend` existingClientInstallFlags+++getSpecsAndTargetSelectors+ :: Verbosity+ -> Verbosity+ -> SourcePackageDb+ -> [TargetSelector]+ -> DistDirLayout+ -> ProjectBaseContext+ -> Maybe ComponentKindFilter+ -> IO ([PackageSpecifier UnresolvedSourcePackage], [TargetSelector])+getSpecsAndTargetSelectors verbosity reducedVerbosity pkgDb targetSelectors localDistDirLayout localBaseCtx targetFilter =+ withInstallPlan reducedVerbosity localBaseCtx $ \elaboratedPlan _ -> do+ -- Split into known targets and hackage packages.+ (targets, hackageNames) <-+ partitionToKnownTargetsAndHackagePackages+ verbosity pkgDb elaboratedPlan targetSelectors++ let+ planMap = InstallPlan.toMap elaboratedPlan+ targetIds = Map.keys targets++ sdistize (SpecificSourcePackage spkg) =+ SpecificSourcePackage spkg'+ where+ sdistPath = distSdistFile localDistDirLayout (packageId spkg)+ spkg' = spkg { srcpkgSource = LocalTarballPackage sdistPath }+ sdistize named = named++ local = sdistize <$> localPackages localBaseCtx++ gatherTargets :: UnitId -> TargetSelector+ gatherTargets targetId = TargetPackageNamed pkgName targetFilter+ where+ targetUnit = Map.findWithDefault (error "cannot find target unit") targetId planMap+ PackageIdentifier{..} = packageId targetUnit++ targets' = fmap gatherTargets targetIds++ hackagePkgs :: [PackageSpecifier UnresolvedSourcePackage]+ hackagePkgs = flip NamedPackage [] <$> hackageNames++ hackageTargets :: [TargetSelector]+ hackageTargets =+ flip TargetPackageNamed targetFilter <$> hackageNames++ createDirectoryIfMissing True (distSdistDirectory localDistDirLayout)++ unless (Map.null targets) $ for_ (localPackages localBaseCtx) $ \lpkg -> case lpkg of+ SpecificSourcePackage pkg -> packageToSdist verbosity+ (distProjectRootDirectory localDistDirLayout) TarGzArchive+ (distSdistFile localDistDirLayout (packageId pkg)) pkg+ NamedPackage pkgName _ -> error $ "Got NamedPackage " ++ prettyShow pkgName++ if null targets+ then return (hackagePkgs, hackageTargets)+ else return (local ++ hackagePkgs, targets' ++ hackageTargets)++-- | Partitions the target selectors into known local targets and hackage packages.+partitionToKnownTargetsAndHackagePackages+ :: Verbosity+ -> SourcePackageDb+ -> ElaboratedInstallPlan+ -> [TargetSelector]+ -> IO (Map UnitId [(ComponentTarget,[TargetSelector])], [PackageName])+partitionToKnownTargetsAndHackagePackages verbosity pkgDb elaboratedPlan targetSelectors = do+ let mTargets = resolveTargets+ selectPackageTargets+ selectComponentTarget+ elaboratedPlan+ (Just pkgDb)+ targetSelectors+ case mTargets of+ Right targets ->+ -- Everything is a local dependency.+ return (targets, [])+ Left errs -> do+ -- Not everything is local.+ let+ (errs', hackageNames) = partitionEithers . flip fmap errs $ \case+ TargetAvailableInIndex name -> Right name+ err -> Left err++ -- report incorrect case for known package.+ for_ errs' $ \case+ TargetNotInProject hn ->+ case searchByName (packageIndex pkgDb) (unPackageName hn) of+ [] -> return ()+ xs -> die' verbosity . concat $+ [ "Unknown package \"", unPackageName hn, "\". "+ , "Did you mean any of the following?\n"+ , unlines (("- " ++) . unPackageName . fst <$> xs)+ ]+ _ -> return ()++ when (not . null $ errs') $ reportBuildTargetProblems verbosity errs'++ let+ targetSelectors' = flip filter targetSelectors $ \case+ TargetComponentUnknown name _ _+ | name `elem` hackageNames -> False+ TargetPackageNamed name _+ | name `elem` hackageNames -> False+ _ -> True++ -- This can't fail, because all of the errors are+ -- removed (or we've given up).+ targets <-+ either (reportBuildTargetProblems verbosity) return $+ resolveTargets+ selectPackageTargets+ selectComponentTarget+ elaboratedPlan+ Nothing+ targetSelectors'++ return (targets, hackageNames)++++constructProjectBuildContext+ :: Verbosity+ -> ProjectBaseContext+ -- ^ The synthetic base context to use to produce the full build context.+ -> [TargetSelector]+ -> IO ProjectBuildContext+constructProjectBuildContext verbosity baseCtx targetSelectors = do+ runProjectPreBuildPhase verbosity baseCtx $ \elaboratedPlan -> do+ -- Interpret the targets on the command line as build targets+ targets <- either (reportBuildTargetProblems verbosity) return $+ resolveTargets+ selectPackageTargets+ selectComponentTarget+ elaboratedPlan+ Nothing+ targetSelectors++ let prunedToTargetsElaboratedPlan =+ pruneInstallPlanToTargets TargetActionBuild targets elaboratedPlan+ prunedElaboratedPlan <-+ if buildSettingOnlyDeps (buildSettings baseCtx)+ then either (reportCannotPruneDependencies verbosity) return $+ pruneInstallPlanToDependencies (Map.keysSet targets)+ prunedToTargetsElaboratedPlan+ else return prunedToTargetsElaboratedPlan++ return (prunedElaboratedPlan, targets)++ -- | Install any built exe by symlinking/copying it -- we don't use BuildOutcomes because we also need the component names installExes@@ -625,6 +583,7 @@ -> IO () installExes verbosity baseCtx buildCtx platform compiler configFlags clientInstallFlags = do+ installPath <- defaultInstallPath let storeDirLayout = cabalStoreDirLayout $ cabalDirLayout baseCtx prefix = fromFlagOrDefault "" (fmap InstallDirs.fromPathTemplate (configProgPrefix configFlags))@@ -642,12 +601,17 @@ mkFinalExeName exe = prefix <> unUnqualComponentName exe <> suffix <.> exeExtension platform installdirUnknown = "installdir is not defined. Set it in your cabal config file "- ++ "or use --installdir=<path>"+ ++ "or use --installdir=<path>. Using default installdir: " ++ show installPath - installdir <- fromFlagOrDefault (die' verbosity installdirUnknown) $+ installdir <- fromFlagOrDefault+ (warn verbosity installdirUnknown >> pure installPath) $ pure <$> cinstInstalldir clientInstallFlags createDirectoryIfMissingVerbose verbosity False installdir warnIfNoExes verbosity buildCtx++ installMethod <- flagElim defaultMethod return $+ cinstInstallMethod clientInstallFlags+ let doInstall = installUnitExes verbosity@@ -658,9 +622,19 @@ where overwritePolicy = fromFlagOrDefault NeverOverwrite $ cinstOverwritePolicy clientInstallFlags- installMethod = fromFlagOrDefault InstallMethodSymlink $- cinstInstallMethod clientInstallFlags+ isWindows = buildOS == Windows + -- This is in IO as we will make environment checks,+ -- to decide which method is best+ defaultMethod :: IO InstallMethod+ defaultMethod+ -- Try symlinking in temporary directory, if it works default to+ -- symlinking even on windows+ | isWindows = do+ symlinks <- trySymlink verbosity+ return $ if symlinks then InstallMethodSymlink else InstallMethodCopy+ | otherwise = return InstallMethodSymlink+ -- | Install any built library by adding it to the default ghc environment installLibraries :: Verbosity@@ -704,10 +678,14 @@ warnIfNoExes verbosity buildCtx = when noExes $ warn verbosity $- "You asked to install executables, but there are no executables in "- <> plural (listPlural selectors) "target" "targets" <> ": "- <> intercalate ", " (showTargetSelector <$> selectors) <> ". "- <> "Perhaps you want to use --lib to install libraries instead."+ "\n" <>+ "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" <>+ "@ WARNING: Installation might not be completed as desired! @\n" <>+ "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" <>+ "Without flags, the command \"cabal install\" doesn't expose" <>+ " libraries in a usable manner. You might have wanted to run" <>+ " \"cabal install --lib " <>+ unwords (showTargetSelector <$> selectors) <> "\". " where targets = concat $ Map.elems $ targetsMap buildCtx components = fst <$> targets@@ -726,6 +704,19 @@ , "bin-package-db" ] +-- | Return the package specifiers and non-global environment file entries.+getEnvSpecsAndNonGlobalEntries+ :: PI.InstalledPackageIndex+ -> [GhcEnvironmentFileEntry]+ -> Bool+ -> ([PackageSpecifier a], [GhcEnvironmentFileEntry])+getEnvSpecsAndNonGlobalEntries installedIndex entries installLibs =+ if installLibs+ then (envSpecs, envEntries')+ else ([], envEntries')+ where+ (envSpecs, envEntries') = environmentFileToSpecifiers installedIndex entries+ environmentFileToSpecifiers :: PI.InstalledPackageIndex -> [GhcEnvironmentFileEntry] -> ([PackageSpecifier a], [GhcEnvironmentFileEntry])@@ -804,24 +795,26 @@ installBuiltExe verbosity overwritePolicy sourceDir exeName finalExeName installdir InstallMethodSymlink = do- notice verbosity $ "Symlinking '" <> exeName <> "'"+ notice verbosity $ "Symlinking '" <> exeName <> "' to '" <> destination <> "'" symlinkBinary overwritePolicy installdir sourceDir finalExeName exeName+ where+ destination = installdir </> finalExeName installBuiltExe verbosity overwritePolicy sourceDir exeName finalExeName installdir InstallMethodCopy = do- notice verbosity $ "Copying '" <> exeName <> "'"+ notice verbosity $ "Copying '" <> exeName <> "' to '" <> destination <> "'" exists <- doesPathExist destination case (exists, overwritePolicy) of (True , NeverOverwrite ) -> pure False (True , AlwaysOverwrite) -> remove >> copy (False, _ ) -> copy where- source = sourceDir </> exeName+ source = sourceDir </> exeName destination = installdir </> finalExeName remove = do isDir <- doesDirectoryExist destination@@ -845,63 +838,73 @@ | any hasLib targets = [GhcEnvFilePackageId unitId] | otherwise = [] --- | Create a dummy project context, without a .cabal or a .cabal.project file--- (a place where to put a temporary dist directory is still needed)-establishDummyProjectBaseContext- :: Verbosity- -> ProjectConfig- -> FilePath- -- ^ Where to put the dist directory- -> [PackageSpecifier UnresolvedSourcePackage]- -- ^ The packages to be included in the project- -> CurrentCommand- -> IO ProjectBaseContext-establishDummyProjectBaseContext verbosity cliConfig tmpDir- localPackages currentCommand = do- cabalDir <- getCabalDir - -- Create the dist directories- createDirectoryIfMissingVerbose verbosity True $ distDirectory distDirLayout- createDirectoryIfMissingVerbose verbosity True $- distProjectCacheDirectory distDirLayout-- globalConfig <- runRebuild ""- $ readGlobalConfig verbosity- $ projectConfigConfigFile- $ projectConfigShared cliConfig- let projectConfig = globalConfig <> cliConfig-- let ProjectConfigBuildOnly {- projectConfigLogsDir- } = projectConfigBuildOnly projectConfig+-- | Gets the file path to the request environment file.+getEnvFile :: ClientInstallFlags -> Platform -> Version -> IO FilePath+getEnvFile clientInstallFlags platform compilerVersion = do+ appDir <- getGhcAppDir+ case flagToMaybe (cinstEnvironmentPath clientInstallFlags) of+ Just spec+ -- Is spec a bare word without any "pathy" content, then it refers to+ -- a named global environment.+ | takeBaseName spec == spec ->+ return (getGlobalEnv appDir platform compilerVersion spec)+ | otherwise -> do+ spec' <- makeAbsolute spec+ isDir <- doesDirectoryExist spec'+ if isDir+ -- If spec is a directory, then make an ambient environment inside+ -- that directory.+ then return (getLocalEnv spec' platform compilerVersion)+ -- Otherwise, treat it like a literal file path.+ else return spec'+ Nothing ->+ return (getGlobalEnv appDir platform compilerVersion "default") - ProjectConfigShared {- projectConfigStoreDir- } = projectConfigShared projectConfig+-- | Returns the list of @GhcEnvFilePackageIj@ values already existing in the+-- environment being operated on.+getExistingEnvEntries :: Verbosity -> CompilerFlavor -> Bool -> FilePath -> IO [GhcEnvironmentFileEntry]+getExistingEnvEntries verbosity compilerFlavor supportsPkgEnvFiles envFile = do+ envFileExists <- doesFileExist envFile+ filterEnvEntries <$> if+ (compilerFlavor == GHC || compilerFlavor == GHCJS)+ && supportsPkgEnvFiles && envFileExists+ then catch (readGhcEnvironmentFile envFile) $ \(_ :: ParseErrorExc) ->+ warn verbosity ("The environment file " ++ envFile +++ " is unparsable. Libraries cannot be installed.") >> return []+ else return []+ where+ -- Why? We know what the first part will be, we only care about the packages.+ filterEnvEntries = filter $ \case+ GhcEnvFilePackageId _ -> True+ _ -> False - mlogsDir = flagToMaybe projectConfigLogsDir- mstoreDir = flagToMaybe projectConfigStoreDir- cabalDirLayout = mkCabalDirLayout cabalDir mstoreDir mlogsDir+-- | Constructs the path to the global GHC environment file.+--+-- TODO(m-renaud): Create PkgEnvName newtype wrapper.+getGlobalEnv :: FilePath -> Platform -> Version -> String -> FilePath+getGlobalEnv appDir platform compilerVersion name =+ appDir </> ghcPlatformAndVersionString platform compilerVersion+ </> "environments" </> name - buildSettings = resolveBuildTimeSettings- verbosity cabalDirLayout- projectConfig+-- | Constructs the path to a local GHC environment file.+getLocalEnv :: FilePath -> Platform -> Version -> FilePath+getLocalEnv dir platform compilerVersion =+ dir </>+ ".ghc.environment." <> ghcPlatformAndVersionString platform compilerVersion - return ProjectBaseContext {- distDirLayout,- cabalDirLayout,- projectConfig,- localPackages,- buildSettings,- currentCommand- }- where- mdistDirectory = flagToMaybe- $ projectConfigDistDir- $ projectConfigShared cliConfig- projectRoot = ProjectRootImplicit tmpDir- distDirLayout = defaultDistDirLayout projectRoot- mdistDirectory+getPackageDbStack+ :: CompilerId+ -> Flag FilePath+ -> Flag FilePath+ -> IO PackageDBStack+getPackageDbStack compilerId storeDirFlag logsDirFlag = do+ cabalDir <- getCabalDir+ mstoreDir <- traverse makeAbsolute $ flagToMaybe storeDirFlag+ let+ mlogsDir = flagToMaybe logsDirFlag+ cabalLayout = mkCabalDirLayout cabalDir mstoreDir mlogsDir+ pure $ storePackageDBStack (cabalStoreDirLayout cabalLayout) compilerId -- | This defines what a 'TargetSelector' means for the @bench@ command. -- It selects the 'AvailableTarget's that the 'TargetSelector' refers to,@@ -913,7 +916,7 @@ -- selectPackageTargets :: TargetSelector- -> [AvailableTarget k] -> Either TargetProblem [k]+ -> [AvailableTarget k] -> Either TargetProblem' [k] selectPackageTargets targetSelector targets -- If there are any buildable targets then we select those@@ -947,36 +950,11 @@ -- selectComponentTarget :: SubComponentTarget- -> AvailableTarget k -> Either TargetProblem k-selectComponentTarget subtarget =- either (Left . TargetProblemCommon) Right- . selectComponentTargetBasic subtarget----- | The various error conditions that can occur when matching a--- 'TargetSelector' against 'AvailableTarget's for the @build@ command.----data TargetProblem =- TargetProblemCommon TargetProblemCommon-- -- | The 'TargetSelector' matches targets but none are buildable- | TargetProblemNoneEnabled TargetSelector [AvailableTarget ()]-- -- | There are no targets at all- | TargetProblemNoTargets TargetSelector- deriving (Eq, Show)--reportTargetProblems :: Verbosity -> [TargetProblem] -> IO a-reportTargetProblems verbosity =- die' verbosity . unlines . map renderTargetProblem+ -> AvailableTarget k -> Either TargetProblem' k+selectComponentTarget = selectComponentTargetBasic -renderTargetProblem :: TargetProblem -> String-renderTargetProblem (TargetProblemCommon problem) =- renderTargetProblemCommon "build" problem-renderTargetProblem (TargetProblemNoneEnabled targetSelector targets) =- renderTargetProblemNoneEnabled "build" targetSelector targets-renderTargetProblem(TargetProblemNoTargets targetSelector) =- renderTargetProblemNoTargets "build" targetSelector+reportBuildTargetProblems :: Verbosity -> [TargetProblem'] -> IO a+reportBuildTargetProblems verbosity problems = reportTargetProblems verbosity "build" problems reportCannotPruneDependencies :: Verbosity -> CannotPruneDependencies -> IO a reportCannotPruneDependencies verbosity =
cabal/cabal-install/Distribution/Client/CmdInstall/ClientInstallFlags.hs view
@@ -8,23 +8,21 @@ ) where import Distribution.Client.Compat.Prelude+import Prelude () import Distribution.ReadE- ( ReadE(..), succeedReadE )+ ( succeedReadE, parsecToReadE ) import Distribution.Simple.Command ( ShowOrParseArgs(..), OptionField(..), option, reqArg ) import Distribution.Simple.Setup ( Flag(..), trueArg, flagToList, toFlag ) -import Distribution.Client.InstallSymlink+import Distribution.Client.Types.InstallMethod+ ( InstallMethod (..) )+import Distribution.Client.Types.OverwritePolicy ( OverwritePolicy(..) ) --data InstallMethod = InstallMethodCopy- | InstallMethodSymlink- deriving (Eq, Show, Generic, Bounded, Enum)--instance Binary InstallMethod+import qualified Distribution.Compat.CharParsing as P data ClientInstallFlags = ClientInstallFlags { cinstInstallLibs :: Flag Bool@@ -42,6 +40,7 @@ (<>) = gmappend instance Binary ClientInstallFlags+instance Structured ClientInstallFlags defaultClientInstallFlags :: ClientInstallFlags defaultClientInstallFlags = ClientInstallFlags@@ -65,41 +64,26 @@ , option [] ["overwrite-policy"] "How to handle already existing symlinks." cinstOverwritePolicy (\v flags -> flags { cinstOverwritePolicy = v })- $ reqArg- "always|never"- readOverwritePolicyFlag- showOverwritePolicyFlag+ $ reqArg "always|never"+ (parsecToReadE (\err -> "Error parsing overwrite-policy: " ++ err) (toFlag `fmap` parsec)) + (map prettyShow . flagToList) , option [] ["install-method"] "How to install the executables." cinstInstallMethod (\v flags -> flags { cinstInstallMethod = v }) $ reqArg- "copy|symlink"- readInstallMethodFlag- showInstallMethodFlag+ "default|copy|symlink"+ (parsecToReadE (\err -> "Error parsing install-method: " ++ err) (toFlag `fmap` parsecInstallMethod))+ (map prettyShow . flagToList) , option [] ["installdir"] "Where to install (by symlinking or copying) the executables in." cinstInstalldir (\v flags -> flags { cinstInstalldir = v }) $ reqArg "DIR" (succeedReadE Flag) flagToList ] -readOverwritePolicyFlag :: ReadE (Flag OverwritePolicy)-readOverwritePolicyFlag = ReadE $ \case- "always" -> Right $ Flag AlwaysOverwrite- "never" -> Right $ Flag NeverOverwrite- policy -> Left $ "'" <> policy <> "' isn't a valid overwrite policy"--showOverwritePolicyFlag :: Flag OverwritePolicy -> [String]-showOverwritePolicyFlag (Flag AlwaysOverwrite) = ["always"]-showOverwritePolicyFlag (Flag NeverOverwrite) = ["never"]-showOverwritePolicyFlag NoFlag = []--readInstallMethodFlag :: ReadE (Flag InstallMethod)-readInstallMethodFlag = ReadE $ \case- "copy" -> Right $ Flag InstallMethodCopy- "symlink" -> Right $ Flag InstallMethodSymlink- method -> Left $ "'" <> method <> "' isn't a valid install-method"--showInstallMethodFlag :: Flag InstallMethod -> [String]-showInstallMethodFlag (Flag InstallMethodCopy) = ["copy"]-showInstallMethodFlag (Flag InstallMethodSymlink) = ["symlink"]-showInstallMethodFlag NoFlag = []+parsecInstallMethod :: CabalParsing m => m InstallMethod+parsecInstallMethod = do+ name <- P.munch1 isAlpha+ case name of+ "copy" -> pure InstallMethodCopy+ "symlink" -> pure InstallMethodSymlink+ _ -> P.unexpected $ "InstallMethod: " ++ name
+ cabal/cabal-install/Distribution/Client/CmdInstall/ClientInstallTargetSelector.hs view
@@ -0,0 +1,68 @@+module Distribution.Client.CmdInstall.ClientInstallTargetSelector (+ WithoutProjectTargetSelector (..),+ parseWithoutProjectTargetSelector,+ woPackageNames,+ woPackageTargets,+ woPackageSpecifiers,+ ) where++import Distribution.Client.Compat.Prelude+import Prelude ()++import Network.URI (URI, parseURI)++import Distribution.Client.TargetSelector+import Distribution.Client.Types+import Distribution.Compat.CharParsing (char, optional)+import Distribution.Package+import Distribution.Simple.LocalBuildInfo (ComponentName (CExeName))+import Distribution.Simple.Utils (die')+import Distribution.Solver.Types.PackageConstraint (PackageProperty (..))+import Distribution.Version++data WithoutProjectTargetSelector+ = WoPackageId PackageId+ | WoPackageComponent PackageId ComponentName+ | WoURI URI+ deriving (Show)++parseWithoutProjectTargetSelector :: Verbosity -> String -> IO WithoutProjectTargetSelector+parseWithoutProjectTargetSelector verbosity input =+ case explicitEitherParsec parser input of+ Right ts -> return ts+ Left err -> case parseURI input of+ Just uri -> return (WoURI uri)+ Nothing -> die' verbosity $ "Invalid package ID: " ++ input ++ "\n" ++ err+ where+ parser :: CabalParsing m => m WithoutProjectTargetSelector+ parser = do+ pid <- parsec+ cn <- optional (char ':' *> parsec)+ return $ case cn of+ Nothing -> WoPackageId pid+ Just cn' -> WoPackageComponent pid (CExeName cn')++woPackageNames :: WithoutProjectTargetSelector -> [PackageName]+woPackageNames (WoPackageId pid) = [pkgName pid]+woPackageNames (WoPackageComponent pid _) = [pkgName pid]+woPackageNames (WoURI _) = []++woPackageTargets :: WithoutProjectTargetSelector -> TargetSelector+woPackageTargets (WoPackageId pid) =+ TargetPackageNamed (pkgName pid) Nothing+woPackageTargets (WoPackageComponent pid cn) =+ TargetComponentUnknown (pkgName pid) (Right cn) WholeComponent+woPackageTargets (WoURI _) =+ TargetAllPackages (Just ExeKind)++woPackageSpecifiers :: WithoutProjectTargetSelector -> Either URI (PackageSpecifier pkg)+woPackageSpecifiers (WoPackageId pid) = Right (pidPackageSpecifiers pid)+woPackageSpecifiers (WoPackageComponent pid _) = Right (pidPackageSpecifiers pid)+woPackageSpecifiers (WoURI uri) = Left uri++pidPackageSpecifiers :: PackageId -> PackageSpecifier pkg+pidPackageSpecifiers pid+ | pkgVersion pid == nullVersion = NamedPackage (pkgName pid) []+ | otherwise = NamedPackage (pkgName pid)+ [ PackagePropertyVersion (thisVersion (pkgVersion pid))+ ]
cabal/cabal-install/Distribution/Client/CmdLegacy.hs view
@@ -16,11 +16,11 @@ import Distribution.Simple.Command import Distribution.Simple.Utils ( wrapText )-import Distribution.Verbosity - ( Verbosity, normal )+import Distribution.Verbosity+ ( normal ) import Control.Exception- ( SomeException(..), try )+ ( try ) import qualified Data.Text as T -- Tweaked versions of code from Main.@@ -39,7 +39,7 @@ let verbosity' = Setup.fromFlagOrDefault normal (verbosityFlag flags) load <- try (loadConfigOrSandboxConfig verbosity' globalFlags)- let config = either (\(SomeException _) -> mempty) snd load+ let config = either (\(SomeException _) -> mempty) id load distPref <- findSavedDistPref config (distPrefFlag flags) let setupScriptOptions = defaultSetupScriptOptions { useDistPref = distPref } @@ -50,7 +50,7 @@ -- -class HasVerbosity a where +class HasVerbosity a where verbosity :: a -> Verbosity instance HasVerbosity (Setup.Flag Verbosity) where@@ -59,8 +59,8 @@ instance (HasVerbosity a) => HasVerbosity (a, b) where verbosity (a, _) = verbosity a -instance (HasVerbosity b) => HasVerbosity (a, b, c) where- verbosity (_ , b, _) = verbosity b+instance (HasVerbosity a) => HasVerbosity (a, b, c) where+ verbosity (a , _, _) = verbosity a instance (HasVerbosity a) => HasVerbosity (a, b, c, d) where verbosity (a, _, _, _) = verbosity a@@ -95,12 +95,6 @@ instance HasVerbosity Setup.CleanFlags where verbosity = verbosity . Setup.cleanVerbosity -instance HasVerbosity Client.SDistFlags where- verbosity = verbosity . Client.sDistVerbosity--instance HasVerbosity Client.SandboxFlags where- verbosity = verbosity . Client.sandboxVerbosity- instance HasVerbosity Setup.DoctestFlags where verbosity = verbosity . Setup.doctestVerbosity @@ -140,7 +134,7 @@ cmd ui = CommandSpec ui (flip commandAddAction action) NormalCommand newMsg = T.unpack . T.replace "v2-" "new-" . T.pack- newUi = origUi + newUi = origUi { commandName = newMsg commandName , commandUsage = newMsg . commandUsage , commandDescription = (newMsg .) <$> commandDescription@@ -148,7 +142,7 @@ } defaultMsg = T.unpack . T.replace "v2-" "" . T.pack- defaultUi = origUi + defaultUi = origUi { commandName = defaultMsg commandName , commandUsage = defaultMsg . commandUsage , commandDescription = (defaultMsg .) <$> commandDescription
+ cabal/cabal-install/Distribution/Client/CmdListBin.hs view
@@ -0,0 +1,368 @@+{-# LANGUAGE MultiWayIf #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE TupleSections #-}+module Distribution.Client.CmdListBin (+ listbinCommand,+ listbinAction,+) where++import Distribution.Client.Compat.Prelude+import Prelude ()++import Distribution.Client.CmdErrorMessages+ (plural, renderListCommaAnd, renderTargetProblem, renderTargetProblemNoTargets,+ renderTargetSelector, showTargetSelector, targetSelectorFilter, targetSelectorPluralPkgs)+import Distribution.Client.DistDirLayout (DistDirLayout (..), ProjectRoot (..))+import Distribution.Client.NixStyleOptions+ (NixStyleFlags (..), defaultNixStyleFlags, nixStyleOptions)+import Distribution.Client.ProjectConfig+ (ProjectConfig, projectConfigConfigFile, projectConfigShared, withProjectOrGlobalConfig)+import Distribution.Client.ProjectFlags (ProjectFlags (..))+import Distribution.Client.ProjectOrchestration+import Distribution.Client.ProjectPlanning.Types+import Distribution.Client.Setup (GlobalFlags (..))+import Distribution.Client.TargetProblem (TargetProblem (..))+import Distribution.Simple.BuildPaths (dllExtension, exeExtension)+import Distribution.Simple.Command (CommandUI (..))+import Distribution.Simple.Setup (configVerbosity, fromFlagOrDefault)+import Distribution.Simple.Utils (die', ordNub, wrapText)+import Distribution.System (Platform)+import Distribution.Types.ComponentName (showComponentName)+import Distribution.Types.UnitId (UnitId)+import Distribution.Types.UnqualComponentName (UnqualComponentName)+import Distribution.Verbosity (silent, verboseStderr)+import System.Directory (getCurrentDirectory)+import System.FilePath ((<.>), (</>))++import qualified Data.Map as Map+import qualified Data.Set as Set+import qualified Distribution.Client.InstallPlan as IP+import qualified Distribution.Simple.InstallDirs as InstallDirs+import qualified Distribution.Solver.Types.ComponentDeps as CD++-------------------------------------------------------------------------------+-- Command+-------------------------------------------------------------------------------++listbinCommand :: CommandUI (NixStyleFlags ())+listbinCommand = CommandUI+ { commandName = "list-bin"+ , commandSynopsis = "list path to a single executable."+ , commandUsage = \pname ->+ "Usage: " ++ pname ++ " list-bin [FLAGS] TARGET\n"+ , commandDescription = Just $ \_ -> wrapText+ "List path to a build product."+ , commandNotes = Nothing+ , commandDefaultFlags = defaultNixStyleFlags ()+ , commandOptions = nixStyleOptions (const [])+ }++-------------------------------------------------------------------------------+-- Action+-------------------------------------------------------------------------------++listbinAction :: NixStyleFlags () -> [String] -> GlobalFlags -> IO ()+listbinAction flags@NixStyleFlags{..} args globalFlags = do+ -- fail early if multiple target selectors specified+ target <- case args of+ [] -> die' verbosity "One target is required, none provided"+ [x] -> return x+ _ -> die' verbosity "One target is required, given multiple"++ -- configure+ (baseCtx, distDirLayout) <- withProjectOrGlobalConfig verbosity ignoreProject globalConfigFlag withProject withoutProject+ let localPkgs = localPackages baseCtx++ -- elaborate target selectors+ targetSelectors <- either (reportTargetSelectorProblems verbosity) return+ =<< readTargetSelectors localPkgs Nothing [target]++ buildCtx <-+ runProjectPreBuildPhase verbosity baseCtx $ \elaboratedPlan -> do+ -- Interpret the targets on the command line as build targets+ -- (as opposed to say repl or haddock targets).+ targets <- either (reportTargetProblems verbosity) return+ $ resolveTargets+ selectPackageTargets+ selectComponentTarget+ elaboratedPlan+ Nothing+ targetSelectors++ -- Reject multiple targets, or at least targets in different+ -- components. It is ok to have two module/file targets in the+ -- same component, but not two that live in different components.+ --+ -- Note that we discard the target and return the whole 'TargetsMap',+ -- so this check will be repeated (and must succeed) after+ -- the 'runProjectPreBuildPhase'. Keep it in mind when modifying this.+ _ <- singleComponentOrElse+ (reportTargetProblems+ verbosity+ [multipleTargetsProblem targets])+ targets++ let elaboratedPlan' = pruneInstallPlanToTargets+ TargetActionBuild+ targets+ elaboratedPlan+ return (elaboratedPlan', targets)++ (selectedUnitId, _selectedComponent) <-+ -- Slight duplication with 'runProjectPreBuildPhase'.+ singleComponentOrElse+ (die' verbosity $ "No or multiple targets given, but the run "+ ++ "phase has been reached. This is a bug.")+ $ targetsMap buildCtx++ printPlan verbosity baseCtx buildCtx++ binfiles <- case Map.lookup selectedUnitId $ IP.toMap (elaboratedPlanOriginal buildCtx) of+ Nothing -> die' verbosity "No or multiple targets given..."+ Just gpp -> return $ IP.foldPlanPackage+ (const []) -- IPI don't have executables+ (elaboratedPackage distDirLayout (elaboratedShared buildCtx))+ gpp++ case binfiles of+ [exe] -> putStrLn exe+ _ -> die' verbosity "No or multiple targets given"+ where+ defaultVerbosity = verboseStderr silent+ verbosity = fromFlagOrDefault defaultVerbosity (configVerbosity configFlags)+ ignoreProject = flagIgnoreProject projectFlags+ prjConfig = commandLineFlagsToProjectConfig globalFlags flags mempty -- ClientInstallFlags, not needed here+ globalConfigFlag = projectConfigConfigFile (projectConfigShared prjConfig)++ withProject :: IO (ProjectBaseContext, DistDirLayout)+ withProject = do+ baseCtx <- establishProjectBaseContext verbosity prjConfig OtherCommand+ return (baseCtx, distDirLayout baseCtx)++ withoutProject :: ProjectConfig -> IO (ProjectBaseContext, DistDirLayout)+ withoutProject config = do+ cwd <- getCurrentDirectory+ baseCtx <- establishProjectBaseContextWithRoot verbosity (config <> prjConfig) (ProjectRootImplicit cwd) OtherCommand+ return (baseCtx, distDirLayout baseCtx)++ -- this is copied from+ elaboratedPackage+ :: DistDirLayout+ -> ElaboratedSharedConfig+ -> ElaboratedConfiguredPackage+ -> [FilePath]+ elaboratedPackage distDirLayout elaboratedSharedConfig elab = case elabPkgOrComp elab of+ ElabPackage pkg ->+ [ bin+ | (c, _) <- CD.toList $ CD.zip (pkgLibDependencies pkg)+ (pkgExeDependencies pkg)+ , bin <- bin_file c+ ]+ ElabComponent comp -> bin_file (compSolverName comp)+ where+ dist_dir = distBuildDirectory distDirLayout (elabDistDirParams elaboratedSharedConfig elab)++ bin_file c = case c of+ CD.ComponentExe s -> [bin_file' s]+ CD.ComponentTest s -> [bin_file' s]+ CD.ComponentBench s -> [bin_file' s]+ CD.ComponentFLib s -> [flib_file' s]+ _ -> []++ plat :: Platform+ plat = pkgConfigPlatform elaboratedSharedConfig++ -- here and in PlanOutput,+ -- use binDirectoryFor?+ bin_file' s =+ if elabBuildStyle elab == BuildInplaceOnly+ then dist_dir </> "build" </> prettyShow s </> prettyShow s <.> exeExtension plat+ else InstallDirs.bindir (elabInstallDirs elab) </> prettyShow s <.> exeExtension plat++ flib_file' s =+ if elabBuildStyle elab == BuildInplaceOnly+ then dist_dir </> "build" </> prettyShow s </> ("lib" ++ prettyShow s) <.> dllExtension plat+ else InstallDirs.bindir (elabInstallDirs elab) </> ("lib" ++ prettyShow s) <.> dllExtension plat++-------------------------------------------------------------------------------+-- Target Problem: the very similar to CmdRun+-------------------------------------------------------------------------------++singleComponentOrElse :: IO (UnitId, UnqualComponentName) -> TargetsMap -> IO (UnitId, UnqualComponentName)+singleComponentOrElse action targetsMap =+ case Set.toList . distinctTargetComponents $ targetsMap+ of [(unitId, CExeName component)] -> return (unitId, component)+ [(unitId, CTestName component)] -> return (unitId, component)+ [(unitId, CBenchName component)] -> return (unitId, component)+ [(unitId, CFLibName component)] -> return (unitId, component)+ _ -> action++-- | This defines what a 'TargetSelector' means for the @list-bin@ command.+-- It selects the 'AvailableTarget's that the 'TargetSelector' refers to,+-- or otherwise classifies the problem.+--+-- For the @list-bin@ command we select the exe or flib if there is only one+-- and it's buildable. Fail if there are no or multiple buildable exe components.+--+selectPackageTargets :: TargetSelector+ -> [AvailableTarget k] -> Either ListBinTargetProblem [k]+selectPackageTargets targetSelector targets++ -- If there is exactly one buildable executable then we select that+ | [target] <- targetsExesBuildable+ = Right [target]++ -- but fail if there are multiple buildable executables.+ | not (null targetsExesBuildable)+ = Left (matchesMultipleProblem targetSelector targetsExesBuildable')++ -- If there are executables but none are buildable then we report those+ | not (null targetsExes)+ = Left (TargetProblemNoneEnabled targetSelector targetsExes)++ -- If there are no executables but some other targets then we report that+ | not (null targets)+ = Left (noComponentsProblem targetSelector)++ -- If there are no targets at all then we report that+ | otherwise+ = Left (TargetProblemNoTargets targetSelector)+ where+ -- Targets that can be executed+ targetsExecutableLike =+ concatMap (\kind -> filterTargetsKind kind targets)+ [ExeKind, TestKind, BenchKind]+ (targetsExesBuildable,+ targetsExesBuildable') = selectBuildableTargets' targetsExecutableLike++ targetsExes = forgetTargetsDetail targetsExecutableLike+++-- | For a 'TargetComponent' 'TargetSelector', check if the component can be+-- selected.+--+-- For the @run@ command we just need to check it is a executable-like+-- (an executable, a test, or a benchmark), in addition+-- to the basic checks on being buildable etc.+--+selectComponentTarget :: SubComponentTarget+ -> AvailableTarget k -> Either ListBinTargetProblem k+selectComponentTarget subtarget@WholeComponent t+ = case availableTargetComponentName t+ of CExeName _ -> component+ CTestName _ -> component+ CBenchName _ -> component+ CFLibName _ -> component+ _ -> Left (componentNotRightKindProblem pkgid cname)+ where pkgid = availableTargetPackageId t+ cname = availableTargetComponentName t+ component = selectComponentTargetBasic subtarget t++selectComponentTarget subtarget t+ = Left (isSubComponentProblem (availableTargetPackageId t)+ (availableTargetComponentName t)+ subtarget)++-- | The various error conditions that can occur when matching a+-- 'TargetSelector' against 'AvailableTarget's for the @run@ command.+--+data ListBinProblem =+ -- | The 'TargetSelector' matches targets but no executables+ TargetProblemNoRightComps TargetSelector++ -- | A single 'TargetSelector' matches multiple targets+ | TargetProblemMatchesMultiple TargetSelector [AvailableTarget ()]++ -- | Multiple 'TargetSelector's match multiple targets+ | TargetProblemMultipleTargets TargetsMap++ -- | The 'TargetSelector' refers to a component that is not an executable+ | TargetProblemComponentNotRightKind PackageId ComponentName++ -- | Asking to run an individual file or module is not supported+ | TargetProblemIsSubComponent PackageId ComponentName SubComponentTarget+ deriving (Eq, Show)++type ListBinTargetProblem = TargetProblem ListBinProblem++noComponentsProblem :: TargetSelector -> ListBinTargetProblem+noComponentsProblem = CustomTargetProblem . TargetProblemNoRightComps++matchesMultipleProblem :: TargetSelector -> [AvailableTarget ()] -> ListBinTargetProblem+matchesMultipleProblem selector targets = CustomTargetProblem $+ TargetProblemMatchesMultiple selector targets++multipleTargetsProblem :: TargetsMap -> TargetProblem ListBinProblem+multipleTargetsProblem = CustomTargetProblem . TargetProblemMultipleTargets++componentNotRightKindProblem :: PackageId -> ComponentName -> TargetProblem ListBinProblem+componentNotRightKindProblem pkgid name = CustomTargetProblem $+ TargetProblemComponentNotRightKind pkgid name++isSubComponentProblem+ :: PackageId+ -> ComponentName+ -> SubComponentTarget+ -> TargetProblem ListBinProblem+isSubComponentProblem pkgid name subcomponent = CustomTargetProblem $+ TargetProblemIsSubComponent pkgid name subcomponent++reportTargetProblems :: Verbosity -> [ListBinTargetProblem] -> IO a+reportTargetProblems verbosity =+ die' verbosity . unlines . map renderListBinTargetProblem++renderListBinTargetProblem :: ListBinTargetProblem -> String+renderListBinTargetProblem (TargetProblemNoTargets targetSelector) =+ case targetSelectorFilter targetSelector of+ Just kind | kind /= ExeKind+ -> "The list-bin command is for finding binaries, but the target '"+ ++ showTargetSelector targetSelector ++ "' refers to "+ ++ renderTargetSelector targetSelector ++ "."++ _ -> renderTargetProblemNoTargets "list-bin" targetSelector+renderListBinTargetProblem problem =+ renderTargetProblem "list-bin" renderListBinProblem problem++renderListBinProblem :: ListBinProblem -> String+renderListBinProblem (TargetProblemMatchesMultiple targetSelector targets) =+ "The list-bin command is for finding a single binary at once. The target '"+ ++ showTargetSelector targetSelector ++ "' refers to "+ ++ renderTargetSelector targetSelector ++ " which includes "+ ++ renderListCommaAnd ( ("the "++) <$>+ showComponentName <$>+ availableTargetComponentName <$>+ foldMap+ (\kind -> filterTargetsKind kind targets)+ [ExeKind, TestKind, BenchKind] )+ ++ "."++renderListBinProblem (TargetProblemMultipleTargets selectorMap) =+ "The list-bin command is for finding a single binary at once. The targets "+ ++ renderListCommaAnd [ "'" ++ showTargetSelector ts ++ "'"+ | ts <- ordNub (concatMap snd (concat (Map.elems selectorMap))) ]+ ++ " refer to different executables."++renderListBinProblem (TargetProblemComponentNotRightKind pkgid cname) =+ "The list-bin command is for finding binaries, but the target '"+ ++ showTargetSelector targetSelector ++ "' refers to "+ ++ renderTargetSelector targetSelector ++ " from the package "+ ++ prettyShow pkgid ++ "."+ where+ targetSelector = TargetComponent pkgid cname WholeComponent++renderListBinProblem (TargetProblemIsSubComponent pkgid cname subtarget) =+ "The list-bin command can only find a binary as a whole, "+ ++ "not files or modules within them, but the target '"+ ++ showTargetSelector targetSelector ++ "' refers to "+ ++ renderTargetSelector targetSelector ++ "."+ where+ targetSelector = TargetComponent pkgid cname subtarget++renderListBinProblem (TargetProblemNoRightComps targetSelector) =+ "Cannot list-bin the target '" ++ showTargetSelector targetSelector+ ++ "' which refers to " ++ renderTargetSelector targetSelector+ ++ " because "+ ++ plural (targetSelectorPluralPkgs targetSelector) "it does" "they do"+ ++ " not contain any executables or foreign libraries."
cabal/cabal-install/Distribution/Client/CmdRepl.hs view
@@ -12,7 +12,7 @@ replAction, -- * Internals exposed for testing- TargetProblem(..),+ matchesMultipleProblem, selectPackageTargets, selectComponentTarget ) where@@ -23,33 +23,37 @@ import Distribution.Compat.Lens import qualified Distribution.Types.Lens as L +import Distribution.Client.NixStyleOptions+ ( NixStyleFlags (..), nixStyleOptions, defaultNixStyleFlags ) import Distribution.Client.CmdErrorMessages-import Distribution.Client.CmdInstall- ( establishDummyProjectBaseContext )+ ( renderTargetSelector, showTargetSelector,+ renderTargetProblem,+ targetSelectorRefersToPkgs,+ renderComponentKind, renderListCommaAnd, renderListSemiAnd,+ componentKind, sortGroupOn, Plural(..) )+import Distribution.Client.TargetProblem+ ( TargetProblem(..) ) import qualified Distribution.Client.InstallPlan as InstallPlan import Distribution.Client.ProjectBuilding ( rebuildTargetsDryRun, improveInstallPlanWithUpToDatePackages ) import Distribution.Client.ProjectConfig ( ProjectConfig(..), withProjectOrGlobalConfig- , projectConfigConfigFile, readGlobalConfig )+ , projectConfigConfigFile ) import Distribution.Client.ProjectOrchestration-import Distribution.Client.ProjectPlanning +import Distribution.Client.ProjectPlanning ( ElaboratedSharedConfig(..), ElaboratedInstallPlan ) import Distribution.Client.ProjectPlanning.Types ( elabOrderExeDependencies )-import Distribution.Client.RebuildMonad- ( runRebuild ) import Distribution.Client.Setup- ( GlobalFlags, ConfigFlags(..), ConfigExFlags, InstallFlags )+ ( GlobalFlags, ConfigFlags(..) ) import qualified Distribution.Client.Setup as Client import Distribution.Client.Types ( PackageLocation(..), PackageSpecifier(..), UnresolvedSourcePackage ) import Distribution.Simple.Setup- ( HaddockFlags, TestFlags, BenchmarkFlags- , fromFlagOrDefault, replOptions+ ( fromFlagOrDefault, replOptions , Flag(..), toFlag, trueArg, falseArg ) import Distribution.Simple.Command- ( CommandUI(..), liftOption, usageAlternatives, option+ ( CommandUI(..), liftOptionL, usageAlternatives, option , ShowOrParseArgs, OptionField, reqArg ) import Distribution.Compiler ( CompilerFlavor(GHC) )@@ -59,9 +63,7 @@ ( Package(..), packageName, UnitId, installedUnitId ) import Distribution.PackageDescription.PrettyPrint import Distribution.Parsec- ( Parsec(..), parsecCommaList )-import Distribution.Pretty- ( prettyShow )+ ( parsecCommaList ) import Distribution.ReadE ( ReadE, parsecToReadE ) import qualified Distribution.SPDX.License as SPDX@@ -74,11 +76,9 @@ import Distribution.Types.CondTree ( CondTree(..), traverseCondTreeC ) import Distribution.Types.Dependency- ( Dependency(..) )+ ( Dependency(..), mainLibSet ) import Distribution.Types.GenericPackageDescription ( emptyGenericPackageDescription )-import Distribution.Types.LibraryName- ( LibraryName(..) ) import Distribution.Types.PackageDescription ( PackageDescription(..), emptyPackageDescription ) import Distribution.Types.PackageName.Magic@@ -89,16 +89,16 @@ ( mkVersion ) import Distribution.Types.VersionRange ( anyVersion )-import Distribution.Deprecated.Text- ( display ) import Distribution.Utils.Generic ( safeHead ) import Distribution.Verbosity- ( Verbosity, normal, lessVerbose )+ ( normal, lessVerbose ) import Distribution.Simple.Utils ( wrapText, die', debugNoWrap, ordNub, createTempDirectory, handleDoesNotExist ) import Language.Haskell.Extension ( Language(..) )+import Distribution.CabalSpecVersion+ ( CabalSpecVersion (..) ) import Data.List ( (\\) )@@ -111,7 +111,7 @@ type ReplFlags = [String] -data EnvFlags = EnvFlags +data EnvFlags = EnvFlags { envPackages :: [Dependency] , envIncludeTransitive :: Flag Bool , envIgnoreProject :: Flag Bool@@ -127,9 +127,9 @@ envOptions :: ShowOrParseArgs -> [OptionField EnvFlags] envOptions _ = [ option ['b'] ["build-depends"]- "Include an additional package in the environment presented to GHCi."+ "Include additional packages in the environment presented to GHCi." envPackages (\p flags -> flags { envPackages = p ++ envPackages flags })- (reqArg "DEPENDENCY" dependencyReadE (fmap prettyShow :: [Dependency] -> [String]))+ (reqArg "DEPENDENCIES" dependenciesReadE (fmap prettyShow :: [Dependency] -> [String])) , option [] ["no-transitive-deps"] "Don't automatically include transitive dependencies of requested packages." envIncludeTransitive (\p flags -> flags { envIncludeTransitive = p })@@ -140,16 +140,13 @@ trueArg ] where- dependencyReadE :: ReadE [Dependency]- dependencyReadE =+ dependenciesReadE :: ReadE [Dependency]+ dependenciesReadE = parsecToReadE- ("couldn't parse dependency: " ++)+ ("couldn't parse dependencies: " ++) (parsecCommaList parsec) -replCommand :: CommandUI ( ConfigFlags, ConfigExFlags, InstallFlags- , HaddockFlags, TestFlags, BenchmarkFlags- , ReplFlags, EnvFlags- )+replCommand :: CommandUI (NixStyleFlags (ReplFlags, EnvFlags)) replCommand = Client.installCommand { commandName = "v2-repl", commandSynopsis = "Open an interactive session for the given component.",@@ -187,31 +184,11 @@ ++ "to the default component (or no component if there is no project present)\n" ++ cmdCommonHelpTextNewBuildBeta,- commandDefaultFlags = ( configFlags, configExFlags, installFlags- , haddockFlags, testFlags, benchmarkFlags- , [], defaultEnvFlags- ),- commandOptions = \showOrParseArgs ->- map liftOriginal (commandOptions Client.installCommand showOrParseArgs)- ++ map liftReplOpts (replOptions showOrParseArgs)- ++ map liftEnvOpts (envOptions showOrParseArgs)- }- where- (configFlags,configExFlags,installFlags,haddockFlags,testFlags,benchmarkFlags)- = commandDefaultFlags Client.installCommand-- liftOriginal = liftOption projectOriginal updateOriginal- liftReplOpts = liftOption projectReplOpts updateReplOpts- liftEnvOpts = liftOption projectEnvOpts updateEnvOpts-- projectOriginal (a,b,c,d,e,f,_,_) = (a,b,c,d,e,f)- updateOriginal (a,b,c,d,e,f) (_,_,_,_,_,_,g,h) = (a,b,c,d,e,f,g,h)-- projectReplOpts (_,_,_,_,_,_,g,_) = g- updateReplOpts g (a,b,c,d,e,f,_,h) = (a,b,c,d,e,f,g,h)-- projectEnvOpts (_,_,_,_,_,_,_,h) = h- updateEnvOpts h (a,b,c,d,e,f,g,_) = (a,b,c,d,e,f,g,h)+ commandDefaultFlags = defaultNixStyleFlags ([], defaultEnvFlags),+ commandOptions = nixStyleOptions $ \showOrParseArgs ->+ map (liftOptionL _1) (replOptions showOrParseArgs) +++ map (liftOptionL _2) (envOptions showOrParseArgs)+ } -- | The @repl@ command is very much like @build@. It brings the install plan -- up to date, selects that part of the plan needed by the given or implicit@@ -224,25 +201,15 @@ -- For more details on how this works, see the module -- "Distribution.Client.ProjectOrchestration" ---replAction :: ( ConfigFlags, ConfigExFlags, InstallFlags- , HaddockFlags, TestFlags, BenchmarkFlags- , ReplFlags, EnvFlags )- -> [String] -> GlobalFlags -> IO ()-replAction ( configFlags, configExFlags, installFlags- , haddockFlags, testFlags, benchmarkFlags- , replFlags, envFlags )- targetStrings globalFlags = do+replAction :: NixStyleFlags (ReplFlags, EnvFlags) -> [String] -> GlobalFlags -> IO ()+replAction flags@NixStyleFlags { extraFlags = (replFlags, envFlags), ..} targetStrings globalFlags = do let- ignoreProject = fromFlagOrDefault False (envIgnoreProject envFlags) with = withProject cliConfig verbosity targetStrings without config = withoutProject (config <> cliConfig) verbosity targetStrings- - (baseCtx, targetSelectors, finalizer, replType) <- if ignoreProject- then do- globalConfig <- runRebuild "" $ readGlobalConfig verbosity globalConfigFlag- without globalConfig- else withProjectOrGlobalConfig verbosity globalConfigFlag with without + (baseCtx, targetSelectors, finalizer, replType) <-+ withProjectOrGlobalConfig verbosity ignoreProject globalConfigFlag with without+ when (buildSettingOnlyDeps (buildSettings baseCtx)) $ die' verbosity $ "The repl command does not support '--only-dependencies'. " ++ "You may wish to use 'build --only-dependencies' and then "@@ -255,39 +222,40 @@ -- help us resolve the targets, but that isn't ideal for performance, -- especially in the no-project case. withInstallPlan (lessVerbose verbosity) baseCtx $ \elaboratedPlan _ -> do+ -- targets should be non-empty map, but there's no NonEmptyMap yet. targets <- validatedTargets elaboratedPlan targetSelectors- + let- Just (unitId, _) = safeHead $ Map.toList targets+ (unitId, _) = fromMaybe (error "panic: targets should be non-empty") $ safeHead $ Map.toList targets originalDeps = installedUnitId <$> InstallPlan.directDeps elaboratedPlan unitId oci = OriginalComponentInfo unitId originalDeps- Just pkgId = packageId <$> InstallPlan.lookup elaboratedPlan unitId + pkgId = fromMaybe (error $ "cannot find " ++ prettyShow unitId) $ packageId <$> InstallPlan.lookup elaboratedPlan unitId baseCtx' = addDepsToProjectTarget (envPackages envFlags) pkgId baseCtx return (Just oci, baseCtx')- - -- Now, we run the solver again with the added packages. While the graph ++ -- Now, we run the solver again with the added packages. While the graph -- won't actually reflect the addition of transitive dependencies, -- they're going to be available already and will be offered to the REPL -- and that's good enough. --- -- In addition, to avoid a *third* trip through the solver, we are + -- In addition, to avoid a *third* trip through the solver, we are -- replicating the second half of 'runProjectPreBuildPhase' by hand -- here. (buildCtx, replFlags'') <- withInstallPlan verbosity baseCtx' $ \elaboratedPlan elaboratedShared' -> do let ProjectBaseContext{..} = baseCtx'- + -- Recalculate with updated project. targets <- validatedTargets elaboratedPlan targetSelectors - let + let elaboratedPlan' = pruneInstallPlanToTargets TargetActionRepl targets elaboratedPlan includeTransitive = fromFlagOrDefault True (envIncludeTransitive envFlags)- + pkgsBuildStatus <- rebuildTargetsDryRun distDirLayout elaboratedShared' elaboratedPlan' @@ -295,26 +263,26 @@ pkgsBuildStatus elaboratedPlan' debugNoWrap verbosity (InstallPlan.showInstallPlan elaboratedPlan'') - let - buildCtx = ProjectBuildContext + let+ buildCtx = ProjectBuildContext { elaboratedPlanOriginal = elaboratedPlan , elaboratedPlanToExecute = elaboratedPlan'' , elaboratedShared = elaboratedShared' , pkgsBuildStatus , targetsMap = targets }- + ElaboratedSharedConfig { pkgConfigCompiler = compiler } = elaboratedShared'- + -- First version of GHC where GHCi supported the flag we need. -- https://downloads.haskell.org/~ghc/7.6.1/docs/html/users_guide/release-7-6-1.html minGhciScriptVersion = mkVersion [7, 6] - replFlags' = case originalComponent of + replFlags' = case originalComponent of Just oci -> generateReplFlags includeTransitive elaboratedPlan' oci Nothing -> [] replFlags'' = case replType of- GlobalRepl scriptPath + GlobalRepl scriptPath | Just version <- compilerCompatVersion GHC compiler , version >= minGhciScriptVersion -> ("-ghci-script" ++ scriptPath) : replFlags' _ -> replFlags'@@ -332,13 +300,10 @@ finalizer where verbosity = fromFlagOrDefault normal (configVerbosity configFlags)- cliConfig = commandLineFlagsToProjectConfig- globalFlags configFlags configExFlags- installFlags- mempty -- ClientInstallFlags, not needed here- haddockFlags testFlags benchmarkFlags+ ignoreProject = envIgnoreProject envFlags+ cliConfig = commandLineFlagsToProjectConfig globalFlags flags mempty -- ClientInstallFlags, not needed here globalConfigFlag = projectConfigConfigFile (projectConfigShared cliConfig)- + validatedTargets elaboratedPlan targetSelectors = do -- Interpret the targets on the command line as repl targets -- (as opposed to say build or haddock targets).@@ -346,7 +311,6 @@ $ resolveTargets selectPackageTargets selectComponentTarget- TargetProblemCommon elaboratedPlan Nothing targetSelectors@@ -356,7 +320,7 @@ -- same component, but not two that live in different components. when (Set.size (distinctTargetComponents targets) > 1) $ reportTargetProblems verbosity- [TargetProblemMultipleTargets targets]+ [multipleTargetsProblem targets] return targets @@ -367,7 +331,7 @@ deriving (Show) -- | Tracks what type of GHCi instance we're creating.-data ReplType = ProjectRepl +data ReplType = ProjectRepl | GlobalRepl FilePath -- ^ The 'FilePath' argument is path to a GHCi -- script responsible for changing to the -- correct directory. Only works on GHC geq@@ -396,17 +360,17 @@ -- We need to create a dummy package that lives in our dummy project. let sourcePackage = SourcePackage- { packageInfoId = pkgId- , packageDescription = genericPackageDescription- , packageSource = LocalUnpackedPackage tempDir- , packageDescrOverride = Nothing+ { srcpkgPackageId = pkgId+ , srcpkgDescription = genericPackageDescription+ , srcpkgSource = LocalUnpackedPackage tempDir+ , srcpkgDescrOverride = Nothing }- genericPackageDescription = emptyGenericPackageDescription + genericPackageDescription = emptyGenericPackageDescription & L.packageDescription .~ packageDescription & L.condLibrary .~ Just (CondNode library [baseDep] []) packageDescription = emptyPackageDescription { package = pkgId- , specVersionRaw = Left (mkVersion [2, 2])+ , specVersion = CabalSpecV2_2 , licenseRaw = Left SPDX.NONE } library = emptyLibrary { libBuildInfo = buildInfo }@@ -414,20 +378,21 @@ { targetBuildDepends = [baseDep] , defaultLanguage = Just Haskell2010 }- baseDep = Dependency "base" anyVersion (Set.singleton LMainLibName)+ baseDep = Dependency "base" anyVersion mainLibSet pkgId = fakePackageId writeGenericPackageDescription (tempDir </> "fake-package.cabal") genericPackageDescription- + let ghciScriptPath = tempDir </> "setcwd.ghci" cwd <- getCurrentDirectory writeFile ghciScriptPath (":cd " ++ cwd) - baseCtx <- + distDirLayout <- establishDummyDistDirLayout verbosity config tempDir+ baseCtx <- establishDummyProjectBaseContext verbosity config- tempDir+ distDirLayout [SpecificSourcePackage sourcePackage] OtherCommand @@ -441,7 +406,7 @@ -> PackageId -> ProjectBaseContext -> ProjectBaseContext-addDepsToProjectTarget deps pkgId ctx = +addDepsToProjectTarget deps pkgId ctx = (\p -> ctx { localPackages = p }) . fmap addDeps . localPackages $ ctx where addDeps :: PackageSpecifier UnresolvedSourcePackage@@ -449,8 +414,8 @@ addDeps (SpecificSourcePackage pkg) | packageId pkg /= pkgId = SpecificSourcePackage pkg | SourcePackage{..} <- pkg =- SpecificSourcePackage $ pkg { packageDescription = - packageDescription & (\f -> L.allCondTrees $ traverseCondTreeC f)+ SpecificSourcePackage $ pkg { srcpkgDescription =+ srcpkgDescription & (\f -> L.allCondTrees $ traverseCondTreeC f) %~ (deps ++) } addDeps spec = spec@@ -459,8 +424,8 @@ generateReplFlags includeTransitive elaboratedPlan OriginalComponentInfo{..} = flags where exeDeps :: [UnitId]- exeDeps = - foldMap + exeDeps =+ foldMap (InstallPlan.foldPlanPackage (const []) elabOrderExeDependencies) (InstallPlan.dependencyClosure elaboratedPlan [ociUnitId]) @@ -489,7 +454,7 @@ -- multiple libs or exes. -- selectPackageTargets :: TargetSelector- -> [AvailableTarget k] -> Either TargetProblem [k]+ -> [AvailableTarget k] -> Either ReplTargetProblem [k] selectPackageTargets targetSelector targets -- If there is exactly one buildable library then we select that@@ -498,7 +463,7 @@ -- but fail if there are multiple buildable libraries. | not (null targetsLibsBuildable)- = Left (TargetProblemMatchesMultiple targetSelector targetsLibsBuildable')+ = Left (matchesMultipleProblem targetSelector targetsLibsBuildable') -- If there is exactly one buildable executable then we select that | [target] <- targetsExesBuildable@@ -506,7 +471,7 @@ -- but fail if there are multiple buildable executables. | not (null targetsExesBuildable)- = Left (TargetProblemMatchesMultiple targetSelector targetsExesBuildable')+ = Left (matchesMultipleProblem targetSelector targetsExesBuildable') -- If there is exactly one other target then we select that | [target] <- targetsBuildable@@ -514,7 +479,7 @@ -- but fail if there are multiple such targets | not (null targetsBuildable)- = Left (TargetProblemMatchesMultiple targetSelector targetsBuildable')+ = Left (matchesMultipleProblem targetSelector targetsBuildable') -- If there are targets but none are buildable then we report those | not (null targets)@@ -551,40 +516,43 @@ -- For the @repl@ command we just need the basic checks on being buildable etc. -- selectComponentTarget :: SubComponentTarget- -> AvailableTarget k -> Either TargetProblem k-selectComponentTarget subtarget =- either (Left . TargetProblemCommon) Right- . selectComponentTargetBasic subtarget+ -> AvailableTarget k -> Either ReplTargetProblem k+selectComponentTarget = selectComponentTargetBasic +data ReplProblem+ = TargetProblemMatchesMultiple TargetSelector [AvailableTarget ()]++ -- | Multiple 'TargetSelector's match multiple targets+ | TargetProblemMultipleTargets TargetsMap+ deriving (Eq, Show)+ -- | The various error conditions that can occur when matching a -- 'TargetSelector' against 'AvailableTarget's for the @repl@ command. ---data TargetProblem =- TargetProblemCommon TargetProblemCommon-- -- | The 'TargetSelector' matches targets but none are buildable- | TargetProblemNoneEnabled TargetSelector [AvailableTarget ()]-- -- | There are no targets at all- | TargetProblemNoTargets TargetSelector+type ReplTargetProblem = TargetProblem ReplProblem - -- | A single 'TargetSelector' matches multiple targets- | TargetProblemMatchesMultiple TargetSelector [AvailableTarget ()]+matchesMultipleProblem+ :: TargetSelector+ -> [AvailableTarget ()]+ -> ReplTargetProblem+matchesMultipleProblem targetSelector targetsExesBuildable =+ CustomTargetProblem $ TargetProblemMatchesMultiple targetSelector targetsExesBuildable - -- | Multiple 'TargetSelector's match multiple targets- | TargetProblemMultipleTargets TargetsMap- deriving (Eq, Show)+multipleTargetsProblem+ :: TargetsMap+ -> ReplTargetProblem+multipleTargetsProblem = CustomTargetProblem . TargetProblemMultipleTargets -reportTargetProblems :: Verbosity -> [TargetProblem] -> IO a+reportTargetProblems :: Verbosity -> [TargetProblem ReplProblem] -> IO a reportTargetProblems verbosity =- die' verbosity . unlines . map renderTargetProblem+ die' verbosity . unlines . map renderReplTargetProblem -renderTargetProblem :: TargetProblem -> String-renderTargetProblem (TargetProblemCommon problem) =- renderTargetProblemCommon "open a repl for" problem+renderReplTargetProblem :: TargetProblem ReplProblem -> String+renderReplTargetProblem = renderTargetProblem "open a repl for" renderReplProblem -renderTargetProblem (TargetProblemMatchesMultiple targetSelector targets) =+renderReplProblem :: ReplProblem -> String+renderReplProblem (TargetProblemMatchesMultiple targetSelector targets) = "Cannot open a repl for multiple components at once. The target '" ++ showTargetSelector targetSelector ++ "' refers to " ++ renderTargetSelector targetSelector ++ " which "@@ -592,7 +560,7 @@ ++ renderListSemiAnd [ "the " ++ renderComponentKind Plural ckind ++ " " ++ renderListCommaAnd- [ maybe (display pkgname) display (componentNameString cname)+ [ maybe (prettyShow pkgname) prettyShow (componentNameString cname) | t <- ts , let cname = availableTargetComponentName t pkgname = packageName (availableTargetPackageId t)@@ -604,7 +572,7 @@ availableTargetComponentKind = componentKind . availableTargetComponentName -renderTargetProblem (TargetProblemMultipleTargets selectorMap) =+renderReplProblem (TargetProblemMultipleTargets selectorMap) = "Cannot open a repl for multiple components at once. The targets " ++ renderListCommaAnd [ "'" ++ showTargetSelector ts ++ "'"@@ -612,16 +580,8 @@ ++ " refer to different components." ++ ".\n\n" ++ explanationSingleComponentLimitation -renderTargetProblem (TargetProblemNoneEnabled targetSelector targets) =- renderTargetProblemNoneEnabled "open a repl for" targetSelector targets--renderTargetProblem (TargetProblemNoTargets targetSelector) =- renderTargetProblemNoTargets "open a repl for" targetSelector-- explanationSingleComponentLimitation :: String explanationSingleComponentLimitation = "The reason for this limitation is that current versions of ghci do not " ++ "support loading multiple components as source. Load just one component " ++ "and when you make changes to a dependent component then quit and reload."-
cabal/cabal-install/Distribution/Client/CmdRun.hs view
@@ -12,7 +12,8 @@ handleShebang, validScript, -- * Internals exposed for testing- TargetProblem(..),+ matchesMultipleProblem,+ noExesProblem, selectPackageTargets, selectComponentTarget ) where@@ -22,30 +23,36 @@ import Distribution.Client.ProjectOrchestration import Distribution.Client.CmdErrorMessages+ ( renderTargetSelector, showTargetSelector,+ renderTargetProblem,+ renderTargetProblemNoTargets, plural, targetSelectorPluralPkgs,+ targetSelectorFilter, renderListCommaAnd )+import Distribution.Client.TargetProblem+ ( TargetProblem (..) ) +import Distribution.Client.NixStyleOptions+ ( NixStyleFlags (..), nixStyleOptions, defaultNixStyleFlags ) import Distribution.Client.Setup- ( GlobalFlags(..), ConfigFlags(..), ConfigExFlags, InstallFlags )+ ( GlobalFlags(..), ConfigFlags(..) ) import Distribution.Client.GlobalFlags ( defaultGlobalFlags )-import qualified Distribution.Client.Setup as Client-import Distribution.Simple.Setup- ( HaddockFlags, TestFlags, BenchmarkFlags, fromFlagOrDefault )+import Distribution.Simple.Flag+ ( fromFlagOrDefault ) import Distribution.Simple.Command ( CommandUI(..), usageAlternatives ) import Distribution.Types.ComponentName ( showComponentName )-import Distribution.Deprecated.Text- ( display )+import Distribution.CabalSpecVersion (CabalSpecVersion (..), cabalSpecLatest) import Distribution.Verbosity- ( Verbosity, normal )+ ( normal ) import Distribution.Simple.Utils ( wrapText, warn, die', ordNub, info , createTempDirectory, handleDoesNotExist )-import Distribution.Client.CmdInstall- ( establishDummyProjectBaseContext ) import Distribution.Client.ProjectConfig ( ProjectConfig(..), ProjectConfigShared(..) , withProjectOrGlobalConfig )+import Distribution.Client.ProjectFlags+ ( flagIgnoreProject ) import Distribution.Client.ProjectPlanning ( ElaboratedConfiguredPackage(..) , ElaboratedInstallPlan, binDirectoryFor )@@ -63,8 +70,6 @@ import Distribution.Types.UnitId ( UnitId ) -import Distribution.CabalSpecVersion- ( cabalSpecLatest ) import Distribution.Client.Types ( PackageLocation(..), PackageSpecifier(..) ) import Distribution.FieldGrammar@@ -90,8 +95,6 @@ ( GenericPackageDescription(..), emptyGenericPackageDescription ) import Distribution.Types.PackageDescription ( PackageDescription(..), emptyPackageDescription )-import Distribution.Types.Version- ( mkVersion ) import Distribution.Types.PackageName.Magic ( fakePackageId ) import Language.Haskell.Extension@@ -107,44 +110,44 @@ ( (</>), isValid, isPathSeparator, takeExtension ) -runCommand :: CommandUI ( ConfigFlags, ConfigExFlags, InstallFlags- , HaddockFlags, TestFlags, BenchmarkFlags- )-runCommand = Client.installCommand {- commandName = "v2-run",- commandSynopsis = "Run an executable.",- commandUsage = usageAlternatives "v2-run"- [ "[TARGET] [FLAGS] [-- EXECUTABLE_FLAGS]" ],- commandDescription = Just $ \pname -> wrapText $- "Runs the specified executable-like component (an executable, a test, "- ++ "or a benchmark), first ensuring it is up to date.\n\n"+runCommand :: CommandUI (NixStyleFlags ())+runCommand = CommandUI+ { commandName = "v2-run"+ , commandSynopsis = "Run an executable."+ , commandUsage = usageAlternatives "v2-run"+ [ "[TARGET] [FLAGS] [-- EXECUTABLE_FLAGS]" ]+ , commandDescription = Just $ \pname -> wrapText $+ "Runs the specified executable-like component (an executable, a test, "+ ++ "or a benchmark), first ensuring it is up to date.\n\n" - ++ "Any executable-like component in any package in the project can be "- ++ "specified. A package can be specified if contains just one "- ++ "executable-like. The default is to use the package in the current "- ++ "directory if it contains just one executable-like.\n\n"+ ++ "Any executable-like component in any package in the project can be "+ ++ "specified. A package can be specified if contains just one "+ ++ "executable-like. The default is to use the package in the current "+ ++ "directory if it contains just one executable-like.\n\n" - ++ "Extra arguments can be passed to the program, but use '--' to "- ++ "separate arguments for the program from arguments for " ++ pname- ++ ". The executable is run in an environment where it can find its "- ++ "data files inplace in the build tree.\n\n"+ ++ "Extra arguments can be passed to the program, but use '--' to "+ ++ "separate arguments for the program from arguments for " ++ pname+ ++ ". The executable is run in an environment where it can find its "+ ++ "data files inplace in the build tree.\n\n" - ++ "Dependencies are built or rebuilt as necessary. Additional "- ++ "configuration flags can be specified on the command line and these "- ++ "extend the project configuration from the 'cabal.project', "- ++ "'cabal.project.local' and other files.",- commandNotes = Just $ \pname ->- "Examples:\n"- ++ " " ++ pname ++ " v2-run\n"- ++ " Run the executable-like in the package in the current directory\n"- ++ " " ++ pname ++ " v2-run foo-tool\n"- ++ " Run the named executable-like (in any package in the project)\n"- ++ " " ++ pname ++ " v2-run pkgfoo:foo-tool\n"- ++ " Run the executable-like 'foo-tool' in the package 'pkgfoo'\n"- ++ " " ++ pname ++ " v2-run foo -O2 -- dothing --fooflag\n"- ++ " Build with '-O2' and run the program, passing it extra arguments.\n\n"+ ++ "Dependencies are built or rebuilt as necessary. Additional "+ ++ "configuration flags can be specified on the command line and these "+ ++ "extend the project configuration from the 'cabal.project', "+ ++ "'cabal.project.local' and other files."+ , commandNotes = Just $ \pname ->+ "Examples:\n"+ ++ " " ++ pname ++ " v2-run\n"+ ++ " Run the executable-like in the package in the current directory\n"+ ++ " " ++ pname ++ " v2-run foo-tool\n"+ ++ " Run the named executable-like (in any package in the project)\n"+ ++ " " ++ pname ++ " v2-run pkgfoo:foo-tool\n"+ ++ " Run the executable-like 'foo-tool' in the package 'pkgfoo'\n"+ ++ " " ++ pname ++ " v2-run foo -O2 -- dothing --fooflag\n"+ ++ " Build with '-O2' and run the program, passing it extra arguments.\n\n" - ++ cmdCommonHelpTextNewBuildBeta+ ++ cmdCommonHelpTextNewBuildBeta+ , commandDefaultFlags = defaultNixStyleFlags ()+ , commandOptions = nixStyleOptions (const []) } -- | The @run@ command runs a specified executable-like component, building it@@ -155,22 +158,19 @@ -- For more details on how this works, see the module -- "Distribution.Client.ProjectOrchestration" ---runAction :: ( ConfigFlags, ConfigExFlags, InstallFlags- , HaddockFlags, TestFlags, BenchmarkFlags )- -> [String] -> GlobalFlags -> IO ()-runAction ( configFlags, configExFlags, installFlags- , haddockFlags, testFlags, benchmarkFlags )- targetStrings globalFlags = do+runAction :: NixStyleFlags () -> [String] -> GlobalFlags -> IO ()+runAction flags@NixStyleFlags {..} targetStrings globalFlags = do globalTmp <- getTemporaryDirectory- tempDir <- createTempDirectory globalTmp "cabal-repl."+ tmpDir <- createTempDirectory globalTmp "cabal-repl." let with = establishProjectBaseContext verbosity cliConfig OtherCommand- without config =- establishDummyProjectBaseContext verbosity (config <> cliConfig) tempDir [] OtherCommand+ without config = do+ distDirLayout <- establishDummyDistDirLayout verbosity (config <> cliConfig) tmpDir+ establishDummyProjectBaseContext verbosity (config <> cliConfig) distDirLayout [] OtherCommand - baseCtx <- withProjectOrGlobalConfig verbosity globalConfigFlag with without+ baseCtx <- withProjectOrGlobalConfig verbosity ignoreProject globalConfigFlag with without let scriptOrError script err = do@@ -178,7 +178,7 @@ let pol | takeExtension script == ".lhs" = LiterateHaskell | otherwise = PlainHaskell if exists- then BS.readFile script >>= handleScriptCase verbosity pol baseCtx tempDir+ then BS.readFile script >>= handleScriptCase verbosity pol baseCtx tmpDir else reportTargetSelectorProblems verbosity err (baseCtx', targetSelectors) <-@@ -208,7 +208,6 @@ $ resolveTargets selectPackageTargets selectComponentTarget- TargetProblemCommon elaboratedPlan Nothing targetSelectors@@ -223,7 +222,7 @@ _ <- singleExeOrElse (reportTargetProblems verbosity- [TargetProblemMultipleTargets targets])+ [multipleTargetsProblem targets]) targets let elaboratedPlan' = pruneInstallPlanToTargets@@ -269,17 +268,17 @@ [] -> die' verbosity $ "Unknown executable " ++ exeName ++ " in package "- ++ display selectedUnitId+ ++ prettyShow selectedUnitId [elabPkg] -> do info verbosity $ "Selecting "- ++ display selectedUnitId+ ++ prettyShow selectedUnitId ++ " to supply " ++ exeName return elabPkg elabPkgs -> die' verbosity $ "Multiple matching executables found matching " ++ exeName ++ ":\n"- ++ unlines (fmap (\p -> " - in package " ++ display (elabUnitId p)) elabPkgs)+ ++ unlines (fmap (\p -> " - in package " ++ prettyShow (elabUnitId p)) elabPkgs) let exePath = binDirectoryFor (distDirLayout baseCtx) (elaboratedShared buildCtx) pkg@@ -296,14 +295,11 @@ elaboratedPlan } - handleDoesNotExist () (removeDirectoryRecursive tempDir)+ handleDoesNotExist () (removeDirectoryRecursive tmpDir) where verbosity = fromFlagOrDefault normal (configVerbosity configFlags)- cliConfig = commandLineFlagsToProjectConfig- globalFlags configFlags configExFlags- installFlags- mempty -- ClientInstallFlags, not needed here- haddockFlags testFlags benchmarkFlags+ ignoreProject = flagIgnoreProject projectFlags+ cliConfig = commandLineFlagsToProjectConfig globalFlags flags mempty -- ClientInstallFlags, not needed here globalConfigFlag = projectConfigConfigFile (projectConfigShared cliConfig) -- | Used by the main CLI parser as heuristic to decide whether @cabal@ was@@ -400,7 +396,7 @@ -> FilePath -> BS.ByteString -> IO (ProjectBaseContext, [TargetSelector])-handleScriptCase verbosity pol baseCtx tempDir scriptContents = do+handleScriptCase verbosity pol baseCtx tmpDir scriptContents = do (executable, contents') <- readScriptBlockFromScript verbosity pol scriptContents -- We need to create a dummy package that lives in our dummy project.@@ -410,10 +406,10 @@ LiterateHaskell -> "Main.lhs" sourcePackage = SourcePackage- { packageInfoId = pkgId- , SP.packageDescription = genericPackageDescription- , packageSource = LocalUnpackedPackage tempDir- , packageDescrOverride = Nothing+ { srcpkgPackageId = pkgId+ , srcpkgDescription = genericPackageDescription+ , srcpkgSource = LocalUnpackedPackage tmpDir+ , srcpkgDescrOverride = Nothing } genericPackageDescription = emptyGenericPackageDescription { GPD.packageDescription = packageDescription@@ -431,13 +427,13 @@ binfo@BuildInfo{..} = buildInfo executable packageDescription = emptyPackageDescription { package = pkgId- , specVersionRaw = Left (mkVersion [2, 2])+ , specVersion = CabalSpecV2_2 , licenseRaw = Left SPDX.NONE } pkgId = fakePackageId - writeGenericPackageDescription (tempDir </> "fake-package.cabal") genericPackageDescription- BS.writeFile (tempDir </> mainName) contents'+ writeGenericPackageDescription (tmpDir </> "fake-package.cabal") genericPackageDescription+ BS.writeFile (tmpDir </> mainName) contents' let baseCtx' = baseCtx@@ -477,7 +473,7 @@ -- buildable. Fail if there are no or multiple buildable exe components. -- selectPackageTargets :: TargetSelector- -> [AvailableTarget k] -> Either TargetProblem [k]+ -> [AvailableTarget k] -> Either RunTargetProblem [k] selectPackageTargets targetSelector targets -- If there is exactly one buildable executable then we select that@@ -486,7 +482,7 @@ -- but fail if there are multiple buildable executables. | not (null targetsExesBuildable)- = Left (TargetProblemMatchesMultiple targetSelector targetsExesBuildable')+ = Left (matchesMultipleProblem targetSelector targetsExesBuildable') -- If there are executables but none are buildable then we report those | not (null targetsExes)@@ -494,7 +490,7 @@ -- If there are no executables but some other targets then we report that | not (null targets)- = Left (TargetProblemNoExes targetSelector)+ = Left (noExesProblem targetSelector) -- If there are no targets at all then we report that | otherwise@@ -518,36 +514,28 @@ -- to the basic checks on being buildable etc. -- selectComponentTarget :: SubComponentTarget- -> AvailableTarget k -> Either TargetProblem k+ -> AvailableTarget k -> Either RunTargetProblem k selectComponentTarget subtarget@WholeComponent t = case availableTargetComponentName t of CExeName _ -> component CTestName _ -> component CBenchName _ -> component- _ -> Left (TargetProblemComponentNotExe pkgid cname)+ _ -> Left (componentNotExeProblem pkgid cname) where pkgid = availableTargetPackageId t cname = availableTargetComponentName t- component = either (Left . TargetProblemCommon) return $- selectComponentTargetBasic subtarget t+ component = selectComponentTargetBasic subtarget t selectComponentTarget subtarget t- = Left (TargetProblemIsSubComponent (availableTargetPackageId t)- (availableTargetComponentName t)- subtarget)+ = Left (isSubComponentProblem (availableTargetPackageId t)+ (availableTargetComponentName t)+ subtarget) -- | The various error conditions that can occur when matching a -- 'TargetSelector' against 'AvailableTarget's for the @run@ command. ---data TargetProblem =- TargetProblemCommon TargetProblemCommon- -- | The 'TargetSelector' matches targets but none are buildable- | TargetProblemNoneEnabled TargetSelector [AvailableTarget ()]-- -- | There are no targets at all- | TargetProblemNoTargets TargetSelector-+data RunProblem = -- | The 'TargetSelector' matches targets but no executables- | TargetProblemNoExes TargetSelector+ TargetProblemNoExes TargetSelector -- | A single 'TargetSelector' matches multiple targets | TargetProblemMatchesMultiple TargetSelector [AvailableTarget ()]@@ -562,25 +550,36 @@ | TargetProblemIsSubComponent PackageId ComponentName SubComponentTarget deriving (Eq, Show) -reportTargetProblems :: Verbosity -> [TargetProblem] -> IO a-reportTargetProblems verbosity =- die' verbosity . unlines . map renderTargetProblem+type RunTargetProblem = TargetProblem RunProblem -renderTargetProblem :: TargetProblem -> String-renderTargetProblem (TargetProblemCommon problem) =- renderTargetProblemCommon "run" problem+noExesProblem :: TargetSelector -> RunTargetProblem+noExesProblem = CustomTargetProblem . TargetProblemNoExes -renderTargetProblem (TargetProblemNoneEnabled targetSelector targets) =- renderTargetProblemNoneEnabled "run" targetSelector targets+matchesMultipleProblem :: TargetSelector -> [AvailableTarget ()] -> RunTargetProblem+matchesMultipleProblem selector targets = CustomTargetProblem $+ TargetProblemMatchesMultiple selector targets -renderTargetProblem (TargetProblemNoExes targetSelector) =- "Cannot run the target '" ++ showTargetSelector targetSelector- ++ "' which refers to " ++ renderTargetSelector targetSelector- ++ " because "- ++ plural (targetSelectorPluralPkgs targetSelector) "it does" "they do"- ++ " not contain any executables."+multipleTargetsProblem :: TargetsMap -> TargetProblem RunProblem+multipleTargetsProblem = CustomTargetProblem . TargetProblemMultipleTargets -renderTargetProblem (TargetProblemNoTargets targetSelector) =+componentNotExeProblem :: PackageId -> ComponentName -> TargetProblem RunProblem+componentNotExeProblem pkgid name = CustomTargetProblem $+ TargetProblemComponentNotExe pkgid name++isSubComponentProblem+ :: PackageId+ -> ComponentName+ -> SubComponentTarget+ -> TargetProblem RunProblem+isSubComponentProblem pkgid name subcomponent = CustomTargetProblem $+ TargetProblemIsSubComponent pkgid name subcomponent++reportTargetProblems :: Verbosity -> [RunTargetProblem] -> IO a+reportTargetProblems verbosity =+ die' verbosity . unlines . map renderRunTargetProblem++renderRunTargetProblem :: RunTargetProblem -> String+renderRunTargetProblem (TargetProblemNoTargets targetSelector) = case targetSelectorFilter targetSelector of Just kind | kind /= ExeKind -> "The run command is for running executables, but the target '"@@ -588,8 +587,11 @@ ++ renderTargetSelector targetSelector ++ "." _ -> renderTargetProblemNoTargets "run" targetSelector+renderRunTargetProblem problem =+ renderTargetProblem "run" renderRunProblem problem -renderTargetProblem (TargetProblemMatchesMultiple targetSelector targets) =+renderRunProblem :: RunProblem -> String+renderRunProblem (TargetProblemMatchesMultiple targetSelector targets) = "The run command is for running a single executable at once. The target '" ++ showTargetSelector targetSelector ++ "' refers to " ++ renderTargetSelector targetSelector ++ " which includes "@@ -601,24 +603,31 @@ [ExeKind, TestKind, BenchKind] ) ++ "." -renderTargetProblem (TargetProblemMultipleTargets selectorMap) =+renderRunProblem (TargetProblemMultipleTargets selectorMap) = "The run command is for running a single executable at once. The targets " ++ renderListCommaAnd [ "'" ++ showTargetSelector ts ++ "'" | ts <- ordNub (concatMap snd (concat (Map.elems selectorMap))) ] ++ " refer to different executables." -renderTargetProblem (TargetProblemComponentNotExe pkgid cname) =+renderRunProblem (TargetProblemComponentNotExe pkgid cname) = "The run command is for running executables, but the target '" ++ showTargetSelector targetSelector ++ "' refers to " ++ renderTargetSelector targetSelector ++ " from the package "- ++ display pkgid ++ "."+ ++ prettyShow pkgid ++ "." where targetSelector = TargetComponent pkgid cname WholeComponent -renderTargetProblem (TargetProblemIsSubComponent pkgid cname subtarget) =+renderRunProblem (TargetProblemIsSubComponent pkgid cname subtarget) = "The run command can only run an executable as a whole, " ++ "not files or modules within them, but the target '" ++ showTargetSelector targetSelector ++ "' refers to " ++ renderTargetSelector targetSelector ++ "." where targetSelector = TargetComponent pkgid cname subtarget++renderRunProblem (TargetProblemNoExes targetSelector) =+ "Cannot run the target '" ++ showTargetSelector targetSelector+ ++ "' which refers to " ++ renderTargetSelector targetSelector+ ++ " because "+ ++ plural (targetSelectorPluralPkgs targetSelector) "it does" "they do"+ ++ " not contain any executables."
cabal/cabal-install/Distribution/Client/CmdSdist.hs view
@@ -6,18 +6,20 @@ {-# LANGUAGE ViewPatterns #-} module Distribution.Client.CmdSdist ( sdistCommand, sdistAction, packageToSdist- , SdistFlags(..), defaultSdistFlags , OutputFormat(..)) where +import Prelude ()+import Distribution.Client.Compat.Prelude+ import Distribution.Client.CmdErrorMessages ( Plural(..), renderComponentKind ) import Distribution.Client.ProjectOrchestration- ( ProjectBaseContext(..), CurrentCommand(..), establishProjectBaseContext )+ ( ProjectBaseContext(..), CurrentCommand(..), establishProjectBaseContext, establishProjectBaseContextWithRoot)+import Distribution.Client.NixStyleOptions+ ( NixStyleFlags (..), defaultNixStyleFlags ) import Distribution.Client.TargetSelector ( TargetSelector(..), ComponentKind , readTargetSelectors, reportTargetSelectorProblems )-import Distribution.Client.RebuildMonad- ( runRebuild ) import Distribution.Client.Setup ( GlobalFlags(..) ) import Distribution.Solver.Types.SourcePackage@@ -25,31 +27,32 @@ import Distribution.Client.Types ( PackageSpecifier(..), PackageLocation(..), UnresolvedSourcePackage ) import Distribution.Client.DistDirLayout- ( DistDirLayout(..), defaultDistDirLayout )+ ( DistDirLayout(..), ProjectRoot (..) ) import Distribution.Client.ProjectConfig- ( findProjectRoot, readProjectConfig )--import Distribution.Compat.Semigroup- ((<>))+ ( ProjectConfig, withProjectOrGlobalConfig, commandLineFlagsToProjectConfig, projectConfigConfigFile, projectConfigShared )+import Distribution.Client.ProjectFlags+ ( ProjectFlags (..), defaultProjectFlags, projectFlagsOptions ) +import Distribution.Compat.Lens+ ( _1, _2 ) import Distribution.Package ( Package(packageId) ) import Distribution.PackageDescription.Configuration ( flattenPackageDescription )-import Distribution.Pretty- ( prettyShow ) import Distribution.ReadE ( succeedReadE ) import Distribution.Simple.Command- ( CommandUI(..), option, reqArg )+ ( CommandUI(..), OptionField, option, reqArg, liftOptionL, ShowOrParseArgs ) import Distribution.Simple.PreProcess ( knownSuffixHandlers ) import Distribution.Simple.Setup ( Flag(..), toFlag, fromFlagOrDefault, flagToList, flagToMaybe- , optionVerbosity, optionDistPref, trueArg+ , optionVerbosity, optionDistPref, trueArg, configVerbosity, configDistPref ) import Distribution.Simple.SrcDist ( listPackageSources )+import Distribution.Client.SrcDist+ ( packageDirToSdist ) import Distribution.Simple.Utils ( die', notice, withOutputMarker, wrapText ) import Distribution.Types.ComponentName@@ -57,35 +60,21 @@ import Distribution.Types.PackageName ( PackageName, unPackageName ) import Distribution.Verbosity- ( Verbosity, normal )+ ( normal ) -import qualified Codec.Archive.Tar as Tar-import qualified Codec.Archive.Tar.Entry as Tar-import qualified Codec.Compression.GZip as GZip-import Control.Exception- ( throwIO )-import Control.Monad- ( when, forM_ )-import Control.Monad.Trans- ( liftIO )-import Control.Monad.State.Lazy- ( StateT, modify, gets, evalStateT )-import Control.Monad.Writer.Lazy- ( WriterT, tell, execWriterT )-import qualified Data.ByteString.Char8 as BS import qualified Data.ByteString.Lazy.Char8 as BSL-import Data.Either- ( partitionEithers )-import Data.List- ( find, sortOn, nub )-import qualified Data.Set as Set import System.Directory- ( getCurrentDirectory, setCurrentDirectory- , createDirectoryIfMissing, makeAbsolute )+ ( getCurrentDirectory+ , createDirectoryIfMissing, makeAbsolute+ ) import System.FilePath- ( (</>), (<.>), makeRelative, normalise, takeDirectory )+ ( (</>), (<.>), makeRelative, normalise ) -sdistCommand :: CommandUI SdistFlags+-------------------------------------------------------------------------------+-- Command+-------------------------------------------------------------------------------++sdistCommand :: CommandUI (ProjectFlags, SdistFlags) sdistCommand = CommandUI { commandName = "v2-sdist" , commandSynopsis = "Generate a source distribution file (.tar.gz)."@@ -94,36 +83,19 @@ , commandDescription = Just $ \_ -> wrapText "Generates tarballs of project packages suitable for upload to Hackage." , commandNotes = Nothing- , commandDefaultFlags = defaultSdistFlags+ , commandDefaultFlags = (defaultProjectFlags, defaultSdistFlags) , commandOptions = \showOrParseArgs ->- [ optionVerbosity- sdistVerbosity (\v flags -> flags { sdistVerbosity = v })- , optionDistPref- sdistDistDir (\dd flags -> flags { sdistDistDir = dd })- showOrParseArgs- , option [] ["project-file"]- "Set the name of the cabal.project file to search for in parent directories"- sdistProjectFile (\pf flags -> flags { sdistProjectFile = pf })- (reqArg "FILE" (succeedReadE Flag) flagToList)- , option ['l'] ["list-only"]- "Just list the sources, do not make a tarball"- sdistListSources (\v flags -> flags { sdistListSources = v })- trueArg- , option ['z'] ["null-sep"]- "Separate the source files with NUL bytes rather than newlines."- sdistNulSeparated (\v flags -> flags { sdistNulSeparated = v })- trueArg- , option ['o'] ["output-dir", "outputdir"]- "Choose the output directory of this command. '-' sends all output to stdout"- sdistOutputPath (\o flags -> flags { sdistOutputPath = o })- (reqArg "PATH" (succeedReadE Flag) flagToList)- ]+ map (liftOptionL _1) (projectFlagsOptions showOrParseArgs) +++ map (liftOptionL _2) (sdistOptions showOrParseArgs) } +-------------------------------------------------------------------------------+-- Flags+-------------------------------------------------------------------------------+ data SdistFlags = SdistFlags { sdistVerbosity :: Flag Verbosity , sdistDistDir :: Flag FilePath- , sdistProjectFile :: Flag FilePath , sdistListSources :: Flag Bool , sdistNulSeparated :: Flag Bool , sdistOutputPath :: Flag FilePath@@ -133,40 +105,57 @@ defaultSdistFlags = SdistFlags { sdistVerbosity = toFlag normal , sdistDistDir = mempty- , sdistProjectFile = mempty , sdistListSources = toFlag False , sdistNulSeparated = toFlag False , sdistOutputPath = mempty } ---+sdistOptions :: ShowOrParseArgs -> [OptionField SdistFlags]+sdistOptions showOrParseArgs =+ [ optionVerbosity+ sdistVerbosity (\v flags -> flags { sdistVerbosity = v })+ , optionDistPref+ sdistDistDir (\dd flags -> flags { sdistDistDir = dd })+ showOrParseArgs+ , option ['l'] ["list-only"]+ "Just list the sources, do not make a tarball"+ sdistListSources (\v flags -> flags { sdistListSources = v })+ trueArg+ , option [] ["null-sep"]+ "Separate the source files with NUL bytes rather than newlines."+ sdistNulSeparated (\v flags -> flags { sdistNulSeparated = v })+ trueArg+ , option ['o'] ["output-directory", "outputdir"]+ "Choose the output directory of this command. '-' sends all output to stdout"+ sdistOutputPath (\o flags -> flags { sdistOutputPath = o })+ (reqArg "PATH" (succeedReadE Flag) flagToList)+ ] -sdistAction :: SdistFlags -> [String] -> GlobalFlags -> IO ()-sdistAction SdistFlags{..} targetStrings globalFlags = do- let verbosity = fromFlagOrDefault normal sdistVerbosity- mDistDirectory = flagToMaybe sdistDistDir- mProjectFile = flagToMaybe sdistProjectFile- globalConfig = globalConfigFile globalFlags- listSources = fromFlagOrDefault False sdistListSources- nulSeparated = fromFlagOrDefault False sdistNulSeparated- mOutputPath = flagToMaybe sdistOutputPath+-------------------------------------------------------------------------------+-- Action+------------------------------------------------------------------------------- - projectRoot <- either throwIO return =<< findProjectRoot Nothing mProjectFile- let distLayout = defaultDistDirLayout projectRoot mDistDirectory- dir <- getCurrentDirectory- projectConfig <- runRebuild dir $ readProjectConfig verbosity globalConfig distLayout- baseCtx <- establishProjectBaseContext verbosity projectConfig OtherCommand+sdistAction :: (ProjectFlags, SdistFlags) -> [String] -> GlobalFlags -> IO ()+sdistAction (ProjectFlags{..}, SdistFlags{..}) targetStrings globalFlags = do+ (baseCtx, distDirLayout) <- withProjectOrGlobalConfig verbosity ignoreProject globalConfigFlag withProject withoutProject+ let localPkgs = localPackages baseCtx targetSelectors <- either (reportTargetSelectorProblems verbosity) return =<< readTargetSelectors localPkgs Nothing targetStrings + -- elaborate path, create target directory mOutputPath' <- case mOutputPath of Just "-" -> return (Just "-")- Just path -> Just <$> makeAbsolute path- Nothing -> return Nothing+ Just path -> do+ abspath <- makeAbsolute path+ createDirectoryIfMissing True abspath+ return (Just abspath)+ Nothing -> do+ createDirectoryIfMissing True (distSdistDirectory distDirLayout)+ return Nothing - let+ let format :: OutputFormat format = if | listSources, nulSeparated -> SourceList '\0' | listSources -> SourceList '\n'@@ -182,9 +171,8 @@ | otherwise -> path </> prettyShow (packageId pkg) <.> ext Nothing | listSources -> "-"- | otherwise -> distSdistFile distLayout (packageId pkg)+ | otherwise -> distSdistFile distDirLayout (packageId pkg) - createDirectoryIfMissing True (distSdistDirectory distLayout) case reifyTargetSelectors localPkgs targetSelectors of Left errs -> die' verbosity . unlines . fmap renderTargetProblem $ errs@@ -192,11 +180,38 @@ | length pkgs > 1, not listSources, Just "-" <- mOutputPath' -> die' verbosity "Can't write multiple tarballs to standard output!" | otherwise ->- mapM_ (\pkg -> packageToSdist verbosity (distProjectRootDirectory distLayout) format (outputPath pkg) pkg) pkgs+ traverse_ (\pkg -> packageToSdist verbosity (distProjectRootDirectory distDirLayout) format (outputPath pkg) pkg) pkgs+ where+ verbosity = fromFlagOrDefault normal sdistVerbosity+ listSources = fromFlagOrDefault False sdistListSources+ nulSeparated = fromFlagOrDefault False sdistNulSeparated+ mOutputPath = flagToMaybe sdistOutputPath+ ignoreProject = flagIgnoreProject -data IsExec = Exec | NoExec- deriving (Show, Eq)+ prjConfig :: ProjectConfig+ prjConfig = commandLineFlagsToProjectConfig+ globalFlags+ (defaultNixStyleFlags ())+ { configFlags = (configFlags $ defaultNixStyleFlags ())+ { configVerbosity = sdistVerbosity+ , configDistPref = sdistDistDir+ }+ }+ mempty + globalConfigFlag = projectConfigConfigFile (projectConfigShared prjConfig)++ withProject :: IO (ProjectBaseContext, DistDirLayout)+ withProject = do+ baseCtx <- establishProjectBaseContext verbosity prjConfig OtherCommand+ return (baseCtx, distDirLayout baseCtx)++ withoutProject :: ProjectConfig -> IO (ProjectBaseContext, DistDirLayout)+ withoutProject config = do+ cwd <- getCurrentDirectory+ baseCtx <- establishProjectBaseContextWithRoot verbosity (config <> prjConfig) (ProjectRootImplicit cwd) OtherCommand+ return (baseCtx, distDirLayout baseCtx)+ data OutputFormat = SourceList Char | TarGzArchive deriving (Show, Eq)@@ -204,7 +219,7 @@ packageToSdist :: Verbosity -> FilePath -> OutputFormat -> FilePath -> UnresolvedSourcePackage -> IO () packageToSdist verbosity projectRootDir format outputFile pkg = do let death = die' verbosity ("The impossible happened: a local package isn't local" <> (show pkg))- dir0 <- case packageSource pkg of+ dir0 <- case srcpkgSource pkg of LocalUnpackedPackage path -> pure (Right path) RemoteSourceRepoPackage _ (Just path) -> pure (Right path) RemoteSourceRepoPackage {} -> death@@ -214,83 +229,34 @@ RepoTarballPackage {} -> death let -- Write String to stdout or file, using the default TextEncoding.- write- | outputFile == "-" = putStr . withOutputMarker verbosity- | otherwise = writeFile outputFile+ write str+ | outputFile == "-" = putStr (withOutputMarker verbosity str)+ | otherwise = do+ writeFile outputFile str+ notice verbosity $ "Wrote source list to " ++ outputFile ++ "\n" -- Write raw ByteString to stdout or file as it is, without encoding.- writeLBS- | outputFile == "-" = BSL.putStr- | otherwise = BSL.writeFile outputFile+ writeLBS lbs+ | outputFile == "-" = BSL.putStr lbs+ | otherwise = do+ BSL.writeFile outputFile lbs+ notice verbosity $ "Wrote tarball sdist to " ++ outputFile ++ "\n" case dir0 of Left tgz -> do case format of TarGzArchive -> do writeLBS =<< BSL.readFile tgz- when (outputFile /= "-") $- notice verbosity $ "Wrote tarball sdist to " ++ outputFile ++ "\n" _ -> die' verbosity ("cannot convert tarball package to " ++ show format) - Right dir -> do- oldPwd <- getCurrentDirectory- setCurrentDirectory dir-- let norm flag = fmap ((flag, ) . normalise)- (norm NoExec -> nonexec, norm Exec -> exec) <-- listPackageSources verbosity (flattenPackageDescription $ packageDescription pkg) knownSuffixHandlers-- let files = nub . sortOn snd $ nonexec ++ exec-- case format of- SourceList nulSep -> do- let prefix = makeRelative projectRootDir dir- write $ concat [prefix </> i ++ [nulSep] | (_, i) <- files]- when (outputFile /= "-") $- notice verbosity $ "Wrote source list to " ++ outputFile ++ "\n"- TarGzArchive -> do- let entriesM :: StateT (Set.Set FilePath) (WriterT [Tar.Entry] IO) ()- entriesM = do- let prefix = prettyShow (packageId pkg)- modify (Set.insert prefix)- case Tar.toTarPath True prefix of- Left err -> liftIO $ die' verbosity ("Error packing sdist: " ++ err)- Right path -> tell [Tar.directoryEntry path]-- forM_ files $ \(perm, file) -> do- let fileDir = takeDirectory (prefix </> file)- perm' = case perm of- Exec -> Tar.executableFilePermissions- NoExec -> Tar.ordinaryFilePermissions- needsEntry <- gets (Set.notMember fileDir)-- when needsEntry $ do- modify (Set.insert fileDir)- case Tar.toTarPath True fileDir of- Left err -> liftIO $ die' verbosity ("Error packing sdist: " ++ err)- Right path -> tell [Tar.directoryEntry path]-- contents <- liftIO . fmap BSL.fromStrict . BS.readFile $ file- case Tar.toTarPath False (prefix </> file) of- Left err -> liftIO $ die' verbosity ("Error packing sdist: " ++ err)- Right path -> tell [(Tar.fileEntry path contents) { Tar.entryPermissions = perm' }]-- entries <- execWriterT (evalStateT entriesM mempty)- let -- Pretend our GZip file is made on Unix.- normalize bs = BSL.concat [first, "\x03", rest']- where- (first, rest) = BSL.splitAt 9 bs- rest' = BSL.tail rest- -- The Unix epoch, which is the default value, is- -- unsuitable because it causes unpacking problems on- -- Windows; we need a post-1980 date. One gigasecond- -- after the epoch is during 2001-09-09, so that does- -- nicely. See #5596.- setModTime entry = entry { Tar.entryTime = 1000000000 }- writeLBS . normalize . GZip.compress . Tar.write $ fmap setModTime entries- when (outputFile /= "-") $- notice verbosity $ "Wrote tarball sdist to " ++ outputFile ++ "\n"+ Right dir -> case format of+ SourceList nulSep -> do+ files' <- listPackageSources verbosity dir (flattenPackageDescription $ srcpkgDescription pkg) knownSuffixHandlers+ let files = nub $ sort $ map normalise files'+ let prefix = makeRelative projectRootDir dir+ write $ concat [prefix </> i ++ [nulSep] | i <- files] - setCurrentDirectory oldPwd+ TarGzArchive -> do+ packageDirToSdist verbosity (srcpkgDescription pkg) dir >>= writeLBS --
cabal/cabal-install/Distribution/Client/CmdTest.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE RecordWildCards #-} -- | cabal-install CLI command: test --@@ -8,38 +8,43 @@ testAction, -- * Internals exposed for testing- TargetProblem(..),+ isSubComponentProblem,+ notTestProblem,+ noTestsProblem, selectPackageTargets, selectComponentTarget ) where +import Distribution.Client.Compat.Prelude+import Prelude ()+ import Distribution.Client.ProjectOrchestration import Distribution.Client.CmdErrorMessages-+ ( renderTargetSelector, showTargetSelector, targetSelectorFilter, plural,+ renderTargetProblem,+ renderTargetProblemNoTargets, targetSelectorPluralPkgs )+import Distribution.Client.TargetProblem+ ( TargetProblem (..) )+import Distribution.Client.NixStyleOptions+ ( NixStyleFlags (..), nixStyleOptions, defaultNixStyleFlags ) import Distribution.Client.Setup- ( GlobalFlags(..), ConfigFlags(..), ConfigExFlags, InstallFlags )-import qualified Distribution.Client.Setup as Client+ ( GlobalFlags(..), ConfigFlags(..) ) import Distribution.Simple.Setup- ( HaddockFlags, TestFlags(..), BenchmarkFlags(..), fromFlagOrDefault )+ ( TestFlags(..), fromFlagOrDefault ) import Distribution.Simple.Command ( CommandUI(..), usageAlternatives ) import Distribution.Simple.Flag ( Flag(..) )-import Distribution.Deprecated.Text- ( display ) import Distribution.Verbosity- ( Verbosity, normal )+ ( normal ) import Distribution.Simple.Utils ( notice, wrapText, die' ) -import Control.Monad (when) import qualified System.Exit (exitSuccess) -testCommand :: CommandUI ( ConfigFlags, ConfigExFlags, InstallFlags- , HaddockFlags, TestFlags, BenchmarkFlags- )-testCommand = Client.installCommand+testCommand :: CommandUI (NixStyleFlags ())+testCommand = CommandUI { commandName = "v2-test" , commandSynopsis = "Run test-suites" , commandUsage = usageAlternatives "v2-test" [ "[TARGETS] [FLAGS]" ]@@ -72,6 +77,8 @@ ++ cmdCommonHelpTextNewBuildBeta + , commandDefaultFlags = defaultNixStyleFlags ()+ , commandOptions = nixStyleOptions (const []) } @@ -86,12 +93,8 @@ -- For more details on how this works, see the module -- "Distribution.Client.ProjectOrchestration" ---testAction :: ( ConfigFlags, ConfigExFlags, InstallFlags- , HaddockFlags, TestFlags, BenchmarkFlags )- -> [String] -> GlobalFlags -> IO ()-testAction ( configFlags, configExFlags, installFlags- , haddockFlags, testFlags, benchmarkFlags )- targetStrings globalFlags = do+testAction :: NixStyleFlags () -> [String] -> GlobalFlags -> IO ()+testAction flags@NixStyleFlags {..} targetStrings globalFlags = do baseCtx <- establishProjectBaseContext verbosity cliConfig OtherCommand @@ -113,7 +116,6 @@ $ resolveTargets selectPackageTargets selectComponentTarget- TargetProblemCommon elaboratedPlan Nothing targetSelectors@@ -131,11 +133,7 @@ where failWhenNoTestSuites = testFailWhenNoTestSuites testFlags verbosity = fromFlagOrDefault normal (configVerbosity configFlags)- cliConfig = commandLineFlagsToProjectConfig- globalFlags configFlags configExFlags- installFlags- mempty -- ClientInstallFlags, not needed here- haddockFlags testFlags benchmarkFlags+ cliConfig = commandLineFlagsToProjectConfig globalFlags flags mempty -- ClientInstallFlags -- | This defines what a 'TargetSelector' means for the @test@ command. -- It selects the 'AvailableTarget's that the 'TargetSelector' refers to,@@ -145,7 +143,7 @@ -- or fail if there are no test-suites or no buildable test-suites. -- selectPackageTargets :: TargetSelector- -> [AvailableTarget k] -> Either TargetProblem [k]+ -> [AvailableTarget k] -> Either TestTargetProblem [k] selectPackageTargets targetSelector targets -- If there are any buildable test-suite targets then we select those@@ -158,7 +156,7 @@ -- If there are no test-suite but some other targets then we report that | not (null targets)- = Left (TargetProblemNoTests targetSelector)+ = Left (noTestsProblem targetSelector) -- If there are no targets at all then we report that | otherwise@@ -180,34 +178,28 @@ -- to the basic checks on being buildable etc. -- selectComponentTarget :: SubComponentTarget- -> AvailableTarget k -> Either TargetProblem k+ -> AvailableTarget k -> Either TestTargetProblem k selectComponentTarget subtarget@WholeComponent t | CTestName _ <- availableTargetComponentName t- = either (Left . TargetProblemCommon) return $+ = either Left return $ selectComponentTargetBasic subtarget t | otherwise- = Left (TargetProblemComponentNotTest (availableTargetPackageId t)- (availableTargetComponentName t))+ = Left (notTestProblem+ (availableTargetPackageId t)+ (availableTargetComponentName t)) selectComponentTarget subtarget t- = Left (TargetProblemIsSubComponent (availableTargetPackageId t)- (availableTargetComponentName t)- subtarget)+ = Left (isSubComponentProblem+ (availableTargetPackageId t)+ (availableTargetComponentName t)+ subtarget) -- | The various error conditions that can occur when matching a -- 'TargetSelector' against 'AvailableTarget's for the @test@ command. ---data TargetProblem =- TargetProblemCommon TargetProblemCommon-- -- | The 'TargetSelector' matches targets but none are buildable- | TargetProblemNoneEnabled TargetSelector [AvailableTarget ()]-- -- | There are no targets at all- | TargetProblemNoTargets TargetSelector-+data TestProblem = -- | The 'TargetSelector' matches targets but no test-suites- | TargetProblemNoTests TargetSelector+ TargetProblemNoTests TargetSelector -- | The 'TargetSelector' refers to a component that is not a test-suite | TargetProblemComponentNotTest PackageId ComponentName@@ -216,17 +208,35 @@ | TargetProblemIsSubComponent PackageId ComponentName SubComponentTarget deriving (Eq, Show) -reportTargetProblems :: Verbosity -> Flag Bool -> [TargetProblem] -> IO a++type TestTargetProblem = TargetProblem TestProblem+++noTestsProblem :: TargetSelector -> TargetProblem TestProblem+noTestsProblem = CustomTargetProblem . TargetProblemNoTests++notTestProblem :: PackageId -> ComponentName -> TargetProblem TestProblem+notTestProblem pkgid name = CustomTargetProblem $ TargetProblemComponentNotTest pkgid name++isSubComponentProblem+ :: PackageId+ -> ComponentName+ -> SubComponentTarget+ -> TargetProblem TestProblem+isSubComponentProblem pkgid name subcomponent = CustomTargetProblem $+ TargetProblemIsSubComponent pkgid name subcomponent++reportTargetProblems :: Verbosity -> Flag Bool -> [TestTargetProblem] -> IO a reportTargetProblems verbosity failWhenNoTestSuites problems = case (failWhenNoTestSuites, problems) of- (Flag True, [TargetProblemNoTests _]) ->+ (Flag True, [CustomTargetProblem (TargetProblemNoTests _)]) -> die' verbosity problemsMessage- (_, [TargetProblemNoTests selector]) -> do+ (_, [CustomTargetProblem (TargetProblemNoTests selector)]) -> do notice verbosity (renderAllowedNoTestsProblem selector) System.Exit.exitSuccess (_, _) -> die' verbosity problemsMessage where- problemsMessage = unlines . map renderTargetProblem $ problems+ problemsMessage = unlines . map renderTestTargetProblem $ problems -- | Unless @--test-fail-when-no-test-suites@ flag is passed, we don't -- @die@ when the target problem is 'TargetProblemNoTests'.@@ -236,21 +246,8 @@ renderAllowedNoTestsProblem selector = "No tests to run for " ++ renderTargetSelector selector -renderTargetProblem :: TargetProblem -> String-renderTargetProblem (TargetProblemCommon problem) =- renderTargetProblemCommon "run" problem--renderTargetProblem (TargetProblemNoneEnabled targetSelector targets) =- renderTargetProblemNoneEnabled "test" targetSelector targets--renderTargetProblem (TargetProblemNoTests targetSelector) =- "Cannot run tests for the target '" ++ showTargetSelector targetSelector- ++ "' which refers to " ++ renderTargetSelector targetSelector- ++ " because "- ++ plural (targetSelectorPluralPkgs targetSelector) "it does" "they do"- ++ " not contain any test suites."--renderTargetProblem (TargetProblemNoTargets targetSelector) =+renderTestTargetProblem :: TestTargetProblem -> String+renderTestTargetProblem (TargetProblemNoTargets targetSelector) = case targetSelectorFilter targetSelector of Just kind | kind /= TestKind -> "The test command is for running test suites, but the target '"@@ -259,16 +256,27 @@ ++ "\n" ++ show targetSelector _ -> renderTargetProblemNoTargets "test" targetSelector+renderTestTargetProblem problem =+ renderTargetProblem "test" renderTestProblem problem -renderTargetProblem (TargetProblemComponentNotTest pkgid cname) =++renderTestProblem :: TestProblem -> String+renderTestProblem (TargetProblemNoTests targetSelector) =+ "Cannot run tests for the target '" ++ showTargetSelector targetSelector+ ++ "' which refers to " ++ renderTargetSelector targetSelector+ ++ " because "+ ++ plural (targetSelectorPluralPkgs targetSelector) "it does" "they do"+ ++ " not contain any test suites."++renderTestProblem (TargetProblemComponentNotTest pkgid cname) = "The test command is for running test suites, but the target '" ++ showTargetSelector targetSelector ++ "' refers to " ++ renderTargetSelector targetSelector ++ " from the package "- ++ display pkgid ++ "."+ ++ prettyShow pkgid ++ "." where targetSelector = TargetComponent pkgid cname WholeComponent -renderTargetProblem (TargetProblemIsSubComponent pkgid cname subtarget) =+renderTestProblem (TargetProblemIsSubComponent pkgid cname subtarget) = "The test command can only run test suites as a whole, " ++ "not files or modules within them, but the target '" ++ showTargetSelector targetSelector ++ "' refers to "
cabal/cabal-install/Distribution/Client/CmdUpdate.hs view
@@ -15,6 +15,8 @@ import Prelude () import Distribution.Client.Compat.Prelude +import Distribution.Client.NixStyleOptions+ ( NixStyleFlags (..), nixStyleOptions, defaultNixStyleFlags ) import Distribution.Client.Compat.Directory ( setModificationTime ) import Distribution.Client.ProjectOrchestration@@ -23,8 +25,10 @@ , ProjectConfigShared(projectConfigConfigFile) , projectConfigWithSolverRepoContext , withProjectOrGlobalConfig )+import Distribution.Client.ProjectFlags+ ( ProjectFlags (..) ) import Distribution.Client.Types- ( Repo(..), RemoteRepo(..), isRepoRemote )+ ( Repo(..), RepoName (..), unRepoName, RemoteRepo(..), isRepoRemote ) import Distribution.Client.HttpUtils ( DownloadResult(..) ) import Distribution.Client.FetchUtils@@ -32,48 +36,42 @@ import Distribution.Client.JobControl ( newParallelJobControl, spawnJob, collectJob ) import Distribution.Client.Setup- ( GlobalFlags, ConfigFlags(..), ConfigExFlags, InstallFlags+ ( GlobalFlags, ConfigFlags(..) , UpdateFlags, defaultUpdateFlags , RepoContext(..) )-import Distribution.Simple.Setup- ( HaddockFlags, TestFlags, BenchmarkFlags, fromFlagOrDefault )+import Distribution.Simple.Flag+ ( fromFlagOrDefault ) import Distribution.Simple.Utils ( die', notice, wrapText, writeFileAtomic, noticeNoWrap ) import Distribution.Verbosity- ( Verbosity, normal, lessVerbose )+ ( normal, lessVerbose ) import Distribution.Client.IndexUtils.Timestamp+import Distribution.Client.IndexUtils.IndexState import Distribution.Client.IndexUtils ( updateRepoIndexCache, Index(..), writeIndexTimestamp , currentIndexTimestamp, indexBaseName )-import Distribution.Deprecated.Text- ( Text(..), display, simpleParse ) -import Data.Maybe (fromJust)-import qualified Distribution.Deprecated.ReadP as ReadP-import qualified Text.PrettyPrint as Disp+import qualified Data.Maybe as Unsafe (fromJust)+import qualified Distribution.Compat.CharParsing as P+import qualified Text.PrettyPrint as Disp -import Control.Monad (mapM, mapM_) import qualified Data.ByteString.Lazy as BS import Distribution.Client.GZipUtils (maybeDecompress) import System.FilePath ((<.>), dropExtension) import Data.Time (getCurrentTime) import Distribution.Simple.Command ( CommandUI(..), usageAlternatives )-import qualified Distribution.Client.Setup as Client import qualified Hackage.Security.Client as Sec -updateCommand :: CommandUI ( ConfigFlags, ConfigExFlags- , InstallFlags, HaddockFlags- , TestFlags, BenchmarkFlags- )-updateCommand = Client.installCommand {- commandName = "v2-update",- commandSynopsis = "Updates list of known packages.",- commandUsage = usageAlternatives "v2-update" [ "[FLAGS] [REPOS]" ],- commandDescription = Just $ \_ -> wrapText $- "For all known remote repositories, download the package list.",- commandNotes = Just $ \pname ->+updateCommand :: CommandUI (NixStyleFlags ())+updateCommand = CommandUI+ { commandName = "v2-update"+ , commandSynopsis = "Updates list of known packages."+ , commandUsage = usageAlternatives "v2-update" [ "[FLAGS] [REPOS]" ]+ , commandDescription = Just $ \_ -> wrapText $+ "For all known remote repositories, download the package list."+ , commandNotes = Just $ \pname -> "REPO has the format <repo-id>[,<index-state>] where index-state follows\n" ++ "the same format and syntax that is supported by the --index-state flag.\n\n" ++ "Examples:\n"@@ -97,32 +95,31 @@ ++ "https://github.com/haskell/cabal/issues and if you\nhave any time " ++ "to get involved and help with testing, fixing bugs etc then\nthat " ++ "is very much appreciated.\n"+ -- TODO: Add ProjectFlags to NixStyleFlags,+ -- so project-file won't be ambiguous+ , commandOptions = nixStyleOptions $ const []+ , commandDefaultFlags = defaultNixStyleFlags () } data UpdateRequest = UpdateRequest- { _updateRequestRepoName :: String- , _updateRequestRepoState :: IndexState+ { _updateRequestRepoName :: RepoName+ , _updateRequestRepoState :: RepoIndexState } deriving (Show) -instance Text UpdateRequest where- disp (UpdateRequest n s) = Disp.text n Disp.<> Disp.char ',' Disp.<> disp s- parse = parseWithState ReadP.+++ parseHEAD- where parseWithState = do- name <- ReadP.many1 (ReadP.satisfy (\c -> c /= ','))- _ <- ReadP.char ','- state <- parse- return (UpdateRequest name state)- parseHEAD = do- name <- ReadP.manyTill (ReadP.satisfy (\c -> c /= ',')) ReadP.eof- return (UpdateRequest name IndexStateHead)+instance Pretty UpdateRequest where+ pretty (UpdateRequest n s) = pretty n <<>> Disp.comma <<>> pretty s -updateAction :: ( ConfigFlags, ConfigExFlags, InstallFlags- , HaddockFlags, TestFlags, BenchmarkFlags )- -> [String] -> GlobalFlags -> IO ()-updateAction ( configFlags, configExFlags, installFlags- , haddockFlags, testFlags, benchmarkFlags )- extraArgs globalFlags = do- projectConfig <- withProjectOrGlobalConfig verbosity globalConfigFlag+instance Parsec UpdateRequest where+ parsec = do+ name <- parsec+ state <- P.char ',' *> parsec <|> pure IndexStateHead+ return (UpdateRequest name state)++updateAction :: NixStyleFlags () -> [String] -> GlobalFlags -> IO ()+updateAction flags@NixStyleFlags {..} extraArgs globalFlags = do+ let ignoreProject = flagIgnoreProject projectFlags++ projectConfig <- withProjectOrGlobalConfig verbosity ignoreProject globalConfigFlag (projectConfig <$> establishProjectBaseContext verbosity cliConfig OtherCommand) (\globalConfig -> return $ globalConfig <> cliConfig) @@ -132,11 +129,11 @@ let repos = filter isRepoRemote $ repoContextRepos repoCtxt repoName = remoteRepoName . repoRemote parseArg :: String -> IO UpdateRequest- parseArg s = case simpleParse s of+ parseArg s = case simpleParsec s of Just r -> return r Nothing -> die' verbosity $ "'v2-update' unable to parse repo: \"" ++ s ++ "\""- updateRepoRequests <- mapM parseArg extraArgs+ updateRepoRequests <- traverse parseArg extraArgs unless (null updateRepoRequests) $ do let remoteRepoNames = map repoName repos@@ -144,17 +141,17 @@ , not (r `elem` remoteRepoNames)] unless (null unknownRepos) $ die' verbosity $ "'v2-update' repo(s): \""- ++ intercalate "\", \"" unknownRepos+ ++ intercalate "\", \"" (map unRepoName unknownRepos) ++ "\" can not be found in known remote repo(s): "- ++ intercalate ", " remoteRepoNames+ ++ intercalate ", " (map unRepoName remoteRepoNames) - let reposToUpdate :: [(Repo, IndexState)]+ let reposToUpdate :: [(Repo, RepoIndexState)] reposToUpdate = case updateRepoRequests of -- If we are not given any specific repository, update all -- repositories to HEAD. [] -> map (,IndexStateHead) repos updateRequests -> let repoMap = [(repoName r, r) | r <- repos]- lookup' k = fromJust (lookup k repoMap)+ lookup' k = Unsafe.fromJust (lookup k repoMap) in [ (lookup' name, state) | (UpdateRequest name state) <- updateRequests ] @@ -162,31 +159,27 @@ [] -> return () [(remoteRepo, _)] -> notice verbosity $ "Downloading the latest package list from "- ++ repoName remoteRepo+ ++ unRepoName (repoName remoteRepo) _ -> notice verbosity . unlines $ "Downloading the latest package lists from: "- : map (("- " ++) . repoName . fst) reposToUpdate+ : map (("- " ++) . unRepoName . repoName . fst) reposToUpdate jobCtrl <- newParallelJobControl (length reposToUpdate)- mapM_ (spawnJob jobCtrl . updateRepo verbosity defaultUpdateFlags repoCtxt)+ traverse_ (spawnJob jobCtrl . updateRepo verbosity defaultUpdateFlags repoCtxt) reposToUpdate- mapM_ (\_ -> collectJob jobCtrl) reposToUpdate+ traverse_ (\_ -> collectJob jobCtrl) reposToUpdate where verbosity = fromFlagOrDefault normal (configVerbosity configFlags)- cliConfig = commandLineFlagsToProjectConfig- globalFlags configFlags configExFlags- installFlags- mempty -- ClientInstallFlags, not needed here- haddockFlags testFlags benchmarkFlags+ cliConfig = commandLineFlagsToProjectConfig globalFlags flags mempty -- ClientInstallFlags, not needed here globalConfigFlag = projectConfigConfigFile (projectConfigShared cliConfig) -updateRepo :: Verbosity -> UpdateFlags -> RepoContext -> (Repo, IndexState)+updateRepo :: Verbosity -> UpdateFlags -> RepoContext -> (Repo, RepoIndexState) -> IO () updateRepo verbosity _updateFlags repoCtxt (repo, indexState) = do transport <- repoContextGetTransport repoCtxt case repo of- RepoLocal{..} -> return ()+ RepoLocalNoIndex{} -> return () RepoRemote{..} -> do downloadResult <- downloadIndex transport verbosity repoRemote repoLocalDir@@ -209,19 +202,30 @@ then Just `fmap` getCurrentTime else return Nothing updated <- Sec.uncheckClientErrors $ Sec.checkForUpdates repoSecure ce++ let rname = remoteRepoName (repoRemote repo)+ -- Update cabal's internal index as well so that it's not out of sync -- (If all access to the cache goes through hackage-security this can go) case updated of- Sec.NoUpdates ->- setModificationTime (indexBaseName repo <.> "tar")- =<< getCurrentTime- Sec.HasUpdates ->+ Sec.NoUpdates -> do+ now <- getCurrentTime+ setModificationTime (indexBaseName repo <.> "tar") now+ noticeNoWrap verbosity $+ "Package list of " ++ prettyShow rname +++ " is up to date at index-state " ++ prettyShow (IndexStateTime current_ts)++ Sec.HasUpdates -> do updateRepoIndexCache verbosity index- -- TODO: This will print multiple times if there are multiple- -- repositories: main problem is we don't have a way of updating- -- a specific repo. Once we implement that, update this.- when (current_ts /= nullTimestamp) $- noticeNoWrap verbosity $- "To revert to previous state run:\n" ++- " cabal v2-update '" ++ remoteRepoName (repoRemote repo)- ++ "," ++ display current_ts ++ "'\n"+ new_ts <- currentIndexTimestamp (lessVerbose verbosity) repoCtxt repo+ noticeNoWrap verbosity $+ "Updated package list of " ++ prettyShow rname +++ " to the index-state " ++ prettyShow (IndexStateTime new_ts)++ -- TODO: This will print multiple times if there are multiple+ -- repositories: main problem is we don't have a way of updating+ -- a specific repo. Once we implement that, update this.+ when (current_ts /= nullTimestamp) $+ noticeNoWrap verbosity $+ "To revert to previous state run:\n" +++ " cabal v2-update '" ++ prettyShow (UpdateRequest rname (IndexStateTime current_ts)) ++ "'\n"
cabal/cabal-install/Distribution/Client/Compat/Directory.hs view
@@ -1,13 +1,58 @@ {-# LANGUAGE CPP #-}-module Distribution.Client.Compat.Directory (setModificationTime) where+module Distribution.Client.Compat.Directory (+ setModificationTime,+ createFileLink,+ pathIsSymbolicLink,+ getSymbolicLinkTarget,+ ) where #if MIN_VERSION_directory(1,2,3) import System.Directory (setModificationTime) #else- import Data.Time.Clock (UTCTime)+#endif +#if MIN_VERSION_directory(1,3,1)+import System.Directory (createFileLink, getSymbolicLinkTarget, pathIsSymbolicLink)+#elif defined(MIN_VERSION_unix)+import System.Posix.Files (createSymbolicLink, getSymbolicLinkStatus, isSymbolicLink, readSymbolicLink)+#endif++-------------------------------------------------------------------------------+-- setModificationTime+-------------------------------------------------------------------------------++#if !MIN_VERSION_directory(1,2,3)+ setModificationTime :: FilePath -> UTCTime -> IO () setModificationTime _fp _t = return () +#endif++-------------------------------------------------------------------------------+-- Symlink+-------------------------------------------------------------------------------++#if MIN_VERSION_directory(1,3,1)+#elif defined(MIN_VERSION_unix)+createFileLink :: FilePath -> FilePath -> IO ()+createFileLink = createSymbolicLink++pathIsSymbolicLink :: FilePath -> IO Bool+pathIsSymbolicLink fp = do+ status <- getSymbolicLinkStatus fp+ return (isSymbolicLink status)++getSymbolicLinkTarget :: FilePath -> IO FilePath+getSymbolicLinkTarget = readSymbolicLink++#else+createFileLink :: FilePath -> FilePath -> IO ()+createFileLink _ _ = fail "Symlinking feature not available"++pathIsSymbolicLink :: FilePath -> IO Bool+pathIsSymbolicLink _ = fail "Symlinking feature not available"++getSymbolicLinkTarget :: FilePath -> IO FilePath+getSymbolicLinkTarget _ = fail "Symlinking feature not available" #endif
cabal/cabal-install/Distribution/Client/Compat/ExecutablePath.hs view
@@ -7,6 +7,8 @@ module Distribution.Client.Compat.ExecutablePath ( getExecutablePath ) where +import Prelude+ -- The imports are purposely kept completely disjoint to prevent edits -- to one OS implementation from breaking another.
cabal/cabal-install/Distribution/Client/Compat/FilePerms.hs view
@@ -6,6 +6,8 @@ setFileHidden, ) where +import Prelude (FilePath, IO, return, ($))+ #ifndef mingw32_HOST_OS import System.Posix.Types ( FileMode )
+ cabal/cabal-install/Distribution/Client/Compat/Orphans.hs view
@@ -0,0 +1,41 @@+{-# LANGUAGE BangPatterns #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+module Distribution.Client.Compat.Orphans () where++import Control.Exception (SomeException)+import Distribution.Compat.Binary (Binary (..))+import Distribution.Compat.Typeable (typeRep)+import Distribution.Utils.Structured (Structure (Nominal), Structured (..))+import Network.URI (URI (..), URIAuth (..))+import Prelude (error, return)++-------------------------------------------------------------------------------+-- network-uri+-------------------------------------------------------------------------------++-- note, network-uri-2.6.0.3+ provide a Generic instance but earlier+-- versions do not, so we use manual Binary instances here+instance Binary URI where+ put (URI a b c d e) = do put a; put b; put c; put d; put e+ get = do !a <- get; !b <- get; !c <- get; !d <- get; !e <- get+ return (URI a b c d e)++instance Structured URI where+ structure p = Nominal (typeRep p) 0 "URI" []++instance Binary URIAuth where+ put (URIAuth a b c) = do put a; put b; put c+ get = do !a <- get; !b <- get; !c <- get; return (URIAuth a b c)++-------------------------------------------------------------------------------+-- base+-------------------------------------------------------------------------------++--FIXME: Duncan Coutts: this is a total cheat+--Added in 46aa019ec85e313e257d122a3549cce01996c566+instance Binary SomeException where+ put _ = return ()+ get = error "cannot serialise exceptions"++instance Structured SomeException where+ structure p = Nominal (typeRep p) 0 "SomeException" []
cabal/cabal-install/Distribution/Client/Compat/Prelude.hs view
@@ -12,8 +12,13 @@ -- module Distribution.Client.Compat.Prelude ( module Distribution.Compat.Prelude.Internal- , Prelude.IO+ , module X ) where -import Prelude (IO)-import Distribution.Compat.Prelude.Internal hiding (IO)+import Distribution.Client.Compat.Orphans ()+import Distribution.Compat.Prelude.Internal+import Prelude ()++import Distribution.Parsec as X (CabalParsing, Parsec (..), eitherParsec, explicitEitherParsec, simpleParsec)+import Distribution.Pretty as X (Pretty (..), prettyShow)+import Distribution.Verbosity as X (Verbosity)
cabal/cabal-install/Distribution/Client/Compat/Process.hs view
@@ -16,6 +16,8 @@ readProcessWithExitCode ) where +import Prelude (FilePath, IO, String, return, (||))+ import Control.Exception (catch, throw) import System.Exit (ExitCode (ExitFailure)) import System.IO.Error (isDoesNotExistError, isPermissionError)@@ -35,6 +37,9 @@ -- exception. This variant catches \"does not exist\" and -- \"permission denied\" exceptions and turns them into -- @ExitFailure@s.+--+-- TODO: this doesn't use 'Distrubution.Compat.Process'.+-- readProcessWithExitCode :: FilePath -> [String] -> String -> IO (ExitCode, String, String) readProcessWithExitCode cmd args input = P.readProcessWithExitCode cmd args input
cabal/cabal-install/Distribution/Client/Compat/Semaphore.hs view
@@ -7,11 +7,15 @@ , signalQSem ) where +import Prelude (IO, return, Eq (..), Int, Bool (..), ($), ($!), Num (..), flip)+ import Control.Concurrent.STM (TVar, atomically, newTVar, readTVar, retry, writeTVar) import Control.Exception (mask_, onException) import Control.Monad (join, unless) import Data.Typeable (Typeable)+import Data.List.NonEmpty (NonEmpty (..))+import qualified Data.List.NonEmpty as NE -- | 'QSem' is a quantity semaphore in which the resource is aqcuired -- and released in units of one. It provides guaranteed FIFO ordering@@ -97,8 +101,8 @@ checkwake2 [] = do writeTVar q 1 return (return ())- checkwake2 ys = do- let (z:zs) = reverse ys+ checkwake2 (y:ys) = do+ let (z:|zs) = NE.reverse (y:|ys) writeTVar b1 zs writeTVar b2 [] return (wake s z)
cabal/cabal-install/Distribution/Client/Config.hs view
@@ -28,6 +28,7 @@ defaultConfigFile, defaultCacheDir, defaultCompiler,+ defaultInstallPath, defaultLogsDir, defaultUserInstall, @@ -43,38 +44,42 @@ userConfigUpdate, createDefaultConfigFile, - remoteRepoFields+ remoteRepoFields,+ postProcessRepo, ) where +import Distribution.Client.Compat.Prelude+import Prelude ()+ import Language.Haskell.Extension ( Language(Haskell2010) ) import Distribution.Deprecated.ViewAsFieldDescr ( viewAsFieldDescr ) import Distribution.Client.Types- ( RemoteRepo(..), Username(..), Password(..), emptyRemoteRepo+ ( RemoteRepo(..), LocalRepo (..), emptyRemoteRepo , AllowOlder(..), AllowNewer(..), RelaxDeps(..), isRelaxDeps+ , RepoName (..), unRepoName )+import Distribution.Client.Types.Credentials (Username (..), Password (..)) import Distribution.Client.BuildReports.Types ( ReportLevel(..) ) import qualified Distribution.Client.Init.Types as IT ( InitFlags(..) )+import qualified Distribution.Client.Init.Defaults as IT import Distribution.Client.Setup ( GlobalFlags(..), globalCommand, defaultGlobalFlags , ConfigExFlags(..), configureExOptions, defaultConfigExFlags , initOptions , InstallFlags(..), installOptions, defaultInstallFlags , UploadFlags(..), uploadCommand- , ReportFlags(..), reportCommand- , showRepo, parseRepo, readRepo )+ , ReportFlags(..), reportCommand ) import Distribution.Client.CmdInstall.ClientInstallFlags ( ClientInstallFlags(..), defaultClientInstallFlags , clientInstallOptions ) import Distribution.Utils.NubList ( NubList, fromNubList, toNubList, overNubList ) -import Distribution.License- ( License(BSD3) ) import Distribution.Simple.Compiler ( DebugInfoLevel(..), OptimisationLevel(..) ) import Distribution.Simple.Setup@@ -94,41 +99,36 @@ , locatedErrorMsg, showPWarning , readFields, warning, lineNo , simpleField, listField, spaceListField- , parseFilePathQ, parseOptCommaList, parseTokenQ )+ , parseFilePathQ, parseOptCommaList, parseTokenQ, syntaxError+ , simpleFieldParsec, listFieldParsec+ ) import Distribution.Client.ParseUtils ( parseFields, ppFields, ppSection ) import Distribution.Client.HttpUtils ( isOldHackageURI ) import qualified Distribution.Deprecated.ParseUtils as ParseUtils ( Field(..) )-import qualified Distribution.Deprecated.Text as Text- ( Text(..), display ) import Distribution.Simple.Command ( CommandUI(commandOptions), commandDefaultFlags, ShowOrParseArgs(..) ) import Distribution.Simple.Program ( defaultProgramDb ) import Distribution.Simple.Utils ( die', notice, warn, lowercase, cabalVersion )+import Distribution.Client.Utils+ ( cabalInstallVersion ) import Distribution.Compiler ( CompilerFlavor(..), defaultCompilerFlavor ) import Distribution.Verbosity- ( Verbosity, normal )-import Distribution.Version- ( mkVersion )-+ ( normal )+import qualified Distribution.Compat.CharParsing as P+import Distribution.Client.ProjectFlags (ProjectFlags (..)) import Distribution.Solver.Types.ConstraintSource -import Data.List- ( partition, find, foldl', nubBy )-import Data.Maybe- ( fromMaybe )-import Control.Monad- ( when, unless, foldM, liftM ) import qualified Distribution.Deprecated.ReadP as Parse ( (<++), option )-import Distribution.Compat.Semigroup import qualified Text.PrettyPrint as Disp ( render, text, empty )+import Distribution.Parsec (parsecOptCommaList) import Text.PrettyPrint ( ($+$) ) import Text.PrettyPrint.HughesPJ@@ -143,38 +143,28 @@ ( isDoesNotExistError ) import Distribution.Compat.Environment ( getEnvironment, lookupEnv )-import Distribution.Compat.Exception- ( catchIO )-import qualified Paths_cabal_install- ( version )-import Data.Version- ( showVersion )-import Data.Char- ( isSpace ) import qualified Data.Map as M-import Data.Function- ( on )-import GHC.Generics ( Generic ) -- -- * Configuration saved in the config file -- -data SavedConfig = SavedConfig {- savedGlobalFlags :: GlobalFlags,- savedInitFlags :: IT.InitFlags,- savedInstallFlags :: InstallFlags,- savedClientInstallFlags :: ClientInstallFlags,- savedConfigureFlags :: ConfigFlags,- savedConfigureExFlags :: ConfigExFlags,- savedUserInstallDirs :: InstallDirs (Flag PathTemplate),- savedGlobalInstallDirs :: InstallDirs (Flag PathTemplate),- savedUploadFlags :: UploadFlags,- savedReportFlags :: ReportFlags,- savedHaddockFlags :: HaddockFlags,- savedTestFlags :: TestFlags,- savedBenchmarkFlags :: BenchmarkFlags- } deriving Generic+data SavedConfig = SavedConfig+ { savedGlobalFlags :: GlobalFlags+ , savedInitFlags :: IT.InitFlags+ , savedInstallFlags :: InstallFlags+ , savedClientInstallFlags :: ClientInstallFlags+ , savedConfigureFlags :: ConfigFlags+ , savedConfigureExFlags :: ConfigExFlags+ , savedUserInstallDirs :: InstallDirs (Flag PathTemplate)+ , savedGlobalInstallDirs :: InstallDirs (Flag PathTemplate)+ , savedUploadFlags :: UploadFlags+ , savedReportFlags :: ReportFlags+ , savedHaddockFlags :: HaddockFlags+ , savedTestFlags :: TestFlags+ , savedBenchmarkFlags :: BenchmarkFlags+ , savedProjectFlags :: ProjectFlags+ } deriving Generic instance Monoid SavedConfig where mempty = gmempty@@ -194,7 +184,8 @@ savedReportFlags = combinedSavedReportFlags, savedHaddockFlags = combinedSavedHaddockFlags, savedTestFlags = combinedSavedTestFlags,- savedBenchmarkFlags = combinedSavedBenchmarkFlags+ savedBenchmarkFlags = combinedSavedBenchmarkFlags,+ savedProjectFlags = combinedSavedProjectFlags } where -- This is ugly, but necessary. If we're mappending two config files, we@@ -249,15 +240,13 @@ globalVersion = combine globalVersion, globalNumericVersion = combine globalNumericVersion, globalConfigFile = combine globalConfigFile,- globalSandboxConfigFile = combine globalSandboxConfigFile, globalConstraintsFile = combine globalConstraintsFile, globalRemoteRepos = lastNonEmptyNL globalRemoteRepos, globalCacheDir = combine globalCacheDir,- globalLocalRepos = lastNonEmptyNL globalLocalRepos,+ globalLocalNoIndexRepos = lastNonEmptyNL globalLocalNoIndexRepos,+ globalActiveRepos = combine globalActiveRepos, globalLogsDir = combine globalLogsDir, globalWorldFile = combine globalWorldFile,- globalRequireSandbox = combine globalRequireSandbox,- globalIgnoreSandbox = combine globalIgnoreSandbox, globalIgnoreExpiry = combine globalIgnoreExpiry, globalHttpTransport = combine globalHttpTransport, globalNix = combine globalNix,@@ -312,6 +301,7 @@ installMaxBackjumps = combine installMaxBackjumps, installReorderGoals = combine installReorderGoals, installCountConflicts = combine installCountConflicts,+ installFineGrainedConflicts = combine installFineGrainedConflicts, installMinimizeConflictSet = combine installMinimizeConflictSet, installIndependentGoals = combine installIndependentGoals, installShadowPkgs = combine installShadowPkgs,@@ -336,19 +326,18 @@ installNumJobs = combine installNumJobs, installKeepGoing = combine installKeepGoing, installRunTests = combine installRunTests,- installOfflineMode = combine installOfflineMode,- installProjectFileName = combine installProjectFileName+ installOfflineMode = combine installOfflineMode } where combine = combine' savedInstallFlags lastNonEmptyNL = lastNonEmptyNL' savedInstallFlags - combinedSavedClientInstallFlags = ClientInstallFlags {- cinstInstallLibs = combine cinstInstallLibs,- cinstEnvironmentPath = combine cinstEnvironmentPath,- cinstOverwritePolicy = combine cinstOverwritePolicy,- cinstInstallMethod = combine cinstInstallMethod,- cinstInstalldir = combine cinstInstalldir+ combinedSavedClientInstallFlags = ClientInstallFlags+ { cinstInstallLibs = combine cinstInstallLibs+ , cinstEnvironmentPath = combine cinstEnvironmentPath+ , cinstOverwritePolicy = combine cinstOverwritePolicy+ , cinstInstallMethod = combine cinstInstallMethod+ , cinstInstalldir = combine cinstInstalldir } where combine = combine' savedClientInstallFlags@@ -527,6 +516,12 @@ combine = combine' savedBenchmarkFlags lastNonEmpty = lastNonEmpty' savedBenchmarkFlags + combinedSavedProjectFlags = ProjectFlags+ { flagProjectFileName = combine flagProjectFileName+ , flagIgnoreProject = combine flagIgnoreProject+ }+ where+ combine = combine' savedProjectFlags -- -- * Default config@@ -559,7 +554,7 @@ } } --- | This is the initial configuration that we write out to to the config file+-- | This is the initial configuration that we write out to the config file -- if the file does not exist (or the config we use if the file cannot be read -- for some other reason). When the config gets loaded it gets layered on top -- of 'baseSavedConfig' so we do not need to include it into the initial@@ -583,7 +578,7 @@ }, savedInstallFlags = mempty { installSummaryFile = toNubList [toPathTemplate (logsDir </> "build.log")],- installBuildReports= toFlag AnonymousReports,+ installBuildReports= toFlag NoReports, installNumJobs = toFlag Nothing }, savedClientInstallFlags = mempty {@@ -643,8 +638,9 @@ defaultRemoteRepo :: RemoteRepo defaultRemoteRepo = RemoteRepo name uri Nothing [] 0 False where- name = "hackage.haskell.org"- uri = URI "http:" (Just (URIAuth "" name "")) "/" "" ""+ str = "hackage.haskell.org"+ name = RepoName str+ uri = URI "http:" (Just (URIAuth "" str "")) "/" "" "" -- Note that lots of old ~/.cabal/config files will have the old url -- http://hackage.haskell.org/packages/archive -- but new config files can use the new url (without the /packages/archive)@@ -824,8 +820,8 @@ ,"--" ,"-- This config file was generated using the following versions" ,"-- of Cabal and cabal-install:"- ,"-- Cabal library version: " ++ Text.display cabalVersion- ,"-- cabal-install version: " ++ showVersion Paths_cabal_install.version+ ,"-- Cabal library version: " ++ prettyShow cabalVersion+ ,"-- cabal-install version: " ++ prettyShow cabalInstallVersion ,"","" ] @@ -844,11 +840,11 @@ }, savedInitFlags = mempty { IT.interactive = toFlag False,- IT.cabalVersion = toFlag (mkVersion [1,10]),+ IT.cabalVersion = toFlag IT.defaultCabalVersion, IT.language = toFlag Haskell2010,- IT.license = toFlag BSD3,- IT.sourceDirs = Nothing,- IT.applicationDirs = Nothing+ IT.license = NoFlag,+ IT.sourceDirs = Just [IT.defaultSourceDir],+ IT.applicationDirs = Just [IT.defaultApplicationDir] }, savedInstallFlags = defaultInstallFlags, savedClientInstallFlags= defaultClientInstallFlags,@@ -888,7 +884,7 @@ toSavedConfig liftGlobalFlag (commandOptions (globalCommand []) ParseArgs)- ["version", "numeric-version", "config-file", "sandbox-config-file"] []+ ["version", "numeric-version", "config-file"] [] ++ toSavedConfig liftConfigFlag (configureOptions ParseArgs)@@ -898,8 +894,8 @@ -- This is only here because viewAsFieldDescr gives us a parser -- that only recognises 'ghc' etc, the case-sensitive flag names, not -- what the normal case-insensitive parser gives us.- [simpleField "compiler"- (fromFlagOrDefault Disp.empty . fmap Text.disp) (optional Text.parse)+ [simpleFieldParsec "compiler"+ (fromFlagOrDefault Disp.empty . fmap pretty) (Flag <$> parsec <|> pure NoFlag) configHcFlavor (\v flags -> flags { configHcFlavor = v }) -- TODO: The following is a temporary fix. The "optimization"@@ -961,16 +957,16 @@ (configureExOptions ParseArgs src) [] [let pkgs = (Just . AllowOlder . RelaxDepsSome)- `fmap` parseOptCommaList Text.parse+ `fmap` parsecOptCommaList parsec parseAllowOlder = ((Just . AllowOlder . toRelaxDeps)- `fmap` Text.parse) Parse.<++ pkgs+ `fmap` parsec) Parse.<++ pkgs in simpleField "allow-older" (showRelaxDeps . fmap unAllowOlder) parseAllowOlder configAllowOlder (\v flags -> flags { configAllowOlder = v }) ,let pkgs = (Just . AllowNewer . RelaxDepsSome)- `fmap` parseOptCommaList Text.parse+ `fmap` parsecOptCommaList parsec parseAllowNewer = ((Just . AllowNewer . toRelaxDeps)- `fmap` Text.parse) Parse.<++ pkgs+ `fmap` parsec) Parse.<++ pkgs in simpleField "allow-newer" (showRelaxDeps . fmap unAllowNewer) parseAllowNewer configAllowNewer (\v flags -> flags { configAllowNewer = v })@@ -1018,9 +1014,7 @@ name = fieldName field replacement = find ((== name) . fieldName) replacements , name `notElem` exclusions ]- optional = Parse.option mempty . fmap toFlag - showRelaxDeps Nothing = mempty showRelaxDeps (Just rd) | isRelaxDeps rd = Disp.text "True" | otherwise = Disp.text "False"@@ -1034,8 +1028,8 @@ deprecatedFieldDescriptions :: [FieldDescr SavedConfig] deprecatedFieldDescriptions = [ liftGlobalFlag $- listField "repos"- (Disp.text . showRepo) parseRepo+ listFieldParsec "repos"+ pretty parsec (fromNubList . globalRemoteRepos) (\rs cfg -> cfg { globalRemoteRepos = toNubList rs }) , liftGlobalFlag $@@ -1118,9 +1112,9 @@ let init0 = savedInitFlags config user0 = savedUserInstallDirs config global0 = savedGlobalInstallDirs config- (remoteRepoSections0, haddockFlags, initFlags, user, global, paths, args) <-+ (remoteRepoSections0, localRepoSections0, haddockFlags, initFlags, user, global, paths, args) <- foldM parseSections- ([], savedHaddockFlags config, init0, user0, global0, [], [])+ ([], [], savedHaddockFlags config, init0, user0, global0, [], []) knownSections let remoteRepoSections =@@ -1128,9 +1122,15 @@ . nubBy ((==) `on` remoteRepoName) $ remoteRepoSections0 + let localRepoSections =+ reverse+ . nubBy ((==) `on` localRepoName)+ $ localRepoSections0+ return . fixConfigMultilines $ config { savedGlobalFlags = (savedGlobalFlags config) { globalRemoteRepos = toNubList remoteRepoSections,+ globalLocalNoIndexRepos = toNubList localRepoSections, -- the global extra prog path comes from the configure flag prog path globalProgPathExtra = configProgramPathExtra (savedConfigureFlags config) },@@ -1186,61 +1186,59 @@ parse = parseFields (configFieldDescriptions src ++ deprecatedFieldDescriptions) initial - parseSections (rs, h, i, u, g, p, a)- (ParseUtils.Section _ "repository" name fs) = do- r' <- parseFields remoteRepoFields (emptyRemoteRepo name) fs- when (remoteRepoKeyThreshold r' > length (remoteRepoRootKeys r')) $- warning $ "'key-threshold' for repository " ++ show (remoteRepoName r')- ++ " higher than number of keys"- when (not (null (remoteRepoRootKeys r'))- && remoteRepoSecure r' /= Just True) $- warning $ "'root-keys' for repository " ++ show (remoteRepoName r')- ++ " non-empty, but 'secure' not set to True."- return (r':rs, h, i, u, g, p, a)+ parseSections (rs, ls, h, i, u, g, p, a)+ (ParseUtils.Section lineno "repository" name fs) = do+ name' <- maybe (ParseFailed $ NoParse "repository name" lineno) return $+ simpleParsec name+ r' <- parseFields remoteRepoFields (emptyRemoteRepo name') fs+ r'' <- postProcessRepo lineno name r'+ case r'' of+ Left local -> return (rs, local:ls, h, i, u, g, p, a)+ Right remote -> return (remote:rs, ls, h, i, u, g, p, a) - parseSections (rs, h, i, u, g, p, a)+ parseSections (rs, ls, h, i, u, g, p, a) (ParseUtils.F lno "remote-repo" raw) = do- let mr' = readRepo raw+ let mr' = simpleParsec raw r' <- maybe (ParseFailed $ NoParse "remote-repo" lno) return mr'- return (r':rs, h, i, u, g, p, a)+ return (r':rs, ls, h, i, u, g, p, a) - parseSections accum@(rs, h, i, u, g, p, a)+ parseSections accum@(rs, ls, h, i, u, g, p, a) (ParseUtils.Section _ "haddock" name fs) | name == "" = do h' <- parseFields haddockFlagsFields h fs- return (rs, h', i, u, g, p, a)+ return (rs, ls, h', i, u, g, p, a) | otherwise = do warning "The 'haddock' section should be unnamed" return accum - parseSections accum@(rs, h, i, u, g, p, a)+ parseSections accum@(rs, ls, h, i, u, g, p, a) (ParseUtils.Section _ "init" name fs) | name == "" = do i' <- parseFields initFlagsFields i fs- return (rs, h, i', u, g, p, a)+ return (rs, ls, h, i', u, g, p, a) | otherwise = do warning "The 'init' section should be unnamed" return accum - parseSections accum@(rs, h, i, u, g, p, a)+ parseSections accum@(rs, ls, h, i, u, g, p, a) (ParseUtils.Section _ "install-dirs" name fs) | name' == "user" = do u' <- parseFields installDirsFields u fs- return (rs, h, i, u', g, p, a)+ return (rs, ls, h, i, u', g, p, a) | name' == "global" = do g' <- parseFields installDirsFields g fs- return (rs, h, i, u, g', p, a)+ return (rs, ls, h, i, u, g', p, a) | otherwise = do warning "The 'install-paths' section should be for 'user' or 'global'" return accum where name' = lowercase name- parseSections accum@(rs, h, i, u, g, p, a)+ parseSections accum@(rs, ls, h, i, u, g, p, a) (ParseUtils.Section _ "program-locations" name fs) | name == "" = do p' <- parseFields withProgramsFields p fs- return (rs, h, i, u, g, p', a)+ return (rs, ls, h, i, u, g, p', a) | otherwise = do warning "The 'program-locations' section should be unnamed" return accum- parseSections accum@(rs, h, i, u, g, p, a)+ parseSections accum@(rs, ls, h, i, u, g, p, a) (ParseUtils.Section _ "program-default-options" name fs) | name == "" = do a' <- parseFields withProgramOptionsFields a fs- return (rs, h, i, u, g, p, a')+ return (rs, ls, h, i, u, g, p, a') | otherwise = do warning "The 'program-default-options' section should be unnamed" return accum@@ -1248,6 +1246,37 @@ warning $ "Unrecognized stanza on line " ++ show (lineNo f) return accum +postProcessRepo :: Int -> String -> RemoteRepo -> ParseResult (Either LocalRepo RemoteRepo)+postProcessRepo lineno reponameStr repo0 = do+ when (null reponameStr) $+ syntaxError lineno $ "a 'repository' section requires the "+ ++ "repository name as an argument"++ reponame <- maybe (fail $ "Invalid repository name " ++ reponameStr) return $+ simpleParsec reponameStr++ case uriScheme (remoteRepoURI repo0) of+ -- TODO: check that there are no authority, query or fragment+ -- Note: the trailing colon is important+ "file+noindex:" -> do+ let uri = remoteRepoURI repo0+ return $ Left $ LocalRepo reponame (uriPath uri) (uriFragment uri == "#shared-cache")++ _ -> do+ let repo = repo0 { remoteRepoName = reponame }++ when (remoteRepoKeyThreshold repo > length (remoteRepoRootKeys repo)) $+ warning $ "'key-threshold' for repository "+ ++ show (remoteRepoName repo)+ ++ " higher than number of keys"++ when (not (null (remoteRepoRootKeys repo)) && remoteRepoSecure repo /= Just True) $+ warning $ "'root-keys' for repository "+ ++ show (remoteRepoName repo)+ ++ " non-empty, but 'secure' not set to True."++ return $ Right repo+ showConfig :: SavedConfig -> String showConfig = showConfigWithComments mempty @@ -1297,22 +1326,22 @@ installDirsFields = map viewAsFieldDescr installDirsOptions ppRemoteRepoSection :: RemoteRepo -> RemoteRepo -> Doc-ppRemoteRepoSection def vals = ppSection "repository" (remoteRepoName vals)- remoteRepoFields (Just def) vals+ppRemoteRepoSection def vals = ppSection "repository" (unRepoName (remoteRepoName vals))+ remoteRepoFields (Just def) vals remoteRepoFields :: [FieldDescr RemoteRepo] remoteRepoFields = [ simpleField "url" (text . show) (parseTokenQ >>= parseURI') remoteRepoURI (\x repo -> repo { remoteRepoURI = x })- , simpleField "secure"- showSecure (Just `fmap` Text.parse)+ , simpleFieldParsec "secure"+ showSecure (Just `fmap` parsec) remoteRepoSecure (\x repo -> repo { remoteRepoSecure = x }) , listField "root-keys" text parseTokenQ remoteRepoRootKeys (\x repo -> repo { remoteRepoRootKeys = x })- , simpleField "key-threshold"- showThreshold Text.parse+ , simpleFieldParsec "key-threshold"+ showThreshold P.integral remoteRepoKeyThreshold (\x repo -> repo { remoteRepoKeyThreshold = x }) ] where
cabal/cabal-install/Distribution/Client/Configure.hs view
@@ -63,12 +63,10 @@ ( InstalledPackageIndex, lookupPackageName ) import Distribution.Package ( Package(..), packageName, PackageId )-import Distribution.Types.Dependency- ( thisPackageVersion ) import Distribution.Types.GivenComponent ( GivenComponent(..) ) import Distribution.Types.PackageVersionConstraint- ( PackageVersionConstraint(..) )+ ( PackageVersionConstraint(..), thisPackageVersionConstraint ) import qualified Distribution.PackageDescription as PkgDesc import Distribution.PackageDescription.Parsec ( readGenericPackageDescription )@@ -82,12 +80,7 @@ , defaultPackageDesc ) import Distribution.System ( Platform )-import Distribution.Deprecated.Text ( display )-import Distribution.Verbosity as Verbosity- ( Verbosity ) -import Data.Foldable- ( forM_ ) import System.FilePath ( (</>) ) -- | Choose the Cabal version such that the setup scripts compiled against this@@ -245,7 +238,7 @@ maybeSetupBuildInfo :: Maybe PkgDesc.SetupBuildInfo maybeSetupBuildInfo = do ReadyPackage cpkg <- mpkg- let gpkg = packageDescription (confPkgSource cpkg)+ let gpkg = srcpkgDescription (confPkgSource cpkg) PkgDesc.setupBuildInfo (PkgDesc.packageDescription gpkg) -- Was a default 'custom-setup' stanza added by 'cabal-install' itself? If@@ -275,12 +268,12 @@ -> ConfigExFlags -> IO () checkConfigExFlags verbosity installedPkgIndex sourcePkgIndex flags = do- forM_ (safeHead unknownConstraints) $ \h ->+ for_ (safeHead unknownConstraints) $ \h -> warn verbosity $ "Constraint refers to an unknown package: " ++ showConstraint h- forM_ (safeHead unknownPreferences) $ \h ->+ for_ (safeHead unknownPreferences) $ \h -> warn verbosity $ "Preference refers to an unknown package: "- ++ display h+ ++ prettyShow h where unknownConstraints = filter (unknown . userConstraintPackageName . fst) $ configExConstraints flags@@ -289,7 +282,7 @@ unknown pkg = null (lookupPackageName installedPkgIndex pkg) && not (elemByPackageName sourcePkgIndex pkg) showConstraint (uc, src) =- display uc ++ " (" ++ showConstraintSource src ++ ")"+ prettyShow uc ++ " (" ++ showConstraintSource src ++ ")" -- | Make an 'InstallPlan' for the unpacked package in the current directory, -- and all its dependencies.@@ -312,10 +305,10 @@ let -- We create a local package and ask to resolve a dependency on it localPkg = SourcePackage {- packageInfoId = packageId pkg,- packageDescription = pkg,- packageSource = LocalUnpackedPackage ".",- packageDescrOverride = Nothing+ srcpkgPackageId = packageId pkg,+ srcpkgDescription = pkg,+ srcpkgSource = LocalUnpackedPackage ".",+ srcpkgDescrOverride = Nothing } testsEnabled = fromFlagOrDefault False $ configTests configFlags@@ -399,17 +392,17 @@ scriptOptions (Just pkg) configureCommand configureFlags (const extraArgs) where- gpkg = packageDescription spkg+ gpkg = srcpkgDescription spkg configureFlags = filterConfigureFlags configFlags { configIPID = if isJust (flagToMaybe (configIPID configFlags)) -- Make sure cabal configure --ipid works. then configIPID configFlags- else toFlag (display ipid),+ else toFlag (prettyShow ipid), configConfigurationsFlags = flags, -- We generate the legacy constraints as well as the new style precise -- deps. In the end only one set gets passed to Setup.hs configure, -- depending on the Cabal version we are talking to.- configConstraints = [ thisPackageVersion srcid+ configConstraints = [ thisPackageVersionConstraint srcid | ConfiguredId srcid (Just (PkgDesc.CLibName PkgDesc.LMainLibName)) _uid <- CD.nonSetupDeps deps ], configDependencies = [ GivenComponent (packageName srcid) cname uid
cabal/cabal-install/Distribution/Client/Dependency.hs view
@@ -34,9 +34,6 @@ standardInstallPolicy, PackageSpecifier(..), - -- ** Sandbox policy- applySandboxInstallPolicy,- -- ** Extra policy options upgradeDependencies, reinstallTargets,@@ -47,6 +44,7 @@ setPreferenceDefault, setReorderGoals, setCountConflicts,+ setFineGrainedConflicts, setMinimizeConflictSet, setIndependentGoals, setAvoidReinstalls,@@ -66,6 +64,9 @@ addSetupCabalMaxVersionConstraint, ) where +import Distribution.Client.Compat.Prelude+import qualified Prelude as Unsafe (head)+ import Distribution.Solver.Modular ( modularResolver, SolverConfig(..), PruneAfterFirstSuccess(..) ) import Distribution.Simple.PackageIndex (InstalledPackageIndex)@@ -82,8 +83,6 @@ import Distribution.Client.Dependency.Types ( PreSolver(..), Solver(..) , PackagesPreferenceDefault(..) )-import Distribution.Client.Sandbox.Types- ( SandboxPackageInfo(..) ) import Distribution.Package ( PackageName, mkPackageName, PackageIdentifier(PackageIdentifier), PackageId , Package(..), packageName, packageVersion )@@ -92,22 +91,16 @@ import qualified Distribution.PackageDescription.Configuration as PD import Distribution.PackageDescription.Configuration ( finalizePD )-import Distribution.Client.PackageUtils- ( externalBuildDepends ) import Distribution.Compiler ( CompilerInfo(..) ) import Distribution.System ( Platform ) import Distribution.Client.Utils ( duplicatesBy, mergeBy, MergeResult(..) )-import Distribution.Simple.Utils- ( comparing ) import Distribution.Simple.Setup ( asBool )-import Distribution.Deprecated.Text- ( display ) import Distribution.Verbosity- ( normal, Verbosity )+ ( normal ) import Distribution.Version import qualified Distribution.Compat.Graph as Graph @@ -132,12 +125,9 @@ import Distribution.Solver.Types.Variable import Data.List- ( foldl', sort, sortBy, nubBy, maximumBy, intercalate, nub )-import Data.Function (on)-import Data.Maybe (fromMaybe, mapMaybe)+ ( maximumBy ) import qualified Data.Map as Map import qualified Data.Set as Set-import Data.Set (Set) import Control.Exception ( assert ) @@ -159,6 +149,7 @@ depResolverSourcePkgIndex :: PackageIndex.PackageIndex UnresolvedSourcePackage, depResolverReorderGoals :: ReorderGoals, depResolverCountConflicts :: CountConflicts,+ depResolverFineGrainedConflicts :: FineGrainedConflicts, depResolverMinimizeConflictSet :: MinimizeConflictSet, depResolverIndependentGoals :: IndependentGoals, depResolverAvoidReinstalls :: AvoidReinstalls,@@ -187,7 +178,7 @@ showDepResolverParams :: DepResolverParams -> String showDepResolverParams p =- "targets: " ++ intercalate ", " (map display $ Set.toList (depResolverTargets p))+ "targets: " ++ intercalate ", " (map prettyShow $ Set.toList (depResolverTargets p)) ++ "\nconstraints: " ++ concatMap (("\n " ++) . showLabeledConstraint) (depResolverConstraints p)@@ -197,6 +188,7 @@ ++ "\nstrategy: " ++ show (depResolverPreferenceDefault p) ++ "\nreorder goals: " ++ show (asBool (depResolverReorderGoals p)) ++ "\ncount conflicts: " ++ show (asBool (depResolverCountConflicts p))+ ++ "\nfine grained conflicts: " ++ show (asBool (depResolverFineGrainedConflicts p)) ++ "\nminimize conflict set: " ++ show (asBool (depResolverMinimizeConflictSet p)) ++ "\nindependent goals: " ++ show (asBool (depResolverIndependentGoals p)) ++ "\navoid reinstalls: " ++ show (asBool (depResolverAvoidReinstalls p))@@ -235,11 +227,11 @@ -- showPackagePreference :: PackagePreference -> String showPackagePreference (PackageVersionPreference pn vr) =- display pn ++ " " ++ display (simplifyVersionRange vr)+ prettyShow pn ++ " " ++ prettyShow (simplifyVersionRange vr) showPackagePreference (PackageInstalledPreference pn ip) =- display pn ++ " " ++ show ip+ prettyShow pn ++ " " ++ show ip showPackagePreference (PackageStanzasPreference pn st) =- display pn ++ " " ++ show st+ prettyShow pn ++ " " ++ show st basicDepResolverParams :: InstalledPackageIndex -> PackageIndex.PackageIndex UnresolvedSourcePackage@@ -254,6 +246,7 @@ depResolverSourcePkgIndex = sourcePkgIndex, depResolverReorderGoals = ReorderGoals False, depResolverCountConflicts = CountConflicts True,+ depResolverFineGrainedConflicts = FineGrainedConflicts True, depResolverMinimizeConflictSet = MinimizeConflictSet False, depResolverIndependentGoals = IndependentGoals False, depResolverAvoidReinstalls = AvoidReinstalls False,@@ -310,6 +303,12 @@ depResolverCountConflicts = count } +setFineGrainedConflicts :: FineGrainedConflicts -> DepResolverParams -> DepResolverParams+setFineGrainedConflicts fineGrained params =+ params {+ depResolverFineGrainedConflicts = fineGrained+ }+ setMinimizeConflictSet :: MinimizeConflictSet -> DepResolverParams -> DepResolverParams setMinimizeConflictSet minimize params = params {@@ -467,9 +466,8 @@ sourcePkgIndex' = fmap relaxDeps $ depResolverSourcePkgIndex params relaxDeps :: UnresolvedSourcePackage -> UnresolvedSourcePackage- relaxDeps srcPkg = srcPkg {- packageDescription = relaxPackageDeps relKind relDeps- (packageDescription srcPkg)+ relaxDeps srcPkg = srcPkg+ { srcpkgDescription = relaxPackageDeps relKind relDeps (srcpkgDescription srcPkg) } -- | Relax the dependencies of this package if needed.@@ -544,7 +542,7 @@ applyDefaultSetupDeps :: UnresolvedSourcePackage -> UnresolvedSourcePackage applyDefaultSetupDeps srcpkg = srcpkg {- packageDescription = gpkgdesc {+ srcpkgDescription = gpkgdesc { PD.packageDescription = pkgdesc { PD.setupBuildInfo = case PD.setupBuildInfo pkgdesc of@@ -561,7 +559,7 @@ } where isCustom = PD.buildType pkgdesc == PD.Custom- gpkgdesc = packageDescription srcpkg+ gpkgdesc = srcpkgDescription srcpkg pkgdesc = PD.packageDescription gpkgdesc -- | If a package has a custom setup then we need to add a setup-depends@@ -654,11 +652,10 @@ -- Force Cabal >= 1.24 dep when the package is affected by #3199. mkDefaultSetupDeps :: UnresolvedSourcePackage -> Maybe [Dependency] mkDefaultSetupDeps srcpkg | affected =- Just [Dependency (mkPackageName "Cabal")- (orLaterVersion $ mkVersion [1,24]) (Set.singleton PD.LMainLibName)]+ Just [Dependency (mkPackageName "Cabal") (orLaterVersion $ mkVersion [1,24]) mainLibSet] | otherwise = Nothing where- gpkgdesc = packageDescription srcpkg+ gpkgdesc = srcpkgDescription srcpkg pkgdesc = PD.packageDescription gpkgdesc bt = PD.buildType pkgdesc affected = bt == PD.Custom && hasBuildableFalse gpkgdesc@@ -676,48 +673,6 @@ alwaysTrue (PD.Lit True) = True alwaysTrue _ = False --applySandboxInstallPolicy :: SandboxPackageInfo- -> DepResolverParams- -> DepResolverParams-applySandboxInstallPolicy- (SandboxPackageInfo modifiedDeps otherDeps allSandboxPkgs _allDeps)- params-- = addPreferences [ PackageInstalledPreference n PreferInstalled- | n <- installedNotModified ]-- . addTargets installedNotModified-- . addPreferences- [ PackageVersionPreference (packageName pkg)- (thisVersion (packageVersion pkg)) | pkg <- otherDeps ]-- . addConstraints- [ let pc = PackageConstraint- (scopeToplevel $ packageName pkg)- (PackagePropertyVersion $ thisVersion (packageVersion pkg))- in LabeledPackageConstraint pc ConstraintSourceModifiedAddSourceDep- | pkg <- modifiedDeps ]-- . addTargets [ packageName pkg | pkg <- modifiedDeps ]-- . hideInstalledPackagesSpecificBySourcePackageId- [ packageId pkg | pkg <- modifiedDeps ]-- -- We don't need to add source packages for add-source deps to the- -- 'installedPkgIndex' since 'getSourcePackages' did that for us.-- $ params-- where- installedPkgIds =- map fst . InstalledPackageIndex.allPackagesBySourcePackageId- $ allSandboxPkgs- modifiedPkgIds = map packageId modifiedDeps- installedNotModified = [ packageName pkg | pkg <- installedPkgIds,- pkg `notElem` modifiedPkgIds ]- -- ------------------------------------------------------------ -- * Interface to the standard resolver -- ------------------------------------------------------------@@ -755,20 +710,22 @@ Step (showDepResolverParams finalparams) $ fmap (validateSolverResult platform comp indGoals)- $ runSolver solver (SolverConfig reordGoals cntConflicts minimize indGoals noReinstalls+ $ runSolver solver (SolverConfig reordGoals cntConflicts fineGrained minimize+ indGoals noReinstalls shadowing strFlags allowBootLibs onlyConstrained_ maxBkjumps enableBj solveExes order verbosity (PruneAfterFirstSuccess False)) platform comp installedPkgIndex sourcePkgIndex pkgConfigDB preferences constraints targets where - finalparams @ (DepResolverParams+ finalparams@(DepResolverParams targets constraints prefs defpref installedPkgIndex sourcePkgIndex reordGoals cntConflicts+ fineGrained minimize indGoals noReinstalls@@ -868,12 +825,12 @@ showPlanPackageProblem :: PlanPackageProblem -> String showPlanPackageProblem (InvalidConfiguredPackage pkg packageProblems) =- "Package " ++ display (packageId pkg)+ "Package " ++ prettyShow (packageId pkg) ++ " has an invalid configuration, in particular:\n" ++ unlines [ " " ++ showPackageProblem problem | problem <- packageProblems ] showPlanPackageProblem (DuplicatePackageSolverId pid dups) =- "Package " ++ display (packageId pid) ++ " has "+ "Package " ++ prettyShow (packageId pid) ++ " has " ++ show (length dups) ++ " duplicate instances." planPackagesProblems :: Platform -> CompilerInfo@@ -884,7 +841,7 @@ | Configured pkg <- pkgs , let packageProblems = configuredPackageProblems platform cinfo pkg , not (null packageProblems) ]- ++ [ DuplicatePackageSolverId (Graph.nodeKey (head dups)) dups+ ++ [ DuplicatePackageSolverId (Graph.nodeKey (Unsafe.head dups)) dups | dups <- duplicatesBy (comparing Graph.nodeKey) pkgs ] data PackageProblem = DuplicateFlag PD.FlagName@@ -907,20 +864,20 @@ showPackageProblem (DuplicateDeps pkgids) = "duplicate packages specified as selected dependencies: "- ++ intercalate ", " (map display pkgids)+ ++ intercalate ", " (map prettyShow pkgids) showPackageProblem (MissingDep dep) =- "the package has a dependency " ++ display dep+ "the package has a dependency " ++ prettyShow dep ++ " but no package has been selected to satisfy it." showPackageProblem (ExtraDep pkgid) =- "the package configuration specifies " ++ display pkgid+ "the package configuration specifies " ++ prettyShow pkgid ++ " but (with the given flag assignment) the package does not actually" ++ " depend on any version of that package." showPackageProblem (InvalidDep dep pkgid) =- "the package depends on " ++ display dep- ++ " but the configuration specifies " ++ display pkgid+ "the package depends on " ++ prettyShow dep+ ++ " but the configuration specifies " ++ prettyShow pkgid ++ " which does not satisfy the dependency." -- | A 'ConfiguredPackage' is valid if the flag assignment is total and if@@ -930,25 +887,30 @@ configuredPackageProblems :: Platform -> CompilerInfo -> SolverPackage UnresolvedPkgLoc -> [PackageProblem] configuredPackageProblems platform cinfo- (SolverPackage pkg specifiedFlags stanzas specifiedDeps' _specifiedExeDeps') =+ (SolverPackage pkg specifiedFlags stanzas specifiedDeps0 _specifiedExeDeps') = [ DuplicateFlag flag | flag <- PD.findDuplicateFlagAssignments specifiedFlags ] ++ [ MissingFlag flag | OnlyInLeft flag <- mergedFlags ] ++ [ ExtraFlag flag | OnlyInRight flag <- mergedFlags ] ++ [ DuplicateDeps pkgs | pkgs <- CD.nonSetupDeps (fmap (duplicatesBy (comparing packageName))- specifiedDeps) ]+ specifiedDeps1) ] ++ [ MissingDep dep | OnlyInLeft dep <- mergedDeps ] ++ [ ExtraDep pkgid | OnlyInRight pkgid <- mergedDeps ] ++ [ InvalidDep dep pkgid | InBoth dep pkgid <- mergedDeps , not (packageSatisfiesDependency pkgid dep) ] -- TODO: sanity tests on executable deps where- specifiedDeps :: ComponentDeps [PackageId]- specifiedDeps = fmap (map solverSrcId) specifiedDeps'+ thisPkgName = packageName (srcpkgDescription pkg) + specifiedDeps1 :: ComponentDeps [PackageId]+ specifiedDeps1 = fmap (map solverSrcId) specifiedDeps0++ specifiedDeps :: [PackageId]+ specifiedDeps = CD.flatDeps specifiedDeps1+ mergedFlags = mergeBy compare- (sort $ map PD.flagName (PD.genPackageFlags (packageDescription pkg)))+ (sort $ map PD.flagName (PD.genPackageFlags (srcpkgDescription pkg))) (sort $ map fst (PD.unFlagAssignment specifiedFlags)) -- TODO packageSatisfiesDependency@@ -959,7 +921,7 @@ dependencyName (Dependency name _ _) = name mergedDeps :: [MergeResult Dependency PackageId]- mergedDeps = mergeDeps requiredDeps (CD.flatDeps specifiedDeps)+ mergedDeps = mergeDeps requiredDeps specifiedDeps mergeDeps :: [Dependency] -> [PackageId] -> [MergeResult Dependency PackageId]@@ -985,9 +947,17 @@ (const True) platform cinfo []- (packageDescription pkg) of+ (srcpkgDescription pkg) of Right (resolvedPkg, _) ->- externalBuildDepends resolvedPkg compSpec+ -- we filter self/internal dependencies. They are still there.+ -- This is INCORRECT.+ --+ -- If we had per-component solver, it would make this unnecessary,+ -- but no finalizePDs picks components we are not building, eg. exes.+ -- See #3775+ --+ filter ((/= thisPkgName) . dependencyName)+ (PD.enabledBuildDepends resolvedPkg compSpec) ++ maybe [] PD.setupDepends (PD.setupBuildInfo resolvedPkg) Left _ -> error "configuredPackageInvalidDeps internal error"@@ -1015,9 +985,9 @@ -> Either [ResolveNoDepsError] [UnresolvedSourcePackage] resolveWithoutDependencies (DepResolverParams targets constraints prefs defpref installedPkgIndex sourcePkgIndex- _reorderGoals _countConflicts _minimizeConflictSet- _indGoals _avoidReinstalls _shadowing _strFlags- _maxBjumps _enableBj _solveExes+ _reorderGoals _countConflicts _fineGrained+ _minimizeConflictSet _indGoals _avoidReinstalls+ _shadowing _strFlags _maxBjumps _enableBj _solveExes _allowBootLibInstalls _onlyConstrained _order _verbosity) = collectEithers $ map selectPackage (Set.toList targets) where@@ -1066,11 +1036,6 @@ where collect ([], xs) = Right xs collect (errs,_) = Left errs- partitionEithers :: [Either a b] -> ([a],[b])- partitionEithers = foldr (either left right) ([],[])- where- left a (l, r) = (a:l, r)- right a (l, r) = (l, a:r) -- | Errors for 'resolveWithoutDependencies'. --@@ -1083,5 +1048,5 @@ instance Show ResolveNoDepsError where show (ResolveUnsatisfiable name ver) =- "There is no available version of " ++ display name- ++ " that satisfies " ++ display (simplifyVersionRange ver)+ "There is no available version of " ++ prettyShow name+ ++ " that satisfies " ++ prettyShow (simplifyVersionRange ver)
cabal/cabal-install/Distribution/Client/Dependency/Types.hs view
@@ -2,23 +2,15 @@ module Distribution.Client.Dependency.Types ( PreSolver(..), Solver(..),- PackagesPreferenceDefault(..),- ) where -import Data.Char- ( isAlpha, toLower )+import Distribution.Client.Compat.Prelude+import Prelude () -import qualified Distribution.Deprecated.ReadP as Parse- ( pfail, munch1 )-import Distribution.Deprecated.Text- ( Text(..) )+import Text.PrettyPrint (text) -import Text.PrettyPrint- ( text )-import GHC.Generics (Generic)-import Distribution.Compat.Binary (Binary(..))+import qualified Distribution.Compat.CharParsing as P -- | All the solvers that can be selected.@@ -32,13 +24,18 @@ instance Binary PreSolver instance Binary Solver -instance Text PreSolver where- disp AlwaysModular = text "modular"- parse = do- name <- Parse.munch1 isAlpha- case map toLower name of- "modular" -> return AlwaysModular- _ -> Parse.pfail+instance Structured PreSolver+instance Structured Solver++instance Pretty PreSolver where+ pretty AlwaysModular = text "modular"++instance Parsec PreSolver where+ parsec = do+ name <- P.munch1 isAlpha+ case map toLower name of+ "modular" -> return AlwaysModular+ _ -> P.unexpected $ "PreSolver: " ++ name -- | Global policy for all packages to say if we prefer package versions that -- are already installed locally or if we just prefer the latest available.
cabal/cabal-install/Distribution/Client/DistDirLayout.hs view
@@ -22,7 +22,9 @@ defaultCabalDirLayout ) where -import Data.Maybe (fromMaybe)+import Distribution.Client.Compat.Prelude+import Prelude ()+ import System.FilePath import Distribution.Package@@ -30,9 +32,6 @@ import Distribution.Compiler import Distribution.Simple.Compiler ( PackageDB(..), PackageDBStack, OptimisationLevel(..) )-import Distribution.Deprecated.Text-import Distribution.Pretty- ( prettyShow ) import Distribution.Types.ComponentName import Distribution.Types.LibraryName import Distribution.System@@ -155,11 +154,11 @@ -- | Information about the root directory of the project. ----- It can either be an implict project root in the current dir if no+-- It can either be an implicit project root in the current dir if no -- @cabal.project@ file is found, or an explicit root if the file is found. -- data ProjectRoot =- -- | -- ^ An implict project root. It contains the absolute project+ -- | -- ^ An implicit project root. It contains the absolute project -- root dir. ProjectRootImplicit FilePath @@ -193,29 +192,29 @@ distBuildRootDirectory = distDirectory </> "build" distBuildDirectory params = distBuildRootDirectory </>- display (distParamPlatform params) </>- display (distParamCompilerId params) </>- display (distParamPackageId params) </>+ prettyShow (distParamPlatform params) </>+ prettyShow (distParamCompilerId params) </>+ prettyShow (distParamPackageId params) </> (case distParamComponentName params of Nothing -> "" Just (CLibName LMainLibName) -> ""- Just (CLibName (LSubLibName name)) -> "l" </> display name- Just (CFLibName name) -> "f" </> display name- Just (CExeName name) -> "x" </> display name- Just (CTestName name) -> "t" </> display name- Just (CBenchName name) -> "b" </> display name) </>+ Just (CLibName (LSubLibName name)) -> "l" </> prettyShow name+ Just (CFLibName name) -> "f" </> prettyShow name+ Just (CExeName name) -> "x" </> prettyShow name+ Just (CTestName name) -> "t" </> prettyShow name+ Just (CBenchName name) -> "b" </> prettyShow name) </> (case distParamOptimization params of NoOptimisation -> "noopt" NormalOptimisation -> "" MaximumOptimisation -> "opt") </>- (let uid_str = display (distParamUnitId params)- in if uid_str == display (distParamComponentId params)+ (let uid_str = prettyShow (distParamUnitId params)+ in if uid_str == prettyShow (distParamComponentId params) then "" else uid_str) distUnpackedSrcRootDirectory = distDirectory </> "src" distUnpackedSrcDirectory pkgid = distUnpackedSrcRootDirectory- </> display pkgid+ </> prettyShow pkgid -- we shouldn't get name clashes so this should be fine: distDownloadSrcDirectory = distUnpackedSrcRootDirectory @@ -233,7 +232,7 @@ distBinDirectory = distDirectory </> "bin" - distPackageDBPath compid = distDirectory </> "packagedb" </> display compid+ distPackageDBPath compid = distDirectory </> "packagedb" </> prettyShow compid distPackageDB = SpecificPackageDB . distPackageDBPath @@ -242,10 +241,10 @@ StoreDirLayout {..} where storeDirectory compid =- storeRoot </> display compid+ storeRoot </> prettyShow compid storePackageDirectory compid ipkgid =- storeDirectory compid </> display ipkgid+ storeDirectory compid </> prettyShow ipkgid storePackageDBPath compid = storeDirectory compid </> "package.db"@@ -260,7 +259,7 @@ storeDirectory compid </> "incoming" storeIncomingLock compid unitid =- storeIncomingDirectory compid </> display unitid <.> "lock"+ storeIncomingDirectory compid </> prettyShow unitid <.> "lock" defaultCabalDirLayout :: FilePath -> CabalDirLayout
cabal/cabal-install/Distribution/Client/Exec.hs view
@@ -14,44 +14,28 @@ import Prelude () import Distribution.Client.Compat.Prelude -import qualified Distribution.Simple.GHC as GHC-import qualified Distribution.Simple.GHCJS as GHCJS--import Distribution.Client.Sandbox (getSandboxConfigFilePath)-import Distribution.Client.Sandbox.PackageEnvironment (sandboxPackageDBPath)-import Distribution.Client.Sandbox.Types (UseSandbox (..))--import Distribution.Simple.Compiler (Compiler, CompilerFlavor(..), compilerFlavor)-import Distribution.Simple.Program (ghcProgram, ghcjsProgram, lookupProgram)+import Distribution.Simple.Compiler (Compiler) import Distribution.Simple.Program.Db (ProgramDb, requireProgram, modifyProgramSearchPath)-import Distribution.Simple.Program.Find (ProgramSearchPathEntry(..)) import Distribution.Simple.Program.Run (programInvocation, runProgramInvocation) import Distribution.Simple.Program.Types ( simpleProgram, ConfiguredProgram(..) )-import Distribution.Simple.Utils (die', warn)--import Distribution.System (Platform(..), OS(..), buildOS)-import Distribution.Verbosity (Verbosity)--import System.Directory ( doesDirectoryExist )-import System.Environment (lookupEnv)-import System.FilePath (searchPathSeparator, (</>))+import Distribution.Simple.Utils (die') +import Distribution.System (Platform(..)) -- | Execute the given command in the package's environment. -- -- The given command is executed with GHC configured to use the correct -- package database and with the sandbox bin directory added to the PATH. exec :: Verbosity- -> UseSandbox -> Compiler -> Platform -> ProgramDb -> [String] -> IO ()-exec verbosity useSandbox comp platform programDb extraArgs =+exec verbosity _comp _platform programDb extraArgs = case extraArgs of (exe:args) -> do- program <- requireProgram' verbosity useSandbox programDb exe+ program <- requireProgram' verbosity programDb exe env <- environmentOverrides (programOverrideEnv program) let invocation = programInvocation program { programOverrideEnv = env }@@ -60,113 +44,15 @@ [] -> die' verbosity "Please specify an executable to run" where- environmentOverrides env =- case useSandbox of- NoSandbox -> return env- (UseSandbox sandboxDir) ->- sandboxEnvironment verbosity sandboxDir comp platform programDb env----- | Return the package's sandbox environment.------ The environment sets GHC_PACKAGE_PATH so that GHC will use the sandbox.-sandboxEnvironment :: Verbosity- -> FilePath- -> Compiler- -> Platform- -> ProgramDb- -> [(String, Maybe String)] -- environment overrides so far- -> IO [(String, Maybe String)]-sandboxEnvironment verbosity sandboxDir comp platform programDb iEnv =- case compilerFlavor comp of- GHC -> env GHC.getGlobalPackageDB ghcProgram "GHC_PACKAGE_PATH"- GHCJS -> env GHCJS.getGlobalPackageDB ghcjsProgram "GHCJS_PACKAGE_PATH"- _ -> die' verbosity "exec only works with GHC and GHCJS"- where- (Platform _ os) = platform- ldPath = case os of- OSX -> "DYLD_LIBRARY_PATH"- Windows -> "PATH"- _ -> "LD_LIBRARY_PATH"- env getGlobalPackageDB hcProgram packagePathEnvVar = do- let Just program = lookupProgram hcProgram programDb- gDb <- getGlobalPackageDB verbosity program- sandboxConfigFilePath <- getSandboxConfigFilePath mempty- let sandboxPackagePath = sandboxPackageDBPath sandboxDir comp platform- compilerPackagePaths = prependToSearchPath gDb sandboxPackagePath- -- Packages database must exist, otherwise things will start- -- failing in mysterious ways.- exists <- doesDirectoryExist sandboxPackagePath- unless exists $ warn verbosity $ "Package database is not a directory: "- ++ sandboxPackagePath- -- MASSIVE HACK. We need this to be synchronized with installLibDir- -- in defaultInstallDirs' in Distribution.Simple.InstallDirs,- -- which has a special case for Windows (WHY? Who knows; it's been- -- around as long as Windows exists.) The sane thing to do here- -- would be to read out the actual install dirs that were associated- -- with the package in question, but that's not a well-formed question- -- here because there is not actually install directory for the- -- "entire" sandbox. Since we want to kill this code in favor of- -- new-build, I decided it wasn't worth fixing this "properly."- -- Also, this doesn't handle LHC correctly but I don't care -- ezyang- let extraLibPath =- case buildOS of- Windows -> sandboxDir- _ -> sandboxDir </> "lib"- -- 2016-11-26 Apologies for the spaghetti code here.- -- Essentially we just want to add the sandbox's lib/ dir to- -- whatever the library search path environment variable is:- -- this allows running existing executables against foreign- -- libraries (meaning Haskell code with a bunch of foreign- -- exports). However, on Windows this variable is equal to the- -- executable search path env var. And we try to keep not only- -- what was already set in the environment, but also the- -- additional directories we add below in requireProgram'. So- -- the strategy is that we first take the environment- -- overrides from requireProgram' below. If the library search- -- path env is overridden (e.g. because we're on windows), we- -- prepend the lib/ dir to the relevant override. If not, we- -- want to avoid wiping the user's own settings, so we first- -- read the env var's current value, and then prefix ours if- -- the user had any set.- iEnv' <-- if any ((==ldPath) . fst) iEnv- then return $ updateLdPath extraLibPath iEnv- else do- currentLibraryPath <- lookupEnv ldPath- let updatedLdPath =- case currentLibraryPath of- Nothing -> Just extraLibPath- Just paths ->- Just $ extraLibPath ++ [searchPathSeparator] ++ paths- return $ (ldPath, updatedLdPath) : iEnv-- -- Build the environment- return $ [ (packagePathEnvVar, Just compilerPackagePaths)- , ("CABAL_SANDBOX_PACKAGE_PATH", Just compilerPackagePaths)- , ("CABAL_SANDBOX_CONFIG", Just sandboxConfigFilePath)- ] ++ iEnv'-- prependToSearchPath path newValue =- newValue ++ [searchPathSeparator] ++ path-- updateLdPath path = map update- where- update (name, Just current)- | name == ldPath = (ldPath, Just $ path ++ [searchPathSeparator] ++ current)- update (name, Nothing)- | name == ldPath = (ldPath, Just path)- update x = x-+ environmentOverrides env = return env -- | Check that a program is configured and available to be run. If -- a sandbox is available check in the sandbox's directory. requireProgram' :: Verbosity- -> UseSandbox -> ProgramDb -> String -> IO ConfiguredProgram-requireProgram' verbosity useSandbox programDb exe = do+requireProgram' verbosity programDb exe = do (program, _) <- requireProgram verbosity (simpleProgram exe)@@ -174,8 +60,4 @@ return program where updateSearchPath =- flip modifyProgramSearchPath programDb $ \searchPath ->- case useSandbox of- NoSandbox -> searchPath- UseSandbox sandboxDir ->- ProgramSearchPathDir (sandboxDir </> "bin") : searchPath+ flip modifyProgramSearchPath programDb $ \searchPath -> searchPath
cabal/cabal-install/Distribution/Client/Fetch.hs view
@@ -14,6 +14,9 @@ fetch, ) where +import Distribution.Client.Compat.Prelude+import Prelude ()+ import Distribution.Client.Types import Distribution.Client.Targets import Distribution.Client.FetchUtils hiding (fetchPackage)@@ -44,14 +47,7 @@ ( die', notice, debug ) import Distribution.System ( Platform )-import Distribution.Deprecated.Text- ( display )-import Distribution.Verbosity- ( Verbosity ) -import Control.Monad- ( filterM )- -- ------------------------------------------------------------ -- * The fetch command -- ------------------------------------------------------------@@ -84,7 +80,7 @@ fetch verbosity packageDBs repoCtxt comp platform progdb globalFlags fetchFlags userTargets = do - mapM_ (checkTarget verbosity) userTargets+ traverse_ (checkTarget verbosity) userTargets installedPkgIndex <- getInstalledPackages verbosity comp packageDBs progdb sourcePkgDb <- getSourcePackages verbosity repoCtxt@@ -99,7 +95,7 @@ verbosity comp platform fetchFlags installedPkgIndex sourcePkgDb pkgConfigDb pkgSpecifiers - pkgs' <- filterM (fmap not . isFetched . packageSource) pkgs+ pkgs' <- filterM (fmap not . isFetched . srcpkgSource) pkgs if null pkgs' --TODO: when we add support for remote tarballs then this message -- will need to be changed because for remote tarballs we fetch them@@ -110,9 +106,9 @@ else if dryRun then notice verbosity $ unlines $ "The following packages would be fetched:"- : map (display . packageId) pkgs'+ : map (prettyShow . packageId) pkgs' - else mapM_ (fetchPackage verbosity repoCtxt . packageSource) pkgs'+ else traverse_ (fetchPackage verbosity repoCtxt . srcpkgSource) pkgs' where dryRun = fromFlag (fetchDryRun fetchFlags)@@ -162,6 +158,8 @@ . setCountConflicts countConflicts + . setFineGrainedConflicts fineGrainedConflicts+ . setMinimizeConflictSet minimizeConflictSet . setShadowPkgs shadowPkgs@@ -199,6 +197,7 @@ reorderGoals = fromFlag (fetchReorderGoals fetchFlags) countConflicts = fromFlag (fetchCountConflicts fetchFlags)+ fineGrainedConflicts = fromFlag (fetchFineGrainedConflicts fetchFlags) minimizeConflictSet = fromFlag (fetchMinimizeConflictSet fetchFlags) independentGoals = fromFlag (fetchIndependentGoals fetchFlags) shadowPkgs = fromFlag (fetchShadowPkgs fetchFlags)
cabal/cabal-install/Distribution/Client/FetchUtils.hs view
@@ -32,6 +32,9 @@ downloadIndex, ) where +import Distribution.Client.Compat.Prelude+import Prelude ()+ import Distribution.Client.Types import Distribution.Client.HttpUtils ( downloadURI, isOldHackageURI, DownloadResult(..)@@ -41,19 +44,14 @@ ( PackageId, packageName, packageVersion ) import Distribution.Simple.Utils ( notice, info, debug, die' )-import Distribution.Deprecated.Text- ( display ) import Distribution.Verbosity- ( Verbosity, verboseUnmarkOutput )+ ( verboseUnmarkOutput ) import Distribution.Client.GlobalFlags ( RepoContext(..) ) import Distribution.Client.Utils ( ProgressPhase(..), progressMessage ) -import Data.Maybe-import Data.Map (Map) import qualified Data.Map as Map-import Control.Monad import Control.Exception import Control.Concurrent.Async import Control.Concurrent.MVar@@ -84,8 +82,8 @@ RemoteTarballPackage _uri local -> return (isJust local) RepoTarballPackage repo pkgid _ -> doesFileExist (packageFile repo pkgid) RemoteSourceRepoPackage _ local -> return (isJust local)- + -- | Checks if the package has already been fetched (or does not need -- fetching) and if so returns evidence in the form of a 'PackageLocation' -- with a resolved local file location.@@ -101,8 +99,8 @@ return (Just $ RemoteTarballPackage uri file) RepoTarballPackage repo pkgid (Just file) -> return (Just $ RepoTarballPackage repo pkgid file)- RemoteSourceRepoPackage repo (Just dir) ->- return (Just $ RemoteSourceRepoPackage repo dir)+ RemoteSourceRepoPackage repo (Just file) ->+ return (Just $ RemoteSourceRepoPackage repo file) RemoteTarballPackage _uri Nothing -> return Nothing RemoteSourceRepoPackage _repo Nothing -> return Nothing@@ -165,18 +163,18 @@ fetchRepoTarball verbosity' repoCtxt repo pkgid = do fetched <- doesFileExist (packageFile repo pkgid) if fetched- then do info verbosity $ display pkgid ++ " has already been downloaded."+ then do info verbosity $ prettyShow pkgid ++ " has already been downloaded." return (packageFile repo pkgid)- else do progressMessage verbosity ProgressDownloading (display pkgid)+ else do progressMessage verbosity ProgressDownloading (prettyShow pkgid) res <- downloadRepoPackage- progressMessage verbosity ProgressDownloaded (display pkgid)+ progressMessage verbosity ProgressDownloaded (prettyShow pkgid) return res where -- whether we download or not is non-deterministic verbosity = verboseUnmarkOutput verbosity' downloadRepoPackage = case repo of- RepoLocal{..} -> return (packageFile repo pkgid)+ RepoLocalNoIndex{} -> return (packageFile repo pkgid) RepoRemote{..} -> do transport <- repoContextGetTransport repoCtxt@@ -237,13 +235,15 @@ asyncFetchPackages verbosity repoCtxt pkglocs body = do --TODO: [nice to have] use parallel downloads? - asyncDownloadVars <- sequence [ do v <- newEmptyMVar- return (pkgloc, v)- | pkgloc <- pkglocs ]+ asyncDownloadVars <- sequenceA+ [ do v <- newEmptyMVar+ return (pkgloc, v)+ | pkgloc <- pkglocs+ ] let fetchPackages :: IO () fetchPackages =- forM_ asyncDownloadVars $ \(pkgloc, var) -> do+ for_ asyncDownloadVars $ \(pkgloc, var) -> do -- Suppress marking here, because 'withAsync' means -- that we get nondeterministic interleaving result <- try $ fetchPackage (verboseUnmarkOutput verbosity)@@ -285,16 +285,17 @@ -- packageFile :: Repo -> PackageId -> FilePath packageFile repo pkgid = packageDir repo pkgid- </> display pkgid+ </> prettyShow pkgid <.> "tar.gz" -- | Generate the full path to the directory where the local cached copy of -- the tarball for a given @PackageIdentifer@ is stored. -- packageDir :: Repo -> PackageId -> FilePath+packageDir (RepoLocalNoIndex (LocalRepo _ dir _) _) _pkgid = dir packageDir repo pkgid = repoLocalDir repo- </> display (packageName pkgid)- </> display (packageVersion pkgid)+ </> prettyShow (packageName pkgid)+ </> prettyShow (packageVersion pkgid) -- | Generate the URI of the tarball for a given package. --@@ -303,14 +304,14 @@ (remoteRepoURI repo) { uriPath = FilePath.Posix.joinPath [uriPath (remoteRepoURI repo)- ,display (packageName pkgid)- ,display (packageVersion pkgid)- ,display pkgid <.> "tar.gz"]+ ,prettyShow (packageName pkgid)+ ,prettyShow (packageVersion pkgid)+ ,prettyShow pkgid <.> "tar.gz"] } packageURI repo pkgid = (remoteRepoURI repo) { uriPath = FilePath.Posix.joinPath [uriPath (remoteRepoURI repo) ,"package"- ,display pkgid <.> "tar.gz"]+ ,prettyShow pkgid <.> "tar.gz"] }
cabal/cabal-install/Distribution/Client/FileMonitor.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE DeriveGeneric, DeriveFunctor, GeneralizedNewtypeDeriving, NamedFieldPuns, BangPatterns #-} {-# OPTIONS_GHC -fno-warn-orphans #-}@@ -34,6 +35,11 @@ updateFileMonitor, MonitorTimestamp, beginUpdateFileMonitor,++ -- * Internal+ MonitorStateFileSet,+ MonitorStateFile,+ MonitorStateGlob, ) where import Prelude ()@@ -41,7 +47,6 @@ import qualified Data.Map.Strict as Map import qualified Data.ByteString.Lazy as BS-import qualified Distribution.Compat.Binary as Binary import qualified Data.Hashable as Hashable import Control.Monad@@ -56,7 +61,7 @@ import Distribution.Client.Glob import Distribution.Simple.Utils (handleDoesNotExist, writeFileAtomic) import Distribution.Client.Utils (mergeBy, MergeResult(..))-+import Distribution.Utils.Structured (structuredDecodeOrFailIO, structuredEncode) import System.FilePath import System.Directory import System.IO@@ -99,6 +104,10 @@ instance Binary MonitorKindFile instance Binary MonitorKindDir +instance Structured MonitorFilePath+instance Structured MonitorKindFile+instance Structured MonitorKindDir+ -- | Monitor a single file for changes, based on its modification time. -- The monitored file is considered to have changed if it no longer -- exists or if its modification time has changed.@@ -202,8 +211,11 @@ -- there is also no particular gain either. That said, we do preserve the -- order of the lists just to reduce confusion (and have predictable I/O -- patterns).- deriving Show+ deriving (Show, Generic) +instance Binary MonitorStateFileSet+instance Structured MonitorStateFileSet+ type Hash = Int -- | The state necessary to determine whether a monitored file has changed.@@ -232,6 +244,8 @@ instance Binary MonitorStateFile instance Binary MonitorStateFileStatus+instance Structured MonitorStateFile+instance Structured MonitorStateFileStatus -- | The state necessary to determine whether the files matched by a globbing -- match have changed.@@ -257,6 +271,9 @@ instance Binary MonitorStateGlob instance Binary MonitorStateGlobRel +instance Structured MonitorStateGlob+instance Structured MonitorStateGlobRel+ -- | We can build a 'MonitorStateFileSet' from a set of 'MonitorFilePath' by -- inspecting the state of the file system, and we can go in the reverse -- direction by just forgetting the extra info.@@ -399,7 +416,7 @@ -- See 'FileMonitor' for a full explanation. -- checkFileMonitorChanged- :: (Binary a, Binary b)+ :: (Binary a, Structured a, Binary b, Structured b) => FileMonitor a b -- ^ cache file path -> FilePath -- ^ root directory -> a -- ^ guard or key value@@ -477,23 +494,24 @@ -- -- This determines the type and format of the binary cache file. ---readCacheFile :: (Binary a, Binary b)+readCacheFile :: (Binary a, Structured a, Binary b, Structured b) => FileMonitor a b -> IO (Either String (MonitorStateFileSet, a, b)) readCacheFile FileMonitor {fileMonitorCacheFile} =- withBinaryFile fileMonitorCacheFile ReadMode $ \hnd ->- Binary.decodeOrFailIO =<< BS.hGetContents hnd+ withBinaryFile fileMonitorCacheFile ReadMode $ \hnd -> do+ contents <- BS.hGetContents hnd+ structuredDecodeOrFailIO contents -- | Helper for writing the cache file. -- -- This determines the type and format of the binary cache file. ---rewriteCacheFile :: (Binary a, Binary b)+rewriteCacheFile :: (Binary a, Structured a, Binary b, Structured b) => FileMonitor a b -> MonitorStateFileSet -> a -> b -> IO () rewriteCacheFile FileMonitor {fileMonitorCacheFile} fileset key result = writeFileAtomic fileMonitorCacheFile $- Binary.encode (fileset, key, result)+ structuredEncode (fileset, key, result) -- | Probe the file system to see if any of the monitored files have changed. --@@ -634,7 +652,7 @@ . filter (matchGlob glob) =<< liftIO (getDirectoryContents (root </> dirName)) - children' <- mapM probeMergeResult $+ children' <- traverse probeMergeResult $ mergeBy (\(path1,_) path2 -> compare path1 path2) children (sort matches)@@ -699,14 +717,14 @@ matches <- return . filter (matchGlob glob) =<< liftIO (getDirectoryContents (root </> dirName)) - mapM_ probeMergeResult $+ traverse_ probeMergeResult $ mergeBy (\(path1,_) path2 -> compare path1 path2) children (sort matches) return mtime' -- Check that none of the children have changed- forM_ children $ \(file, status) ->+ for_ children $ \(file, status) -> probeMonitorStateFileStatus root (dirName </> file) status @@ -754,7 +772,7 @@ -- any files then you can use @Nothing@ for the timestamp parameter. -- updateFileMonitor- :: (Binary a, Binary b)+ :: (Binary a, Structured a, Binary b, Structured b) => FileMonitor a b -- ^ cache file path -> FilePath -- ^ root directory -> Maybe MonitorTimestamp -- ^ timestamp when the update action started@@ -910,7 +928,7 @@ subdirs <- filterM (\subdir -> doesDirectoryExist (absdir </> subdir)) $ filter (matchGlob glob) dirEntries subdirStates <-- forM (sort subdirs) $ \subdir -> do+ for (sort subdirs) $ \subdir -> do fstate <- buildMonitorStateGlobRel mstartTime hashcache kindfile kinddir root (dir </> subdir) globPath'@@ -920,7 +938,7 @@ GlobFile glob -> do let files = filter (matchGlob glob) dirEntries filesStates <-- forM (sort files) $ \file -> do+ for (sort files) $ \file -> do fstate <- buildMonitorStateFile mstartTime hashcache kindfile kinddir root (dir </> file)@@ -961,7 +979,7 @@ -- that the set of files to monitor can change then it's simpler just to throw -- away the structure and use a finite map. ---readCacheFileHashes :: (Binary a, Binary b)+readCacheFileHashes :: (Binary a, Structured a, Binary b, Structured b) => FileMonitor a b -> IO FileHashCache readCacheFileHashes monitor = handleDoesNotExist Map.empty $@@ -1080,12 +1098,17 @@ then return Nothing else return (Just mtime') --- | Run an IO computation, returning @e@ if there is an 'error'+-- | Run an IO computation, returning the first argument @e@ if there is an 'error' -- call. ('ErrorCall') handleErrorCall :: a -> IO a -> IO a-handleErrorCall e =- handle (\(ErrorCall _) -> return e)+handleErrorCall e = handle handler where+#if MIN_VERSION_base(4,9,0)+ handler (ErrorCallWithLocation _ _) = return e+#else+ handler (ErrorCall _) = return e+#endif + -- | Run an IO computation, returning @e@ if there is any 'IOException'. -- -- This policy is OK in the file monitor code because it just causes the@@ -1105,15 +1128,3 @@ -- Instances -- -instance Binary MonitorStateFileSet where- put (MonitorStateFileSet singlePaths globPaths) = do- put (1 :: Int) -- version- put singlePaths- put globPaths- get = do- ver <- get- if ver == (1 :: Int)- then do singlePaths <- get- globPaths <- get- return $! MonitorStateFileSet singlePaths globPaths- else fail "MonitorStateFileSet: wrong version"
cabal/cabal-install/Distribution/Client/Freeze.hs view
@@ -33,8 +33,6 @@ import Distribution.Client.Sandbox.PackageEnvironment ( loadUserConfig, pkgEnvSavedConfig, showPackageEnvironment, userPackageEnvironmentFile )-import Distribution.Client.Sandbox.Types- ( SandboxPackageInfo(..) ) import Distribution.Solver.Types.ConstraintSource import Distribution.Solver.Types.LabeledPackageConstraint@@ -52,15 +50,10 @@ import Distribution.Simple.Setup ( fromFlag, fromFlagOrDefault, flagToMaybe ) import Distribution.Simple.Utils- ( die', notice, debug, writeFileAtomic )+ ( die', notice, debug, writeFileAtomic, toUTF8LBS) import Distribution.System ( Platform )-import Distribution.Deprecated.Text- ( display )-import Distribution.Verbosity- ( Verbosity ) -import qualified Data.ByteString.Lazy.Char8 as BS.Char8 import Distribution.Version ( thisVersion ) @@ -77,15 +70,14 @@ -> Compiler -> Platform -> ProgramDb- -> Maybe SandboxPackageInfo -> GlobalFlags -> FreezeFlags -> IO ()-freeze verbosity packageDBs repoCtxt comp platform progdb mSandboxPkgInfo+freeze verbosity packageDBs repoCtxt comp platform progdb globalFlags freezeFlags = do pkgs <- getFreezePkgs- verbosity packageDBs repoCtxt comp platform progdb mSandboxPkgInfo+ verbosity packageDBs repoCtxt comp platform progdb globalFlags freezeFlags if null pkgs@@ -109,11 +101,10 @@ -> Compiler -> Platform -> ProgramDb- -> Maybe SandboxPackageInfo -> GlobalFlags -> FreezeFlags -> IO [SolverPlanPackage]-getFreezePkgs verbosity packageDBs repoCtxt comp platform progdb mSandboxPkgInfo+getFreezePkgs verbosity packageDBs repoCtxt comp platform progdb globalFlags freezeFlags = do installedPkgIndex <- getInstalledPackages verbosity comp packageDBs progdb@@ -127,7 +118,7 @@ sanityCheck pkgSpecifiers planPackages- verbosity comp platform mSandboxPkgInfo freezeFlags+ verbosity comp platform freezeFlags installedPkgIndex sourcePkgDb pkgConfigDb pkgSpecifiers where sanityCheck pkgSpecifiers = do@@ -141,14 +132,13 @@ planPackages :: Verbosity -> Compiler -> Platform- -> Maybe SandboxPackageInfo -> FreezeFlags -> InstalledPackageIndex -> SourcePackageDb -> PkgConfigDb -> [PackageSpecifier UnresolvedSourcePackage] -> IO [SolverPlanPackage]-planPackages verbosity comp platform mSandboxPkgInfo freezeFlags+planPackages verbosity comp platform freezeFlags installedPkgIndex sourcePkgDb pkgConfigDb pkgSpecifiers = do solver <- chooseSolver verbosity@@ -175,6 +165,8 @@ . setCountConflicts countConflicts + . setFineGrainedConflicts fineGrainedConflicts+ . setMinimizeConflictSet minimizeConflictSet . setShadowPkgs shadowPkgs@@ -194,8 +186,6 @@ in LabeledPackageConstraint pc ConstraintSourceFreeze | pkgSpecifier <- pkgSpecifiers ] - . maybe id applySandboxInstallPolicy mSandboxPkgInfo- $ standardInstallPolicy installedPkgIndex sourcePkgDb pkgSpecifiers logMsg message rest = debug verbosity message >> rest@@ -207,6 +197,7 @@ reorderGoals = fromFlag (freezeReorderGoals freezeFlags) countConflicts = fromFlag (freezeCountConflicts freezeFlags)+ fineGrainedConflicts = fromFlag (freezeFineGrainedConflicts freezeFlags) minimizeConflictSet = fromFlag (freezeMinimizeConflictSet freezeFlags) independentGoals = fromFlag (freezeIndependentGoals freezeFlags) shadowPkgs = fromFlag (freezeShadowPkgs freezeFlags)@@ -264,12 +255,12 @@ UserConstraint (UserQualified UserQualToplevel (packageName pkgId)) (PackagePropertyVersion $ thisVersion (packageVersion pkgId)) createPkgEnv config = mempty { pkgEnvSavedConfig = config }- showPkgEnv = BS.Char8.pack . showPackageEnvironment+ showPkgEnv = toUTF8LBS . showPackageEnvironment formatPkgs :: Package pkg => [pkg] -> [String] formatPkgs = map $ showPkg . packageId where showPkg pid = name pid ++ " == " ++ version pid- name = display . packageName- version = display . packageVersion+ name = prettyShow . packageName+ version = prettyShow . packageVersion
cabal/cabal-install/Distribution/Client/GZipUtils.hs view
@@ -18,12 +18,18 @@ maybeDecompress, ) where +import Prelude ()+import Distribution.Client.Compat.Prelude+ import Codec.Compression.Zlib.Internal import Data.ByteString.Lazy.Internal as BS (ByteString(Empty, Chunk)) +#ifndef MIN_VERSION_zlib+#define MIN_VERSION_zlib(x,y,z) 1+#endif+ #if MIN_VERSION_zlib(0,6,0) import Control.Exception (throw)-import Control.Monad (liftM) import Control.Monad.ST.Lazy (ST, runST) import qualified Data.ByteString as Strict #endif
cabal/cabal-install/Distribution/Client/GenBounds.hs view
@@ -23,8 +23,6 @@ ( incVersion ) import Distribution.Client.Freeze ( getFreezePkgs )-import Distribution.Client.Sandbox.Types- ( SandboxPackageInfo(..) ) import Distribution.Client.Setup ( GlobalFlags(..), FreezeFlags(..), RepoContext ) import Distribution.Package@@ -46,10 +44,6 @@ ( tryFindPackageDesc ) import Distribution.System ( Platform )-import Distribution.Deprecated.Text- ( display )-import Distribution.Verbosity- ( Verbosity ) import Distribution.Version ( Version, alterVersion , LowerBound(..), UpperBound(..), VersionRange, asVersionIntervals@@ -93,7 +87,7 @@ showInterval (LowerBound _ _, NoUpperBound) = error "Error: expected upper bound...this should never happen!" showInterval (LowerBound l _, UpperBound u _) =- unwords [">=", display l, "&& <", display u]+ unwords [">=", prettyShow l, "&& <", prettyShow u] -- | Entry point for the @gen-bounds@ command. genBounds@@ -103,13 +97,10 @@ -> Compiler -> Platform -> ProgramDb- -> Maybe SandboxPackageInfo -> GlobalFlags -> FreezeFlags -> IO ()-genBounds verbosity packageDBs repoCtxt comp platform progdb mSandboxPkgInfo- globalFlags freezeFlags = do-+genBounds verbosity packageDBs repoCtxt comp platform progdb globalFlags freezeFlags = do let cinfo = compilerInfo comp cwd <- getCurrentDirectory@@ -133,7 +124,7 @@ go needBounds = do pkgs <- getFreezePkgs verbosity packageDBs repoCtxt comp platform progdb- mSandboxPkgInfo globalFlags freezeFlags+ globalFlags freezeFlags putStrLn boundsNeededMsg
cabal/cabal-install/Distribution/Client/Get.hs view
@@ -24,7 +24,6 @@ import Prelude () import Distribution.Client.Compat.Prelude hiding (get)-import Data.Ord (comparing) import Distribution.Compat.Directory ( listDirectory ) import Distribution.Package@@ -33,14 +32,11 @@ ( Flag(..), fromFlag, fromFlagOrDefault, flagToMaybe ) import Distribution.Simple.Utils ( notice, die', info, writeFileAtomic )-import Distribution.Verbosity- ( Verbosity )-import Distribution.Deprecated.Text (display) import qualified Distribution.PackageDescription as PD import Distribution.Simple.Program ( programName ) import Distribution.Types.SourceRepo (RepoKind (..))-import Distribution.Client.SourceRepo (SourceRepositoryPackage (..), SourceRepoProxy, srpToProxy)+import Distribution.Client.Types.SourceRepo (SourceRepositoryPackage (..), SourceRepoProxy, srpToProxy) import Distribution.Client.Setup ( GlobalFlags(..), GetFlags(..), RepoContext(..) )@@ -50,19 +46,13 @@ import Distribution.Client.VCS import Distribution.Client.FetchUtils import qualified Distribution.Client.Tar as Tar (extractTarGzFile)-import Distribution.Client.IndexUtils as IndexUtils- ( getSourcePackagesAtIndexState )+import Distribution.Client.IndexUtils+ ( getSourcePackagesAtIndexState, TotalIndexState, ActiveRepos ) import Distribution.Solver.Types.SourcePackage -import Control.Exception- ( Exception(..), catch, throwIO )-import Control.Monad- ( mapM, forM_, mapM_ ) import qualified Data.Map as Map import System.Directory ( createDirectoryIfMissing, doesDirectoryExist, doesFileExist )-import System.Exit- ( ExitCode(..) ) import System.FilePath ( (</>), (<.>), addTrailingPathSeparator ) @@ -83,12 +73,16 @@ _ -> True unless useSourceRepo $- mapM_ (checkTarget verbosity) userTargets+ traverse_ (checkTarget verbosity) userTargets - let idxState = flagToMaybe $ getIndexState getFlags+ let idxState :: Maybe TotalIndexState+ idxState = flagToMaybe $ getIndexState getFlags - sourcePkgDb <- getSourcePackagesAtIndexState verbosity repoCtxt idxState+ activeRepos :: Maybe ActiveRepos+ activeRepos = flagToMaybe $ getActiveRepos getFlags + (sourcePkgDb, _, _) <- getSourcePackagesAtIndexState verbosity repoCtxt idxState activeRepos+ pkgSpecifiers <- resolveUserTargets verbosity repoCtxt (fromFlag $ globalWorldFile globalFlags) (packageIndex sourcePkgDb)@@ -120,15 +114,15 @@ packageSourceRepos :: SourcePackage loc -> [PD.SourceRepo] packageSourceRepos = PD.sourceRepos . PD.packageDescription- . packageDescription+ . srcpkgDescription unpack :: [UnresolvedSourcePackage] -> IO () unpack pkgs = do- forM_ pkgs $ \pkg -> do- location <- fetchPackage verbosity repoCtxt (packageSource pkg)+ for_ pkgs $ \pkg -> do+ location <- fetchPackage verbosity repoCtxt (srcpkgSource pkg) let pkgid = packageId pkg descOverride | usePristine = Nothing- | otherwise = packageDescrOverride pkg+ | otherwise = srcpkgDescrOverride pkg case location of LocalTarballPackage tarballPath -> unpackPackage verbosity prefix pkgid descOverride tarballPath@@ -166,7 +160,7 @@ -> PackageDescriptionOverride -> FilePath -> IO () unpackPackage verbosity prefix pkgid descOverride pkgPath = do- let pkgdirname = display pkgid+ let pkgdirname = prettyShow pkgid pkgdir = prefix </> pkgdirname pkgdir' = addTrailingPathSeparator pkgdir emptyDirectory directory = null <$> listDirectory directory@@ -185,7 +179,7 @@ case descOverride of Nothing -> return () Just pkgtxt -> do- let descFilePath = pkgdir </> display (packageName pkgid) <.> "cabal"+ let descFilePath = pkgdir </> prettyShow (packageName pkgid) <.> "cabal" info verbosity $ "Updating " ++ descFilePath ++ " with the latest revision from the index."@@ -209,37 +203,37 @@ instance Exception ClonePackageException where displayException (ClonePackageNoSourceRepos pkgid) =- "Cannot fetch a source repository for package " ++ display pkgid+ "Cannot fetch a source repository for package " ++ prettyShow pkgid ++ ". The package does not specify any source repositories." displayException (ClonePackageNoSourceReposOfKind pkgid repoKind) =- "Cannot fetch a source repository for package " ++ display pkgid+ "Cannot fetch a source repository for package " ++ prettyShow pkgid ++ ". The package does not specify a source repository of the requested "- ++ "kind" ++ maybe "." (\k -> " (kind " ++ display k ++ ").") repoKind+ ++ "kind" ++ maybe "." (\k -> " (kind " ++ prettyShow k ++ ").") repoKind displayException (ClonePackageNoRepoType pkgid _repo) =- "Cannot fetch the source repository for package " ++ display pkgid+ "Cannot fetch the source repository for package " ++ prettyShow pkgid ++ ". The package's description specifies a source repository but does " ++ "not specify the repository 'type' field (e.g. git, darcs or hg)." displayException (ClonePackageUnsupportedRepoType pkgid _ repoType) =- "Cannot fetch the source repository for package " ++ display pkgid- ++ ". The repository type '" ++ display repoType+ "Cannot fetch the source repository for package " ++ prettyShow pkgid+ ++ ". The repository type '" ++ prettyShow repoType ++ "' is not yet supported." displayException (ClonePackageNoRepoLocation pkgid _repo) =- "Cannot fetch the source repository for package " ++ display pkgid+ "Cannot fetch the source repository for package " ++ prettyShow pkgid ++ ". The package's description specifies a source repository but does " ++ "not specify the repository 'location' field (i.e. the URL)." displayException (ClonePackageDestinationExists pkgid dest isdir) =- "Not fetching the source repository for package " ++ display pkgid ++ ". "+ "Not fetching the source repository for package " ++ prettyShow pkgid ++ ". " ++ if isdir then "The destination directory " ++ dest ++ " already exists." else "A file " ++ dest ++ " is in the way." displayException (ClonePackageFailedWithExitCode pkgid repo vcsprogname exitcode) =- "Failed to fetch the source repository for package " ++ display pkgid+ "Failed to fetch the source repository for package " ++ prettyShow pkgid ++ ", repository location " ++ srpLocation repo ++ " (" ++ vcsprogname ++ " failed with " ++ show exitcode ++ ")." @@ -259,7 +253,7 @@ preferredRepoKind pkgrepos = do -- Do a bunch of checks and collect the required info- pkgrepos' <- mapM preCloneChecks pkgrepos+ pkgrepos' <- traverse preCloneChecks pkgrepos -- Configure the VCS drivers for all the repository types we may need vcss <- configureVCSs verbosity $@@ -273,7 +267,7 @@ throwIO (ClonePackageFailedWithExitCode pkgid (srpToProxy repo) (programName (vcsProgram vcs)) exitcode) | (pkgid, repo, vcs, destDir) <- pkgrepos'- , let Just vcs' = Map.lookup (vcsRepoType vcs) vcss+ , let vcs' = Map.findWithDefault (error $ "Cannot configure " ++ prettyShow (vcsRepoType vcs)) (vcsRepoType vcs) vcss ] where@@ -297,7 +291,7 @@ Left SourceRepoLocationUnspecified -> throwIO (ClonePackageNoRepoLocation pkgid repo) - let destDir = destDirPrefix </> display (packageName pkgid)+ let destDir = destDirPrefix </> prettyShow (packageName pkgid) destDirExists <- doesDirectoryExist destDir destFileExists <- doesFileExist destDir when (destDirExists || destFileExists) $
cabal/cabal-install/Distribution/Client/Glob.hs view
@@ -15,19 +15,15 @@ , getFilePathRootDirectory ) where -import Prelude () import Distribution.Client.Compat.Prelude--import Data.List (stripPrefix)-import Control.Monad (mapM)+import Prelude () -import Distribution.Deprecated.Text-import Distribution.Deprecated.ReadP (ReadP, (<++), (+++))-import qualified Distribution.Deprecated.ReadP as Parse-import qualified Text.PrettyPrint as Disp+import Data.List (stripPrefix)+import System.Directory+import System.FilePath -import System.FilePath-import System.Directory+import qualified Distribution.Compat.CharParsing as P+import qualified Text.PrettyPrint as Disp -- | A file path specified by globbing@@ -61,6 +57,10 @@ instance Binary FilePathGlobRel instance Binary GlobPiece +instance Structured FilePathGlob+instance Structured FilePathRoot+instance Structured FilePathGlobRel+instance Structured GlobPiece -- | Check if a 'FilePathGlob' doesn't actually make use of any globbing and -- is in fact equivalent to a non-glob 'FilePath'.@@ -127,7 +127,7 @@ subdirs <- filterM (\subdir -> doesDirectoryExist (root </> dir </> subdir)) $ filter (matchGlob glob) entries- concat <$> mapM (\subdir -> go globPath (dir </> subdir)) subdirs+ concat <$> traverse (\subdir -> go globPath (dir </> subdir)) subdirs go GlobDirTrailing dir = return [dir] @@ -164,61 +164,50 @@ -- Parsing & printing -- -instance Text FilePathGlob where- disp (FilePathGlob root pathglob) = disp root Disp.<> disp pathglob- parse =- parse >>= \root ->- (FilePathGlob root <$> parse)- <++ (when (root == FilePathRelative) Parse.pfail >>- return (FilePathGlob root GlobDirTrailing))--instance Text FilePathRoot where- disp FilePathRelative = Disp.empty- disp (FilePathRoot root) = Disp.text root- disp FilePathHomeDir = Disp.char '~' Disp.<> Disp.char '/'+instance Pretty FilePathGlob where+ pretty (FilePathGlob root pathglob) = pretty root Disp.<> pretty pathglob - parse =- ( (Parse.char '/' >> return (FilePathRoot "/"))- +++ (Parse.char '~' >> Parse.char '/' >> return FilePathHomeDir)- +++ (do drive <- Parse.satisfy (\c -> (c >= 'a' && c <= 'z')- || (c >= 'A' && c <= 'Z'))- _ <- Parse.char ':'- _ <- Parse.char '/' +++ Parse.char '\\'- return (FilePathRoot (toUpper drive : ":\\")))- )- <++ return FilePathRelative+instance Parsec FilePathGlob where+ parsec = do+ root <- parsec+ case root of+ FilePathRelative -> FilePathGlob root <$> parsec+ _ -> FilePathGlob root <$> parsec <|> pure (FilePathGlob root GlobDirTrailing) -instance Text FilePathGlobRel where- disp (GlobDir glob pathglob) = dispGlob glob- Disp.<> Disp.char '/'- Disp.<> disp pathglob- disp (GlobFile glob) = dispGlob glob- disp GlobDirTrailing = Disp.empty+instance Pretty FilePathRoot where+ pretty FilePathRelative = Disp.empty+ pretty (FilePathRoot root) = Disp.text root+ pretty FilePathHomeDir = Disp.char '~' Disp.<> Disp.char '/' - parse = parsePath- where- parsePath :: ReadP r FilePathGlobRel- parsePath =- parseGlob >>= \globpieces ->- asDir globpieces- <++ asTDir globpieces- <++ asFile globpieces+instance Parsec FilePathRoot where+ parsec = root <|> P.try home <|> P.try drive <|> pure FilePathRelative where+ root = FilePathRoot "/" <$ P.char '/'+ home = FilePathHomeDir <$ P.string "~/"+ drive = do+ dr <- P.satisfy $ \c -> (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')+ _ <- P.char ':'+ _ <- P.char '/' <|> P.char '\\'+ return (FilePathRoot (toUpper dr : ":\\")) - asDir glob = do dirSep- globs <- parsePath- return (GlobDir glob globs)- asTDir glob = do dirSep- return (GlobDir glob GlobDirTrailing)- asFile glob = return (GlobFile glob)+instance Pretty FilePathGlobRel where+ pretty (GlobDir glob pathglob) = dispGlob glob+ Disp.<> Disp.char '/'+ Disp.<> pretty pathglob+ pretty (GlobFile glob) = dispGlob glob+ pretty GlobDirTrailing = Disp.empty - dirSep = (Parse.char '/' >> return ())- +++ (do _ <- Parse.char '\\'- -- check this isn't an escape code- following <- Parse.look- case following of- (c:_) | isGlobEscapedChar c -> Parse.pfail- _ -> return ())+instance Parsec FilePathGlobRel where+ parsec = parsecPath where+ parsecPath :: CabalParsing m => m FilePathGlobRel+ parsecPath = do+ glob <- parsecGlob+ dirSep *> (GlobDir glob <$> parsecPath <|> pure (GlobDir glob GlobDirTrailing)) <|> pure (GlobFile glob) + dirSep :: CabalParsing m => m ()+ dirSep = () <$ P.char '/' <|> P.try (do+ _ <- P.char '\\'+ -- check this isn't an escape code+ P.notFollowedBy (P.satisfy isGlobEscapedChar)) dispGlob :: Glob -> Disp.Doc dispGlob = Disp.hcat . map dispPiece@@ -234,29 +223,18 @@ | isGlobEscapedChar c = '\\' : c : escape cs | otherwise = c : escape cs -parseGlob :: ReadP r Glob-parseGlob = Parse.many1 parsePiece- where- parsePiece = literal +++ wildcard +++ union-- wildcard = Parse.char '*' >> return WildCard-- union = Parse.between (Parse.char '{') (Parse.char '}') $- fmap Union (Parse.sepBy1 parseGlob (Parse.char ','))-- literal = Literal `fmap` litchars1-- litchar = normal +++ escape+parsecGlob :: CabalParsing m => m Glob+parsecGlob = some parsecPiece where+ parsecPiece = P.choice [ literal, wildcard, union ] - normal = Parse.satisfy (\c -> not (isGlobEscapedChar c)- && c /= '/' && c /= '\\')- escape = Parse.char '\\' >> Parse.satisfy isGlobEscapedChar+ wildcard = WildCard <$ P.char '*'+ union = Union . toList <$> P.between (P.char '{') (P.char '}') (P.sepByNonEmpty parsecGlob (P.char ','))+ literal = Literal <$> some litchar - litchars1 :: ReadP r [Char]- litchars1 = liftM2 (:) litchar litchars+ litchar = normal <|> escape - litchars :: ReadP r [Char]- litchars = litchars1 <++ return []+ normal = P.satisfy (\c -> not (isGlobEscapedChar c) && c /= '/' && c /= '\\')+ escape = P.try $ P.char '\\' >> P.satisfy isGlobEscapedChar isGlobEscapedChar :: Char -> Bool isGlobEscapedChar '*' = True
cabal/cabal-install/Distribution/Client/GlobalFlags.hs view
@@ -17,22 +17,21 @@ import Distribution.Client.Compat.Prelude import Distribution.Client.Types- ( Repo(..), RemoteRepo(..) )+ ( Repo(..), unRepoName, RemoteRepo(..), LocalRepo (..), localRepoCacheKey ) import Distribution.Simple.Setup ( Flag(..), fromFlag, flagToMaybe ) import Distribution.Utils.NubList ( NubList, fromNubList ) import Distribution.Client.HttpUtils ( HttpTransport, configureTransport )-import Distribution.Verbosity- ( Verbosity ) import Distribution.Simple.Utils- ( info )+ ( info, warn ) +import Distribution.Client.IndexUtils.ActiveRepos+ ( ActiveRepos )+ import Control.Concurrent ( MVar, newMVar, modifyMVar )-import Control.Exception- ( throwIO ) import System.FilePath ( (</>) ) import Network.URI@@ -48,58 +47,57 @@ import qualified Distribution.Client.Security.HTTP as Sec.HTTP import qualified Distribution.Client.Security.DNS as Sec.DNS +import qualified System.FilePath.Posix as FilePath.Posix+ -- ------------------------------------------------------------ -- * Global flags -- ------------------------------------------------------------ -- | Flags that apply at the top level, not to any sub-command.-data GlobalFlags = GlobalFlags {- globalVersion :: Flag Bool,- globalNumericVersion :: Flag Bool,- globalConfigFile :: Flag FilePath,- globalSandboxConfigFile :: Flag FilePath,- globalConstraintsFile :: Flag FilePath,- globalRemoteRepos :: NubList RemoteRepo, -- ^ Available Hackage servers.- globalCacheDir :: Flag FilePath,- globalLocalRepos :: NubList FilePath,- globalLogsDir :: Flag FilePath,- globalWorldFile :: Flag FilePath,- globalRequireSandbox :: Flag Bool,- globalIgnoreSandbox :: Flag Bool,- globalIgnoreExpiry :: Flag Bool, -- ^ Ignore security expiry dates- globalHttpTransport :: Flag String,- globalNix :: Flag Bool, -- ^ Integrate with Nix- globalStoreDir :: Flag FilePath,- globalProgPathExtra :: NubList FilePath -- ^ Extra program path used for packagedb lookups in a global context (i.e. for http transports)- } deriving Generic +data GlobalFlags = GlobalFlags+ { globalVersion :: Flag Bool+ , globalNumericVersion :: Flag Bool+ , globalConfigFile :: Flag FilePath+ , globalConstraintsFile :: Flag FilePath+ , globalRemoteRepos :: NubList RemoteRepo -- ^ Available Hackage servers.+ , globalCacheDir :: Flag FilePath+ , globalLocalNoIndexRepos :: NubList LocalRepo+ , globalActiveRepos :: Flag ActiveRepos+ , globalLogsDir :: Flag FilePath+ , globalWorldFile :: Flag FilePath+ , globalIgnoreExpiry :: Flag Bool -- ^ Ignore security expiry dates+ , globalHttpTransport :: Flag String+ , globalNix :: Flag Bool -- ^ Integrate with Nix+ , globalStoreDir :: Flag FilePath+ , globalProgPathExtra :: NubList FilePath -- ^ Extra program path used for packagedb lookups in a global context (i.e. for http transports)+ } deriving Generic+ defaultGlobalFlags :: GlobalFlags-defaultGlobalFlags = GlobalFlags {- globalVersion = Flag False,- globalNumericVersion = Flag False,- globalConfigFile = mempty,- globalSandboxConfigFile = mempty,- globalConstraintsFile = mempty,- globalRemoteRepos = mempty,- globalCacheDir = mempty,- globalLocalRepos = mempty,- globalLogsDir = mempty,- globalWorldFile = mempty,- globalRequireSandbox = Flag False,- globalIgnoreSandbox = Flag False,- globalIgnoreExpiry = Flag False,- globalHttpTransport = mempty,- globalNix = Flag False,- globalStoreDir = mempty,- globalProgPathExtra = mempty- }+defaultGlobalFlags = GlobalFlags+ { globalVersion = Flag False+ , globalNumericVersion = Flag False+ , globalConfigFile = mempty+ , globalConstraintsFile = mempty+ , globalRemoteRepos = mempty+ , globalCacheDir = mempty+ , globalLocalNoIndexRepos = mempty+ , globalActiveRepos = mempty+ , globalLogsDir = mempty+ , globalWorldFile = mempty+ , globalIgnoreExpiry = Flag False+ , globalHttpTransport = mempty+ , globalNix = Flag False+ , globalStoreDir = mempty+ , globalProgPathExtra = mempty+ } instance Monoid GlobalFlags where- mempty = gmempty- mappend = (<>)+ mempty = gmempty+ mappend = (<>) instance Semigroup GlobalFlags where- (<>) = gmappend+ (<>) = gmappend -- ------------------------------------------------------------ -- * Repo context@@ -141,20 +139,24 @@ withRepoContext verbosity globalFlags = withRepoContext' verbosity- (fromNubList (globalRemoteRepos globalFlags))- (fromNubList (globalLocalRepos globalFlags))- (fromFlag (globalCacheDir globalFlags))- (flagToMaybe (globalHttpTransport globalFlags))- (flagToMaybe (globalIgnoreExpiry globalFlags))- (fromNubList (globalProgPathExtra globalFlags))+ (fromNubList (globalRemoteRepos globalFlags))+ (fromNubList (globalLocalNoIndexRepos globalFlags))+ (fromFlag (globalCacheDir globalFlags))+ (flagToMaybe (globalHttpTransport globalFlags))+ (flagToMaybe (globalIgnoreExpiry globalFlags))+ (fromNubList (globalProgPathExtra globalFlags)) -withRepoContext' :: Verbosity -> [RemoteRepo] -> [FilePath]+withRepoContext' :: Verbosity -> [RemoteRepo] -> [LocalRepo] -> FilePath -> Maybe String -> Maybe Bool -> [FilePath] -> (RepoContext -> IO a) -> IO a-withRepoContext' verbosity remoteRepos localRepos+withRepoContext' verbosity remoteRepos localNoIndexRepos sharedCacheDir httpTransport ignoreExpiry extraPaths = \callback -> do+ for_ localNoIndexRepos $ \local ->+ unless (FilePath.Posix.isAbsolute (localRepoPath local)) $+ warn verbosity $ "file+noindex " ++ unRepoName (localRepoName local) ++ " repository path is not absolute; this is fragile, and not recommended"+ transportRef <- newMVar Nothing let httpLib = Sec.HTTP.transportAdapter verbosity@@ -162,7 +164,7 @@ initSecureRepos verbosity httpLib secureRemoteRepos $ \secureRepos' -> callback RepoContext { repoContextRepos = allRemoteRepos- ++ map RepoLocal localRepos+ ++ allLocalNoIndexRepos , repoContextGetTransport = getTransport transportRef , repoContextWithSecureRepo = withSecureRepo secureRepos' , repoContextIgnoreExpiry = fromMaybe False ignoreExpiry@@ -170,11 +172,21 @@ where secureRemoteRepos = [ (remote, cacheDir) | RepoSecure remote cacheDir <- allRemoteRepos ]++ allRemoteRepos :: [Repo] allRemoteRepos = [ (if isSecure then RepoSecure else RepoRemote) remote cacheDir | remote <- remoteRepos- , let cacheDir = sharedCacheDir </> remoteRepoName remote+ , let cacheDir = sharedCacheDir </> unRepoName (remoteRepoName remote) isSecure = remoteRepoSecure remote == Just True+ ]++ allLocalNoIndexRepos :: [Repo]+ allLocalNoIndexRepos =+ [ RepoLocalNoIndex local cacheDir+ | local <- localNoIndexRepos+ , let cacheDir | localRepoSharedCache local = sharedCacheDir </> localRepoCacheKey local+ | otherwise = localRepoPath local ] getTransport :: MVar (Maybe HttpTransport) -> IO HttpTransport
cabal/cabal-install/Distribution/Client/Haddock.hs view
@@ -16,8 +16,10 @@ ) where +import Distribution.Client.Compat.Prelude+import Prelude ()+ import Data.List (maximumBy)-import Data.Foldable (forM_) import System.Directory (createDirectoryIfMissing, renameFile) import System.FilePath ((</>), splitFileName) import Distribution.Package@@ -26,11 +28,10 @@ import Distribution.Simple.Program (haddockProgram, ProgramDb , runProgram, requireProgramVersion) import Distribution.Version (mkVersion, orLaterVersion)-import Distribution.Verbosity (Verbosity) import Distribution.Simple.PackageIndex ( InstalledPackageIndex, allPackagesByName ) import Distribution.Simple.Utils- ( comparing, debug, installDirectoryContents, withTempDirectory )+ ( debug, installDirectoryContents, withTempDirectory ) import Distribution.InstalledPackageInfo as InstalledPackageInfo ( InstalledPackageInfo(exposed) ) @@ -41,7 +42,7 @@ regenerateHaddockIndex verbosity pkgs progdb index = do (paths, warns) <- haddockPackagePaths pkgs' Nothing let paths' = [ (interface, html) | (interface, Just html, _) <- paths]- forM_ warns (debug verbosity)+ for_ warns (debug verbosity) (confHaddock, _, _) <- requireProgramVersion verbosity haddockProgram
+ cabal/cabal-install/Distribution/Client/HashValue.hs view
@@ -0,0 +1,85 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+module Distribution.Client.HashValue (+ HashValue,+ hashValue,+ truncateHash,+ showHashValue,+ readFileHashValue,+ hashFromTUF,+ ) where++import Distribution.Client.Compat.Prelude+import Prelude ()++import qualified Hackage.Security.Client as Sec++import qualified Crypto.Hash.SHA256 as SHA256+import qualified Data.ByteString.Base16 as Base16+import qualified Data.ByteString.Char8 as BS+import qualified Data.ByteString.Lazy.Char8 as LBS++import System.IO (IOMode (..), withBinaryFile)++-----------------------------------------------+-- The specific choice of hash implementation+--++-- Is a crypto hash necessary here? One thing to consider is who controls the+-- inputs and what's the result of a hash collision. Obviously we should not+-- install packages we don't trust because they can run all sorts of code, but+-- if I've checked there's no TH, no custom Setup etc, is there still a+-- problem? If someone provided us a tarball that hashed to the same value as+-- some other package and we installed it, we could end up re-using that+-- installed package in place of another one we wanted. So yes, in general+-- there is some value in preventing intentional hash collisions in installed+-- package ids.++newtype HashValue = HashValue BS.ByteString+ deriving (Eq, Generic, Show, Typeable)++-- Cannot do any sensible validation here. Although we use SHA256+-- for stuff we hash ourselves, we can also get hashes from TUF+-- and that can in principle use different hash functions in future.+--+-- Therefore, we simply derive this structurally.+instance Binary HashValue+instance Structured HashValue++-- | Hash some data. Currently uses SHA256.+--+hashValue :: LBS.ByteString -> HashValue+hashValue = HashValue . SHA256.hashlazy++showHashValue :: HashValue -> String+showHashValue (HashValue digest) = BS.unpack (Base16.encode digest)++-- | Hash the content of a file. Uses SHA256.+--+readFileHashValue :: FilePath -> IO HashValue+readFileHashValue tarball =+ withBinaryFile tarball ReadMode $ \hnd ->+ evaluate . hashValue =<< LBS.hGetContents hnd++-- | Convert a hash from TUF metadata into a 'PackageSourceHash'.+--+-- Note that TUF hashes don't neessarily have to be SHA256, since it can+-- support new algorithms in future.+--+hashFromTUF :: Sec.Hash -> HashValue+hashFromTUF (Sec.Hash hashstr) =+ --TODO: [code cleanup] either we should get TUF to use raw bytestrings or+ -- perhaps we should also just use a base16 string as the internal rep.+ case Base16.decode (BS.pack hashstr) of+ (hash, trailing) | not (BS.null hash) && BS.null trailing+ -> HashValue hash+ _ -> error "hashFromTUF: cannot decode base16 hash"+++-- | Truncate a 32 byte SHA256 hash to+--+-- For example 20 bytes render as 40 hex chars, which we use for unit-ids.+-- Or even 4 bytes for 'hashedInstalledPackageIdShort'+--+truncateHash :: Int -> HashValue -> HashValue+truncateHash n (HashValue h) = HashValue (BS.take n h)
cabal/cabal-install/Distribution/Client/HttpUtils.hs view
@@ -28,23 +28,13 @@ ( browse, setOutHandler, setErrHandler, setProxy , setAuthorityGen, request, setAllowBasicAuth, setUserAgent ) import qualified Control.Exception as Exception-import Control.Exception- ( evaluate )-import Control.DeepSeq- ( force )-import Control.Monad- ( guard )-import qualified Data.ByteString.Lazy.Char8 as BS-import qualified Paths_cabal_install (version)-import Distribution.Verbosity (Verbosity)-import Distribution.Pretty (prettyShow) import Distribution.Simple.Utils ( die', info, warn, debug, notice- , copyFileVerbose, withTempFile )+ , copyFileVerbose, withTempFile, IOData (..) ) import Distribution.Client.Utils- ( withTempFileName )+ ( withTempFileName, cabalInstallVersion ) import Distribution.Client.Types- ( RemoteRepo(..) )+ ( unRepoName, RemoteRepo(..) ) import Distribution.System ( buildOS, buildArch ) import qualified System.FilePath.Posix as FilePath.Posix@@ -71,9 +61,14 @@ ( getProgramInvocationOutputAndErrors ) import Numeric (showHex) import System.Random (randomRIO)-import System.Exit (ExitCode(..))-import Data.Version (showVersion) +import qualified Crypto.Hash.SHA256 as SHA256+import qualified Data.ByteString.Base16 as Base16+import qualified Distribution.Compat.CharParsing as P+import qualified Data.ByteString as BS+import qualified Data.ByteString.Char8 as BS8+import qualified Data.ByteString.Lazy as LBS+import qualified Data.ByteString.Lazy.Char8 as LBS8 ------------------------------------------------------------------------------ -- Downloading a URI, given an HttpTransport@@ -83,6 +78,12 @@ | FileDownloaded FilePath deriving (Eq) +data DownloadCheck+ = Downloaded -- ^ already downloaded and sha256 matches+ | CheckETag String -- ^ already downloaded and we have etag+ | NeedsDownload (Maybe BS.ByteString) -- ^ needs download with optional hash check+ deriving Eq+ downloadURI :: HttpTransport -> Verbosity -> URI -- ^ What to download@@ -96,14 +97,35 @@ downloadURI transport verbosity uri path = do - let etagPath = path <.> "etag"- targetExists <- doesFileExist path- etagPathExists <- doesFileExist etagPath- -- In rare cases the target file doesn't exist, but the etag does.- etag <- if targetExists && etagPathExists- then Just <$> readFile etagPath- else return Nothing+ targetExists <- doesFileExist path + downloadCheck <-+ -- if we have uriFrag, then we expect there to be #sha256=...+ if not (null uriFrag)+ then case sha256parsed of+ -- we know the hash, and target exists+ Right expected | targetExists -> do+ contents <- LBS.readFile path+ let actual = SHA256.hashlazy contents+ if expected == actual+ then return Downloaded+ else return (NeedsDownload (Just expected))++ -- we known the hash, target doesn't exist+ Right expected -> return (NeedsDownload (Just expected))++ -- we failed to parse uriFragment+ Left err -> die' verbosity $+ "Cannot parse URI fragment " ++ uriFrag ++ " " ++ err++ -- if there are no uri fragment, use ETag+ else do+ etagPathExists <- doesFileExist etagPath+ -- In rare cases the target file doesn't exist, but the etag does.+ if targetExists && etagPathExists+ then return (CheckETag etagPath)+ else return (NeedsDownload Nothing)+ -- Only use the external http transports if we actually have to -- (or have been told to do so) let transport'@@ -114,12 +136,29 @@ | otherwise = transport - withTempFileName (takeDirectory path) (takeFileName path) $ \tmpFile -> do+ case downloadCheck of+ Downloaded -> return FileAlreadyInCache+ CheckETag etag -> makeDownload transport' Nothing (Just etag)+ NeedsDownload hash -> makeDownload transport' hash Nothing++ where+ makeDownload transport' sha256 etag = withTempFileName (takeDirectory path) (takeFileName path) $ \tmpFile -> do result <- getHttp transport' verbosity uri etag tmpFile [] -- Only write the etag if we get a 200 response code. -- A 304 still sends us an etag header. case result of+ -- if we have hash, we don't care about etag.+ (200, _) | Just expected <- sha256 -> do+ contents <- LBS.readFile tmpFile+ let actual = SHA256.hashlazy contents+ unless (actual == expected) $+ die' verbosity $ unwords+ [ "Failed to download", show uri+ , ": SHA256 don't match; expected:", BS8.unpack (Base16.encode expected)+ , "actual:", BS8.unpack (Base16.encode actual)+ ]+ (200, Just newEtag) -> writeFile etagPath newEtag _ -> return () @@ -131,9 +170,20 @@ 304 -> do notice verbosity "Skipping download: local and remote files match." return FileAlreadyInCache- errCode -> die' verbosity $ "Failed to download " ++ show uri+ errCode -> die' verbosity $ "failed to download " ++ show uri ++ " : HTTP code " ++ show errCode + etagPath = path <.> "etag"+ uriFrag = uriFragment uri++ sha256parsed :: Either String BS.ByteString+ sha256parsed = explicitEitherParsec fragmentParser uriFrag++ fragmentParser = do+ _ <- P.string "#sha256="+ str <- some P.hexDigit+ return (fst (Base16.decode (BS8.pack str)))+ ------------------------------------------------------------------------------ -- Utilities for repo url management --@@ -142,8 +192,8 @@ remoteRepoCheckHttps verbosity transport repo | uriScheme (remoteRepoURI repo) == "https:" , not (transportSupportsHttps transport)- = die' verbosity $ "The remote repository '" ++ remoteRepoName repo- ++ "' specifies a URL that " ++ requiresHttpsErrorMessage+ = die' verbosity $ "The remote repository '" ++ unRepoName (remoteRepoName repo)+ ++ "' specifies a URL that " ++ requiresHttpsErrorMessage | otherwise = return () transportCheckHttps :: Verbosity -> HttpTransport -> URI -> IO ()@@ -282,7 +332,7 @@ Just prog -> snd <$> requireProgram verbosity prog baseProgDb -- ^^ if it fails, it'll fail here - let Just transport = mkTrans progdb+ let transport = fromMaybe (error "configureTransport: failed to make transport") $ mkTrans progdb return transport { transportManuallySelected = True } Nothing -> die' verbosity $ "Unknown HTTP transport specified: " ++ name@@ -351,7 +401,7 @@ addAuthConfig auth progInvocation = progInvocation { progInvokeInput = do (uname, passwd) <- auth- return $ unlines+ return $ IODataText $ unlines [ "--digest" , "--user " ++ uname ++ ":" ++ passwd ]@@ -463,7 +513,7 @@ \responseFile responseHandle -> do hClose responseHandle (body, boundary) <- generateMultipartBody path- BS.hPut tmpHandle body+ LBS.hPut tmpHandle body hClose tmpHandle let args = [ "--post-file=" ++ tmpFile , "--user-agent=" ++ userAgent@@ -508,7 +558,7 @@ -- and sensitive data should not be passed via command line arguments. let invocation = (programInvocation prog ("--input-file=-" : args))- { progInvokeInput = Just (uriToString id uri "")+ { progInvokeInput = Just $ IODataText $ uriToString id uri "" } -- wget returns its output on stderr rather than stdout@@ -586,7 +636,7 @@ withTempFile (takeDirectory path) (takeFileName path) $ \tmpFile tmpHandle -> do (body, boundary) <- generateMultipartBody path- BS.hPut tmpHandle body+ LBS.hPut tmpHandle body hClose tmpHandle fullPath <- canonicalizePath tmpFile @@ -619,7 +669,7 @@ ] debug verbosity script getProgramInvocationOutput verbosity (programInvocation prog args)- { progInvokeInput = Just (script ++ "\nExit(0);")+ { progInvokeInput = Just $ IODataText $ script ++ "\nExit(0);" } escape = show@@ -645,9 +695,11 @@ HdrIfModifiedSince -> "IfModifiedSince = " ++ escape value HdrReferer -> "Referer = " ++ escape value HdrTransferEncoding -> "TransferEncoding = " ++ escape value- HdrRange -> let (start, _:end) =+ HdrRange -> let (start, end) = if "bytes=" `isPrefixOf` value- then break (== '-') value'+ then case break (== '-') value' of+ (start', '-':end') -> (start', end')+ _ -> error $ "Could not decode range: " ++ value else error $ "Could not decode range: " ++ value value' = drop 6 value in "AddRange(\"bytes\", " ++ escape start ++ ", " ++ escape end ++ ");"@@ -734,7 +786,7 @@ rqHeaders = [ Header HdrIfNoneMatch t | t <- maybeToList etag ] ++ reqHeaders,- rqBody = BS.empty+ rqBody = LBS.empty } (_, resp) <- cabalBrowse verbosity Nothing (request req) let code = convertRspCode (rspCode resp)@@ -750,7 +802,7 @@ (body, boundary) <- generateMultipartBody path let headers = [ Header HdrContentType ("multipart/form-data; boundary="++boundary)- , Header HdrContentLength (show (BS.length body))+ , Header HdrContentLength (show (LBS8.length body)) , Header HdrAccept ("text/plain") ] req = Request {@@ -763,11 +815,11 @@ return (convertRspCode (rspCode resp), rspErrorString resp) puthttpfile verbosity uri path auth headers = do- body <- BS.readFile path+ body <- LBS8.readFile path let req = Request { rqURI = uri, rqMethod = PUT,- rqHeaders = Header HdrContentLength (show (BS.length body))+ rqHeaders = Header HdrContentLength (show (LBS8.length body)) : Header HdrAccept "text/plain" : headers, rqBody = body@@ -781,7 +833,7 @@ case lookupHeader HdrContentType (rspHeaders resp) of Just contenttype | takeWhile (/= ';') contenttype == "text/plain"- -> BS.unpack (rspBody resp)+ -> LBS8.unpack (rspBody resp) _ -> rspReason resp cabalBrowse verbosity auth act = do@@ -808,7 +860,7 @@ -- userAgent :: String-userAgent = concat [ "cabal-install/", showVersion Paths_cabal_install.version+userAgent = concat [ "cabal-install/", prettyShow cabalInstallVersion , " (", prettyShow buildOS, "; ", prettyShow buildArch, ")" ] @@ -827,17 +879,17 @@ -- Multipart stuff partially taken from cgi package. -- -generateMultipartBody :: FilePath -> IO (BS.ByteString, String)+generateMultipartBody :: FilePath -> IO (LBS.ByteString, String) generateMultipartBody path = do- content <- BS.readFile path+ content <- LBS.readFile path boundary <- genBoundary- let !body = formatBody content (BS.pack boundary)+ let !body = formatBody content (LBS8.pack boundary) return (body, boundary) where formatBody content boundary =- BS.concat $+ LBS8.concat $ [ crlf, dd, boundary, crlf ]- ++ [ BS.pack (show header) | header <- headers ]+ ++ [ LBS8.pack (show header) | header <- headers ] ++ [ crlf , content , crlf, dd, boundary, dd, crlf ]@@ -849,8 +901,8 @@ , Header HdrContentType "application/x-gzip" ] - crlf = BS.pack "\r\n"- dd = BS.pack "--"+ crlf = LBS8.pack "\r\n"+ dd = LBS8.pack "--" genBoundary :: IO String genBoundary = do
cabal/cabal-install/Distribution/Client/IndexUtils.hs view
@@ -3,6 +3,7 @@ {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE BangPatterns #-} {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE GADTs #-} -----------------------------------------------------------------------------@@ -25,17 +26,18 @@ getSourcePackages, getSourcePackagesMonitorFiles, - IndexState(..),+ TotalIndexState, getSourcePackagesAtIndexState,+ ActiveRepos, Index(..),+ RepoIndexState (..), PackageEntry(..), parsePackageIndex, updateRepoIndexCache, updatePackageIndexCacheFile, writeIndexTimestamp, currentIndexTimestamp,- readCacheStrict, -- only used by soon-to-be-obsolete sandbox code BuildTreeRefType(..), refTypeFromTypeCode, typeCodeFromRefType ) where@@ -47,9 +49,12 @@ import qualified Codec.Archive.Tar.Entry as Tar import qualified Codec.Archive.Tar.Index as Tar import qualified Distribution.Client.Tar as Tar+import Distribution.Client.IndexUtils.ActiveRepos+import Distribution.Client.IndexUtils.IndexState import Distribution.Client.IndexUtils.Timestamp import Distribution.Client.Types import Distribution.Verbosity+import Distribution.Parsec (simpleParsecBS) import Distribution.Package ( PackageId, PackageIdentifier(..), mkPackageName@@ -65,12 +70,11 @@ ( ProgramDb ) import qualified Distribution.Simple.Configure as Configure ( getInstalledPackages, getInstalledPackagesMonitorFiles )+import Distribution.Types.PackageName (PackageName) import Distribution.Version- ( Version, mkVersion, intersectVersionRanges )-import Distribution.Deprecated.Text- ( display, simpleParse )+ ( Version, VersionRange, mkVersion, intersectVersionRanges ) import Distribution.Simple.Utils- ( die', warn, info )+ ( die', warn, info, createDirectoryIfMissingVerbose ) import Distribution.Client.Setup ( RepoContext(..) ) @@ -83,9 +87,9 @@ import Distribution.Solver.Types.SourcePackage import qualified Data.Map as Map-import Control.DeepSeq-import Control.Monad+import qualified Data.Set as Set import Control.Exception+import Data.List (stripPrefix) import qualified Data.ByteString.Lazy as BS import qualified Data.ByteString.Lazy.Char8 as BS.Char8 import qualified Data.ByteString.Char8 as BSS@@ -93,18 +97,20 @@ import Distribution.Client.GZipUtils (maybeDecompress) import Distribution.Client.Utils ( byteStringToFilePath , tryFindAddSourcePackageDesc )-import Distribution.Compat.Binary-import Distribution.Compat.Exception (catchIO)+import Distribution.Utils.Structured (Structured (..), nominalStructure, structuredEncodeFile, structuredDecodeFileOrFail) import Distribution.Compat.Time (getFileAge, getModTime) import System.Directory (doesFileExist, doesDirectoryExist) import System.FilePath- ( (</>), (<.>), takeExtension, replaceExtension, splitDirectories, normalise )-import System.FilePath.Posix as FilePath.Posix- ( takeFileName )+ ( (</>), (<.>), takeFileName, takeExtension, replaceExtension, splitDirectories, normalise, takeDirectory )+import qualified System.FilePath.Posix as FilePath.Posix import System.IO import System.IO.Unsafe (unsafeInterleaveIO) import System.IO.Error (isDoesNotExistError)+import Distribution.Compat.Directory (listDirectory)+import Distribution.Utils.Generic (fstOf3) +import qualified Codec.Compression.GZip as GZip+ import qualified Hackage.Security.Client as Sec import qualified Hackage.Security.Util.Some as Sec @@ -130,9 +136,9 @@ indexBaseName repo = repoLocalDir repo </> fn where fn = case repo of- RepoSecure {} -> "01-index"- RepoRemote {} -> "00-index"- RepoLocal {} -> "00-index"+ RepoSecure {} -> "01-index"+ RepoRemote {} -> "00-index"+ RepoLocalNoIndex {} -> "noindex" ------------------------------------------------------------------------ -- Reading the source package index@@ -168,7 +174,7 @@ -- resulting index cache. -- -- Note: 'filterCache' is idempotent in the 'Cache' value-filterCache :: IndexState -> Cache -> (Cache, IndexStateInfo)+filterCache :: RepoIndexState -> Cache -> (Cache, IndexStateInfo) filterCache IndexStateHead cache = (cache, IndexStateInfo{..}) where isiMaxTime = cacheHeadTs cache@@ -189,7 +195,7 @@ -- This is a higher level wrapper used internally in cabal-install. getSourcePackages :: Verbosity -> RepoContext -> IO SourcePackageDb getSourcePackages verbosity repoCtxt =- getSourcePackagesAtIndexState verbosity repoCtxt Nothing+ fstOf3 <$> getSourcePackagesAtIndexState verbosity repoCtxt Nothing Nothing -- | Variant of 'getSourcePackages' which allows getting the source -- packages at a particular 'IndexState'.@@ -197,32 +203,42 @@ -- Current choices are either the latest (aka HEAD), or the index as -- it was at a particular time. ----- TODO: Enhance to allow specifying per-repo 'IndexState's and also--- report back per-repo 'IndexStateInfo's (in order for @v2-freeze@--- to access it)-getSourcePackagesAtIndexState :: Verbosity -> RepoContext -> Maybe IndexState- -> IO SourcePackageDb-getSourcePackagesAtIndexState verbosity repoCtxt _+-- Returns also the total index where repositories'+-- RepoIndexState's are not HEAD. This is used in v2-freeze.+--+getSourcePackagesAtIndexState+ :: Verbosity+ -> RepoContext+ -> Maybe TotalIndexState+ -> Maybe ActiveRepos+ -> IO (SourcePackageDb, TotalIndexState, ActiveRepos)+getSourcePackagesAtIndexState verbosity repoCtxt _ _ | null (repoContextRepos repoCtxt) = do -- In the test suite, we routinely don't have any remote package -- servers, so don't bleat about it warn (verboseUnmarkOutput verbosity) $ "No remote package servers have been specified. Usually " ++ "you would have one specified in the config file."- return SourcePackageDb {+ return (SourcePackageDb { packageIndex = mempty, packagePreferences = mempty- }-getSourcePackagesAtIndexState verbosity repoCtxt mb_idxState = do+ }, headTotalIndexState, ActiveRepos [])+getSourcePackagesAtIndexState verbosity repoCtxt mb_idxState mb_activeRepos = do let describeState IndexStateHead = "most recent state"- describeState (IndexStateTime time) = "historical state as of " ++ display time+ describeState (IndexStateTime time) = "historical state as of " ++ prettyShow time - pkgss <- forM (repoContextRepos repoCtxt) $ \r -> do- let rname = maybe "" remoteRepoName $ maybeRepoRemote r- info verbosity ("Reading available packages of " ++ rname ++ "...")+ pkgss <- for (repoContextRepos repoCtxt) $ \r -> do+ let rname :: RepoName+ rname = case r of+ RepoRemote remote _ -> remoteRepoName remote+ RepoSecure remote _ -> remoteRepoName remote+ RepoLocalNoIndex local _ -> localRepoName local + info verbosity ("Reading available packages of " ++ unRepoName rname ++ "...")+ idxState <- case mb_idxState of- Just idxState -> do+ Just totalIdxState -> do+ let idxState = lookupIndexState rname totalIdxState info verbosity $ "Using " ++ describeState idxState ++ " as explicitly requested (via command line / project configuration)" return idxState@@ -239,8 +255,8 @@ unless (idxState == IndexStateHead) $ case r of- RepoLocal path -> warn verbosity ("index-state ignored for old-format repositories (local repository '" ++ path ++ "')")- RepoRemote {} -> warn verbosity ("index-state ignored for old-format (remote repository '" ++ rname ++ "')")+ RepoLocalNoIndex {} -> warn verbosity "index-state ignored for file+noindex repositories"+ RepoRemote {} -> warn verbosity ("index-state ignored for old-format (remote repository '" ++ unRepoName rname ++ "')") RepoSecure {} -> pure () let idxState' = case r of@@ -251,44 +267,84 @@ case idxState' of IndexStateHead -> do- info verbosity ("index-state("++rname++") = " ++- display (isiHeadTime isi))+ info verbosity ("index-state("++ unRepoName rname ++") = " ++ prettyShow (isiHeadTime isi)) return () IndexStateTime ts0 -> do when (isiMaxTime isi /= ts0) $ if ts0 > isiMaxTime isi then warn verbosity $- "Requested index-state" ++ display ts0- ++ " is newer than '" ++ rname ++ "'!"+ "Requested index-state " ++ prettyShow ts0+ ++ " is newer than '" ++ unRepoName rname ++ "'!" ++ " Falling back to older state ("- ++ display (isiMaxTime isi) ++ ")."+ ++ prettyShow (isiMaxTime isi) ++ ")." else info verbosity $- "Requested index-state " ++ display ts0- ++ " does not exist in '"++rname++"'!"+ "Requested index-state " ++ prettyShow ts0+ ++ " does not exist in '"++ unRepoName rname ++"'!" ++ " Falling back to older state ("- ++ display (isiMaxTime isi) ++ ")."- info verbosity ("index-state("++rname++") = " ++- display (isiMaxTime isi) ++ " (HEAD = " ++- display (isiHeadTime isi) ++ ")")+ ++ prettyShow (isiMaxTime isi) ++ ")."+ info verbosity ("index-state("++ unRepoName rname ++") = " +++ prettyShow (isiMaxTime isi) ++ " (HEAD = " +++ prettyShow (isiHeadTime isi) ++ ")") - pure (pis,deps)+ pure RepoData+ { rdRepoName = rname+ , rdTimeStamp = isiMaxTime isi+ , rdIndex = pis+ , rdPreferences = deps+ } - let (pkgs, prefs) = mconcat pkgss- prefs' = Map.fromListWith intersectVersionRanges- [ (name, range) | Dependency name range _ <- prefs ]+ let activeRepos :: ActiveRepos+ activeRepos = fromMaybe defaultActiveRepos mb_activeRepos++ pkgss' <- case organizeByRepos activeRepos rdRepoName pkgss of+ Right x -> return x+ Left err -> warn verbosity err >> return (map (\x -> (x, CombineStrategyMerge)) pkgss)++ let activeRepos' :: ActiveRepos+ activeRepos' = ActiveRepos+ [ ActiveRepo (rdRepoName rd) strategy+ | (rd, strategy) <- pkgss'+ ]++ let totalIndexState :: TotalIndexState+ totalIndexState = makeTotalIndexState IndexStateHead $ Map.fromList+ [ (n, IndexStateTime ts)+ | (RepoData n ts _idx _prefs, _strategy) <- pkgss'+ ]++ let addIndex+ :: PackageIndex UnresolvedSourcePackage+ -> (RepoData, CombineStrategy)+ -> PackageIndex UnresolvedSourcePackage+ addIndex acc (RepoData _ _ idx _, CombineStrategyMerge) = PackageIndex.merge acc idx+ addIndex acc (RepoData _ _ idx _, CombineStrategyOverride) = PackageIndex.override acc idx++ let pkgs :: PackageIndex UnresolvedSourcePackage+ pkgs = foldl' addIndex mempty pkgss'++ -- Note: preferences combined without using CombineStrategy+ let prefs :: Map PackageName VersionRange+ prefs = Map.fromListWith intersectVersionRanges+ [ (name, range)+ | (RepoData _n _ts _idx prefs', _strategy) <- pkgss'+ , Dependency name range _ <- prefs'+ ]+ _ <- evaluate pkgs- _ <- evaluate prefs'- return SourcePackageDb {+ _ <- evaluate prefs+ _ <- evaluate totalIndexState+ return (SourcePackageDb { packageIndex = pkgs,- packagePreferences = prefs'- }+ packagePreferences = prefs+ }, totalIndexState, activeRepos') -readCacheStrict :: NFData pkg => Verbosity -> Index -> (PackageEntry -> pkg) -> IO ([pkg], [Dependency])-readCacheStrict verbosity index mkPkg = do- updateRepoIndexCache verbosity index- cache <- readIndexCache verbosity index- withFile (indexFile index) ReadMode $ \indexHnd ->- evaluate . force =<< packageListFromCache verbosity mkPkg indexHnd cache+-- auxiliary data used in getSourcePackagesAtIndexState+data RepoData = RepoData+ { rdRepoName :: RepoName+ , rdTimeStamp :: Timestamp+ , rdIndex :: PackageIndex UnresolvedSourcePackage+ , rdPreferences :: [Dependency]+ } -- | Read a repository index from disk, from the local file specified by -- the 'Repo'.@@ -297,29 +353,29 @@ -- -- This is a higher level wrapper used internally in cabal-install. ---readRepoIndex :: Verbosity -> RepoContext -> Repo -> IndexState+readRepoIndex :: Verbosity -> RepoContext -> Repo -> RepoIndexState -> IO (PackageIndex UnresolvedSourcePackage, [Dependency], IndexStateInfo) readRepoIndex verbosity repoCtxt repo idxState = handleNotFound $ do- warnIfIndexIsOld =<< getIndexFileAge repo+ when (isRepoRemote repo) $ warnIfIndexIsOld =<< getIndexFileAge repo updateRepoIndexCache verbosity (RepoIndex repoCtxt repo) readPackageIndexCacheFile verbosity mkAvailablePackage (RepoIndex repoCtxt repo) idxState where- mkAvailablePackage pkgEntry =- SourcePackage {- packageInfoId = pkgid,- packageDescription = packageDesc pkgEntry,- packageSource = case pkgEntry of+ mkAvailablePackage pkgEntry = SourcePackage+ { srcpkgPackageId = pkgid+ , srcpkgDescription = pkgdesc+ , srcpkgSource = case pkgEntry of NormalPackage _ _ _ _ -> RepoTarballPackage repo pkgid Nothing- BuildTreeRef _ _ _ path _ -> LocalUnpackedPackage path,- packageDescrOverride = case pkgEntry of+ BuildTreeRef _ _ _ path _ -> LocalUnpackedPackage path+ , srcpkgDescrOverride = case pkgEntry of NormalPackage _ _ pkgtxt _ -> Just pkgtxt _ -> Nothing } where+ pkgdesc = packageDesc pkgEntry pkgid = packageId pkgEntry handleNotFound action = catchIO action $ \e -> if isDoesNotExistError e@@ -327,9 +383,10 @@ case repo of RepoRemote{..} -> warn verbosity $ errMissingPackageList repoRemote RepoSecure{..} -> warn verbosity $ errMissingPackageList repoRemote- RepoLocal{..} -> warn verbosity $- "The package list for the local repo '" ++ repoLocalDir- ++ "' is missing. The repo is invalid."+ RepoLocalNoIndex local _ -> warn verbosity $+ "Error during construction of local+noindex "+ ++ unRepoName (localRepoName local) ++ " repository index: "+ ++ show e return (mempty,mempty,emptyStateInfo) else ioError e @@ -338,13 +395,13 @@ when (dt >= isOldThreshold) $ case repo of RepoRemote{..} -> warn verbosity $ errOutdatedPackageList repoRemote dt RepoSecure{..} -> warn verbosity $ errOutdatedPackageList repoRemote dt- RepoLocal{..} -> return ()+ RepoLocalNoIndex {} -> return () errMissingPackageList repoRemote =- "The package list for '" ++ remoteRepoName repoRemote+ "The package list for '" ++ (unRepoName (remoteRepoName repoRemote)) ++ "' does not exist. Run 'hackport update' to download it." errOutdatedPackageList repoRemote dt =- "The package list for '" ++ remoteRepoName repoRemote+ "The package list for '" ++ unRepoName (remoteRepoName repoRemote) ++ "' is " ++ shows (floor dt :: Int) " days old.\nRun " ++ "'cabal update' to get the latest list of available packages." @@ -366,34 +423,40 @@ -- updateRepoIndexCache :: Verbosity -> Index -> IO () updateRepoIndexCache verbosity index =- whenCacheOutOfDate index $ do- updatePackageIndexCacheFile verbosity index+ whenCacheOutOfDate index $ updatePackageIndexCacheFile verbosity index whenCacheOutOfDate :: Index -> IO () -> IO () whenCacheOutOfDate index action = do exists <- doesFileExist $ cacheFile index if not exists- then action- else do- indexTime <- getModTime $ indexFile index- cacheTime <- getModTime $ cacheFile index- when (indexTime > cacheTime) action+ then action+ else if localNoIndex index+ then return () -- TODO: don't update cache for local+noindex repositories+ else do+ indexTime <- getModTime $ indexFile index+ cacheTime <- getModTime $ cacheFile index+ when (indexTime > cacheTime) action +localNoIndex :: Index -> Bool+localNoIndex (RepoIndex _ (RepoLocalNoIndex {})) = True+localNoIndex _ = False+ ------------------------------------------------------------------------ -- Reading the index file -- -- | An index entry is either a normal package, or a local build tree reference.-data PackageEntry =- NormalPackage PackageId GenericPackageDescription ByteString BlockNo+data PackageEntry+ = NormalPackage PackageId GenericPackageDescription ByteString BlockNo | BuildTreeRef BuildTreeRefType PackageId GenericPackageDescription FilePath BlockNo -- | A build tree reference is either a link or a snapshot. data BuildTreeRefType = SnapshotRef | LinkRef- deriving (Eq,Generic)+ deriving (Eq,Show,Generic) instance Binary BuildTreeRefType+instance Structured BuildTreeRefType refTypeFromTypeCode :: Tar.TypeCode -> BuildTreeRefType refTypeFromTypeCode t@@ -459,7 +522,7 @@ Tar.NormalFile content _ | takeExtension fileName == ".cabal" -> case splitDirectories (normalise fileName) of- [pkgname,vers,_] -> case simpleParse vers of+ [pkgname,vers,_] -> case simpleParsec vers of Just ver -> Just . return $ Just (NormalPackage pkgid descr content blockNo) where pkgid = PackageIdentifier (mkPackageName pkgname) ver@@ -496,7 +559,7 @@ -- I'd like to have bleeding-edge packages in system and I don't fear of -- broken packages with improper depends Tar.NormalFile content _- | takeFileName entrypath == "preferred-versions"+ | FilePath.Posix.takeFileName entrypath == "preferred-versions" -> Just prefs where entrypath = Tar.entryPath entry@@ -505,7 +568,7 @@ _ -> Nothing parsePreferredVersions :: ByteString -> [Dependency]-parsePreferredVersions = mapMaybe simpleParse+parsePreferredVersions = mapMaybe simpleParsec . filter (not . isPrefixOf "--") . lines . BS.Char8.unpack -- TODO: Are we sure no unicode?@@ -566,22 +629,28 @@ is01Index (RepoIndex _ repo) = case repo of RepoSecure {} -> True RepoRemote {} -> False- RepoLocal {} -> False+ RepoLocalNoIndex {} -> True is01Index (SandboxIndex _) = False updatePackageIndexCacheFile :: Verbosity -> Index -> IO () updatePackageIndexCacheFile verbosity index = do info verbosity ("Updating index cache file " ++ cacheFile index ++ " ...")- withIndexEntries verbosity index $ \entries -> do- let !maxTs = maximumTimestamp (map cacheEntryTimestamp entries)- cache = Cache { cacheHeadTs = maxTs- , cacheEntries = entries- }- writeIndexCache index cache- info verbosity ("Index cache updated to index-state "- ++ display (cacheHeadTs cache))+ withIndexEntries verbosity index callback callbackNoIndex+ where+ callback entries = do+ let !maxTs = maximumTimestamp (map cacheEntryTimestamp entries)+ cache = Cache { cacheHeadTs = maxTs+ , cacheEntries = entries+ }+ writeIndexCache index cache+ info verbosity ("Index cache updated to index-state "+ ++ prettyShow (cacheHeadTs cache)) + callbackNoIndex entries = do+ writeNoIndexCache verbosity index $ NoIndexCache entries+ info verbosity "Index cache updated"+ -- | Read the index (for the purpose of building a cache) -- -- The callback is provided with list of cache entries, which is guaranteed to@@ -602,8 +671,12 @@ -- TODO: It would be nicer if we actually incrementally updated @cabal@'s -- cache, rather than reconstruct it from zero on each update. However, this -- would require a change in the cache format.-withIndexEntries :: Verbosity -> Index -> ([IndexCacheEntry] -> IO a) -> IO a-withIndexEntries _ (RepoIndex repoCtxt repo@RepoSecure{..}) callback =+withIndexEntries+ :: Verbosity -> Index+ -> ([IndexCacheEntry] -> IO a)+ -> ([NoIndexCacheEntry] -> IO a)+ -> IO a+withIndexEntries _ (RepoIndex repoCtxt repo@RepoSecure{}) callback _ = repoContextWithSecureRepo repoCtxt repo $ \repoSecure -> Sec.withIndex repoSecure $ \Sec.IndexCallbacks{..} -> do -- Incrementally (lazily) read all the entries in the tar file in order,@@ -630,7 +703,60 @@ timestamp = fromMaybe (error "withIndexEntries: invalid timestamp") $ epochTimeToTimestamp $ Sec.indexEntryTime sie -withIndexEntries verbosity index callback = do -- non-secure repositories+withIndexEntries verbosity (RepoIndex _repoCtxt (RepoLocalNoIndex (LocalRepo name localDir _) _cacheDir)) _ callback = do+ dirContents <- listDirectory localDir+ let contentSet = Set.fromList dirContents++ entries <- handle handler $ fmap catMaybes $ for dirContents $ \file -> do+ case isTarGz file of+ Nothing -> do+ unless (takeFileName file == "noindex.cache" || ".cabal" `isSuffixOf` file) $+ info verbosity $ "Skipping " ++ file+ return Nothing+ Just pkgid | cabalPath `Set.member` contentSet -> do+ contents <- BSS.readFile (localDir </> cabalPath)+ for (parseGenericPackageDescriptionMaybe contents) $ \gpd ->+ return (CacheGPD gpd contents)+ where+ cabalPath = prettyShow pkgid ++ ".cabal"+ Just pkgId -> do+ -- check for the right named .cabal file in the compressed tarball+ tarGz <- BS.readFile (localDir </> file)+ let tar = GZip.decompress tarGz+ entries = Tar.read tar++ case Tar.foldEntries (readCabalEntry pkgId) Nothing (const Nothing) entries of+ Just ce -> return (Just ce)+ Nothing -> die' verbosity $ "Cannot read .cabal file inside " ++ file++ info verbosity $ "Entries in file+noindex repository " ++ unRepoName name+ for_ entries $ \(CacheGPD gpd _) ->+ info verbosity $ "- " ++ prettyShow (package $ Distribution.PackageDescription.packageDescription gpd)++ callback entries+ where+ handler :: IOException -> IO a+ handler e = die' verbosity $ "Error while updating index for " ++ unRepoName name ++ " repository " ++ show e++ isTarGz :: FilePath -> Maybe PackageIdentifier+ isTarGz fp = do+ pfx <- stripSuffix ".tar.gz" fp+ simpleParsec pfx++ stripSuffix sfx str = fmap reverse (stripPrefix (reverse sfx) (reverse str))++ -- look for <pkgid>/<pkgname>.cabal inside the tarball+ readCabalEntry :: PackageIdentifier -> Tar.Entry -> Maybe NoIndexCacheEntry -> Maybe NoIndexCacheEntry+ readCabalEntry pkgId entry Nothing+ | filename == Tar.entryPath entry+ , Tar.NormalFile contents _ <- Tar.entryContent entry+ = let bs = BS.toStrict contents+ in fmap (\gpd -> CacheGPD gpd bs) $ parseGenericPackageDescriptionMaybe bs+ where+ filename = prettyShow pkgId FilePath.Posix.</> prettyShow (packageName pkgId) ++ ".cabal"+ readCabalEntry _ _ x = x++withIndexEntries verbosity index callback _ = do -- non-secure repositories withFile (indexFile index) ReadMode $ \h -> do bs <- maybeDecompress `fmap` BS.hGetContents h pkgsOrPrefs <- lazySequence $ parsePackageIndex verbosity bs@@ -645,15 +771,20 @@ => Verbosity -> (PackageEntry -> pkg) -> Index- -> IndexState+ -> RepoIndexState -> IO (PackageIndex pkg, [Dependency], IndexStateInfo)-readPackageIndexCacheFile verbosity mkPkg index idxState = do- cache0 <- readIndexCache verbosity index- indexHnd <- openFile (indexFile index) ReadMode- let (cache,isi) = filterCache idxState cache0- (pkgs,deps) <- packageIndexFromCache verbosity mkPkg indexHnd cache- pure (pkgs,deps,isi)+readPackageIndexCacheFile verbosity mkPkg index idxState+ | localNoIndex index = do+ cache0 <- readNoIndexCache verbosity index+ pkgs <- packageNoIndexFromCache verbosity mkPkg cache0+ pure (pkgs, [], emptyStateInfo) + | otherwise = do+ cache0 <- readIndexCache verbosity index+ indexHnd <- openFile (indexFile index) ReadMode+ let (cache,isi) = filterCache idxState cache0+ (pkgs,deps) <- packageIndexFromCache verbosity mkPkg indexHnd cache+ pure (pkgs,deps,isi) packageIndexFromCache :: Package pkg => Verbosity@@ -666,6 +797,21 @@ pkgIndex <- evaluate $ PackageIndex.fromList pkgs return (pkgIndex, prefs) +packageNoIndexFromCache+ :: forall pkg. Package pkg+ => Verbosity+ -> (PackageEntry -> pkg)+ -> NoIndexCache+ -> IO (PackageIndex pkg)+packageNoIndexFromCache _verbosity mkPkg cache =+ evaluate $ PackageIndex.fromList pkgs+ where+ pkgs =+ [ mkPkg $ NormalPackage pkgId gpd (BS.fromStrict bs) 0+ | CacheGPD gpd bs <- noIndexCacheEntries cache+ , let pkgId = package $ Distribution.PackageDescription.packageDescription gpd+ ]+ -- | Read package list -- -- The result package releases and preference entries are guaranteed@@ -731,10 +877,10 @@ dummyPackageDescription :: Version -> GenericPackageDescription dummyPackageDescription specVer = GenericPackageDescription { packageDescription = emptyPackageDescription- { specVersionRaw = Left specVer- , package = pkgid- , synopsis = dummySynopsis+ { package = pkgid+ , synopsis = dummySynopsis }+ , gpdScannedVersion = Just specVer -- tells index scanner to skip this file. , genPackageFlags = [] , condLibrary = Nothing , condSubLibraries = []@@ -754,8 +900,7 @@ --------------------------------------------------------------------------- Index cache data structure---+-- Index cache data structure -- -- | Read the 'Index' cache from the filesystem --@@ -778,24 +923,50 @@ Right res -> return (hashConsCache res) +readNoIndexCache :: Verbosity -> Index -> IO NoIndexCache+readNoIndexCache verbosity index = do+ cacheOrFail <- readNoIndexCache' index+ case cacheOrFail of+ Left msg -> do+ warn verbosity $ concat+ [ "Parsing the index cache failed (", msg, "). "+ , "Trying to regenerate the index cache..."+ ]++ updatePackageIndexCacheFile verbosity index++ either (die' verbosity) return =<< readNoIndexCache' index++ -- we don't hash cons local repository cache, they are hopefully small+ Right res -> return res+ -- | Read the 'Index' cache from the filesystem without attempting to -- regenerate on parsing failures. readIndexCache' :: Index -> IO (Either String Cache) readIndexCache' index- | is01Index index = decodeFileOrFail' (cacheFile index)+ | is01Index index = structuredDecodeFileOrFail (cacheFile index) | otherwise = liftM (Right .read00IndexCache) $ BSS.readFile (cacheFile index) +readNoIndexCache' :: Index -> IO (Either String NoIndexCache)+readNoIndexCache' index = structuredDecodeFileOrFail (cacheFile index)+ -- | Write the 'Index' cache to the filesystem writeIndexCache :: Index -> Cache -> IO () writeIndexCache index cache- | is01Index index = encodeFile (cacheFile index) cache+ | is01Index index = structuredEncodeFile (cacheFile index) cache | otherwise = writeFile (cacheFile index) (show00IndexCache cache) +writeNoIndexCache :: Verbosity -> Index -> NoIndexCache -> IO ()+writeNoIndexCache verbosity index cache = do+ let path = cacheFile index+ createDirectoryIfMissingVerbose verbosity True (takeDirectory path)+ structuredEncodeFile path cache+ -- | Write the 'IndexState' to the filesystem-writeIndexTimestamp :: Index -> IndexState -> IO ()+writeIndexTimestamp :: Index -> RepoIndexState -> IO () writeIndexTimestamp index st- = writeFile (timestampFile index) (display st)+ = writeFile (timestampFile index) (prettyShow st) -- | Read out the "current" index timestamp, i.e., what -- timestamp you would use to revert to this version@@ -809,9 +980,9 @@ return (isiHeadTime isi) -- | Read the 'IndexState' from the filesystem-readIndexTimestamp :: Index -> IO (Maybe IndexState)+readIndexTimestamp :: Index -> IO (Maybe RepoIndexState) readIndexTimestamp index- = fmap simpleParse (readFile (timestampFile index))+ = fmap simpleParsec (readFile (timestampFile index)) `catchIO` \e -> if isDoesNotExistError e then return Nothing@@ -857,28 +1028,44 @@ -- 'cacheEntries' , cacheEntries :: [IndexCacheEntry] }+ deriving (Show, Generic) instance NFData Cache where rnf = rnf . cacheEntries +-- | Cache format for 'file+noindex' repositories+newtype NoIndexCache = NoIndexCache+ { noIndexCacheEntries :: [NoIndexCacheEntry]+ }+ deriving (Show, Generic)++instance NFData NoIndexCache where+ rnf = rnf . noIndexCacheEntries+ -- | Tar files are block structured with 512 byte blocks. Every header and file -- content starts on a block boundary. -- type BlockNo = Word32 -- Tar.TarEntryOffset - data IndexCacheEntry = CachePackageId PackageId !BlockNo !Timestamp | CachePreference Dependency !BlockNo !Timestamp | CacheBuildTreeRef !BuildTreeRefType !BlockNo -- NB: CacheBuildTreeRef is irrelevant for 01-index & v2-build- deriving (Eq,Generic)+ deriving (Eq,Show,Generic) +data NoIndexCacheEntry+ = CacheGPD GenericPackageDescription !BSS.ByteString+ deriving (Eq,Show,Generic)+ instance NFData IndexCacheEntry where rnf (CachePackageId pkgid _ _) = rnf pkgid rnf (CachePreference dep _ _) = rnf dep rnf (CacheBuildTreeRef _ _) = () +instance NFData NoIndexCacheEntry where+ rnf (CacheGPD gpd bs) = rnf gpd `seq` rnf bs+ cacheEntryTimestamp :: IndexCacheEntry -> Timestamp cacheEntryTimestamp (CacheBuildTreeRef _ _) = nullTimestamp cacheEntryTimestamp (CachePreference _ _ ts) = ts@@ -887,24 +1074,26 @@ ---------------------------------------------------------------------------- -- new binary 01-index.cache format -instance Binary Cache where- put (Cache headTs ents) = do- -- magic / format version- --- -- NB: this currently encodes word-size implicitly; when we- -- switch to CBOR encoding, we will have a platform- -- independent binary encoding- put (0xcaba1002::Word)- put headTs- put ents+instance Binary Cache+instance Binary IndexCacheEntry+instance Binary NoIndexCache +instance Structured Cache+instance Structured IndexCacheEntry+instance Structured NoIndexCache++-- | We need to save only .cabal file contents+instance Binary NoIndexCacheEntry where+ put (CacheGPD _ bs) = put bs+ get = do- magic <- get- when (magic /= (0xcaba1002::Word)) $- fail ("01-index.cache: unexpected magic marker encountered: " ++ show magic)- Cache <$> get <*> get+ bs <- get+ case parseGenericPackageDescriptionMaybe bs of+ Just gpd -> return (CacheGPD gpd bs)+ Nothing -> fail "Failed to parse GPD" -instance Binary IndexCacheEntry+instance Structured NoIndexCacheEntry where+ structure = nominalStructure ---------------------------------------------------------------------------- -- legacy 00-index.cache format@@ -940,7 +1129,7 @@ _ -> Nothing (key: remainder) | key == BSS.pack preferredVersionKey -> do- pref <- simpleParse (BSS.unpack (BSS.unwords remainder))+ pref <- simpleParsecBS (BSS.unwords remainder) return $ CachePreference pref 0 nullTimestamp _ -> Nothing@@ -977,16 +1166,19 @@ show00IndexCacheEntry :: IndexCacheEntry -> String show00IndexCacheEntry entry = unwords $ case entry of- CachePackageId pkgid b _ -> [ packageKey- , display (packageName pkgid)- , display (packageVersion pkgid)- , blocknoKey- , show b- ]- CacheBuildTreeRef tr b -> [ buildTreeRefKey- , [typeCodeFromRefType tr]- , show b- ]- CachePreference dep _ _ -> [ preferredVersionKey- , display dep- ]+ CachePackageId pkgid b _ ->+ [ packageKey+ , prettyShow (packageName pkgid)+ , prettyShow (packageVersion pkgid)+ , blocknoKey+ , show b+ ]+ CacheBuildTreeRef tr b ->+ [ buildTreeRefKey+ , [typeCodeFromRefType tr]+ , show b+ ]+ CachePreference dep _ _ ->+ [ preferredVersionKey+ , prettyShow dep+ ]
+ cabal/cabal-install/Distribution/Client/IndexUtils/ActiveRepos.hs view
@@ -0,0 +1,174 @@+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}+module Distribution.Client.IndexUtils.ActiveRepos (+ ActiveRepos (..),+ defaultActiveRepos,+ ActiveRepoEntry (..),+ CombineStrategy (..),+ organizeByRepos,+) where++import Distribution.Client.Compat.Prelude+import Distribution.Client.Types.RepoName (RepoName (..))+import Prelude ()++import Distribution.Parsec (parsecLeadingCommaNonEmpty)++import qualified Distribution.Compat.CharParsing as P+import qualified Text.PrettyPrint as Disp++-- $setup+-- >>> import Distribution.Parsec++-------------------------------------------------------------------------------+-- Types+-------------------------------------------------------------------------------++-- | Ordered list of active repositories.+newtype ActiveRepos = ActiveRepos [ActiveRepoEntry]+ deriving (Eq, Show, Generic)++defaultActiveRepos :: ActiveRepos+defaultActiveRepos = ActiveRepos [ ActiveRepoRest CombineStrategyMerge ]++instance Binary ActiveRepos+instance Structured ActiveRepos+instance NFData ActiveRepos++instance Pretty ActiveRepos where+ pretty (ActiveRepos [])+ = Disp.text ":none"+ pretty (ActiveRepos repos)+ = Disp.hsep+ $ Disp.punctuate Disp.comma+ $ map pretty repos++-- | Note: empty string is not valid 'ActiveRepos'.+--+-- >>> simpleParsec "" :: Maybe ActiveRepos+-- Nothing+--+-- >>> simpleParsec ":none" :: Maybe ActiveRepos+-- Just (ActiveRepos [])+--+-- >>> simpleParsec ":rest" :: Maybe ActiveRepos+-- Just (ActiveRepos [ActiveRepoRest CombineStrategyMerge])+--+-- >>> simpleParsec "hackage.haskell.org, :rest, head.hackage:override" :: Maybe ActiveRepos+-- Just (ActiveRepos [ActiveRepo (RepoName "hackage.haskell.org") CombineStrategyMerge,ActiveRepoRest CombineStrategyMerge,ActiveRepo (RepoName "head.hackage") CombineStrategyOverride])+--+instance Parsec ActiveRepos where+ parsec = ActiveRepos [] <$ P.try (P.string ":none")+ <|> do+ repos <- parsecLeadingCommaNonEmpty parsec+ return (ActiveRepos (toList repos))++data ActiveRepoEntry+ = ActiveRepoRest CombineStrategy -- ^ rest repositories, i.e. not explicitly listed as 'ActiveRepo'+ | ActiveRepo RepoName CombineStrategy -- ^ explicit repository name+ deriving (Eq, Show, Generic)++instance Binary ActiveRepoEntry+instance Structured ActiveRepoEntry+instance NFData ActiveRepoEntry++instance Pretty ActiveRepoEntry where+ pretty (ActiveRepoRest s) =+ Disp.text ":rest" <<>> Disp.colon <<>> pretty s+ pretty (ActiveRepo r s) =+ pretty r <<>> Disp.colon <<>> pretty s++instance Parsec ActiveRepoEntry where+ parsec = leadColon <|> leadRepo where+ leadColon = do+ _ <- P.char ':'+ token <- P.munch1 isAlpha+ case token of+ "rest" -> ActiveRepoRest <$> strategyP+ "repo" -> P.char ':' *> leadRepo+ _ -> P.unexpected $ "Unknown active repository entry type: " ++ token++ leadRepo = do+ r <- parsec+ s <- strategyP+ return (ActiveRepo r s)++ strategyP = P.option CombineStrategyMerge (P.char ':' *> parsec)++data CombineStrategy+ = CombineStrategyMerge -- ^ merge existing versions+ | CombineStrategyOverride -- ^ if later repository specifies a package,+ -- all package versions are replaced+ deriving (Eq, Show, Enum, Bounded, Generic)++instance Binary CombineStrategy+instance Structured CombineStrategy+instance NFData CombineStrategy++instance Pretty CombineStrategy where+ pretty CombineStrategyMerge = Disp.text "merge"+ pretty CombineStrategyOverride = Disp.text "override"++instance Parsec CombineStrategy where+ parsec = P.choice+ [ CombineStrategyMerge <$ P.string "merge"+ , CombineStrategyOverride <$ P.string "override"+ ]++-------------------------------------------------------------------------------+-- Organisation+-------------------------------------------------------------------------------++-- | Sort values 'RepoName' according to 'ActiveRepos' list.+--+-- >>> let repos = [RepoName "a", RepoName "b", RepoName "c"]+-- >>> organizeByRepos (ActiveRepos [ActiveRepoRest CombineStrategyMerge]) id repos+-- Right [(RepoName "a",CombineStrategyMerge),(RepoName "b",CombineStrategyMerge),(RepoName "c",CombineStrategyMerge)]+--+-- >>> organizeByRepos (ActiveRepos [ActiveRepo (RepoName "b") CombineStrategyOverride, ActiveRepoRest CombineStrategyMerge]) id repos+-- Right [(RepoName "b",CombineStrategyOverride),(RepoName "a",CombineStrategyMerge),(RepoName "c",CombineStrategyMerge)]+--+-- >>> organizeByRepos (ActiveRepos [ActiveRepoRest CombineStrategyMerge, ActiveRepo (RepoName "b") CombineStrategyOverride]) id repos+-- Right [(RepoName "a",CombineStrategyMerge),(RepoName "c",CombineStrategyMerge),(RepoName "b",CombineStrategyOverride)]+--+-- >>> organizeByRepos (ActiveRepos [ActiveRepoRest CombineStrategyMerge, ActiveRepo (RepoName "d") CombineStrategyOverride]) id repos+-- Left "no repository provided d"+--+-- Note: currently if 'ActiveRepoRest' is provided more than once,+-- rest-repositories will be multiple times in the output.+--+organizeByRepos+ :: forall a. ActiveRepos+ -> (a -> RepoName)+ -> [a]+ -> Either String [(a, CombineStrategy)]+organizeByRepos (ActiveRepos xs0) sel ys0 =+ -- here we use lazyness to do only one traversal+ let (rest, result) = case go rest xs0 ys0 of+ Right (rest', result') -> (rest', Right result')+ Left err -> ([], Left err)+ in result+ where+ go :: [a] -> [ActiveRepoEntry] -> [a] -> Either String ([a], [(a, CombineStrategy)])+ go _rest [] ys = Right (ys, [])+ go rest (ActiveRepoRest s : xs) ys =+ go rest xs ys <&> \(rest', result) ->+ (rest', map (\x -> (x, s)) rest ++ result)+ go rest (ActiveRepo r s : xs) ys = do+ (z, zs) <- extract r ys+ go rest xs zs <&> \(rest', result) ->+ (rest', (z, s) : result)++ extract :: RepoName -> [a] -> Either String (a, [a])+ extract r = loop id where+ loop _acc [] = Left $ "no repository provided " ++ prettyShow r+ loop acc (x:xs)+ | sel x == r = Right (x, acc xs)+ | otherwise = loop (acc . (x :)) xs++ (<&>)+ :: Either err ([s], b)+ -> (([s], b) -> ([s], c))+ -> Either err ([s], c)+ (<&>) = flip fmap
+ cabal/cabal-install/Distribution/Client/IndexUtils/IndexState.hs view
@@ -0,0 +1,138 @@+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE OverloadedStrings #-}+-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Client.IndexUtils.IndexUtils+-- Copyright : (c) 2016 Herbert Valerio Riedel+-- License : BSD3+--+-- Package repositories index state.+--+module Distribution.Client.IndexUtils.IndexState (+ RepoIndexState(..),+ TotalIndexState,+ headTotalIndexState,+ makeTotalIndexState,+ lookupIndexState,+ insertIndexState,+) where++import Distribution.Client.Compat.Prelude+import Distribution.Client.IndexUtils.Timestamp (Timestamp)+import Distribution.Client.Types.RepoName (RepoName (..))++import Distribution.Parsec (parsecLeadingCommaNonEmpty)++import qualified Data.Map.Strict as Map+import qualified Distribution.Compat.CharParsing as P+import qualified Text.PrettyPrint as Disp++-- $setup+-- >>> import Distribution.Parsec++-------------------------------------------------------------------------------+-- Total index state+-------------------------------------------------------------------------------++-- | Index state of multiple repositories+data TotalIndexState = TIS RepoIndexState (Map RepoName RepoIndexState)+ deriving (Eq, Show, Generic)++instance Binary TotalIndexState+instance Structured TotalIndexState+instance NFData TotalIndexState++instance Pretty TotalIndexState where+ pretty (TIS IndexStateHead m)+ | not (Map.null m)+ = Disp.hsep $ Disp.punctuate Disp.comma+ [ pretty rn Disp.<+> pretty idx+ | (rn, idx) <- Map.toList m+ ]+ pretty (TIS def m) = foldl' go (pretty def) (Map.toList m) where+ go doc (rn, idx) = doc <<>> Disp.comma Disp.<+> pretty rn Disp.<+> pretty idx++-- |+--+-- >>> simpleParsec "HEAD" :: Maybe TotalIndexState+-- Just (TIS IndexStateHead (fromList []))+--+-- >>> simpleParsec "" :: Maybe TotalIndexState+-- Nothing+--+-- >>> simpleParsec "hackage.haskell.org HEAD" :: Maybe TotalIndexState+-- Just (TIS IndexStateHead (fromList []))+--+-- >>> simpleParsec "2020-02-04T12:34:56Z, hackage.haskell.org HEAD" :: Maybe TotalIndexState+-- Just (TIS (IndexStateTime (TS 1580819696)) (fromList [(RepoName "hackage.haskell.org",IndexStateHead)]))+--+-- >>> simpleParsec "hackage.haskell.org 2020-02-04T12:34:56Z" :: Maybe TotalIndexState+-- Just (TIS IndexStateHead (fromList [(RepoName "hackage.haskell.org",IndexStateTime (TS 1580819696))]))+--+instance Parsec TotalIndexState where+ parsec = normalise . foldl' add headTotalIndexState <$> parsecLeadingCommaNonEmpty single0 where+ single0 = startsWithRepoName <|> TokTimestamp <$> parsec+ startsWithRepoName = do+ reponame <- parsec+ -- the "HEAD" is technically a valid reponame...+ if reponame == RepoName "HEAD"+ then return TokHead+ else do+ P.spaces+ TokRepo reponame <$> parsec++ add :: TotalIndexState -> Tok -> TotalIndexState+ add _ TokHead = headTotalIndexState+ add _ (TokTimestamp ts) = TIS (IndexStateTime ts) Map.empty+ add (TIS def m) (TokRepo rn idx) = TIS def (Map.insert rn idx m)++-- used in Parsec TotalIndexState implementation+data Tok+ = TokRepo RepoName RepoIndexState+ | TokTimestamp Timestamp+ | TokHead++-- | Remove non-default values from 'TotalIndexState'.+normalise :: TotalIndexState -> TotalIndexState+normalise (TIS def m) = TIS def (Map.filter (/= def) m)++-- | 'TotalIndexState' where all repositories are at @HEAD@ index state.+headTotalIndexState :: TotalIndexState+headTotalIndexState = TIS IndexStateHead Map.empty++-- | Create 'TotalIndexState'.+makeTotalIndexState :: RepoIndexState -> Map RepoName RepoIndexState -> TotalIndexState+makeTotalIndexState def m = normalise (TIS def m)++-- | Lookup a 'RepoIndexState' for an individual repository from 'TotalIndexState'.+lookupIndexState :: RepoName -> TotalIndexState -> RepoIndexState+lookupIndexState rn (TIS def m) = Map.findWithDefault def rn m++-- | Insert a 'RepoIndexState' to 'TotalIndexState'.+insertIndexState :: RepoName -> RepoIndexState -> TotalIndexState -> TotalIndexState+insertIndexState rn idx (TIS def m)+ | idx == def = TIS def (Map.delete rn m)+ | otherwise = TIS def (Map.insert rn idx m)++-------------------------------------------------------------------------------+-- Repository index state+-------------------------------------------------------------------------------++-- | Specification of the state of a specific repo package index+data RepoIndexState+ = IndexStateHead -- ^ Use all available entries+ | IndexStateTime !Timestamp -- ^ Use all entries that existed at the specified time+ deriving (Eq,Generic,Show)++instance Binary RepoIndexState+instance Structured RepoIndexState+instance NFData RepoIndexState++instance Pretty RepoIndexState where+ pretty IndexStateHead = Disp.text "HEAD"+ pretty (IndexStateTime ts) = pretty ts++instance Parsec RepoIndexState where+ parsec = parseHead <|> parseTime where+ parseHead = IndexStateHead <$ P.string "HEAD"+ parseTime = IndexStateTime <$> parsec
cabal/cabal-install/Distribution/Client/IndexUtils/Timestamp.hs view
@@ -1,6 +1,7 @@-{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards #-} ----------------------------------------------------------------------------- -- |@@ -17,26 +18,20 @@ , timestampToUTCTime , utcTimeToTimestamp , maximumTimestamp-- , IndexState(..) ) where -import qualified Codec.Archive.Tar.Entry as Tar-import Control.DeepSeq-import Control.Monad-import Data.Char (isDigit)-import Data.Int (Int64)-import Data.Time (UTCTime (..), fromGregorianValid,- makeTimeOfDayValid, showGregorian,- timeOfDayToTime, timeToTimeOfDay)-import Data.Time.Clock.POSIX (posixSecondsToUTCTime,- utcTimeToPOSIXSeconds)-import Distribution.Compat.Binary-import qualified Distribution.Deprecated.ReadP as ReadP-import Distribution.Deprecated.Text-import qualified Text.PrettyPrint as Disp-import GHC.Generics (Generic)+import Distribution.Client.Compat.Prelude +-- read is needed for Text instance+import Prelude (read)++import Data.Time (UTCTime (..), fromGregorianValid, makeTimeOfDayValid, showGregorian, timeOfDayToTime, timeToTimeOfDay)+import Data.Time.Clock.POSIX (posixSecondsToUTCTime, utcTimeToPOSIXSeconds)++import qualified Codec.Archive.Tar.Entry as Tar+import qualified Distribution.Compat.CharParsing as P+import qualified Text.PrettyPrint as Disp+ -- | UNIX timestamp (expressed in seconds since unix epoch, i.e. 1970). newtype Timestamp = TS Int64 -- Tar.EpochTime deriving (Eq,Ord,Enum,NFData,Show,Generic)@@ -98,20 +93,21 @@ where showTOD = show . timeToTimeOfDay -instance Binary Timestamp where- put (TS t) = put t- get = TS `fmap` get+instance Binary Timestamp+instance Structured Timestamp -instance Text Timestamp where- disp = Disp.text . showTimestamp+instance Pretty Timestamp where+ pretty = Disp.text . showTimestamp - parse = parsePosix ReadP.+++ parseUTC+instance Parsec Timestamp where+ parsec = parsePosix <|> parseUTC where -- | Parses unix timestamps, e.g. @"\@1474626019"@ parsePosix = do- _ <- ReadP.char '@'- t <- parseInteger- maybe ReadP.pfail return $ posixSecondsToTimestamp t+ _ <- P.char '@'+ t <- P.integral -- note, no negative timestamps+ maybe (fail (show t ++ " is not representable as timestamp")) return $+ posixSecondsToTimestamp t -- | Parses ISO8601/RFC3339-style UTC timestamps, -- e.g. @"2017-12-31T23:59:59Z"@@@ -122,71 +118,44 @@ -- we want more control over the accepted formats. ye <- parseYear- _ <- ReadP.char '-'+ _ <- P.char '-' mo <- parseTwoDigits- _ <- ReadP.char '-'+ _ <- P.char '-' da <- parseTwoDigits- _ <- ReadP.char 'T'+ _ <- P.char 'T' - utctDay <- maybe ReadP.pfail return $+ utctDay <- maybe (fail (show (ye,mo,da) ++ " is not valid gregorian date")) return $ fromGregorianValid ye mo da ho <- parseTwoDigits- _ <- ReadP.char ':'+ _ <- P.char ':' mi <- parseTwoDigits- _ <- ReadP.char ':'+ _ <- P.char ':' se <- parseTwoDigits- _ <- ReadP.char 'Z'+ _ <- P.char 'Z' - utctDayTime <- maybe ReadP.pfail (return . timeOfDayToTime) $+ utctDayTime <- maybe (fail (show (ho,mi,se) ++ " is not valid time of day")) (return . timeOfDayToTime) $ makeTimeOfDayValid ho mi (realToFrac (se::Int)) - maybe ReadP.pfail return $ utcTimeToTimestamp (UTCTime{..})+ let utc = UTCTime {..} + maybe (fail (show utc ++ " is not representable as timestamp")) return $ utcTimeToTimestamp utc+ parseTwoDigits = do- d1 <- ReadP.satisfy isDigit- d2 <- ReadP.satisfy isDigit+ d1 <- P.satisfy isDigit+ d2 <- P.satisfy isDigit return (read [d1,d2]) -- A year must have at least 4 digits; e.g. "0097" is fine, -- while "97" is not c.f. RFC3339 which -- deprecates 2-digit years parseYear = do- sign <- ReadP.option ' ' (ReadP.char '-')- ds <- ReadP.munch1 isDigit- when (length ds < 4) ReadP.pfail+ sign <- P.option ' ' (P.char '-')+ ds <- P.munch1 isDigit+ when (length ds < 4) $ fail "Year should have at least 4 digits" return (read (sign:ds)) - parseInteger = do- sign <- ReadP.option ' ' (ReadP.char '-')- ds <- ReadP.munch1 isDigit- return (read (sign:ds) :: Integer)- -- | Special timestamp value to be used when 'timestamp' is -- missing/unknown/invalid nullTimestamp :: Timestamp nullTimestamp = TS minBound--------------------------------------------------------------------------------- defined here for now to avoid import cycles---- | Specification of the state of a specific repo package index-data IndexState = IndexStateHead -- ^ Use all available entries- | IndexStateTime !Timestamp -- ^ Use all entries that existed at- -- the specified time- deriving (Eq,Generic,Show)--instance Binary IndexState-instance NFData IndexState--instance Text IndexState where- disp IndexStateHead = Disp.text "HEAD"- disp (IndexStateTime ts) = disp ts-- parse = parseHead ReadP.+++ parseTime- where- parseHead = do- _ <- ReadP.string "HEAD"- return IndexStateHead-- parseTime = IndexStateTime `fmap` parse
cabal/cabal-install/Distribution/Client/Init.hs view
@@ -21,1291 +21,5 @@ ) where -import Prelude ()-import Distribution.Client.Compat.Prelude hiding (empty)--import Distribution.Deprecated.ReadP (readP_to_E)--import System.IO- ( hSetBuffering, stdout, BufferMode(..) )-import System.Directory- ( getCurrentDirectory, doesDirectoryExist, doesFileExist, copyFile- , getDirectoryContents, createDirectoryIfMissing )-import System.FilePath- ( (</>), (<.>), takeBaseName, takeExtension, equalFilePath )-import Data.Time- ( getCurrentTime, utcToLocalTime, toGregorian, localDay, getCurrentTimeZone )--import Data.List- ( (\\) )-import qualified Data.List.NonEmpty as NE-import Data.Function- ( on )-import qualified Data.Map as M-import qualified Data.Set as Set-import Control.Monad- ( (>=>), join, forM_, mapM, mapM_ )-import Control.Arrow- ( (&&&), (***) )--import Text.PrettyPrint hiding (mode, cat)--import Distribution.Version- ( Version, mkVersion, alterVersion, versionNumbers, majorBoundVersion- , orLaterVersion, earlierVersion, intersectVersionRanges, VersionRange )-import Distribution.Verbosity- ( Verbosity )-import Distribution.ModuleName- ( ModuleName ) -- And for the Text instance-import qualified Distribution.ModuleName as ModuleName- ( fromString, toFilePath )-import Distribution.InstalledPackageInfo- ( InstalledPackageInfo, exposed )-import qualified Distribution.Package as P-import Distribution.Types.LibraryName- ( LibraryName(..) )-import Language.Haskell.Extension ( Language(..) )--import Distribution.Client.Init.Types- ( InitFlags(..), BuildType(..), PackageType(..), Category(..)- , displayPackageType )-import Distribution.Client.Init.Licenses- ( bsd2, bsd3, gplv2, gplv3, lgpl21, lgpl3, agplv3, apache20, mit, mpl20, isc )-import Distribution.Client.Init.Heuristics- ( guessPackageName, guessAuthorNameMail, guessMainFileCandidates,- SourceFileEntry(..),- scanForModules, neededBuildPrograms )--import Distribution.License- ( License(..), knownLicenses, licenseToSPDX )-import qualified Distribution.SPDX as SPDX--import Distribution.ReadE- ( runReadE )-import Distribution.Simple.Setup- ( Flag(..), flagToMaybe )-import Distribution.Simple.Utils- ( dropWhileEndLE )-import Distribution.Simple.Configure- ( getInstalledPackages )-import Distribution.Simple.Compiler- ( PackageDBStack, Compiler )-import Distribution.Simple.Program- ( ProgramDb )-import Distribution.Simple.PackageIndex- ( InstalledPackageIndex, moduleNameIndex )-import Distribution.Deprecated.Text- ( display, Text(..) )-import Distribution.Pretty- ( prettyShow )-import Distribution.Parsec- ( eitherParsec )--import Distribution.Solver.Types.PackageIndex- ( elemByPackageName )--import Distribution.Client.IndexUtils- ( getSourcePackages )-import Distribution.Client.Types- ( SourcePackageDb(..) )-import Distribution.Client.Setup- ( RepoContext(..) )--initCabal :: Verbosity- -> PackageDBStack- -> RepoContext- -> Compiler- -> ProgramDb- -> InitFlags- -> IO ()-initCabal verbosity packageDBs repoCtxt comp progdb initFlags = do-- installedPkgIndex <- getInstalledPackages verbosity comp packageDBs progdb- sourcePkgDb <- getSourcePackages verbosity repoCtxt-- hSetBuffering stdout NoBuffering-- initFlags' <- extendFlags installedPkgIndex sourcePkgDb initFlags-- case license initFlags' of- Flag PublicDomain -> return ()- _ -> writeLicense initFlags'- writeSetupFile initFlags'- writeChangeLog initFlags'- createDirectories (sourceDirs initFlags')- createLibHs initFlags'- createDirectories (applicationDirs initFlags')- createMainHs initFlags'- -- If a test suite was requested and this is not an executable-only- -- package, then create the "test" directory.- when (eligibleForTestSuite initFlags') $ do- createDirectories (testDirs initFlags')- createTestHs initFlags'- success <- writeCabalFile initFlags'-- when success $ generateWarnings initFlags'-------------------------------------------------------------------------------- Flag acquisition ------------------------------------------------------------------------------------------------------------------------------------- | Fill in more details by guessing, discovering, or prompting the--- user.-extendFlags :: InstalledPackageIndex -> SourcePackageDb -> InitFlags -> IO InitFlags-extendFlags pkgIx sourcePkgDb =- getSimpleProject- >=> getLibOrExec- >=> getCabalVersion- >=> getPackageName sourcePkgDb- >=> getVersion- >=> getLicense- >=> getAuthorInfo- >=> getHomepage- >=> getSynopsis- >=> getCategory- >=> getExtraSourceFiles- >=> getAppDir- >=> getSrcDir- >=> getGenTests- >=> getTestDir- >=> getLanguage- >=> getGenComments- >=> getModulesBuildToolsAndDeps pkgIx---- | Combine two actions which may return a value, preferring the first. That--- is, run the second action only if the first doesn't return a value.-infixr 1 ?>>-(?>>) :: IO (Maybe a) -> IO (Maybe a) -> IO (Maybe a)-f ?>> g = do- ma <- f- if isJust ma- then return ma- else g---- | Witness the isomorphism between Maybe and Flag.-maybeToFlag :: Maybe a -> Flag a-maybeToFlag = maybe NoFlag Flag--defaultCabalVersion :: Version-defaultCabalVersion = mkVersion [1,10]--displayCabalVersion :: Version -> String-displayCabalVersion v = case versionNumbers v of- [1,10] -> "1.10 (legacy)"- [2,0] -> "2.0 (+ support for Backpack, internal sub-libs, '^>=' operator)"- [2,2] -> "2.2 (+ support for 'common', 'elif', redundant commas, SPDX)"- [2,4] -> "2.4 (+ support for '**' globbing)"- _ -> display v---- | Ask if a simple project with sensible defaults should be created.-getSimpleProject :: InitFlags -> IO InitFlags-getSimpleProject flags = do- simpleProj <- return (flagToMaybe $ simpleProject flags)- ?>> maybePrompt flags- (promptYesNo- "Should I generate a simple project with sensible defaults"- (Just True))- return $ case maybeToFlag simpleProj of- Flag True ->- flags { interactive = Flag False- , simpleProject = Flag True- , packageType = Flag LibraryAndExecutable- , cabalVersion = Flag (mkVersion [2,4])- }- simpleProjFlag@_ ->- flags { simpleProject = simpleProjFlag }----- | Ask which version of the cabal spec to use.-getCabalVersion :: InitFlags -> IO InitFlags-getCabalVersion flags = do- cabVer <- return (flagToMaybe $ cabalVersion flags)- ?>> maybePrompt flags (either (const defaultCabalVersion) id `fmap`- promptList "Please choose version of the Cabal specification to use"- [mkVersion [1,10], mkVersion [2,0], mkVersion [2,2], mkVersion [2,4]]- (Just defaultCabalVersion) displayCabalVersion False)- ?>> return (Just defaultCabalVersion)-- return $ flags { cabalVersion = maybeToFlag cabVer }----- | Get the package name: use the package directory (supplied, or the current--- directory by default) as a guess. It looks at the SourcePackageDb to avoid--- using an existing package name.-getPackageName :: SourcePackageDb -> InitFlags -> IO InitFlags-getPackageName sourcePkgDb flags = do- guess <- traverse guessPackageName (flagToMaybe $ packageDir flags)- ?>> Just `fmap` (getCurrentDirectory >>= guessPackageName)-- let guess' | isPkgRegistered guess = Nothing- | otherwise = guess-- pkgName' <- return (flagToMaybe $ packageName flags)- ?>> maybePrompt flags (prompt "Package name" guess')- ?>> return guess'-- chooseAgain <- if isPkgRegistered pkgName'- then promptYesNo promptOtherNameMsg (Just True)- else return False-- if chooseAgain- then getPackageName sourcePkgDb flags- else return $ flags { packageName = maybeToFlag pkgName' }-- where- isPkgRegistered (Just pkg) = elemByPackageName (packageIndex sourcePkgDb) pkg- isPkgRegistered Nothing = False-- promptOtherNameMsg = "This package name is already used by another " ++- "package on hackage. Do you want to choose a " ++- "different name"---- | Package version: use 0.1.0.0 as a last resort, but try prompting the user--- if possible.-getVersion :: InitFlags -> IO InitFlags-getVersion flags = do- let v = Just $ mkVersion [0,1,0,0]- v' <- return (flagToMaybe $ version flags)- ?>> maybePrompt flags (prompt "Package version" v)- ?>> return v- return $ flags { version = maybeToFlag v' }---- | Choose a license.-getLicense :: InitFlags -> IO InitFlags-getLicense flags = do- lic <- return (flagToMaybe $ license flags)- ?>> fmap (fmap (either UnknownLicense id))- (maybePrompt flags- (promptList "Please choose a license" listedLicenses- (Just BSD3) displayLicense True))-- case checkLicenseInvalid lic of- Just msg -> putStrLn msg >> getLicense flags- Nothing -> return $ flags { license = maybeToFlag lic }-- where- displayLicense l | needSpdx = prettyShow (licenseToSPDX l)- | otherwise = display l-- checkLicenseInvalid (Just (UnknownLicense t))- | needSpdx = case eitherParsec t :: Either String SPDX.License of- Right _ -> Nothing- Left _ -> Just "\nThe license must be a valid SPDX expression."- | otherwise = if any (not . isAlphaNum) t- then Just promptInvalidOtherLicenseMsg- else Nothing- checkLicenseInvalid _ = Nothing-- promptInvalidOtherLicenseMsg = "\nThe license must be alphanumeric. " ++- "If your license name has many words, " ++- "the convention is to use camel case (e.g. PublicDomain). " ++- "Please choose a different license."-- listedLicenses =- knownLicenses \\ [GPL Nothing, LGPL Nothing, AGPL Nothing- , Apache Nothing, OtherLicense]-- needSpdx = maybe False (>= mkVersion [2,2]) $ flagToMaybe (cabalVersion flags)---- | The author's name and email. Prompt, or try to guess from an existing--- darcs repo.-getAuthorInfo :: InitFlags -> IO InitFlags-getAuthorInfo flags = do- (authorName, authorEmail) <-- (flagToMaybe *** flagToMaybe) `fmap` guessAuthorNameMail- authorName' <- return (flagToMaybe $ author flags)- ?>> maybePrompt flags (promptStr "Author name" authorName)- ?>> return authorName-- authorEmail' <- return (flagToMaybe $ email flags)- ?>> maybePrompt flags (promptStr "Maintainer email" authorEmail)- ?>> return authorEmail-- return $ flags { author = maybeToFlag authorName'- , email = maybeToFlag authorEmail'- }---- | Prompt for a homepage URL.-getHomepage :: InitFlags -> IO InitFlags-getHomepage flags = do- hp <- queryHomepage- hp' <- return (flagToMaybe $ homepage flags)- ?>> maybePrompt flags (promptStr "Project homepage URL" hp)- ?>> return hp-- return $ flags { homepage = maybeToFlag hp' }---- | Right now this does nothing, but it could be changed to do some--- intelligent guessing.-queryHomepage :: IO (Maybe String)-queryHomepage = return Nothing -- get default remote darcs repo?---- | Prompt for a project synopsis.-getSynopsis :: InitFlags -> IO InitFlags-getSynopsis flags = do- syn <- return (flagToMaybe $ synopsis flags)- ?>> maybePrompt flags (promptStr "Project synopsis" Nothing)-- return $ flags { synopsis = maybeToFlag syn }---- | Prompt for a package category.--- Note that it should be possible to do some smarter guessing here too, i.e.--- look at the name of the top level source directory.-getCategory :: InitFlags -> IO InitFlags-getCategory flags = do- cat <- return (flagToMaybe $ category flags)- ?>> fmap join (maybePrompt flags- (promptListOptional "Project category" [Codec ..]))- return $ flags { category = maybeToFlag cat }---- | Try to guess extra source files (don't prompt the user).-getExtraSourceFiles :: InitFlags -> IO InitFlags-getExtraSourceFiles flags = do- extraSrcFiles <- return (extraSrc flags)- ?>> Just `fmap` guessExtraSourceFiles flags-- return $ flags { extraSrc = extraSrcFiles }--defaultChangeLog :: FilePath-defaultChangeLog = "CHANGELOG.md"---- | Try to guess things to include in the extra-source-files field.--- For now, we just look for things in the root directory named--- 'readme', 'changes', or 'changelog', with any sort of--- capitalization and any extension.-guessExtraSourceFiles :: InitFlags -> IO [FilePath]-guessExtraSourceFiles flags = do- dir <-- maybe getCurrentDirectory return . flagToMaybe $ packageDir flags- files <- getDirectoryContents dir- let extraFiles = filter isExtra files- if any isLikeChangeLog extraFiles- then return extraFiles- else return (defaultChangeLog : extraFiles)-- where- isExtra = likeFileNameBase ("README" : changeLogLikeBases)- isLikeChangeLog = likeFileNameBase changeLogLikeBases- likeFileNameBase candidates = (`elem` candidates) . map toUpper . takeBaseName- changeLogLikeBases = ["CHANGES", "CHANGELOG"]---- | Ask whether the project builds a library or executable.-getLibOrExec :: InitFlags -> IO InitFlags-getLibOrExec flags = do- pkgType <- return (flagToMaybe $ packageType flags)- ?>> maybePrompt flags (either (const Executable) id `fmap`- promptList "What does the package build"- [Executable, Library, LibraryAndExecutable]- Nothing displayPackageType False)- ?>> return (Just Executable)-- -- If this package contains an executable, get the main file name.- mainFile <- if pkgType == Just Library then return Nothing else- getMainFile flags-- return $ flags { packageType = maybeToFlag pkgType- , mainIs = maybeToFlag mainFile- }----- | Try to guess the main file of the executable, and prompt the user to choose--- one of them. Top-level modules including the word 'Main' in the file name--- will be candidates, and shorter filenames will be preferred.-getMainFile :: InitFlags -> IO (Maybe FilePath)-getMainFile flags =- return (flagToMaybe $ mainIs flags)- ?>> do- candidates <- guessMainFileCandidates flags- let showCandidate = either (++" (does not yet exist, but will be created)") id- defaultFile = listToMaybe candidates- maybePrompt flags (either id (either id id) `fmap`- promptList "What is the main module of the executable"- candidates- defaultFile showCandidate True)- ?>> return (fmap (either id id) defaultFile)---- | Ask if a test suite should be generated for the library.-getGenTests :: InitFlags -> IO InitFlags-getGenTests flags = do- genTests <- return (flagToMaybe $ initializeTestSuite flags)- -- Only generate a test suite if the package contains a library.- ?>> if (packageType flags) == Flag Executable then return (Just False) else return Nothing- ?>> maybePrompt flags- (promptYesNo- "Should I generate a test suite for the library"- (Just True))- return $ flags { initializeTestSuite = maybeToFlag genTests }---- | Ask for the test root directory.-getTestDir :: InitFlags -> IO InitFlags-getTestDir flags = do- dirs <- return (testDirs flags)- -- Only need testDirs when test suite generation is enabled.- ?>> if not (eligibleForTestSuite flags) then return (Just []) else return Nothing- ?>> fmap (fmap ((:[]) . either id id)) (maybePrompt- flags- (promptList "Test directory" ["test"] (Just "test") id True))-- return $ flags { testDirs = dirs }---- | Ask for the base language of the package.-getLanguage :: InitFlags -> IO InitFlags-getLanguage flags = do- lang <- return (flagToMaybe $ language flags)- ?>> maybePrompt flags- (either UnknownLanguage id `fmap`- promptList "What base language is the package written in"- [Haskell2010, Haskell98]- (Just Haskell2010) display True)- ?>> return (Just Haskell2010)-- if invalidLanguage lang- then putStrLn invalidOtherLanguageMsg >> getLanguage flags- else return $ flags { language = maybeToFlag lang }-- where- invalidLanguage (Just (UnknownLanguage t)) = any (not . isAlphaNum) t- invalidLanguage _ = False-- invalidOtherLanguageMsg = "\nThe language must be alphanumeric. " ++- "Please enter a different language."---- | Ask whether to generate explanatory comments.-getGenComments :: InitFlags -> IO InitFlags-getGenComments flags = do- genComments <- return (not <$> flagToMaybe (noComments flags))- ?>> maybePrompt flags (promptYesNo promptMsg (Just False))- ?>> return (Just False)- return $ flags { noComments = maybeToFlag (fmap not genComments) }- where- promptMsg = "Add informative comments to each field in the cabal file (y/n)"---- | Ask for the application root directory.-getAppDir :: InitFlags -> IO InitFlags-getAppDir flags = do- appDirs <- return (applicationDirs flags)- -- No application dir if this is a 'Library'.- ?>> if (packageType flags) == Flag Library then return (Just []) else return Nothing- ?>> fmap (:[]) `fmap` guessAppDir flags- ?>> fmap (>>= fmap ((:[]) . either id id)) (maybePrompt- flags- (promptListOptional'- ("Application " ++ mainFile ++ "directory")- ["src-exe", "app"] id))-- return $ flags { applicationDirs = appDirs }-- where- mainFile = case mainIs flags of- Flag mainPath -> "(" ++ mainPath ++ ") "- _ -> ""---- | Try to guess app directory. Could try harder; for the--- moment just looks to see whether there is a directory called 'app'.-guessAppDir :: InitFlags -> IO (Maybe String)-guessAppDir flags = do- dir <- maybe getCurrentDirectory return . flagToMaybe $ packageDir flags- appIsDir <- doesDirectoryExist (dir </> "app")- return $ if appIsDir- then Just "app"- else Nothing---- | Ask for the source (library) root directory.-getSrcDir :: InitFlags -> IO InitFlags-getSrcDir flags = do- srcDirs <- return (sourceDirs flags)- -- source dir if this is an 'Executable'.- ?>> if (packageType flags) == Flag Executable then return (Just []) else return Nothing- ?>> fmap (:[]) `fmap` guessSourceDir flags- ?>> fmap (>>= fmap ((:[]) . either id id)) (maybePrompt- flags- (promptListOptional' "Library source directory"- ["src", "lib", "src-lib"] id))-- return $ flags { sourceDirs = srcDirs }---- | Try to guess source directory. Could try harder; for the--- moment just looks to see whether there is a directory called 'src'.-guessSourceDir :: InitFlags -> IO (Maybe String)-guessSourceDir flags = do- dir <-- maybe getCurrentDirectory return . flagToMaybe $ packageDir flags- srcIsDir <- doesDirectoryExist (dir </> "src")- return $ if srcIsDir- then Just "src"- else Nothing---- | Check whether a potential source file is located in one of the--- source directories.-isSourceFile :: Maybe [FilePath] -> SourceFileEntry -> Bool-isSourceFile Nothing sf = isSourceFile (Just ["."]) sf-isSourceFile (Just srcDirs) sf = any (equalFilePath (relativeSourcePath sf)) srcDirs---- | Get the list of exposed modules and extra tools needed to build them.-getModulesBuildToolsAndDeps :: InstalledPackageIndex -> InitFlags -> IO InitFlags-getModulesBuildToolsAndDeps pkgIx flags = do- dir <- maybe getCurrentDirectory return . flagToMaybe $ packageDir flags-- sourceFiles0 <- scanForModules dir-- let sourceFiles = filter (isSourceFile (sourceDirs flags)) sourceFiles0-- Just mods <- return (exposedModules flags)- ?>> (return . Just . map moduleName $ sourceFiles)-- tools <- return (buildTools flags)- ?>> (return . Just . neededBuildPrograms $ sourceFiles)-- deps <- return (dependencies flags)- ?>> Just <$> importsToDeps flags- (fromString "Prelude" : -- to ensure we get base as a dep- ( nub -- only need to consider each imported package once- . filter (`notElem` mods) -- don't consider modules from- -- this package itself- . concatMap imports- $ sourceFiles- )- )- pkgIx-- exts <- return (otherExts flags)- ?>> (return . Just . nub . concatMap extensions $ sourceFiles)-- -- If we're initializing a library and there were no modules discovered- -- then create an empty 'MyLib' module.- -- This gets a little tricky when 'sourceDirs' == 'applicationDirs' because- -- then the executable needs to set 'other-modules: MyLib' or else the build- -- fails.- let (finalModsList, otherMods) = case (packageType flags, mods) of-- -- For an executable leave things as they are.- (Flag Executable, _) -> (mods, otherModules flags)-- -- If a non-empty module list exists don't change anything.- (_, (_:_)) -> (mods, otherModules flags)-- -- Library only: 'MyLib' in 'other-modules' only.- (Flag Library, _) -> ([myLibModule], Nothing)-- -- For a 'LibraryAndExecutable' we need to have special handling.- -- If we don't have a module list (Nothing or empty), then create a Lib.- (_, []) ->- if sourceDirs flags == applicationDirs flags- then ([myLibModule], Just [myLibModule])- else ([myLibModule], Nothing)-- return $ flags { exposedModules = Just finalModsList- , otherModules = otherMods- , buildTools = tools- , dependencies = deps- , otherExts = exts- }--importsToDeps :: InitFlags -> [ModuleName] -> InstalledPackageIndex -> IO [P.Dependency]-importsToDeps flags mods pkgIx = do-- let modMap :: M.Map ModuleName [InstalledPackageInfo]- modMap = M.map (filter exposed) $ moduleNameIndex pkgIx-- modDeps :: [(ModuleName, Maybe [InstalledPackageInfo])]- modDeps = map (id &&& flip M.lookup modMap) mods-- message flags "\nGuessing dependencies..."- nub . catMaybes <$> mapM (chooseDep flags) modDeps---- Given a module and a list of installed packages providing it,--- choose a dependency (i.e. package + version range) to use for that--- module.-chooseDep :: InitFlags -> (ModuleName, Maybe [InstalledPackageInfo])- -> IO (Maybe P.Dependency)--chooseDep flags (m, Nothing)- = message flags ("\nWarning: no package found providing " ++ display m ++ ".")- >> return Nothing--chooseDep flags (m, Just [])- = message flags ("\nWarning: no package found providing " ++ display m ++ ".")- >> return Nothing-- -- We found some packages: group them by name.-chooseDep flags (m, Just ps)- = case pkgGroups of- -- if there's only one group, i.e. multiple versions of a single package,- -- we make it into a dependency, choosing the latest-ish version (see toDep).- [grp] -> Just <$> toDep grp- -- otherwise, we refuse to choose between different packages and make the user- -- do it.- grps -> do message flags ("\nWarning: multiple packages found providing "- ++ display m- ++ ": " ++ intercalate ", " (fmap (display . P.pkgName . NE.head) grps))- message flags "You will need to pick one and manually add it to the Build-depends: field."- return Nothing- where- pkgGroups = NE.groupBy ((==) `on` P.pkgName) (map P.packageId ps)-- desugar = maybe True (< mkVersion [2]) $ flagToMaybe (cabalVersion flags)-- -- Given a list of available versions of the same package, pick a dependency.- toDep :: NonEmpty P.PackageIdentifier -> IO P.Dependency-- -- If only one version, easy. We change e.g. 0.4.2 into 0.4.*- toDep (pid:|[]) = return $ P.Dependency (P.pkgName pid) (pvpize desugar . P.pkgVersion $ pid) (Set.singleton LMainLibName) --TODO sublibraries-- -- Otherwise, choose the latest version and issue a warning.- toDep pids = do- message flags ("\nWarning: multiple versions of " ++ display (P.pkgName . NE.head $ pids) ++ " provide " ++ display m ++ ", choosing the latest.")- return $ P.Dependency (P.pkgName . NE.head $ pids)- (pvpize desugar . maximum . fmap P.pkgVersion $ pids)- (Set.singleton LMainLibName) --TODO take into account sublibraries---- | Given a version, return an API-compatible (according to PVP) version range.------ If the boolean argument denotes whether to use a desugared--- representation (if 'True') or the new-style @^>=@-form (if--- 'False').------ Example: @pvpize True (mkVersion [0,4,1])@ produces the version range @>= 0.4 && < 0.5@ (which is the--- same as @0.4.*@).-pvpize :: Bool -> Version -> VersionRange-pvpize False v = majorBoundVersion v-pvpize True v = orLaterVersion v'- `intersectVersionRanges`- earlierVersion (incVersion 1 v')- where v' = alterVersion (take 2) v---- | Increment the nth version component (counting from 0).-incVersion :: Int -> Version -> Version-incVersion n = alterVersion (incVersion' n)- where- incVersion' 0 [] = [1]- incVersion' 0 (v:_) = [v+1]- incVersion' m [] = replicate m 0 ++ [1]- incVersion' m (v:vs) = v : incVersion' (m-1) vs---- | Returns true if this package is eligible for test suite initialization.-eligibleForTestSuite :: InitFlags -> Bool-eligibleForTestSuite flags =- Flag True == initializeTestSuite flags- && Flag Executable /= packageType flags-------------------------------------------------------------------------------- Prompting/user interaction --------------------------------------------------------------------------------------------------------------------------- | Run a prompt or not based on the interactive flag of the--- InitFlags structure.-maybePrompt :: InitFlags -> IO t -> IO (Maybe t)-maybePrompt flags p =- case interactive flags of- Flag True -> Just `fmap` p- _ -> return Nothing---- | Create a prompt with optional default value that returns a--- String.-promptStr :: String -> Maybe String -> IO String-promptStr = promptDefault' Just id---- | Create a yes/no prompt with optional default value.----promptYesNo :: String -> Maybe Bool -> IO Bool-promptYesNo =- promptDefault' recogniseYesNo showYesNo- where- recogniseYesNo s | s == "y" || s == "Y" = Just True- | s == "n" || s == "N" = Just False- | otherwise = Nothing- showYesNo True = "y"- showYesNo False = "n"---- | Create a prompt with optional default value that returns a value--- of some Text instance.-prompt :: Text t => String -> Maybe t -> IO t-prompt = promptDefault'- (either (const Nothing) Just . runReadE (readP_to_E id parse))- display---- | Create a prompt with an optional default value.-promptDefault' :: (String -> Maybe t) -- ^ parser- -> (t -> String) -- ^ pretty-printer- -> String -- ^ prompt message- -> Maybe t -- ^ optional default value- -> IO t-promptDefault' parser pretty pr def = do- putStr $ mkDefPrompt pr (pretty `fmap` def)- inp <- getLine- case (inp, def) of- ("", Just d) -> return d- _ -> case parser inp of- Just t -> return t- Nothing -> do putStrLn $ "Couldn't parse " ++ inp ++ ", please try again!"- promptDefault' parser pretty pr def---- | Create a prompt from a prompt string and a String representation--- of an optional default value.-mkDefPrompt :: String -> Maybe String -> String-mkDefPrompt pr def = pr ++ "?" ++ defStr def- where defStr Nothing = " "- defStr (Just s) = " [default: " ++ s ++ "] "--promptListOptional :: (Text t, Eq t)- => String -- ^ prompt- -> [t] -- ^ choices- -> IO (Maybe (Either String t))-promptListOptional pr choices = promptListOptional' pr choices display--promptListOptional' :: Eq t- => String -- ^ prompt- -> [t] -- ^ choices- -> (t -> String) -- ^ show an item- -> IO (Maybe (Either String t))-promptListOptional' pr choices displayItem =- fmap rearrange- $ promptList pr (Nothing : map Just choices) (Just Nothing)- (maybe "(none)" displayItem) True- where- rearrange = either (Just . Left) (fmap Right)---- | Create a prompt from a list of items.-promptList :: Eq t- => String -- ^ prompt- -> [t] -- ^ choices- -> Maybe t -- ^ optional default value- -> (t -> String) -- ^ show an item- -> Bool -- ^ whether to allow an 'other' option- -> IO (Either String t)-promptList pr choices def displayItem other = do- putStrLn $ pr ++ ":"- let options1 = map (\c -> (Just c == def, displayItem c)) choices- options2 = zip ([1..]::[Int])- (options1 ++ [(False, "Other (specify)") | other])- mapM_ (putStrLn . \(n,(i,s)) -> showOption n i ++ s) options2- promptList' displayItem (length options2) choices def other- where showOption n i | n < 10 = " " ++ star i ++ " " ++ rest- | otherwise = " " ++ star i ++ rest- where rest = show n ++ ") "- star True = "*"- star False = " "--promptList' :: (t -> String) -> Int -> [t] -> Maybe t -> Bool -> IO (Either String t)-promptList' displayItem numChoices choices def other = do- putStr $ mkDefPrompt "Your choice" (displayItem `fmap` def)- inp <- getLine- case (inp, def) of- ("", Just d) -> return $ Right d- _ -> case readMaybe inp of- Nothing -> invalidChoice inp- Just n -> getChoice n- where invalidChoice inp = do putStrLn $ inp ++ " is not a valid choice."- promptList' displayItem numChoices choices def other- getChoice n | n < 1 || n > numChoices = invalidChoice (show n)- | n < numChoices ||- (n == numChoices && not other)- = return . Right $ choices !! (n-1)- | otherwise = Left `fmap` promptStr "Please specify" Nothing-------------------------------------------------------------------------------- File generation ------------------------------------------------------------------------------------------------------------------------------------writeLicense :: InitFlags -> IO ()-writeLicense flags = do- message flags "\nGenerating LICENSE..."- year <- show <$> getYear- let authors = fromMaybe "???" . flagToMaybe . author $ flags- let licenseFile =- case license flags of- Flag BSD2- -> Just $ bsd2 authors year-- Flag BSD3- -> Just $ bsd3 authors year-- Flag (GPL (Just v)) | v == mkVersion [2]- -> Just gplv2-- Flag (GPL (Just v)) | v == mkVersion [3]- -> Just gplv3-- Flag (LGPL (Just v)) | v == mkVersion [2,1]- -> Just lgpl21-- Flag (LGPL (Just v)) | v == mkVersion [3]- -> Just lgpl3-- Flag (AGPL (Just v)) | v == mkVersion [3]- -> Just agplv3-- Flag (Apache (Just v)) | v == mkVersion [2,0]- -> Just apache20-- Flag MIT- -> Just $ mit authors year-- Flag (MPL v) | v == mkVersion [2,0]- -> Just mpl20-- Flag ISC- -> Just $ isc authors year-- _ -> Nothing-- case licenseFile of- Just licenseText -> writeFileSafe flags "LICENSE" licenseText- Nothing -> message flags "Warning: unknown license type, you must put a copy in LICENSE yourself."--getYear :: IO Integer-getYear = do- u <- getCurrentTime- z <- getCurrentTimeZone- let l = utcToLocalTime z u- (y, _, _) = toGregorian $ localDay l- return y--writeSetupFile :: InitFlags -> IO ()-writeSetupFile flags = do- message flags "Generating Setup.hs..."- writeFileSafe flags "Setup.hs" setupFile- where- setupFile = unlines- [ "import Distribution.Simple"- , "main = defaultMain"- ]--writeChangeLog :: InitFlags -> IO ()-writeChangeLog flags = when ((defaultChangeLog `elem`) $ fromMaybe [] (extraSrc flags)) $ do- message flags ("Generating "++ defaultChangeLog ++"...")- writeFileSafe flags defaultChangeLog changeLog- where- changeLog = unlines- [ "# Revision history for " ++ pname- , ""- , "## " ++ pver ++ " -- YYYY-mm-dd"- , ""- , "* First version. Released on an unsuspecting world."- ]- pname = maybe "" display $ flagToMaybe $ packageName flags- pver = maybe "" display $ flagToMaybe $ version flags----writeCabalFile :: InitFlags -> IO Bool-writeCabalFile flags@(InitFlags{packageName = NoFlag}) = do- message flags "Error: no package name provided."- return False-writeCabalFile flags@(InitFlags{packageName = Flag p}) = do- let cabalFileName = display p ++ ".cabal"- message flags $ "Generating " ++ cabalFileName ++ "..."- writeFileSafe flags cabalFileName (generateCabalFile cabalFileName flags)- return True---- | Write a file \"safely\", backing up any existing version (unless--- the overwrite flag is set).-writeFileSafe :: InitFlags -> FilePath -> String -> IO ()-writeFileSafe flags fileName content = do- moveExistingFile flags fileName- writeFile fileName content---- | Create directories, if they were given, and don't already exist.-createDirectories :: Maybe [String] -> IO ()-createDirectories mdirs = case mdirs of- Just dirs -> forM_ dirs (createDirectoryIfMissing True)- Nothing -> return ()---- | Create MyLib.hs file, if its the only module in the liste.-createLibHs :: InitFlags -> IO ()-createLibHs flags = when ((exposedModules flags) == Just [myLibModule]) $ do- let modFilePath = ModuleName.toFilePath myLibModule ++ ".hs"- case sourceDirs flags of- Just (srcPath:_) -> writeLibHs flags (srcPath </> modFilePath)- _ -> writeLibHs flags modFilePath---- | Write a MyLib.hs file if it doesn't already exist.-writeLibHs :: InitFlags -> FilePath -> IO ()-writeLibHs flags libPath = do- dir <- maybe getCurrentDirectory return (flagToMaybe $ packageDir flags)- let libFullPath = dir </> libPath- exists <- doesFileExist libFullPath- unless exists $ do- message flags $ "Generating " ++ libPath ++ "..."- writeFileSafe flags libFullPath myLibHs--myLibModule :: ModuleName-myLibModule = ModuleName.fromString "MyLib"---- | Default MyLib.hs file. Used when no Lib.hs exists.-myLibHs :: String-myLibHs = unlines- [ "module MyLib (someFunc) where"- , ""- , "someFunc :: IO ()"- , "someFunc = putStrLn \"someFunc\""- ]---- | Create Main.hs, but only if we are init'ing an executable and--- the mainIs flag has been provided.-createMainHs :: InitFlags -> IO ()-createMainHs flags =- if hasMainHs flags then- case applicationDirs flags of- Just (appPath:_) -> writeMainHs flags (appPath </> mainFile)- _ -> writeMainHs flags mainFile- else return ()- where- Flag mainFile = mainIs flags----- | Write a main file if it doesn't already exist.-writeMainHs :: InitFlags -> FilePath -> IO ()-writeMainHs flags mainPath = do- dir <- maybe getCurrentDirectory return (flagToMaybe $ packageDir flags)- let mainFullPath = dir </> mainPath- exists <- doesFileExist mainFullPath- unless exists $ do- message flags $ "Generating " ++ mainPath ++ "..."- writeFileSafe flags mainFullPath (mainHs flags)---- | Check that a main file exists.-hasMainHs :: InitFlags -> Bool-hasMainHs flags = case mainIs flags of- Flag _ -> (packageType flags == Flag Executable- || packageType flags == Flag LibraryAndExecutable)- _ -> False---- | Default Main.(l)hs file. Used when no Main.(l)hs exists.------ If we are initializing a new 'LibraryAndExecutable' then import 'MyLib'.-mainHs :: InitFlags -> String-mainHs flags = (unlines . map prependPrefix) $ case packageType flags of- Flag LibraryAndExecutable ->- [ "module Main where"- , ""- , "import qualified MyLib (someFunc)"- , ""- , "main :: IO ()"- , "main = do"- , " putStrLn \"Hello, Haskell!\""- , " MyLib.someFunc"- ]- _ ->- [ "module Main where"- , ""- , "main :: IO ()"- , "main = putStrLn \"Hello, Haskell!\""- ]- where- prependPrefix "" = ""- prependPrefix line- | isLiterate = "> " ++ line- | otherwise = line- isLiterate = case mainIs flags of- Flag mainPath -> takeExtension mainPath == ".lhs"- _ -> False--testFile :: String-testFile = "MyLibTest.hs"---- | Create MyLibTest.hs, but only if we are init'ing a library and--- the initializeTestSuite flag has been set.-createTestHs :: InitFlags -> IO ()-createTestHs flags =- when (eligibleForTestSuite flags) $- case testDirs flags of- Just (testPath:_) -> writeTestHs flags (testPath </> testFile)- _ -> writeMainHs flags testFile----- | Write a test file.-writeTestHs :: InitFlags -> FilePath -> IO ()-writeTestHs flags testPath = do- dir <- maybe getCurrentDirectory return (flagToMaybe $ packageDir flags)- let testFullPath = dir </> testPath- exists <- doesFileExist testFullPath- unless exists $ do- message flags $ "Generating " ++ testPath ++ "..."- writeFileSafe flags testFullPath testHs---- | Default MyLibTest.hs file.-testHs :: String-testHs = unlines- [ "module Main (main) where"- , ""- , "main :: IO ()"- , "main = putStrLn \"Test suite not yet implemented.\""- ]----- | Move an existing file, if there is one, and the overwrite flag is--- not set.-moveExistingFile :: InitFlags -> FilePath -> IO ()-moveExistingFile flags fileName =- unless (overwrite flags == Flag True) $ do- e <- doesFileExist fileName- when e $ do- newName <- findNewName fileName- message flags $ "Warning: " ++ fileName ++ " already exists, backing up old version in " ++ newName- copyFile fileName newName--findNewName :: FilePath -> IO FilePath-findNewName oldName = findNewName' 0- where- findNewName' :: Integer -> IO FilePath- findNewName' n = do- let newName = oldName <.> ("save" ++ show n)- e <- doesFileExist newName- if e then findNewName' (n+1) else return newName---- | Generate a .cabal file from an InitFlags structure. NOTE: this--- is rather ad-hoc! What we would REALLY like is to have a--- standard low-level AST type representing .cabal files, which--- preserves things like comments, and to write an *inverse*--- parser/pretty-printer pair between .cabal files and this AST.--- Then instead of this ad-hoc code we could just map an InitFlags--- structure onto a low-level AST structure and use the existing--- pretty-printing code to generate the file.-generateCabalFile :: String -> InitFlags -> String-generateCabalFile fileName c = trimTrailingWS $- (++ "\n") .- renderStyle style { lineLength = 79, ribbonsPerLine = 1.1 } $- -- Starting with 2.2 the `cabal-version` field needs to be the first line of the PD- (if specVer < mkVersion [1,12]- then field "cabal-version" (Flag $ orLaterVersion specVer) -- legacy- else field "cabal-version" (Flag $ specVer))- Nothing -- NB: the first line must be the 'cabal-version' declaration- False- $$- (if minimal c /= Flag True- then showComment (Just $ "Initial package description '" ++ fileName ++ "' generated "- ++ "by 'cabal init'. For further documentation, see "- ++ "http://haskell.org/cabal/users-guide/")- $$ text ""- else empty)- $$- vcat [ field "name" (packageName c)- (Just "The name of the package.")- True-- , field "version" (version c)- (Just $ "The package version. See the Haskell package versioning policy (PVP) for standards guiding when and how versions should be incremented.\nhttps://pvp.haskell.org\n"- ++ "PVP summary: +-+------- breaking API changes\n"- ++ " | | +----- non-breaking API additions\n"- ++ " | | | +--- code changes with no API change")- True-- , fieldS "synopsis" (synopsis c)- (Just "A short (one-line) description of the package.")- True-- , fieldS "description" NoFlag- (Just "A longer description of the package.")- True-- , fieldS "homepage" (homepage c)- (Just "URL for the project homepage or repository.")- False-- , fieldS "bug-reports" NoFlag- (Just "A URL where users can report bugs.")- True-- , fieldS "license" licenseStr- (Just "The license under which the package is released.")- True-- , case (license c) of- Flag PublicDomain -> empty- _ -> fieldS "license-file" (Flag "LICENSE")- (Just "The file containing the license text.")- True-- , fieldS "author" (author c)- (Just "The package author(s).")- True-- , fieldS "maintainer" (email c)- (Just "An email address to which users can send suggestions, bug reports, and patches.")- True-- , case (license c) of- Flag PublicDomain -> empty- _ -> fieldS "copyright" NoFlag- (Just "A copyright notice.")- True-- , fieldS "category" (either id display `fmap` category c)- Nothing- True-- , fieldS "build-type" (if specVer >= mkVersion [2,2] then NoFlag else Flag "Simple")- Nothing- False-- , fieldS "extra-source-files" (listFieldS (extraSrc c))- (Just "Extra files to be distributed with the package, such as examples or a README.")- True-- , case packageType c of- Flag Executable -> executableStanza- Flag Library -> libraryStanza- Flag LibraryAndExecutable -> libraryStanza $+$ executableStanza- _ -> empty-- , if eligibleForTestSuite c then testSuiteStanza else empty- ]- where- specVer = fromMaybe defaultCabalVersion $ flagToMaybe (cabalVersion c)-- licenseStr | specVer < mkVersion [2,2] = prettyShow `fmap` license c- | otherwise = go `fmap` license c- where- go (UnknownLicense s) = s- go l = prettyShow (licenseToSPDX l)-- generateBuildInfo :: BuildType -> InitFlags -> Doc- generateBuildInfo buildType c' = vcat- [ fieldS "other-modules" (listField otherMods)- (Just $ case buildType of- LibBuild -> "Modules included in this library but not exported."- ExecBuild -> "Modules included in this executable, other than Main.")- True-- , fieldS "other-extensions" (listField (otherExts c'))- (Just "LANGUAGE extensions used by modules in this package.")- True-- , fieldS "build-depends" ((++ myLibDep) <$> listField (dependencies c'))- (Just "Other library packages from which modules are imported.")- True-- , fieldS "hs-source-dirs" (listFieldS (case buildType of- LibBuild -> sourceDirs c'- ExecBuild -> applicationDirs c'))- (Just "Directories containing source files.")- True-- , fieldS "build-tools" (listFieldS (buildTools c'))- (Just "Extra tools (e.g. alex, hsc2hs, ...) needed to build the source.")- False-- , field "default-language" (language c')- (Just "Base language which the package is written in.")- True- ]- -- Hack: Can't construct a 'Dependency' which is just 'packageName'(?).- where- myLibDep = if exposedModules c' == Just [myLibModule] && buildType == ExecBuild- then case packageName c' of- Flag pkgName -> ", " ++ P.unPackageName pkgName- _ -> ""- else ""-- -- Only include 'MyLib' in 'other-modules' of the executable.- otherModsFromFlag = otherModules c'- otherMods = if buildType == LibBuild && otherModsFromFlag == Just [myLibModule]- then Nothing- else otherModsFromFlag-- listField :: Text s => Maybe [s] -> Flag String- listField = listFieldS . fmap (map display)-- listFieldS :: Maybe [String] -> Flag String- listFieldS = Flag . maybe "" (intercalate ", ")-- field :: Text t => String -> Flag t -> Maybe String -> Bool -> Doc- field s f = fieldS s (fmap display f)-- fieldS :: String -- ^ Name of the field- -> Flag String -- ^ Field contents- -> Maybe String -- ^ Comment to explain the field- -> Bool -- ^ Should the field be included (commented out) even if blank?- -> Doc- fieldS _ NoFlag _ inc | not inc || (minimal c == Flag True) = empty- fieldS _ (Flag "") _ inc | not inc || (minimal c == Flag True) = empty- fieldS s f com _ = case (isJust com, noComments c, minimal c) of- (_, _, Flag True) -> id- (_, Flag True, _) -> id- (True, _, _) -> (showComment com $$) . ($$ text "")- (False, _, _) -> ($$ text "")- $- comment f <<>> text s <<>> colon- <<>> text (replicate (20 - length s) ' ')- <<>> text (fromMaybe "" . flagToMaybe $ f)- comment NoFlag = text "-- "- comment (Flag "") = text "-- "- comment _ = text ""-- showComment :: Maybe String -> Doc- showComment (Just t) = vcat- . map (text . ("-- "++)) . lines- . renderStyle style {- lineLength = 76,- ribbonsPerLine = 1.05- }- . vcat- . map (fcat . map text . breakLine)- . lines- $ t- showComment Nothing = text ""-- breakLine [] = []- breakLine cs = case break (==' ') cs of (w,cs') -> w : breakLine' cs'- breakLine' [] = []- breakLine' cs = case span (==' ') cs of (w,cs') -> w : breakLine cs'-- trimTrailingWS :: String -> String- trimTrailingWS = unlines . map (dropWhileEndLE isSpace) . lines-- executableStanza :: Doc- executableStanza = text "\nexecutable" <+>- text (maybe "" display . flagToMaybe $ packageName c) $$- nest 2 (vcat- [ fieldS "main-is" (mainIs c) (Just ".hs or .lhs file containing the Main module.") True-- , generateBuildInfo ExecBuild c- ])-- libraryStanza :: Doc- libraryStanza = text "\nlibrary" $$ nest 2 (vcat- [ fieldS "exposed-modules" (listField (exposedModules c))- (Just "Modules exported by the library.")- True-- , generateBuildInfo LibBuild c- ])-- testSuiteStanza :: Doc- testSuiteStanza = text "\ntest-suite" <+>- text (maybe "" ((++"-test") . display) . flagToMaybe $ packageName c) $$- nest 2 (vcat- [ field "default-language" (language c)- (Just "Base language which the package is written in.")- True-- , fieldS "type" (Flag "exitcode-stdio-1.0")- (Just "The interface type and version of the test suite.")- True-- , fieldS "hs-source-dirs" (listFieldS (testDirs c))- (Just "The directory where the test specifications are found.")- True-- , fieldS "main-is" (Flag testFile)- (Just "The entrypoint to the test suite.")- True-- , fieldS "build-depends" (listField (dependencies c))- (Just "Test dependencies.")- True- ])---- | Generate warnings for missing fields etc.-generateWarnings :: InitFlags -> IO ()-generateWarnings flags = do- message flags ""- when (synopsis flags `elem` [NoFlag, Flag ""])- (message flags "Warning: no synopsis given. You should edit the .cabal file and add one.")-- message flags "You may want to edit the .cabal file and add a Description field."---- | Possibly generate a message to stdout, taking into account the--- --quiet flag.-message :: InitFlags -> String -> IO ()-message (InitFlags{quiet = Flag True}) _ = return ()-message _ s = putStrLn s+import Distribution.Client.Init.Command+ ( initCabal, incVersion )
+ cabal/cabal-install/Distribution/Client/Init/Command.hs view
@@ -0,0 +1,730 @@+-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Client.Init.Command+-- Copyright : (c) Brent Yorgey 2009+-- License : BSD-like+--+-- Maintainer : cabal-devel@haskell.org+-- Stability : provisional+-- Portability : portable+--+-- Implementation of the 'cabal init' command, which creates an initial .cabal+-- file for a project.+--+-----------------------------------------------------------------------------++module Distribution.Client.Init.Command (++ -- * Commands+ initCabal+ , incVersion++ ) where++import Prelude ()+import Distribution.Client.Compat.Prelude hiding (empty)++import System.IO+ ( hSetBuffering, stdout, BufferMode(..) )+import System.Directory+ ( getCurrentDirectory, doesDirectoryExist, getDirectoryContents )+import System.FilePath+ ( (</>), takeBaseName, equalFilePath )++import qualified Data.List.NonEmpty as NE+import qualified Data.Map as M+import Control.Monad+ ( (>=>) )+import Control.Arrow+ ( (&&&), (***) )++import Distribution.CabalSpecVersion+ ( CabalSpecVersion (..), showCabalSpecVersion )+import Distribution.Version+ ( Version, mkVersion, alterVersion, majorBoundVersion+ , orLaterVersion, earlierVersion, intersectVersionRanges, VersionRange )+import Distribution.ModuleName+ ( ModuleName ) -- And for the Text instance+import Distribution.InstalledPackageInfo+ ( InstalledPackageInfo, exposed )+import qualified Distribution.Package as P+import qualified Distribution.SPDX as SPDX+import Language.Haskell.Extension ( Language(..) )++import Distribution.Client.Init.Defaults+ ( defaultApplicationDir, defaultCabalVersion, myLibModule, defaultSourceDir )+import Distribution.Client.Init.FileCreators+ ( writeLicense, writeChangeLog, createDirectories, createLibHs, createMainHs+ , createTestSuiteIfEligible, writeCabalFile )+import Distribution.Client.Init.Prompt+ ( prompt, promptYesNo, promptStr, promptList, maybePrompt+ , promptListOptional )+import Distribution.Client.Init.Utils+ ( eligibleForTestSuite, message )+import Distribution.Client.Init.Types+ ( InitFlags(..), PackageType(..), Category(..)+ , displayPackageType )+import Distribution.Client.Init.Heuristics+ ( guessPackageName, guessAuthorNameMail, guessMainFileCandidates,+ SourceFileEntry(..),+ scanForModules, neededBuildPrograms )++import Distribution.Simple.Flag+ ( maybeToFlag )+import Distribution.Simple.Setup+ ( Flag(..), flagToMaybe )+import Distribution.Simple.Configure+ ( getInstalledPackages )+import Distribution.Simple.Compiler+ ( PackageDBStack, Compiler )+import Distribution.Simple.Program+ ( ProgramDb )+import Distribution.Simple.PackageIndex+ ( InstalledPackageIndex, moduleNameIndex )++import Distribution.Solver.Types.PackageIndex+ ( elemByPackageName )++import Distribution.Client.IndexUtils+ ( getSourcePackages )+import Distribution.Client.Types+ ( SourcePackageDb(..) )+import Distribution.Client.Setup+ ( RepoContext(..) )++initCabal :: Verbosity+ -> PackageDBStack+ -> RepoContext+ -> Compiler+ -> ProgramDb+ -> InitFlags+ -> IO ()+initCabal verbosity packageDBs repoCtxt comp progdb initFlags = do++ installedPkgIndex <- getInstalledPackages verbosity comp packageDBs progdb+ sourcePkgDb <- getSourcePackages verbosity repoCtxt++ hSetBuffering stdout NoBuffering++ initFlags' <- extendFlags installedPkgIndex sourcePkgDb initFlags++ case license initFlags' of+ Flag SPDX.NONE -> return ()+ _ -> writeLicense initFlags'+ writeChangeLog initFlags'+ createDirectories (sourceDirs initFlags')+ createLibHs initFlags'+ createDirectories (applicationDirs initFlags')+ createMainHs initFlags'+ createTestSuiteIfEligible initFlags'+ success <- writeCabalFile initFlags'++ when success $ generateWarnings initFlags'++---------------------------------------------------------------------------+-- Flag acquisition -----------------------------------------------------+---------------------------------------------------------------------------++-- | Fill in more details in InitFlags by guessing, discovering, or prompting+-- the user.+extendFlags :: InstalledPackageIndex -> SourcePackageDb -> InitFlags -> IO InitFlags+extendFlags pkgIx sourcePkgDb =+ getSimpleProject+ >=> getLibOrExec+ >=> getCabalVersion+ >=> getPackageName sourcePkgDb+ >=> getVersion+ >=> getLicense+ >=> getAuthorInfo+ >=> getHomepage+ >=> getSynopsis+ >=> getCategory+ >=> getExtraSourceFiles+ >=> getAppDir+ >=> getSrcDir+ >=> getGenTests+ >=> getTestDir+ >=> getLanguage+ >=> getGenComments+ >=> getModulesBuildToolsAndDeps pkgIx++-- | Combine two actions which may return a value, preferring the first. That+-- is, run the second action only if the first doesn't return a value.+infixr 1 ?>>+(?>>) :: IO (Maybe a) -> IO (Maybe a) -> IO (Maybe a)+f ?>> g = do+ ma <- f+ if isJust ma+ then return ma+ else g++-- | Ask if a simple project with sensible defaults should be created.+getSimpleProject :: InitFlags -> IO InitFlags+getSimpleProject flags = do+ simpleProj <- return (flagToMaybe $ simpleProject flags)+ ?>> maybePrompt flags+ (promptYesNo+ "Should I generate a simple project with sensible defaults"+ (Just True))+ return $ case maybeToFlag simpleProj of+ Flag True ->+ flags { interactive = Flag False+ , simpleProject = Flag True+ , packageType = Flag LibraryAndExecutable+ , cabalVersion = Flag defaultCabalVersion+ }+ simpleProjFlag@_ ->+ flags { simpleProject = simpleProjFlag }+++-- | Get the version of the cabal spec to use.+--+-- The spec version can be specified by the InitFlags cabalVersion field. If+-- none is specified then the user is prompted to pick from a list of+-- supported versions (see code below).+getCabalVersion :: InitFlags -> IO InitFlags+getCabalVersion flags = do+ cabVer <- return (flagToMaybe $ cabalVersion flags)+ ?>> maybePrompt flags (either (const defaultCabalVersion) id `fmap`+ promptList "Please choose version of the Cabal specification to use"+ [CabalSpecV1_10, CabalSpecV2_0, CabalSpecV2_2, CabalSpecV2_4, CabalSpecV3_0]+ (Just defaultCabalVersion) displayCabalVersion False)+ ?>> return (Just defaultCabalVersion)++ return $ flags { cabalVersion = maybeToFlag cabVer }++ where+ displayCabalVersion :: CabalSpecVersion -> String+ displayCabalVersion v = case v of+ CabalSpecV1_10 -> "1.10 (legacy)"+ CabalSpecV2_0 -> "2.0 (+ support for Backpack, internal sub-libs, '^>=' operator)"+ CabalSpecV2_2 -> "2.2 (+ support for 'common', 'elif', redundant commas, SPDX)"+ CabalSpecV2_4 -> "2.4 (+ support for '**' globbing)"+ CabalSpecV3_0 -> "3.0 (+ set notation for ==, common stanzas in ifs, more redundant commas, better pkgconfig-depends)"+ _ -> showCabalSpecVersion v++++-- | Get the package name: use the package directory (supplied, or the current+-- directory by default) as a guess. It looks at the SourcePackageDb to avoid+-- using an existing package name.+getPackageName :: SourcePackageDb -> InitFlags -> IO InitFlags+getPackageName sourcePkgDb flags = do+ guess <- traverse guessPackageName (flagToMaybe $ packageDir flags)+ ?>> Just `fmap` (getCurrentDirectory >>= guessPackageName)++ let guess' | isPkgRegistered guess = Nothing+ | otherwise = guess++ pkgName' <- return (flagToMaybe $ packageName flags)+ ?>> maybePrompt flags (prompt "Package name" guess')+ ?>> return guess'++ chooseAgain <- if isPkgRegistered pkgName'+ then promptYesNo promptOtherNameMsg (Just True)+ else return False++ if chooseAgain+ then getPackageName sourcePkgDb flags+ else return $ flags { packageName = maybeToFlag pkgName' }++ where+ isPkgRegistered (Just pkg) = elemByPackageName (packageIndex sourcePkgDb) pkg+ isPkgRegistered Nothing = False++ promptOtherNameMsg = "This package name is already used by another " +++ "package on hackage. Do you want to choose a " +++ "different name"++-- | Package version: use 0.1.0.0 as a last resort, but try prompting the user+-- if possible.+getVersion :: InitFlags -> IO InitFlags+getVersion flags = do+ let v = Just $ mkVersion [0,1,0,0]+ v' <- return (flagToMaybe $ version flags)+ ?>> maybePrompt flags (prompt "Package version" v)+ ?>> return v+ return $ flags { version = maybeToFlag v' }++-- | Choose a license for the package.+--+-- The license can come from Initflags (license field), if it is not present+-- then prompt the user from a predefined list of licenses.+getLicense :: InitFlags -> IO InitFlags+getLicense flags = do+ elic <- return (fmap Right $ flagToMaybe $ license flags)+ ?>> maybePrompt flags (promptList "Please choose a license" listedLicenses (Just SPDX.NONE) prettyShow True)++ case elic of+ Nothing -> return flags { license = NoFlag }+ Just (Right lic) -> return flags { license = Flag lic }+ Just (Left str) -> case eitherParsec str of+ Right lic -> return flags { license = Flag lic }+ -- on error, loop+ Left err -> do+ putStrLn "The license must be a valid SPDX expression."+ putStrLn err+ getLicense flags+ where+ -- perfectly we'll have this and writeLicense (in FileCreators)+ -- in a single file+ listedLicenses =+ SPDX.NONE :+ map (\lid -> SPDX.License (SPDX.ELicense (SPDX.ELicenseId lid) Nothing))+ [ SPDX.BSD_2_Clause+ , SPDX.BSD_3_Clause+ , SPDX.Apache_2_0+ , SPDX.MIT+ , SPDX.MPL_2_0+ , SPDX.ISC++ , SPDX.GPL_2_0_only+ , SPDX.GPL_3_0_only+ , SPDX.LGPL_2_1_only+ , SPDX.LGPL_3_0_only+ , SPDX.AGPL_3_0_only++ , SPDX.GPL_2_0_or_later+ , SPDX.GPL_3_0_or_later+ , SPDX.LGPL_2_1_or_later+ , SPDX.LGPL_3_0_or_later+ , SPDX.AGPL_3_0_or_later+ ]++-- | The author's name and email. Prompt, or try to guess from an existing+-- darcs repo.+getAuthorInfo :: InitFlags -> IO InitFlags+getAuthorInfo flags = do+ (authorName, authorEmail) <-+ (flagToMaybe *** flagToMaybe) `fmap` guessAuthorNameMail+ authorName' <- return (flagToMaybe $ author flags)+ ?>> maybePrompt flags (promptStr "Author name" authorName)+ ?>> return authorName++ authorEmail' <- return (flagToMaybe $ email flags)+ ?>> maybePrompt flags (promptStr "Maintainer email" authorEmail)+ ?>> return authorEmail++ return $ flags { author = maybeToFlag authorName'+ , email = maybeToFlag authorEmail'+ }++-- | Prompt for a homepage URL for the package.+getHomepage :: InitFlags -> IO InitFlags+getHomepage flags = do+ hp <- queryHomepage+ hp' <- return (flagToMaybe $ homepage flags)+ ?>> maybePrompt flags (promptStr "Project homepage URL" hp)+ ?>> return hp++ return $ flags { homepage = maybeToFlag hp' }++-- | Right now this does nothing, but it could be changed to do some+-- intelligent guessing.+queryHomepage :: IO (Maybe String)+queryHomepage = return Nothing -- get default remote darcs repo?++-- | Prompt for a project synopsis.+getSynopsis :: InitFlags -> IO InitFlags+getSynopsis flags = do+ syn <- return (flagToMaybe $ synopsis flags)+ ?>> maybePrompt flags (promptStr "Project synopsis" Nothing)++ return $ flags { synopsis = maybeToFlag syn }++-- | Prompt for a package category.+-- Note that it should be possible to do some smarter guessing here too, i.e.+-- look at the name of the top level source directory.+getCategory :: InitFlags -> IO InitFlags+getCategory flags = do+ cat <- return (flagToMaybe $ category flags)+ ?>> fmap join (maybePrompt flags+ (promptListOptional "Project category" [Codec ..]))+ return $ flags { category = maybeToFlag cat }++-- | Try to guess extra source files (don't prompt the user).+getExtraSourceFiles :: InitFlags -> IO InitFlags+getExtraSourceFiles flags = do+ extraSrcFiles <- return (extraSrc flags)+ ?>> Just `fmap` guessExtraSourceFiles flags++ return $ flags { extraSrc = extraSrcFiles }++defaultChangeLog :: FilePath+defaultChangeLog = "CHANGELOG.md"++-- | Try to guess things to include in the extra-source-files field.+-- For now, we just look for things in the root directory named+-- 'readme', 'changes', or 'changelog', with any sort of+-- capitalization and any extension.+guessExtraSourceFiles :: InitFlags -> IO [FilePath]+guessExtraSourceFiles flags = do+ dir <-+ maybe getCurrentDirectory return . flagToMaybe $ packageDir flags+ files <- getDirectoryContents dir+ let extraFiles = filter isExtra files+ if any isLikeChangeLog extraFiles+ then return extraFiles+ else return (defaultChangeLog : extraFiles)++ where+ isExtra = likeFileNameBase ("README" : changeLogLikeBases)+ isLikeChangeLog = likeFileNameBase changeLogLikeBases+ likeFileNameBase candidates = (`elem` candidates) . map toUpper . takeBaseName+ changeLogLikeBases = ["CHANGES", "CHANGELOG"]++-- | Ask whether the project builds a library or executable.+getLibOrExec :: InitFlags -> IO InitFlags+getLibOrExec flags = do+ pkgType <- return (flagToMaybe $ packageType flags)+ ?>> maybePrompt flags (either (const Executable) id `fmap`+ promptList "What does the package build"+ [Executable, Library, LibraryAndExecutable]+ Nothing displayPackageType False)+ ?>> return (Just Executable)++ -- If this package contains an executable, get the main file name.+ mainFile <- if pkgType == Just Library then return Nothing else+ getMainFile flags++ return $ flags { packageType = maybeToFlag pkgType+ , mainIs = maybeToFlag mainFile+ }+++-- | Try to guess the main file of the executable, and prompt the user to choose+-- one of them. Top-level modules including the word 'Main' in the file name+-- will be candidates, and shorter filenames will be preferred.+getMainFile :: InitFlags -> IO (Maybe FilePath)+getMainFile flags =+ return (flagToMaybe $ mainIs flags)+ ?>> do+ candidates <- guessMainFileCandidates flags+ let showCandidate = either (++" (does not yet exist, but will be created)") id+ defaultFile = listToMaybe candidates+ maybePrompt flags (either id (either id id) `fmap`+ promptList "What is the main module of the executable"+ candidates+ defaultFile showCandidate True)+ ?>> return (fmap (either id id) defaultFile)++-- | Ask if a test suite should be generated for the library.+getGenTests :: InitFlags -> IO InitFlags+getGenTests flags = do+ genTests <- return (flagToMaybe $ initializeTestSuite flags)+ -- Only generate a test suite if the package contains a library.+ ?>> if (packageType flags) == Flag Executable then return (Just False) else return Nothing+ ?>> maybePrompt flags+ (promptYesNo+ "Should I generate a test suite for the library"+ (Just True))+ return $ flags { initializeTestSuite = maybeToFlag genTests }++-- | Ask for the test suite root directory.+getTestDir :: InitFlags -> IO InitFlags+getTestDir flags = do+ dirs <- return (testDirs flags)+ -- Only need testDirs when test suite generation is enabled.+ ?>> if not (eligibleForTestSuite flags) then return (Just []) else return Nothing+ ?>> fmap (fmap ((:[]) . either id id)) (maybePrompt+ flags+ (promptList "Test directory" ["test"] (Just "test") id True))++ return $ flags { testDirs = dirs }++-- | Ask for the Haskell base language of the package.+getLanguage :: InitFlags -> IO InitFlags+getLanguage flags = do+ lang <- return (flagToMaybe $ language flags)+ ?>> maybePrompt flags+ (either UnknownLanguage id `fmap`+ promptList "What base language is the package written in"+ [Haskell2010, Haskell98]+ (Just Haskell2010) prettyShow True)+ ?>> return (Just Haskell2010)++ if invalidLanguage lang+ then putStrLn invalidOtherLanguageMsg >> getLanguage flags+ else return $ flags { language = maybeToFlag lang }++ where+ invalidLanguage (Just (UnknownLanguage t)) = any (not . isAlphaNum) t+ invalidLanguage _ = False++ invalidOtherLanguageMsg = "\nThe language must be alphanumeric. " +++ "Please enter a different language."++-- | Ask whether to generate explanatory comments.+getGenComments :: InitFlags -> IO InitFlags+getGenComments flags = do+ genComments <- return (not <$> flagToMaybe (noComments flags))+ ?>> maybePrompt flags (promptYesNo promptMsg (Just False))+ ?>> return (Just False)+ return $ flags { noComments = maybeToFlag (fmap not genComments) }+ where+ promptMsg = "Add informative comments to each field in the cabal file (y/n)"++-- | Ask for the application root directory.+getAppDir :: InitFlags -> IO InitFlags+getAppDir flags = do+ appDirs <-+ return (applicationDirs flags)+ ?>> noAppDirIfLibraryOnly+ ?>> guessAppDir flags+ ?>> promptUserForApplicationDir+ ?>> setDefault+ return $ flags { applicationDirs = appDirs }++ where+ -- If the packageType==Library, then there is no application dir.+ noAppDirIfLibraryOnly :: IO (Maybe [String])+ noAppDirIfLibraryOnly =+ if (packageType flags) == Flag Library+ then return (Just [])+ else return Nothing++ -- Set the default application directory.+ setDefault :: IO (Maybe [String])+ setDefault = pure (Just [defaultApplicationDir])++ -- Prompt the user for the application directory (defaulting to "app").+ -- Returns 'Nothing' if in non-interactive mode, otherwise will always+ -- return a 'Just' value ('Just []' if no separate application directory).+ promptUserForApplicationDir :: IO (Maybe [String])+ promptUserForApplicationDir = fmap (either (:[]) id) <$> maybePrompt+ flags+ (promptList+ ("Application " ++ mainFile ++ "directory")+ [[defaultApplicationDir], ["src-exe"], []]+ (Just [defaultApplicationDir])+ showOption True)++ showOption :: [String] -> String+ showOption [] = "(none)"+ showOption (x:_) = x++ -- The name+ mainFile :: String+ mainFile = case mainIs flags of+ Flag mainPath -> "(" ++ mainPath ++ ") "+ _ -> ""++-- | Try to guess app directory. Could try harder; for the+-- moment just looks to see whether there is a directory called 'app'.+guessAppDir :: InitFlags -> IO (Maybe [String])+guessAppDir flags = do+ dir <- maybe getCurrentDirectory return . flagToMaybe $ packageDir flags+ appIsDir <- doesDirectoryExist (dir </> "app")+ return $ if appIsDir+ then Just ["app"]+ else Nothing++-- | Ask for the source (library) root directory.+getSrcDir :: InitFlags -> IO InitFlags+getSrcDir flags = do+ srcDirs <-+ return (sourceDirs flags)+ ?>> noSourceDirIfExecutableOnly+ ?>> guessSourceDir flags+ ?>> promptUserForSourceDir+ ?>> setDefault++ return $ flags { sourceDirs = srcDirs }++ where+ -- If the packageType==Executable, then there is no source dir.+ noSourceDirIfExecutableOnly :: IO (Maybe [String])+ noSourceDirIfExecutableOnly =+ if (packageType flags) == Flag Executable+ then return (Just [])+ else return Nothing++ -- Set the default source directory.+ setDefault :: IO (Maybe [String])+ setDefault = pure (Just [defaultSourceDir])++ -- Prompt the user for the source directory (defaulting to "app").+ -- Returns 'Nothing' if in non-interactive mode, otherwise will always+ -- return a 'Just' value ('Just []' if no separate application directory).+ promptUserForSourceDir :: IO (Maybe [String])+ promptUserForSourceDir = fmap (either (:[]) id) <$> maybePrompt+ flags+ (promptList+ ("Library source directory")+ [[defaultSourceDir], ["lib"], ["src-lib"], []]+ (Just [defaultSourceDir])+ showOption True)++ showOption :: [String] -> String+ showOption [] = "(none)"+ showOption (x:_) = x+++-- | Try to guess source directory. Could try harder; for the+-- moment just looks to see whether there is a directory called 'src'.+guessSourceDir :: InitFlags -> IO (Maybe [String])+guessSourceDir flags = do+ dir <-+ maybe getCurrentDirectory return . flagToMaybe $ packageDir flags+ srcIsDir <- doesDirectoryExist (dir </> "src")+ return $ if srcIsDir+ then Just ["src"]+ else Nothing++-- | Check whether a potential source file is located in one of the+-- source directories.+isSourceFile :: Maybe [FilePath] -> SourceFileEntry -> Bool+isSourceFile Nothing sf = isSourceFile (Just ["."]) sf+isSourceFile (Just srcDirs) sf = any (equalFilePath (relativeSourcePath sf)) srcDirs++-- | Get the list of exposed modules and extra tools needed to build them.+getModulesBuildToolsAndDeps :: InstalledPackageIndex -> InitFlags -> IO InitFlags+getModulesBuildToolsAndDeps pkgIx flags = do+ dir <- maybe getCurrentDirectory return . flagToMaybe $ packageDir flags++ sourceFiles0 <- scanForModules dir++ let sourceFiles = filter (isSourceFile (sourceDirs flags)) sourceFiles0++ Just mods <- return (exposedModules flags)+ ?>> (return . Just . map moduleName $ sourceFiles)++ tools <- return (buildTools flags)+ ?>> (return . Just . neededBuildPrograms $ sourceFiles)++ deps <- return (dependencies flags)+ ?>> Just <$> importsToDeps flags+ (fromString "Prelude" : -- to ensure we get base as a dep+ ( nub -- only need to consider each imported package once+ . filter (`notElem` mods) -- don't consider modules from+ -- this package itself+ . concatMap imports+ $ sourceFiles+ )+ )+ pkgIx++ exts <- return (otherExts flags)+ ?>> (return . Just . nub . concatMap extensions $ sourceFiles)++ -- If we're initializing a library and there were no modules discovered+ -- then create an empty 'MyLib' module.+ -- This gets a little tricky when 'sourceDirs' == 'applicationDirs' because+ -- then the executable needs to set 'other-modules: MyLib' or else the build+ -- fails.+ let (finalModsList, otherMods) = case (packageType flags, mods) of++ -- For an executable leave things as they are.+ (Flag Executable, _) -> (mods, otherModules flags)++ -- If a non-empty module list exists don't change anything.+ (_, (_:_)) -> (mods, otherModules flags)++ -- Library only: 'MyLib' in 'other-modules' only.+ (Flag Library, _) -> ([myLibModule], Nothing)++ -- For a 'LibraryAndExecutable' we need to have special handling.+ -- If we don't have a module list (Nothing or empty), then create a Lib.+ (_, []) ->+ if sourceDirs flags == applicationDirs flags+ then ([myLibModule], Just [myLibModule])+ else ([myLibModule], Nothing)++ return $ flags { exposedModules = Just finalModsList+ , otherModules = otherMods+ , buildTools = tools+ , dependencies = deps+ , otherExts = exts+ }++-- | Given a list of imported modules, retrieve the list of dependencies that+-- provide those modules.+importsToDeps :: InitFlags -> [ModuleName] -> InstalledPackageIndex -> IO [P.Dependency]+importsToDeps flags mods pkgIx = do++ let modMap :: M.Map ModuleName [InstalledPackageInfo]+ modMap = M.map (filter exposed) $ moduleNameIndex pkgIx++ modDeps :: [(ModuleName, Maybe [InstalledPackageInfo])]+ modDeps = map (id &&& flip M.lookup modMap) mods++ message flags "\nGuessing dependencies..."+ nub . catMaybes <$> traverse (chooseDep flags) modDeps++-- Given a module and a list of installed packages providing it,+-- choose a dependency (i.e. package + version range) to use for that+-- module.+chooseDep :: InitFlags -> (ModuleName, Maybe [InstalledPackageInfo])+ -> IO (Maybe P.Dependency)++chooseDep flags (m, Nothing)+ = message flags ("\nWarning: no package found providing " ++ prettyShow m ++ ".")+ >> return Nothing++chooseDep flags (m, Just [])+ = message flags ("\nWarning: no package found providing " ++ prettyShow m ++ ".")+ >> return Nothing++ -- We found some packages: group them by name.+chooseDep flags (m, Just ps)+ = case pkgGroups of+ -- if there's only one group, i.e. multiple versions of a single package,+ -- we make it into a dependency, choosing the latest-ish version (see toDep).+ [grp] -> Just <$> toDep grp+ -- otherwise, we refuse to choose between different packages and make the user+ -- do it.+ grps -> do message flags ("\nWarning: multiple packages found providing "+ ++ prettyShow m+ ++ ": " ++ intercalate ", " (fmap (prettyShow . P.pkgName . NE.head) grps))+ message flags "You will need to pick one and manually add it to the Build-depends: field."+ return Nothing+ where+ pkgGroups = NE.groupBy ((==) `on` P.pkgName) (map P.packageId ps)++ desugar = maybe True (< CabalSpecV2_0) $ flagToMaybe (cabalVersion flags)++ -- Given a list of available versions of the same package, pick a dependency.+ toDep :: NonEmpty P.PackageIdentifier -> IO P.Dependency++ -- If only one version, easy. We change e.g. 0.4.2 into 0.4.*+ toDep (pid:|[]) = return $ P.Dependency (P.pkgName pid) (pvpize desugar . P.pkgVersion $ pid) P.mainLibSet --TODO sublibraries++ -- Otherwise, choose the latest version and issue a warning.+ toDep pids = do+ message flags ("\nWarning: multiple versions of " ++ prettyShow (P.pkgName . NE.head $ pids) ++ " provide " ++ prettyShow m ++ ", choosing the latest.")+ return $ P.Dependency (P.pkgName . NE.head $ pids)+ (pvpize desugar . maximum . fmap P.pkgVersion $ pids)+ P.mainLibSet --TODO take into account sublibraries++-- | Given a version, return an API-compatible (according to PVP) version range.+--+-- If the boolean argument denotes whether to use a desugared+-- representation (if 'True') or the new-style @^>=@-form (if+-- 'False').+--+-- Example: @pvpize True (mkVersion [0,4,1])@ produces the version range @>= 0.4 && < 0.5@ (which is the+-- same as @0.4.*@).+pvpize :: Bool -> Version -> VersionRange+pvpize False v = majorBoundVersion v+pvpize True v = orLaterVersion v'+ `intersectVersionRanges`+ earlierVersion (incVersion 1 v')+ where v' = alterVersion (take 2) v++-- | Increment the nth version component (counting from 0).+incVersion :: Int -> Version -> Version+incVersion n = alterVersion (incVersion' n)+ where+ incVersion' 0 [] = [1]+ incVersion' 0 (v:_) = [v+1]+ incVersion' m [] = replicate m 0 ++ [1]+ incVersion' m (v:vs) = v : incVersion' (m-1) vs++-- | Generate warnings for missing fields etc.+generateWarnings :: InitFlags -> IO ()+generateWarnings flags = do+ message flags ""+ when (synopsis flags `elem` [NoFlag, Flag ""])+ (message flags "Warning: no synopsis given. You should edit the .cabal file and add one.")++ message flags "You may want to edit the .cabal file and add a Description field."
+ cabal/cabal-install/Distribution/Client/Init/Defaults.hs view
@@ -0,0 +1,41 @@+-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Client.Init.Defaults+-- Copyright : (c) Brent Yorgey 2009+-- License : BSD-like+--+-- Maintainer : cabal-devel@haskell.org+-- Stability : provisional+-- Portability : portable+--+-- Default values to use in cabal init (if not specified in config/flags).+--+-----------------------------------------------------------------------------++module Distribution.Client.Init.Defaults (+ defaultApplicationDir+ , defaultSourceDir+ , defaultCabalVersion+ , myLibModule+ ) where++import Prelude (String)++import Distribution.ModuleName+ ( ModuleName ) -- And for the Text instance+import qualified Distribution.ModuleName as ModuleName+ ( fromString )+import Distribution.CabalSpecVersion+ ( CabalSpecVersion (..))++defaultApplicationDir :: String+defaultApplicationDir = "app"++defaultSourceDir :: String+defaultSourceDir = "src"++defaultCabalVersion :: CabalSpecVersion+defaultCabalVersion = CabalSpecV2_4++myLibModule :: ModuleName+myLibModule = ModuleName.fromString "MyLib"
+ cabal/cabal-install/Distribution/Client/Init/FileCreators.hs view
@@ -0,0 +1,650 @@+{-# LANGUAGE OverloadedStrings #-}+-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Client.Init.FileCreators+-- Copyright : (c) Brent Yorgey 2009+-- License : BSD-like+--+-- Maintainer : cabal-devel@haskell.org+-- Stability : provisional+-- Portability : portable+--+-- Functions to create files during 'cabal init'.+--+-----------------------------------------------------------------------------++module Distribution.Client.Init.FileCreators (++ -- * Commands+ writeLicense+ , writeChangeLog+ , createDirectories+ , createLibHs+ , createMainHs+ , createTestSuiteIfEligible+ , writeCabalFile++ -- * For testing+ , generateCabalFile+ ) where++import Prelude ()+import Distribution.Client.Compat.Prelude hiding (empty)++import System.FilePath+ ( (</>), (<.>), takeExtension )++import Distribution.Types.Dependency+import Distribution.Types.VersionRange++import Data.Time+ ( getCurrentTime, utcToLocalTime, toGregorian, localDay, getCurrentTimeZone )+import System.Directory+ ( getCurrentDirectory, doesFileExist, copyFile+ , createDirectoryIfMissing )++import Text.PrettyPrint hiding ((<>), mode, cat)++import Distribution.Client.Init.Defaults+ ( defaultCabalVersion, myLibModule )+import Distribution.Client.Init.Licenses+ ( bsd2, bsd3, gplv2, gplv3, lgpl21, lgpl3, agplv3, apache20, mit, mpl20, isc )+import Distribution.Client.Init.Utils+ ( eligibleForTestSuite, message )+import Distribution.Client.Init.Types+ ( InitFlags(..), BuildType(..), PackageType(..) )++import Distribution.CabalSpecVersion+import Distribution.Compat.Newtype+ ( Newtype )+import Distribution.Fields.Field+ ( FieldName )+import Distribution.License+ ( licenseFromSPDX )+import qualified Distribution.ModuleName as ModuleName+ ( toFilePath )+import Distribution.FieldGrammar.Newtypes+ ( SpecVersion(..) )+import Distribution.PackageDescription.FieldGrammar+ ( formatDependencyList, formatExposedModules, formatHsSourceDirs,+ formatOtherExtensions, formatOtherModules, formatExtraSourceFiles )+import Distribution.Simple.Flag+ ( maybeToFlag )+import Distribution.Simple.Setup+ ( Flag(..), flagToMaybe )+import Distribution.Simple.Utils+ ( toUTF8BS )+import Distribution.Fields.Pretty+ ( PrettyField(..), showFields' )++import qualified Distribution.SPDX as SPDX+++---------------------------------------------------------------------------+-- File generation ------------------------------------------------------+---------------------------------------------------------------------------++-- | Write the LICENSE file, as specified in the InitFlags license field.+--+-- For licences that contain the author's name(s), the values are taken+-- from the 'authors' field of 'InitFlags', and if not specified will+-- be the string "???".+--+-- If the license type is unknown no license file will be created and+-- a warning will be raised.+writeLicense :: InitFlags -> IO ()+writeLicense flags = do+ message flags "\nGenerating LICENSE..."+ year <- show <$> getCurrentYear+ let authors = fromMaybe "???" . flagToMaybe . author $ flags+ let isSimpleLicense :: SPDX.License -> Maybe SPDX.LicenseId+ isSimpleLicense (SPDX.License (SPDX.ELicense (SPDX.ELicenseId lid) Nothing)) = Just lid+ isSimpleLicense _ = Nothing+ let licenseFile =+ case flagToMaybe (license flags) >>= isSimpleLicense of+ Just SPDX.BSD_2_Clause -> Just $ bsd2 authors year+ Just SPDX.BSD_3_Clause -> Just $ bsd3 authors year+ Just SPDX.Apache_2_0 -> Just apache20+ Just SPDX.MIT -> Just $ mit authors year+ Just SPDX.MPL_2_0 -> Just mpl20+ Just SPDX.ISC -> Just $ isc authors year++ -- GNU license come in "only" and "or-later" flavours+ -- license file used are the same.+ Just SPDX.GPL_2_0_only -> Just gplv2+ Just SPDX.GPL_3_0_only -> Just gplv3+ Just SPDX.LGPL_2_1_only -> Just lgpl21+ Just SPDX.LGPL_3_0_only -> Just lgpl3+ Just SPDX.AGPL_3_0_only -> Just agplv3++ Just SPDX.GPL_2_0_or_later -> Just gplv2+ Just SPDX.GPL_3_0_or_later -> Just gplv3+ Just SPDX.LGPL_2_1_or_later -> Just lgpl21+ Just SPDX.LGPL_3_0_or_later -> Just lgpl3+ Just SPDX.AGPL_3_0_or_later -> Just agplv3++ _ -> Nothing++ case licenseFile of+ Just licenseText -> writeFileSafe flags "LICENSE" licenseText+ Nothing -> message flags "Warning: unknown license type, you must put a copy in LICENSE yourself."++-- | Returns the current calendar year.+getCurrentYear :: IO Integer+getCurrentYear = do+ u <- getCurrentTime+ z <- getCurrentTimeZone+ let l = utcToLocalTime z u+ (y, _, _) = toGregorian $ localDay l+ return y++defaultChangeLog :: FilePath+defaultChangeLog = "CHANGELOG.md"++-- | Writes the changelog to the current directory.+writeChangeLog :: InitFlags -> IO ()+writeChangeLog flags = when ((defaultChangeLog `elem`) $ fromMaybe [] (extraSrc flags)) $ do+ message flags ("Generating "++ defaultChangeLog ++"...")+ writeFileSafe flags defaultChangeLog changeLog+ where+ changeLog = unlines+ [ "# Revision history for " ++ pname+ , ""+ , "## " ++ pver ++ " -- YYYY-mm-dd"+ , ""+ , "* First version. Released on an unsuspecting world."+ ]+ pname = maybe "" prettyShow $ flagToMaybe $ packageName flags+ pver = maybe "" prettyShow $ flagToMaybe $ version flags++-- | Creates and writes the initialized .cabal file.+--+-- Returns @False@ if no package name is specified, @True@ otherwise.+writeCabalFile :: InitFlags -> IO Bool+writeCabalFile flags@(InitFlags{packageName = NoFlag}) = do+ message flags "Error: no package name provided."+ return False+writeCabalFile flags@(InitFlags{packageName = Flag p}) = do+ let cabalFileName = prettyShow p ++ ".cabal"+ message flags $ "Generating " ++ cabalFileName ++ "..."+ writeFileSafe flags cabalFileName (generateCabalFile cabalFileName flags)+ return True++-- | Write a file \"safely\", backing up any existing version (unless+-- the overwrite flag is set).+writeFileSafe :: InitFlags -> FilePath -> String -> IO ()+writeFileSafe flags fileName content = do+ moveExistingFile flags fileName+ writeFile fileName content++-- | Create directories, if they were given, and don't already exist.+createDirectories :: Maybe [String] -> IO ()+createDirectories mdirs = case mdirs of+ Just dirs -> for_ dirs (createDirectoryIfMissing True)+ Nothing -> return ()++-- | Create MyLib.hs file, if its the only module in the liste.+createLibHs :: InitFlags -> IO ()+createLibHs flags = when ((exposedModules flags) == Just [myLibModule]) $ do+ let modFilePath = ModuleName.toFilePath myLibModule ++ ".hs"+ case sourceDirs flags of+ Just (srcPath:_) -> writeLibHs flags (srcPath </> modFilePath)+ _ -> writeLibHs flags modFilePath++-- | Write a MyLib.hs file if it doesn't already exist.+writeLibHs :: InitFlags -> FilePath -> IO ()+writeLibHs flags libPath = do+ dir <- maybe getCurrentDirectory return (flagToMaybe $ packageDir flags)+ let libFullPath = dir </> libPath+ exists <- doesFileExist libFullPath+ unless exists $ do+ message flags $ "Generating " ++ libPath ++ "..."+ writeFileSafe flags libFullPath myLibHs++-- | Default MyLib.hs file. Used when no Lib.hs exists.+myLibHs :: String+myLibHs = unlines+ [ "module MyLib (someFunc) where"+ , ""+ , "someFunc :: IO ()"+ , "someFunc = putStrLn \"someFunc\""+ ]++-- | Create Main.hs, but only if we are init'ing an executable and+-- the mainIs flag has been provided.+createMainHs :: InitFlags -> IO ()+createMainHs flags =+ if hasMainHs flags then+ case applicationDirs flags of+ Just (appPath:_) -> writeMainHs flags (appPath </> mainFile)+ _ -> writeMainHs flags mainFile+ else return ()+ where+ mainFile = case mainIs flags of+ Flag x -> x+ NoFlag -> error "createMainHs: no mainIs"++-- | Write a main file if it doesn't already exist.+writeMainHs :: InitFlags -> FilePath -> IO ()+writeMainHs flags mainPath = do+ dir <- maybe getCurrentDirectory return (flagToMaybe $ packageDir flags)+ let mainFullPath = dir </> mainPath+ exists <- doesFileExist mainFullPath+ unless exists $ do+ message flags $ "Generating " ++ mainPath ++ "..."+ writeFileSafe flags mainFullPath (mainHs flags)++-- | Returns true if a main file exists.+hasMainHs :: InitFlags -> Bool+hasMainHs flags = case mainIs flags of+ Flag _ -> (packageType flags == Flag Executable+ || packageType flags == Flag LibraryAndExecutable)+ _ -> False++-- | Default Main.(l)hs file. Used when no Main.(l)hs exists.+--+-- If we are initializing a new 'LibraryAndExecutable' then import 'MyLib'.+mainHs :: InitFlags -> String+mainHs flags = (unlines . map prependPrefix) $ case packageType flags of+ Flag LibraryAndExecutable ->+ [ "module Main where"+ , ""+ , "import qualified MyLib (someFunc)"+ , ""+ , "main :: IO ()"+ , "main = do"+ , " putStrLn \"Hello, Haskell!\""+ , " MyLib.someFunc"+ ]+ _ ->+ [ "module Main where"+ , ""+ , "main :: IO ()"+ , "main = putStrLn \"Hello, Haskell!\""+ ]+ where+ prependPrefix :: String -> String+ prependPrefix "" = ""+ prependPrefix line+ | isLiterate = "> " ++ line+ | otherwise = line+ isLiterate = case mainIs flags of+ Flag mainPath -> takeExtension mainPath == ".lhs"+ _ -> False++-- | Create a test suite for the package if eligible.+createTestSuiteIfEligible :: InitFlags -> IO ()+createTestSuiteIfEligible flags =+ when (eligibleForTestSuite flags) $ do+ createDirectories (testDirs flags)+ createTestHs flags++-- | The name of the test file to generate (if --tests is specified).+testFile :: String+testFile = "MyLibTest.hs"++-- | Create MyLibTest.hs, but only if we are init'ing a library and+-- the initializeTestSuite flag has been set.+--+-- It is up to the caller to verify that the package is eligible+-- for test suite initialization (see eligibleForTestSuite).+createTestHs :: InitFlags -> IO ()+createTestHs flags =+ case testDirs flags of+ Just (testPath:_) -> writeTestHs flags (testPath </> testFile)+ _ -> writeMainHs flags testFile++-- | Write a test file.+writeTestHs :: InitFlags -> FilePath -> IO ()+writeTestHs flags testPath = do+ dir <- maybe getCurrentDirectory return (flagToMaybe $ packageDir flags)+ let testFullPath = dir </> testPath+ exists <- doesFileExist testFullPath+ unless exists $ do+ message flags $ "Generating " ++ testPath ++ "..."+ writeFileSafe flags testFullPath testHs++-- | Default MyLibTest.hs file.+testHs :: String+testHs = unlines+ [ "module Main (main) where"+ , ""+ , "main :: IO ()"+ , "main = putStrLn \"Test suite not yet implemented.\""+ ]+++-- | Move an existing file, if there is one, and the overwrite flag is+-- not set.+moveExistingFile :: InitFlags -> FilePath -> IO ()+moveExistingFile flags fileName =+ unless (overwrite flags == Flag True) $ do+ e <- doesFileExist fileName+ when e $ do+ newName <- findNewName fileName+ message flags $ "Warning: " ++ fileName ++ " already exists, backing up old version in " ++ newName+ copyFile fileName newName+++-- | Given a file path find a new name for the file that does not+-- already exist.+findNewName :: FilePath -> IO FilePath+findNewName oldName = findNewName' 0+ where+ findNewName' :: Integer -> IO FilePath+ findNewName' n = do+ let newName = oldName <.> ("save" ++ show n)+ e <- doesFileExist newName+ if e then findNewName' (n+1) else return newName+++-- | Generate a .cabal file from an InitFlags structure.+generateCabalFile :: String -> InitFlags -> String+generateCabalFile fileName c =+ showFields' annCommentLines postProcessFieldLines 4 $ catMaybes+ [ fieldP "cabal-version" (Flag . SpecVersion $ specVer)+ []+ False++ , field "name" (packageName c)+ ["Initial package description '" ++ fileName ++ "' generated by",+ "'cabal init'. For further documentation, see:",+ " http://haskell.org/cabal/users-guide/",+ "",+ "The name of the package."]+ True++ , field "version" (version c)+ ["The package version.",+ "See the Haskell package versioning policy (PVP) for standards",+ "guiding when and how versions should be incremented.",+ "https://pvp.haskell.org",+ "PVP summary: +-+------- breaking API changes",+ " | | +----- non-breaking API additions",+ " | | | +--- code changes with no API change"]+ True++ , fieldS "synopsis" (synopsis c)+ ["A short (one-line) description of the package."]+ True++ , fieldS "description" NoFlag+ ["A longer description of the package."]+ True++ , fieldS "homepage" (homepage c)+ ["URL for the project homepage or repository."]+ False++ , fieldS "bug-reports" NoFlag+ ["A URL where users can report bugs."]+ True++ , fieldS "license" licenseStr+ ["The license under which the package is released."]+ True++ , case license c of+ NoFlag -> Nothing+ Flag SPDX.NONE -> Nothing+ _ -> fieldS "license-file" (Flag "LICENSE")+ ["The file containing the license text."]+ True++ , fieldS "author" (author c)+ ["The package author(s)."]+ True++ , fieldS "maintainer" (email c)+ ["An email address to which users can send suggestions, bug reports, and patches."]+ True++ , fieldS "copyright" NoFlag+ ["A copyright notice."]+ True++ , fieldS "category" (either id prettyShow `fmap` category c)+ []+ True++ , fieldS "build-type" (if specVer >= CabalSpecV2_2 then NoFlag else Flag "Simple")+ []+ False++ , fieldPAla "extra-source-files" formatExtraSourceFiles (maybeToFlag (extraSrc c))+ ["Extra files to be distributed with the package, such as examples or a README."]+ True+ ]+ +++ (case packageType c of+ Flag Executable -> [executableStanza]+ Flag Library -> [libraryStanza]+ Flag LibraryAndExecutable -> [libraryStanza, executableStanza]+ _ -> [])+ +++ if eligibleForTestSuite c then [testSuiteStanza] else []++ where+ specVer :: CabalSpecVersion+ specVer = fromMaybe defaultCabalVersion $ flagToMaybe (cabalVersion c)++ licenseStr | specVer < CabalSpecV2_2 = prettyShow . licenseFromSPDX <$> license c+ | otherwise = prettyShow <$> license c++ generateBuildInfo :: BuildType -> InitFlags -> [PrettyField FieldAnnotation]+ generateBuildInfo buildType c' = catMaybes+ [ fieldPAla "other-modules" formatOtherModules (maybeToFlag otherMods)+ [ case buildType of+ LibBuild -> "Modules included in this library but not exported."+ ExecBuild -> "Modules included in this executable, other than Main."]+ True++ , fieldPAla "other-extensions" formatOtherExtensions (maybeToFlag (otherExts c))+ ["LANGUAGE extensions used by modules in this package."]+ True++ , fieldPAla "build-depends" formatDependencyList (maybeToFlag buildDependencies)+ ["Other library packages from which modules are imported."]+ True++ , fieldPAla "hs-source-dirs" formatHsSourceDirs+ (maybeToFlag (case buildType of+ LibBuild -> sourceDirs c+ ExecBuild -> applicationDirs c))+ ["Directories containing source files."]+ True++ , fieldS "build-tools" (listFieldS $ buildTools c)+ ["Extra tools (e.g. alex, hsc2hs, ...) needed to build the source."]+ False++ , field "default-language" (language c)+ ["Base language which the package is written in."]+ True+ ]+ -- Hack: Can't construct a 'Dependency' which is just 'packageName'(?).+ where+ buildDependencies :: Maybe [Dependency]+ buildDependencies = (++ myLibDep) <$> dependencies c'++ myLibDep :: [Dependency]+ myLibDep = if exposedModules c' == Just [myLibModule] && buildType == ExecBuild+ then case packageName c' of+ Flag pkgName ->+ [mkDependency pkgName anyVersion mainLibSet]+ _ -> []+ else []++ -- Only include 'MyLib' in 'other-modules' of the executable.+ otherModsFromFlag = otherModules c'+ otherMods = if buildType == LibBuild && otherModsFromFlag == Just [myLibModule]+ then Nothing+ else otherModsFromFlag++ listFieldS :: Maybe [String] -> Flag String+ listFieldS Nothing = NoFlag+ listFieldS (Just []) = NoFlag+ listFieldS (Just xs) = Flag . intercalate ", " $ xs++ -- | Construct a 'PrettyField' from a field that can be automatically+ -- converted to a 'Doc' via 'display'.+ field :: Pretty t+ => FieldName+ -> Flag t+ -> [String]+ -> Bool+ -> Maybe (PrettyField FieldAnnotation)+ field fieldName fieldContentsFlag = fieldS fieldName (prettyShow <$> fieldContentsFlag)++ -- | Construct a 'PrettyField' from a 'String' field.+ fieldS :: FieldName -- ^ Name of the field+ -> Flag String -- ^ Field contents+ -> [String] -- ^ Comment to explain the field+ -> Bool -- ^ Should the field be included (commented out) even if blank?+ -> Maybe (PrettyField FieldAnnotation)+ fieldS fieldName fieldContentsFlag = fieldD fieldName (text <$> fieldContentsFlag)++ -- | Construct a 'PrettyField' from a Flag which can be 'pretty'-ied.+ fieldP :: Pretty a+ => FieldName+ -> Flag a+ -> [String]+ -> Bool+ -> Maybe (PrettyField FieldAnnotation)+ fieldP fieldName fieldContentsFlag fieldComments includeField =+ fieldPAla fieldName Identity fieldContentsFlag fieldComments includeField++ -- | Construct a 'PrettyField' from a flag which can be 'pretty'-ied, wrapped in newtypeWrapper.+ fieldPAla+ :: (Pretty b, Newtype a b)+ => FieldName+ -> (a -> b)+ -> Flag a+ -> [String]+ -> Bool+ -> Maybe (PrettyField FieldAnnotation)+ fieldPAla fieldName newtypeWrapper fieldContentsFlag fieldComments includeField =+ fieldD fieldName (pretty . newtypeWrapper <$> fieldContentsFlag) fieldComments includeField++ -- | Construct a 'PrettyField' from a 'Doc' Flag.+ fieldD :: FieldName -- ^ Name of the field+ -> Flag Doc -- ^ Field contents+ -> [String] -- ^ Comment to explain the field+ -> Bool -- ^ Should the field be included (commented out) even if blank?+ -> Maybe (PrettyField FieldAnnotation)+ fieldD fieldName fieldContentsFlag fieldComments includeField =+ case fieldContentsFlag of+ NoFlag ->+ -- If there is no content, optionally produce a commented out field.+ fieldSEmptyContents fieldName fieldComments includeField++ Flag fieldContents ->+ if isEmpty fieldContents+ then+ -- If the doc is empty, optionally produce a commented out field.+ fieldSEmptyContents fieldName fieldComments includeField+ else+ -- If the doc is not empty, produce a field.+ Just $ case (noComments c, minimal c) of+ -- If the "--no-comments" flag is set, strip comments.+ (Flag True, _) ->+ fieldSWithContents fieldName fieldContents []+ -- If the "--minimal" flag is set, strip comments.+ (_, Flag True) ->+ fieldSWithContents fieldName fieldContents []+ -- Otherwise, include comments.+ (_, _) ->+ fieldSWithContents fieldName fieldContents fieldComments++ -- | Optionally produce a field with no content (depending on flags).+ fieldSEmptyContents :: FieldName+ -> [String]+ -> Bool+ -> Maybe (PrettyField FieldAnnotation)+ fieldSEmptyContents fieldName fieldComments includeField+ | not includeField || (minimal c == Flag True) =+ Nothing+ | otherwise =+ Just (PrettyField (commentedOutWithComments fieldComments) fieldName empty)++ -- | Produce a field with content.+ fieldSWithContents :: FieldName+ -> Doc+ -> [String]+ -> PrettyField FieldAnnotation+ fieldSWithContents fieldName fieldContents fieldComments =+ PrettyField (withComments (map ("-- " ++) fieldComments)) fieldName fieldContents++ executableStanza :: PrettyField FieldAnnotation+ executableStanza = PrettySection annNoComments (toUTF8BS "executable") [exeName] $ catMaybes+ [ fieldS "main-is" (mainIs c)+ [".hs or .lhs file containing the Main module."]+ True+ ]+ +++ generateBuildInfo ExecBuild c+ where+ exeName = text (maybe "" prettyShow . flagToMaybe $ packageName c)++ libraryStanza :: PrettyField FieldAnnotation+ libraryStanza = PrettySection annNoComments (toUTF8BS "library") [] $ catMaybes+ [ fieldPAla "exposed-modules" formatExposedModules (maybeToFlag (exposedModules c))+ ["Modules exported by the library."]+ True+ ]+ +++ generateBuildInfo LibBuild c+++ testSuiteStanza :: PrettyField FieldAnnotation+ testSuiteStanza = PrettySection annNoComments (toUTF8BS "test-suite") [testSuiteName] $ catMaybes+ [ field "default-language" (language c)+ ["Base language which the package is written in."]+ True++ , fieldS "type" (Flag "exitcode-stdio-1.0")+ ["The interface type and version of the test suite."]+ True++ , fieldPAla "hs-source-dirs" formatHsSourceDirs+ (maybeToFlag (testDirs c))+ ["Directories containing source files."]+ True++ , fieldS "main-is" (Flag testFile)+ ["The entrypoint to the test suite."]+ True++ , fieldPAla "build-depends" formatDependencyList (maybeToFlag (dependencies c))+ ["Test dependencies."]+ True+ ]+ where+ testSuiteName =+ text (maybe "" ((++"-test") . prettyShow) . flagToMaybe $ packageName c)++-- | Annotations for cabal file PrettyField.+data FieldAnnotation = FieldAnnotation+ { annCommentedOut :: Bool+ -- ^ True iif the field and its contents should be commented out.+ , annCommentLines :: [String]+ -- ^ Comment lines to place before the field or section.+ }++-- | A field annotation instructing the pretty printer to comment out the field+-- and any contents, with no comments.+commentedOutWithComments :: [String] -> FieldAnnotation+commentedOutWithComments = FieldAnnotation True . map ("-- " ++)++-- | A field annotation with the specified comment lines.+withComments :: [String] -> FieldAnnotation+withComments = FieldAnnotation False++-- | A field annotation with no comments.+annNoComments :: FieldAnnotation+annNoComments = FieldAnnotation False []++postProcessFieldLines :: FieldAnnotation -> [String] -> [String]+postProcessFieldLines ann+ | annCommentedOut ann = map ("-- " ++)+ | otherwise = id
cabal/cabal-install/Distribution/Client/Init/Heuristics.hs view
@@ -24,7 +24,6 @@ import Distribution.Client.Compat.Prelude import Distribution.Utils.Generic (safeHead, safeTail, safeLast) -import Distribution.Parsec (simpleParsec) import Distribution.Simple.Setup (Flag(..), flagToMaybe) import Distribution.ModuleName ( ModuleName, toFilePath )@@ -38,14 +37,11 @@ import Distribution.Solver.Types.PackageIndex ( allPackagesByName ) import Distribution.Solver.Types.SourcePackage- ( packageDescription )+ ( srcpkgDescription ) import Distribution.Client.Types ( SourcePackageDb(..) )-import Control.Monad ( mapM )-import Data.Char ( isNumber, isLower )-import Data.Either ( partitionEithers )+import Data.Char ( isLower ) import Data.List ( isInfixOf )-import Data.Ord ( comparing ) import qualified Data.Set as Set ( fromList, toList ) import System.Directory ( getCurrentDirectory, getDirectoryContents, doesDirectoryExist, doesFileExist, getHomeDirectory, )@@ -55,8 +51,9 @@ import Distribution.Client.Init.Types ( InitFlags(..) ) import Distribution.Client.Compat.Process ( readProcessWithExitCode )-import System.Exit ( ExitCode(..) ) +import qualified Distribution.Utils.ShortText as ShortText+ -- | Return a list of candidate main files for this executable: top-level -- modules including the word 'Main' in the file name. The list is sorted in -- order of preference, shorter file names are preferred. 'Right's are existing@@ -102,8 +99,8 @@ x' -> let (c, r) = first repairComponent $ break (not . isAlphaNum) x' in c ++ repairRest r where- repairComponent c | all isNumber c = invalid c- | otherwise = valid c+ repairComponent c | all isDigit c = invalid c+ | otherwise = valid c repairRest = repair' id ('-' :) -- |Data type of source files found in the working directory@@ -130,12 +127,12 @@ where scan dir hierarchy = do entries <- getDirectoryContents (projectRoot </> dir)- (files, dirs) <- liftM partitionEithers (mapM (tagIsDir dir) entries)+ (files, dirs) <- liftM partitionEithers (traverse (tagIsDir dir) entries) let modules = catMaybes [ guessModuleName hierarchy file | file <- files , maybe False isUpper (safeHead file) ]- modules' <- mapM (findImportsAndExts projectRoot) modules- recMods <- mapM (scanRecursive dir hierarchy) dirs+ modules' <- traverse (findImportsAndExts projectRoot) modules+ recMods <- traverse (scanRecursive dir hierarchy) dirs return $ concat (modules' : recMods) tagIsDir parent entry = do isDir <- doesDirectoryExist (parent </> entry)@@ -347,8 +344,8 @@ knownCategories :: SourcePackageDb -> [String] knownCategories (SourcePackageDb sourcePkgIndex _) = nubSet [ cat | pkg <- maybeToList . safeHead =<< (allPackagesByName sourcePkgIndex)- , let catList = (PD.category . PD.packageDescription . packageDescription) pkg- , cat <- splitString ',' catList+ , let catList = (PD.category . PD.packageDescription . srcpkgDescription) pkg+ , cat <- splitString ',' $ ShortText.fromShortText catList ] -- Parse name and email, from darcs pref files or environment variable
cabal/cabal-install/Distribution/Client/Init/Licenses.hs view
@@ -1,3 +1,13 @@+{-|+Module : Distribution.Client.Init.Licenses++Description : Factory functions for producing known license types.++License : BSD-like+Maintainer : cabal-devel@haskell.org+Stability : provisional+Portability : portable+-} module Distribution.Client.Init.Licenses ( License , bsd2@@ -12,6 +22,8 @@ , mpl20 , isc ) where++import Prelude (String, unlines, (++)) type License = String
+ cabal/cabal-install/Distribution/Client/Init/Prompt.hs view
@@ -0,0 +1,145 @@+-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Client.Init.Prompt+-- Copyright : (c) Brent Yorgey 2009+-- License : BSD-like+--+-- Maintainer : cabal-devel@haskell.org+-- Stability : provisional+-- Portability : portable+--+-- User prompt utility functions for use by the 'cabal init' command.+--+-----------------------------------------------------------------------------++module Distribution.Client.Init.Prompt (++ -- * Commands+ prompt+ , promptYesNo+ , promptStr+ , promptList+ , promptListOptional+ , maybePrompt+ ) where++import Prelude ()+import Distribution.Client.Compat.Prelude hiding (empty)++import Distribution.Client.Init.Types+ ( InitFlags(..) )+import Distribution.Simple.Setup+ ( Flag(..) )+++-- | Run a prompt or not based on the interactive flag of the+-- InitFlags structure.+maybePrompt :: InitFlags -> IO t -> IO (Maybe t)+maybePrompt flags p =+ case interactive flags of+ Flag True -> Just `fmap` p+ _ -> return Nothing++-- | Create a prompt with optional default value that returns a+-- String.+promptStr :: String -> Maybe String -> IO String+promptStr = promptDefault' Just id++-- | Create a yes/no prompt with optional default value.+promptYesNo :: String -- ^ prompt message+ -> Maybe Bool -- ^ optional default value+ -> IO Bool+promptYesNo =+ promptDefault' recogniseYesNo showYesNo+ where+ recogniseYesNo s | s == "y" || s == "Y" = Just True+ | s == "n" || s == "N" = Just False+ | otherwise = Nothing+ showYesNo True = "y"+ showYesNo False = "n"++-- | Create a prompt with optional default value that returns a value+-- of some Text instance.+prompt :: (Parsec t, Pretty t) => String -> Maybe t -> IO t+prompt = promptDefault' simpleParsec prettyShow++-- | Create a prompt with an optional default value.+promptDefault' :: (String -> Maybe t) -- ^ parser+ -> (t -> String) -- ^ pretty-printer+ -> String -- ^ prompt message+ -> Maybe t -- ^ optional default value+ -> IO t+promptDefault' parser ppr pr def = do+ putStr $ mkDefPrompt pr (ppr `fmap` def)+ inp <- getLine+ case (inp, def) of+ ("", Just d) -> return d+ _ -> case parser inp of+ Just t -> return t+ Nothing -> do putStrLn $ "Couldn't parse " ++ inp ++ ", please try again!"+ promptDefault' parser ppr pr def++-- | Create a prompt from a prompt string and a String representation+-- of an optional default value.+mkDefPrompt :: String -> Maybe String -> String+mkDefPrompt pr def = pr ++ "?" ++ defStr def+ where defStr Nothing = " "+ defStr (Just s) = " [default: " ++ s ++ "] "++-- | Create a prompt from a list of items, where no selected items is+-- valid and will be represented as a return value of 'Nothing'.+promptListOptional :: (Pretty t, Eq t)+ => String -- ^ prompt+ -> [t] -- ^ choices+ -> IO (Maybe (Either String t))+promptListOptional pr choices = promptListOptional' pr choices prettyShow++promptListOptional' :: Eq t+ => String -- ^ prompt+ -> [t] -- ^ choices+ -> (t -> String) -- ^ show an item+ -> IO (Maybe (Either String t))+promptListOptional' pr choices displayItem =+ fmap rearrange+ $ promptList pr (Nothing : map Just choices) (Just Nothing)+ (maybe "(none)" displayItem) True+ where+ rearrange = either (Just . Left) (fmap Right)++-- | Create a prompt from a list of items.+promptList :: Eq t+ => String -- ^ prompt+ -> [t] -- ^ choices+ -> Maybe t -- ^ optional default value+ -> (t -> String) -- ^ show an item+ -> Bool -- ^ whether to allow an 'other' option+ -> IO (Either String t)+promptList pr choices def displayItem other = do+ putStrLn $ pr ++ ":"+ let options1 = map (\c -> (Just c == def, displayItem c)) choices+ options2 = zip ([1..]::[Int])+ (options1 ++ [(False, "Other (specify)") | other])+ traverse_ (putStrLn . \(n,(i,s)) -> showOption n i ++ s) options2+ promptList' displayItem (length options2) choices def other+ where showOption n i | n < 10 = " " ++ star i ++ " " ++ rest+ | otherwise = " " ++ star i ++ rest+ where rest = show n ++ ") "+ star True = "*"+ star False = " "++promptList' :: (t -> String) -> Int -> [t] -> Maybe t -> Bool -> IO (Either String t)+promptList' displayItem numChoices choices def other = do+ putStr $ mkDefPrompt "Your choice" (displayItem `fmap` def)+ inp <- getLine+ case (inp, def) of+ ("", Just d) -> return $ Right d+ _ -> case readMaybe inp of+ Nothing -> invalidChoice inp+ Just n -> getChoice n+ where invalidChoice inp = do putStrLn $ inp ++ " is not a valid choice."+ promptList' displayItem numChoices choices def other+ getChoice n | n < 1 || n > numChoices = invalidChoice (show n)+ | n < numChoices ||+ (n == numChoices && not other)+ = return . Right $ choices !! (n-1)+ | otherwise = Left `fmap` promptStr "Please specify" Nothing
cabal/cabal-install/Distribution/Client/Init/Types.hs view
@@ -15,23 +15,23 @@ ----------------------------------------------------------------------------- module Distribution.Client.Init.Types where -import Distribution.Simple.Setup- ( Flag(..) )+import Distribution.Client.Compat.Prelude+import Prelude () +import Distribution.Simple.Setup (Flag(..), toFlag )+ import Distribution.Types.Dependency as P-import Distribution.Compat.Semigroup import Distribution.Version import Distribution.Verbosity import qualified Distribution.Package as P-import Distribution.License+import Distribution.SPDX.License (License) import Distribution.ModuleName+import Distribution.CabalSpecVersion import Language.Haskell.Extension ( Language(..), Extension ) import qualified Text.PrettyPrint as Disp-import qualified Distribution.Deprecated.ReadP as Parse-import Distribution.Deprecated.Text--import GHC.Generics ( Generic )+import qualified Distribution.Compat.CharParsing as P+import qualified Data.Map as Map -- | InitFlags is really just a simple type to represent certain -- portions of a .cabal file. Rather than have a flag for EVERY@@ -48,7 +48,7 @@ , packageName :: Flag P.PackageName , version :: Flag Version- , cabalVersion :: Flag Version+ , cabalVersion :: Flag CabalSpecVersion , license :: Flag License , author :: Flag String , email :: Flag String@@ -103,7 +103,12 @@ instance Semigroup InitFlags where (<>) = gmappend --- | Some common package categories.+defaultInitFlags :: InitFlags+defaultInitFlags = mempty+ { initVerbosity = toFlag normal+ }++-- | Some common package categories (non-exhaustive list). data Category = Codec | Concurrency@@ -124,6 +129,14 @@ | Web deriving (Read, Show, Eq, Ord, Bounded, Enum) -instance Text Category where- disp = Disp.text . show- parse = Parse.choice $ map (fmap read . Parse.string . show) [Codec .. ] -- TODO: eradicateNoParse+instance Pretty Category where+ pretty = Disp.text . show++instance Parsec Category where+ parsec = do+ name <- P.munch1 isAlpha+ case Map.lookup name names of+ Just cat -> pure cat+ _ -> P.unexpected $ "Category: " ++ name+ where+ names = Map.fromList [ (show cat, cat) | cat <- [ minBound .. maxBound ] ]
+ cabal/cabal-install/Distribution/Client/Init/Utils.hs view
@@ -0,0 +1,38 @@+-----------------------------------------------------------------------------+-- |+-- Module : Distribution.Client.Init.Utils+-- Copyright : (c) Brent Yorgey 2009+-- License : BSD-like+--+-- Maintainer : cabal-devel@haskell.org+-- Stability : provisional+-- Portability : portable+--+-- Shared utilities used by multiple cabal init modules.+--+-----------------------------------------------------------------------------++module Distribution.Client.Init.Utils (+ eligibleForTestSuite+ , message+ ) where++import Distribution.Solver.Compat.Prelude+import Prelude ()++import Distribution.Simple.Setup+ ( Flag(..) )+import Distribution.Client.Init.Types+ ( InitFlags(..), PackageType(..) )++-- | Returns true if this package is eligible for test suite initialization.+eligibleForTestSuite :: InitFlags -> Bool+eligibleForTestSuite flags =+ Flag True == initializeTestSuite flags+ && Flag Executable /= packageType flags++-- | Possibly generate a message to stdout, taking into account the+-- --quiet flag.+message :: InitFlags -> String -> IO ()+message (InitFlags{quiet = Flag True}) _ = return ()+message _ s = putStrLn s
cabal/cabal-install/Distribution/Client/Install.hs view
@@ -35,20 +35,8 @@ import qualified Data.List.NonEmpty as NE import qualified Data.Map as Map-import qualified Data.Set as S import Control.Exception as Exception- ( Exception(toException), bracket, catches- , Handler(Handler), handleJust, IOException, SomeException )-#ifndef mingw32_HOST_OS-import Control.Exception as Exception- ( Exception(fromException) )-#endif-import System.Exit- ( ExitCode(..) )-import Distribution.Compat.Exception- ( catchIO, catchExit )-import Control.Monad- ( forM_, mapM )+ ( bracket, catches, Handler(Handler), handleJust ) import System.Directory ( getTemporaryDirectory, doesDirectoryExist, doesFileExist, createDirectoryIfMissing, removeFile, renameDirectory,@@ -84,22 +72,19 @@ , filterTestFlags ) import Distribution.Client.Config ( getCabalDir, defaultUserInstall )-import Distribution.Client.Sandbox.Timestamp- ( withUpdateTimestamps )-import Distribution.Client.Sandbox.Types- ( SandboxPackageInfo(..), UseSandbox(..), isUseSandbox- , whenUsingSandbox ) import Distribution.Client.Tar (extractTarGzFile) import Distribution.Client.Types as Source import Distribution.Client.BuildReports.Types ( ReportLevel(..) ) import Distribution.Client.SetupWrapper ( setupWrapper, SetupScriptOptions(..), defaultSetupScriptOptions )+import Distribution.Client.BuildReports.Anonymous (showBuildReport) import qualified Distribution.Client.BuildReports.Anonymous as BuildReports import qualified Distribution.Client.BuildReports.Storage as BuildReports ( storeAnonymous, storeLocal, fromInstallPlan, fromPlanningFailure ) import qualified Distribution.Client.InstallSymlink as InstallSymlink- ( OverwritePolicy(..), symlinkBinaries )+ ( symlinkBinaries )+import Distribution.Client.Types.OverwritePolicy (OverwritePolicy (..)) import qualified Distribution.Client.Win32SelfUpgrade as Win32SelfUpgrade import qualified Distribution.Client.World as World import qualified Distribution.InstalledPackageInfo as Installed@@ -134,8 +119,7 @@ , registerCommand, RegisterFlags(..), emptyRegisterFlags , testCommand, TestFlags(..) ) import Distribution.Simple.Utils- ( createDirectoryIfMissingVerbose, comparing- , writeFileAtomic, withUTF8FileContents )+ ( createDirectoryIfMissingVerbose, writeFileAtomic ) import Distribution.Simple.InstallDirs as InstallDirs ( PathTemplate, fromPathTemplate, toPathTemplate, substPathTemplate , initialPathTemplateEnv, installDirsTemplateEnv )@@ -146,18 +130,18 @@ , Package(..), HasMungedPackageId(..), HasUnitId(..) , UnitId ) import Distribution.Types.Dependency- ( thisPackageVersion )+ ( Dependency (..), mainLibSet ) import Distribution.Types.GivenComponent ( GivenComponent(..) )-import Distribution.Pretty ( prettyShow ) import Distribution.Types.PackageVersionConstraint- ( PackageVersionConstraint(..) )+ ( PackageVersionConstraint(..), thisPackageVersionConstraint ) import Distribution.Types.MungedPackageId import qualified Distribution.PackageDescription as PackageDescription import Distribution.PackageDescription- ( PackageDescription, GenericPackageDescription(..), Flag(..)- , FlagAssignment, mkFlagAssignment, unFlagAssignment- , showFlagValue, diffFlagAssignment, nullFlagAssignment )+ ( PackageDescription, GenericPackageDescription(..) )+import Distribution.Types.Flag+ ( PackageFlag(..), FlagAssignment, mkFlagAssignment+ , showFlagAssignment, diffFlagAssignment, nullFlagAssignment ) import Distribution.PackageDescription.Configuration ( finalizePD ) import Distribution.Version@@ -167,13 +151,15 @@ , withTempDirectory ) import Distribution.Client.Utils ( determineNumJobs, logDirChange, mergeBy, MergeResult(..)- , tryCanonicalizePath, ProgressPhase(..), progressMessage )+ , ProgressPhase(..), progressMessage ) import Distribution.System ( Platform, OS(Windows), buildOS, buildPlatform ) import Distribution.Verbosity as Verbosity- ( Verbosity, modifyVerbosity, normal, verbose )+ ( modifyVerbosity, normal, verbose ) import Distribution.Simple.BuildPaths ( exeExtension ) +import qualified Data.ByteString as BS+ --TODO: -- * assign flags to packages individually -- * complain about flags that do not apply to any package given as target@@ -199,8 +185,6 @@ -> Compiler -> Platform -> ProgramDb- -> UseSandbox- -> Maybe SandboxPackageInfo -> GlobalFlags -> ConfigFlags -> ConfigExFlags@@ -210,7 +194,7 @@ -> BenchmarkFlags -> [UserTarget] -> IO ()-install verbosity packageDBs repos comp platform progdb useSandbox mSandboxPkgInfo+install verbosity packageDBs repos comp platform progdb globalFlags configFlags configExFlags installFlags haddockFlags testFlags benchmarkFlags userTargets0 = do @@ -220,7 +204,6 @@ ++ " (if you didn't type --root-cmd, comment out root-cmd" ++ " in your ~/.cabal/config file)" let userOrSandbox = fromFlag (configUserInstall configFlags)- || isUseSandbox useSandbox unless userOrSandbox $ warn verbosity $ "the --global flag is deprecated -- " ++ "it is generally considered a bad idea to install packages "@@ -238,18 +221,12 @@ processInstallPlan verbosity args installContext installPlan where args :: InstallArgs- args = (packageDBs, repos, comp, platform, progdb, useSandbox,- mSandboxPkgInfo, globalFlags, configFlags, configExFlags,+ args = (packageDBs, repos, comp, platform, progdb,+ globalFlags, configFlags, configExFlags, installFlags, haddockFlags, testFlags, benchmarkFlags) - die'' message = die' verbosity (message ++ if isUseSandbox useSandbox- then installFailedInSandbox else [])- -- TODO: use a better error message, remove duplication.- installFailedInSandbox =- "\nNote: when using a sandbox, all packages are required to have "- ++ "consistent dependencies. "- ++ "Try reinstalling/unregistering the offending packages or "- ++ "recreating the sandbox."+ die'' = die' verbosity+ logMsg message rest = debugNoWrap verbosity message >> rest -- TODO: Make InstallContext a proper data type with documented fields.@@ -267,8 +244,6 @@ , Compiler , Platform , ProgramDb- , UseSandbox- , Maybe SandboxPackageInfo , GlobalFlags , ConfigFlags , ConfigExFlags@@ -281,14 +256,14 @@ makeInstallContext :: Verbosity -> InstallArgs -> Maybe [UserTarget] -> IO InstallContext makeInstallContext verbosity- (packageDBs, repoCtxt, comp, _, progdb,_,_,+ (packageDBs, repoCtxt, comp, _, progdb, globalFlags, _, configExFlags, installFlags, _, _, _) mUserTargets = do let idxState = flagToMaybe (installIndexState installFlags) - installedPkgIndex <- getInstalledPackages verbosity comp packageDBs progdb- sourcePkgDb <- getSourcePackagesAtIndexState verbosity repoCtxt idxState- pkgConfigDb <- readPkgConfigDb verbosity progdb+ installedPkgIndex <- getInstalledPackages verbosity comp packageDBs progdb+ (sourcePkgDb, _, _) <- getSourcePackagesAtIndexState verbosity repoCtxt idxState Nothing+ pkgConfigDb <- readPkgConfigDb verbosity progdb checkConfigExFlags verbosity installedPkgIndex (packageIndex sourcePkgDb) configExFlags@@ -319,7 +294,7 @@ makeInstallPlan :: Verbosity -> InstallArgs -> InstallContext -> IO (Progress String String SolverInstallPlan) makeInstallPlan verbosity- (_, _, comp, platform, _, _, mSandboxPkgInfo,+ (_, _, comp, platform,_, _, configFlags, configExFlags, installFlags, _, _, _) (installedPkgIndex, sourcePkgDb, pkgConfigDb,@@ -328,7 +303,7 @@ solver <- chooseSolver verbosity (fromFlag (configSolver configExFlags)) (compilerInfo comp) notice verbosity "Resolving dependencies..."- return $ planPackages verbosity comp platform mSandboxPkgInfo solver+ return $ planPackages verbosity comp platform solver configFlags configExFlags installFlags installedPkgIndex sourcePkgDb pkgConfigDb pkgSpecifiers @@ -337,7 +312,7 @@ -> SolverInstallPlan -> IO () processInstallPlan verbosity- args@(_,_, _, _, _, _, _, _, configFlags, _, installFlags, _, _, _)+ args@(_,_, _, _, _, _, configFlags, _, installFlags, _, _, _) (installedPkgIndex, sourcePkgDb, _, userTargets, pkgSpecifiers, _) installPlan0 = do @@ -360,7 +335,6 @@ planPackages :: Verbosity -> Compiler -> Platform- -> Maybe SandboxPackageInfo -> Solver -> ConfigFlags -> ConfigExFlags@@ -370,7 +344,7 @@ -> PkgConfigDb -> [PackageSpecifier UnresolvedSourcePackage] -> Progress String String SolverInstallPlan-planPackages verbosity comp platform mSandboxPkgInfo solver+planPackages verbosity comp platform solver configFlags configExFlags installFlags installedPkgIndex sourcePkgDb pkgConfigDb pkgSpecifiers = @@ -393,6 +367,8 @@ . setCountConflicts countConflicts + . setFineGrainedConflicts fineGrainedConflicts+ . setMinimizeConflictSet minimizeConflictSet . setAvoidReinstalls avoidReinstalls@@ -441,8 +417,6 @@ in LabeledPackageConstraint pc ConstraintSourceConfigFlagOrTarget | pkgSpecifier <- pkgSpecifiers ] - . maybe id applySandboxInstallPolicy mSandboxPkgInfo- . (if reinstall then reinstallTargets else id) -- Don't solve for executables, the legacy install codepath@@ -461,6 +435,7 @@ fromFlag (installReinstall installFlags) reorderGoals = fromFlag (installReorderGoals installFlags) countConflicts = fromFlag (installCountConflicts installFlags)+ fineGrainedConflicts = fromFlag (installFineGrainedConflicts installFlags) minimizeConflictSet = fromFlag (installMinimizeConflictSet installFlags) independentGoals = fromFlag (installIndependentGoals installFlags) avoidReinstalls = fromFlag (installAvoidReinstalls installFlags)@@ -597,8 +572,8 @@ when offline $ do let pkgs = [ confPkgSource cpkg | InstallPlan.Configured cpkg <- InstallPlan.toList installPlan ]- notFetched <- fmap (map packageInfoId)- . filterM (fmap isNothing . checkFetched . packageSource)+ notFetched <- fmap (map packageId)+ . filterM (fmap isNothing . checkFetched . srcpkgSource) $ pkgs unless (null notFetched) $ die' verbosity $ "Can't download packages in offline mode. "@@ -680,24 +655,26 @@ showPkg (pkg, _) = prettyShow (packageId pkg) ++ showLatest (pkg) - showPkgAndReason (ReadyPackage pkg', pr) = prettyShow (packageId pkg') ++- showLatest pkg' ++- showFlagAssignment (nonDefaultFlags pkg') ++- showStanzas (confPkgStanzas pkg') ++- showDep pkg' ++- case pr of- NewPackage -> " (new package)"- NewVersion _ -> " (new version)"- Reinstall _ cs -> " (reinstall)" ++ case cs of+ showPkgAndReason (ReadyPackage pkg', pr) = unwords+ [ prettyShow (packageId pkg')+ , showLatest pkg'+ , showFlagAssignment (nonDefaultFlags pkg')+ , showStanzas (confPkgStanzas pkg')+ , showDep pkg'+ , case pr of+ NewPackage -> "(new package)"+ NewVersion _ -> "(new version)"+ Reinstall _ cs -> "(reinstall)" ++ case cs of [] -> ""- diff -> " (changes: " ++ intercalate ", " (map change diff)+ diff -> "(changes: " ++ intercalate ", " (map change diff) ++ ")"+ ] showLatest :: Package srcpkg => srcpkg -> String showLatest pkg = case mLatestVersion of Just latestVersion -> if packageVersion pkg < latestVersion- then (" (latest: " ++ prettyShow latestVersion ++ ")")+ then ("(latest: " ++ prettyShow latestVersion ++ ")") else "" Nothing -> "" where@@ -708,22 +685,19 @@ (packageIndex sourcePkgDb) (packageName pkg) - toFlagAssignment :: [Flag] -> FlagAssignment+ toFlagAssignment :: [PackageFlag] -> FlagAssignment toFlagAssignment = mkFlagAssignment . map (\ f -> (flagName f, flagDefault f)) nonDefaultFlags :: ConfiguredPackage loc -> FlagAssignment nonDefaultFlags cpkg = let defaultAssignment = toFlagAssignment- (genPackageFlags (SourcePackage.packageDescription $+ (genPackageFlags (SourcePackage.srcpkgDescription $ confPkgSource cpkg)) in confPkgFlags cpkg `diffFlagAssignment` defaultAssignment showStanzas :: [OptionalStanza] -> String- showStanzas = concatMap ((" *" ++) . showStanza)-- showFlagAssignment :: FlagAssignment -> String- showFlagAssignment = concatMap ((' ' :) . showFlagValue) . unFlagAssignment+ showStanzas = unwords . map (("*" ++) . showStanza) change (OnlyInLeft pkgid) = prettyShow pkgid ++ " removed" change (InBoth pkgid pkgid') = prettyShow pkgid ++ " -> "@@ -757,7 +731,7 @@ reportPlanningFailure :: Verbosity -> InstallArgs -> InstallContext -> String -> IO () reportPlanningFailure verbosity- (_, _, comp, platform, _, _, _+ (_, _, comp, platform, _ ,_, configFlags, _, installFlags, _, _, _) (_, sourcePkgDb, _, _, pkgSpecifiers, _) message = do@@ -786,7 +760,7 @@ -- Save solver log case logFile of Nothing -> return ()- Just template -> forM_ pkgids $ \pkgid ->+ Just template -> for_ pkgids $ \pkgid -> let env = initialPathTemplateEnv pkgid dummyIpid (compilerInfo comp) platform path = fromPathTemplate $ substPathTemplate env template@@ -837,18 +811,15 @@ -> BuildOutcomes -> IO () postInstallActions verbosity- (packageDBs, _, comp, platform, progdb, useSandbox, mSandboxPkgInfo+ (packageDBs, _, comp, platform, progdb ,globalFlags, configFlags, _, installFlags, _, _, _) targets installPlan buildOutcomes = do - updateSandboxTimestampsFile verbosity useSandbox mSandboxPkgInfo- comp platform installPlan buildOutcomes- unless oneShot $ World.insert verbosity worldFile --FIXME: does not handle flags- [ World.WorldPkgInfo dep mempty- | UserTargetNamed dep <- targets ]+ [ World.WorldPkgInfo (Dependency pn vr mainLibSet) mempty+ | UserTargetNamed (PackageVersionConstraint pn vr) <- targets ] let buildReports = BuildReports.fromInstallPlan platform (compilerId comp) installPlan buildOutcomes@@ -861,7 +832,7 @@ when (reportingLevel == DetailedReports) $ storeDetailedBuildReports verbosity logsDir buildReports - regenerateHaddockIndex verbosity packageDBs comp platform progdb useSandbox+ regenerateHaddockIndex verbosity packageDBs comp platform progdb configFlags installFlags buildOutcomes symlinkBinaries verbosity platform comp configFlags installFlags@@ -881,13 +852,13 @@ [ do dotCabal <- getCabalDir let logFileName = prettyShow (BuildReports.package report) <.> "log" logFile = logsDir </> logFileName- reportsDir = dotCabal </> "reports" </> remoteRepoName remoteRepo+ reportsDir = dotCabal </> "reports" </> unRepoName (remoteRepoName remoteRepo) reportFile = reportsDir </> logFileName handleMissingLogFile $ do buildLog <- readFile logFile createDirectoryIfMissing True reportsDir -- FIXME- writeFile reportFile (show (BuildReports.show report, buildLog))+ writeFile reportFile (show (showBuildReport report, buildLog)) | (report, Just repo) <- reports , Just remoteRepo <- [maybeRepoRemote repo]@@ -914,12 +885,11 @@ -> Compiler -> Platform -> ProgramDb- -> UseSandbox -> ConfigFlags -> InstallFlags -> BuildOutcomes -> IO ()-regenerateHaddockIndex verbosity packageDBs comp platform progdb useSandbox+regenerateHaddockIndex verbosity packageDBs comp platform progdb configFlags installFlags buildOutcomes | haddockIndexFileIsRequested && shouldRegenerateHaddockIndex = do @@ -947,8 +917,7 @@ -- installed. Since the index can be only per-user or per-sandbox (see -- #1337), we don't do it for global installs or special cases where we're -- installing into a specific db.- shouldRegenerateHaddockIndex = (isUseSandbox useSandbox || normalUserInstall)- && someDocsWereInstalled buildOutcomes+ shouldRegenerateHaddockIndex = normalUserInstall && someDocsWereInstalled buildOutcomes where someDocsWereInstalled = any installedDocs . Map.elems installedDocs (Right (BuildResult DocsOk _ _)) = True@@ -982,7 +951,7 @@ symlinkBinaries verbosity platform comp configFlags installFlags plan buildOutcomes = do failed <- InstallSymlink.symlinkBinaries platform comp- InstallSymlink.NeverOverwrite+ NeverOverwrite configFlags installFlags plan buildOutcomes case failed of@@ -1046,33 +1015,6 @@ onExitFailure _ = "" #endif ---- | If we're working inside a sandbox and some add-source deps were installed,--- update the timestamps of those deps.-updateSandboxTimestampsFile :: Verbosity -> UseSandbox -> Maybe SandboxPackageInfo- -> Compiler -> Platform- -> InstallPlan- -> BuildOutcomes- -> IO ()-updateSandboxTimestampsFile verbosity (UseSandbox sandboxDir)- (Just (SandboxPackageInfo _ _ _ allAddSourceDeps))- comp platform installPlan buildOutcomes =- withUpdateTimestamps verbosity sandboxDir (compilerId comp) platform $ \_ -> do- let allInstalled = [ pkg- | InstallPlan.Configured pkg- <- InstallPlan.toList installPlan- , case InstallPlan.lookupBuildOutcome pkg buildOutcomes of- Just (Right _success) -> True- _ -> False- ]- allSrcPkgs = [ confPkgSource cpkg | cpkg <- allInstalled ]- allPaths = [ pth | LocalUnpackedPackage pth- <- map packageSource allSrcPkgs]- allPathsCanonical <- mapM tryCanonicalizePath allPaths- return $! filter (`S.member` allAddSourceDeps) allPathsCanonical--updateSandboxTimestampsFile _ _ _ _ _ _ _ = return ()- -- ------------------------------------------------------------ -- * Actually do the installations -- ------------------------------------------------------------@@ -1091,16 +1033,11 @@ -> InstallPlan -> IO BuildOutcomes performInstallations verbosity- (packageDBs, repoCtxt, comp, platform, progdb, useSandbox, _,+ (packageDBs, repoCtxt, comp, platform, progdb, globalFlags, configFlags, configExFlags, installFlags, haddockFlags, testFlags, _) installedPkgIndex installPlan = do - -- With 'install -j' it can be a bit hard to tell whether a sandbox is used.- whenUsingSandbox useSandbox $ \sandboxDir ->- when parallelInstall $- notice verbosity $ "Notice: installing into a sandbox located at "- ++ sandboxDir info verbosity $ "Number of threads used: " ++ (show numJobs) ++ "." jobControl <- if parallelInstall then newParallelJobControl numJobs@@ -1261,7 +1198,7 @@ -- We generate the legacy constraints as well as the new style precise deps. -- In the end only one set gets passed to Setup.hs configure, depending on -- the Cabal version we are talking to.- configConstraints = [ thisPackageVersion srcid+ configConstraints = [ thisPackageVersionConstraint srcid | ConfiguredId srcid (Just@@ -1467,7 +1404,7 @@ let packageDBs = interpretPackageDbFlags (fromFlag (configUserInstall configFlags)) (configPackageDBs configFlags)- forM_ ipkgs' $ \ipkg' ->+ for_ ipkgs' $ \ipkg' -> registerPackage verbosity comp progdb packageDBs ipkg' defaultRegisterOptions@@ -1544,21 +1481,21 @@ if is_dir -- Sort so that each prefix of the package -- configurations is well formed- then mapM (readPkgConf pkgConfDest) . sort . filter notHidden+ then traverse (readPkgConf pkgConfDest) . sort . filter notHidden =<< getDirectoryContents pkgConfDest else fmap (:[]) $ readPkgConf "." pkgConfDest else return [] readPkgConf :: FilePath -> FilePath -> IO Installed.InstalledPackageInfo- readPkgConf pkgConfDir pkgConfFile =- (withUTF8FileContents (pkgConfDir </> pkgConfFile) $ \pkgConfText ->- case Installed.parseInstalledPackageInfo pkgConfText of- Left perrors -> pkgConfParseFailed $ unlines $ NE.toList perrors- Right (warns, pkgConf) -> do- unless (null warns) $- warn verbosity $ unlines warns- return pkgConf)+ readPkgConf pkgConfDir pkgConfFile = do+ pkgConfText <- BS.readFile (pkgConfDir </> pkgConfFile)+ case Installed.parseInstalledPackageInfo pkgConfText of+ Left perrors -> pkgConfParseFailed $ unlines $ NE.toList perrors+ Right (warns, pkgConf) -> do+ unless (null warns) $+ warn verbosity $ unlines warns+ return pkgConf pkgConfParseFailed :: String -> IO a pkgConfParseFailed perror =
cabal/cabal-install/Distribution/Client/InstallPlan.hs view
@@ -67,6 +67,10 @@ reverseDependencyClosure, ) where +import Distribution.Client.Compat.Prelude hiding (toList, lookup, tail)+import Prelude (tail)+import Distribution.Compat.Stack (WithCallStack)+ import Distribution.Client.Types hiding (BuildOutcomes) import qualified Distribution.PackageDescription as PD import qualified Distribution.Simple.Configure as Configure@@ -79,7 +83,7 @@ , HasUnitId(..), UnitId ) import Distribution.Solver.Types.SolverPackage import Distribution.Client.JobControl-import Distribution.Deprecated.Text+import Distribution.Pretty (defaultStyle) import Text.PrettyPrint import qualified Distribution.Client.SolverInstallPlan as SolverInstallPlan import Distribution.Client.SolverInstallPlan (SolverInstallPlan)@@ -90,31 +94,19 @@ import Distribution.Solver.Types.InstSolverPackage import Distribution.Utils.LogProgress+import Distribution.Utils.Structured (Structured (..), Structure(Nominal)) -- TODO: Need this when we compute final UnitIds -- import qualified Distribution.Simple.Configure as Configure -import Data.List- ( foldl', intercalate ) import qualified Data.Foldable as Foldable (all, toList)-import Data.Maybe- ( fromMaybe, mapMaybe ) import qualified Distribution.Compat.Graph as Graph import Distribution.Compat.Graph (Graph, IsNode(..))-import Distribution.Compat.Binary (Binary(..))-import GHC.Generics-import Data.Typeable-import Control.Monad import Control.Exception ( assert ) import qualified Data.Map as Map-import Data.Map (Map) import qualified Data.Set as Set-import Data.Set (Set) -import Prelude hiding (lookup)-- -- When cabal tries to install a number of packages, including all their -- dependencies it has a non-trivial problem to solve. --@@ -174,6 +166,11 @@ | Installed srcpkg deriving (Eq, Show, Generic) +displayGenericPlanPackage :: (IsUnit ipkg, IsUnit srcpkg) => GenericPlanPackage ipkg srcpkg -> String+displayGenericPlanPackage (PreExisting pkg) = "PreExisting " ++ prettyShow (nodeKey pkg)+displayGenericPlanPackage (Configured pkg) = "Configured " ++ prettyShow (nodeKey pkg)+displayGenericPlanPackage (Installed pkg) = "Installed " ++ prettyShow (nodeKey pkg)+ -- | Convenience combinator for destructing 'GenericPlanPackage'. -- This is handy because if you case manually, you have to handle -- 'Configured' and 'Installed' separately (where often you want@@ -203,8 +200,8 @@ nodeNeighbors (Configured spkg) = nodeNeighbors spkg nodeNeighbors (Installed spkg) = nodeNeighbors spkg -instance (Binary ipkg, Binary srcpkg)- => Binary (GenericPlanPackage ipkg srcpkg)+instance (Binary ipkg, Binary srcpkg) => Binary (GenericPlanPackage ipkg srcpkg)+instance (Structured ipkg, Structured srcpkg) => Structured (GenericPlanPackage ipkg srcpkg) type PlanPackage = GenericPlanPackage InstalledPackageInfo (ConfiguredPackage UnresolvedPkgLoc)@@ -258,20 +255,27 @@ planIndepGoals = indepGoals } -internalError :: String -> String -> a+internalError :: WithCallStack (String -> String -> a) internalError loc msg = error $ "internal error in InstallPlan." ++ loc ++ if null msg then "" else ": " ++ msg +instance (Structured ipkg, Structured srcpkg) => Structured (GenericInstallPlan ipkg srcpkg) where+ structure p = Nominal (typeRep p) 0 "GenericInstallPlan"+ [ structure (Proxy :: Proxy ipkg)+ , structure (Proxy :: Proxy srcpkg)+ ]+ instance (IsNode ipkg, Key ipkg ~ UnitId, IsNode srcpkg, Key srcpkg ~ UnitId, Binary ipkg, Binary srcpkg) => Binary (GenericInstallPlan ipkg srcpkg) where put GenericInstallPlan { planGraph = graph, planIndepGoals = indepGoals- } = put (graph, indepGoals)+ } = put graph >> put indepGoals get = do- (graph, indepGoals) <- get+ graph <- get+ indepGoals <- get return $! mkInstallPlan "(instance Binary)" graph indepGoals showPlanGraph :: (Package ipkg, Package srcpkg,@@ -281,9 +285,9 @@ vcat (map dispPlanPackage (Foldable.toList graph)) where dispPlanPackage p = hang (hsep [ text (showPlanPackageTag p)- , disp (packageId p)- , parens (disp (nodeKey p))]) 2- (vcat (map disp (nodeNeighbors p)))+ , pretty (packageId p)+ , parens (pretty (nodeKey p))]) 2+ (vcat (map pretty (nodeNeighbors p))) showInstallPlan :: (Package ipkg, Package srcpkg, IsUnit ipkg, IsUnit srcpkg)@@ -462,10 +466,10 @@ mapDep _ ipiMap (PreExistingId _pid uid) | Just pkgs <- Map.lookup uid ipiMap = pkgs- | otherwise = error ("fromSolverInstallPlan: PreExistingId " ++ display uid)+ | otherwise = error ("fromSolverInstallPlan: PreExistingId " ++ prettyShow uid) mapDep pidMap _ (PlannedId pid) | Just pkgs <- Map.lookup pid pidMap = pkgs- | otherwise = error ("fromSolverInstallPlan: PlannedId " ++ display pid)+ | otherwise = error ("fromSolverInstallPlan: PlannedId " ++ prettyShow pid) -- This shouldn't happen, since mapDep should only be called -- on neighbor SolverId, which must have all been done already -- by the reverse top-sort (we assume the graph is not broken).@@ -495,10 +499,10 @@ mapDep _ ipiMap (PreExistingId _pid uid) | Just pkgs <- Map.lookup uid ipiMap = pkgs- | otherwise = error ("fromSolverInstallPlan: PreExistingId " ++ display uid)+ | otherwise = error ("fromSolverInstallPlan: PreExistingId " ++ prettyShow uid) mapDep pidMap _ (PlannedId pid) | Just pkgs <- Map.lookup pid pidMap = pkgs- | otherwise = error ("fromSolverInstallPlan: PlannedId " ++ display pid)+ | otherwise = error ("fromSolverInstallPlan: PlannedId " ++ prettyShow pid) -- This shouldn't happen, since mapDep should only be called -- on neighbor SolverId, which must have all been done already -- by the reverse top-sort (we assume the graph is not broken).@@ -621,7 +625,7 @@ -- and return any packages that are newly in the processing state (ie ready to -- process), along with the updated 'Processing' state. ---completed :: (IsUnit ipkg, IsUnit srcpkg)+completed :: forall ipkg srcpkg. (IsUnit ipkg, IsUnit srcpkg) => GenericInstallPlan ipkg srcpkg -> Processing -> UnitId -> ([GenericReadyPackage srcpkg], Processing)@@ -646,8 +650,9 @@ (map nodeKey newlyReady) processing' = Processing processingSet' completedSet' failedSet - asReadyPackage (Configured pkg) = ReadyPackage pkg- asReadyPackage _ = internalError "completed" ""+ asReadyPackage :: GenericPlanPackage ipkg srcpkg -> GenericReadyPackage srcpkg+ asReadyPackage (Configured pkg) = ReadyPackage pkg+ asReadyPackage pkg = internalError "completed" $ "not in configured state: " ++ displayGenericPlanPackage pkg failed :: (IsUnit ipkg, IsUnit srcpkg) => GenericInstallPlan ipkg srcpkg@@ -673,7 +678,7 @@ processing' = Processing processingSet' completedSet failedSet' asConfiguredPackage (Configured pkg) = pkg- asConfiguredPackage _ = internalError "failed" "not in configured state"+ asConfiguredPackage pkg = internalError "failed" $ "not in configured state: " ++ displayGenericPlanPackage pkg processingInvariant :: (IsUnit ipkg, IsUnit srcpkg) => GenericInstallPlan ipkg srcpkg@@ -891,17 +896,17 @@ showPlanProblem :: (IsUnit ipkg, IsUnit srcpkg) => PlanProblem ipkg srcpkg -> String showPlanProblem (PackageMissingDeps pkg missingDeps) =- "Package " ++ display (nodeKey pkg)+ "Package " ++ prettyShow (nodeKey pkg) ++ " depends on the following packages which are missing from the plan: "- ++ intercalate ", " (map display missingDeps)+ ++ intercalate ", " (map prettyShow missingDeps) showPlanProblem (PackageCycle cycleGroup) = "The following packages are involved in a dependency cycle "- ++ intercalate ", " (map (display . nodeKey) cycleGroup)+ ++ intercalate ", " (map (prettyShow . nodeKey) cycleGroup) showPlanProblem (PackageStateInvalid pkg pkg') =- "Package " ++ display (nodeKey pkg)+ "Package " ++ prettyShow (nodeKey pkg) ++ " is in the " ++ showPlanPackageTag pkg- ++ " state but it depends on package " ++ display (nodeKey pkg')+ ++ " state but it depends on package " ++ prettyShow (nodeKey pkg') ++ " which is in the " ++ showPlanPackageTag pkg' ++ " state"
cabal/cabal-install/Distribution/Client/InstallSymlink.hs view
@@ -13,49 +13,13 @@ -- Managing installing binaries with symlinks. ----------------------------------------------------------------------------- module Distribution.Client.InstallSymlink (- OverwritePolicy(..), symlinkBinaries, symlinkBinary,+ trySymlink, ) where -#ifdef mingw32_HOST_OS--import Distribution.Compat.Binary- ( Binary )--import Distribution.Package (PackageIdentifier)-import Distribution.Types.UnqualComponentName-import Distribution.Client.InstallPlan (InstallPlan)-import Distribution.Client.Types (BuildOutcomes)-import Distribution.Client.Setup (InstallFlags)-import Distribution.Simple.Setup (ConfigFlags)-import Distribution.Simple.Compiler-import Distribution.System-import GHC.Generics (Generic)--data OverwritePolicy = NeverOverwrite | AlwaysOverwrite- deriving (Show, Eq, Generic, Bounded, Enum)--instance Binary OverwritePolicy--symlinkBinaries :: Platform -> Compiler- -> OverwritePolicy- -> ConfigFlags- -> InstallFlags- -> InstallPlan- -> BuildOutcomes- -> IO [(PackageIdentifier, UnqualComponentName, FilePath)]-symlinkBinaries _ _ _ _ _ _ _ = return []--symlinkBinary :: OverwritePolicy- -> FilePath -> FilePath -> FilePath -> String- -> IO Bool-symlinkBinary _ _ _ _ _ = fail "Symlinking feature not available on Windows"--#else--import Distribution.Compat.Binary- ( Binary )+import Distribution.Client.Compat.Prelude hiding (ioError)+import Prelude () import Distribution.Client.Types ( ConfiguredPackage(..), BuildOutcomes )@@ -84,32 +48,23 @@ ( Compiler, compilerInfo, CompilerInfo(..) ) import Distribution.System ( Platform )-import Distribution.Deprecated.Text- ( display )+import Distribution.Simple.Utils ( info, withTempDirectory ) -import System.Posix.Files- ( getSymbolicLinkStatus, isSymbolicLink, createSymbolicLink- , removeLink ) import System.Directory- ( canonicalizePath )+ ( canonicalizePath, getTemporaryDirectory, removeFile ) import System.FilePath ( (</>), splitPath, joinPath, isAbsolute ) -import Prelude hiding (ioError) import System.IO.Error ( isDoesNotExistError, ioError )-import Distribution.Compat.Exception ( catchIO ) import Control.Exception ( assert )-import Data.Maybe- ( catMaybes )-import GHC.Generics- ( Generic ) -data OverwritePolicy = NeverOverwrite | AlwaysOverwrite- deriving (Show, Eq, Generic, Bounded, Enum)+import Distribution.Client.Compat.Directory ( createFileLink, getSymbolicLinkTarget, pathIsSymbolicLink )+import Distribution.Client.Types.OverwritePolicy -instance Binary OverwritePolicy+import qualified Data.ByteString as BS+import qualified Data.ByteString.Char8 as BS8 -- | We would like by default to install binaries into some location that is on -- the user's PATH. For per-user installations on Unix systems that basically@@ -149,12 +104,12 @@ publicBinDir <- canonicalizePath symlinkBinDir -- TODO: do we want to do this here? : -- createDirectoryIfMissing True publicBinDir- fmap catMaybes $ sequence+ fmap catMaybes $ sequenceA [ do privateBinDir <- pkgBinDir pkg ipid ok <- symlinkBinary overwritePolicy publicBinDir privateBinDir- (display publicExeName) privateExeName+ (prettyShow publicExeName) privateExeName if ok then return Nothing else return (Just (pkgid, publicExeName,@@ -179,11 +134,11 @@ , exe <- PackageDescription.executables pkg , PackageDescription.buildable (PackageDescription.buildInfo exe) ] - pkgDescription (ConfiguredPackage _ (SourcePackage _ pkg _ _)+ pkgDescription (ConfiguredPackage _ (SourcePackage _ gpd _ _) flags stanzas _) = case finalizePD flags (enableStanzas stanzas) (const True)- platform cinfo [] pkg of+ platform cinfo [] gpd of Left _ -> error "finalizePD ReadyPackage failed" Right (desc, _) -> desc @@ -214,6 +169,10 @@ cinfo = compilerInfo comp (CompilerId compilerFlavor _) = compilerInfoId cinfo +-- | Symlink binary.+--+-- The paths are take in pieces, so we can make relative link when possible.+-- symlinkBinary :: OverwritePolicy -- ^ Whether to force overwrite an existing file -> FilePath -- ^ The canonical path of the public bin dir eg@@ -240,9 +199,8 @@ AlwaysOverwrite -> rmLink >> mkLink >> return True where relativeBindir = makeRelative publicBindir privateBindir- mkLink = createSymbolicLink (relativeBindir </> privateName)- (publicBindir </> publicName)- rmLink = removeLink (publicBindir </> publicName)+ mkLink = createFileLink (relativeBindir </> privateName) (publicBindir </> publicName)+ rmLink = removeFile (publicBindir </> publicName) -- | Check a file path of a symlink that we would like to create to see if it -- is OK. For it to be OK to overwrite it must either not already exist yet or@@ -254,11 +212,11 @@ -- Use 'canonicalizePath' to make this. -> IO SymlinkStatus targetOkToOverwrite symlink target = handleNotExist $ do- status <- getSymbolicLinkStatus symlink- if not (isSymbolicLink status)+ isLink <- pathIsSymbolicLink symlink+ if not isLink then return NotOurFile- else do target' <- canonicalizePath symlink- -- This relies on canonicalizePath handling symlinks+ else do target' <- canonicalizePath =<< getSymbolicLinkTarget symlink+ -- This partially relies on canonicalizePath handling symlinks if target == target' then return OkToOverwrite else return NotOurFile@@ -290,4 +248,27 @@ in joinPath $ [ ".." | _ <- drop commonLen as ] ++ drop commonLen bs -#endif+-- | Try to make a symlink in a temporary directory.+--+-- If this works, we can try to symlink: even on Windows.+--+trySymlink :: Verbosity -> IO Bool+trySymlink verbosity = do+ tmp <- getTemporaryDirectory+ withTempDirectory verbosity tmp "cabal-symlink-test" $ \tmpDirPath -> do+ let from = tmpDirPath </> "file.txt"+ let to = tmpDirPath </> "file2.txt"++ -- create a file+ BS.writeFile from (BS8.pack "TEST")++ -- create a symbolic link+ let create :: IO Bool+ create = do+ createFileLink from to+ info verbosity $ "Symlinking seems to work"+ return True++ create `catchIO` \exc -> do+ info verbosity $ "Symlinking doesn't seem to be working: " ++ show exc+ return False
cabal/cabal-install/Distribution/Client/JobControl.hs view
@@ -28,13 +28,16 @@ criticalSection ) where -import Control.Monad+import Distribution.Client.Compat.Prelude+import Prelude ()++import Control.Monad (forever, replicateM_) import Control.Concurrent (forkIO) import Control.Concurrent.MVar import Control.Concurrent.STM (STM, atomically) import Control.Concurrent.STM.TVar import Control.Concurrent.STM.TChan-import Control.Exception (SomeException, bracket_, throwIO, try)+import Control.Exception (bracket_, try) import Distribution.Client.Compat.Semaphore
cabal/cabal-install/Distribution/Client/List.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE ScopedTypeVariables #-} ----------------------------------------------------------------------------- -- | -- Module : Distribution.Client.List@@ -13,6 +14,9 @@ list, info ) where +import Prelude ()+import Distribution.Client.Compat.Prelude+ import Distribution.Package ( PackageName, Package(..), packageName , packageVersion, UnitId )@@ -22,26 +26,23 @@ import Distribution.License (License) import qualified Distribution.InstalledPackageInfo as Installed import qualified Distribution.PackageDescription as Source+import qualified Distribution.Types.ModuleReexport as Source import Distribution.PackageDescription- ( Flag(..), unFlagName )+ ( PackageFlag(..), unFlagName ) import Distribution.PackageDescription.Configuration ( flattenPackageDescription )-import Distribution.Pretty (pretty) import Distribution.Simple.Compiler ( Compiler, PackageDBStack ) import Distribution.Simple.Program (ProgramDb) import Distribution.Simple.Utils- ( equating, comparing, die', notice )-import Distribution.Simple.Setup (fromFlag)+ ( equating, die', notice )+import Distribution.Simple.Setup (fromFlag, fromFlagOrDefault) import Distribution.Simple.PackageIndex (InstalledPackageIndex) import qualified Distribution.Simple.PackageIndex as InstalledPackageIndex import Distribution.Version ( Version, mkVersion, versionNumbers, VersionRange, withinRange, anyVersion , intersectVersionRanges, simplifyVersionRange )-import Distribution.Verbosity (Verbosity)-import Distribution.Deprecated.Text- ( Text(disp), display ) import qualified Distribution.SPDX as SPDX @@ -63,61 +64,71 @@ import Distribution.Client.FetchUtils ( isFetched ) +import Data.Bits ((.|.)) import Data.List- ( sortBy, groupBy, sort, nub, intersperse, maximumBy, partition )+ ( maximumBy )+import Data.List.NonEmpty (groupBy, nonEmpty)+import qualified Data.List as L import Data.Maybe- ( listToMaybe, fromJust, fromMaybe, isJust, maybeToList )+ ( fromJust ) import qualified Data.Map as Map import Data.Tree as Tree-import Control.Monad- ( MonadPlus(mplus), join ) import Control.Exception ( assert )-import Text.PrettyPrint as Disp+import qualified Text.PrettyPrint as Disp+import Text.PrettyPrint+ ( lineLength, ribbonsPerLine, Doc, renderStyle, char+ , nest, ($+$), text, vcat, style, parens, fsep) import System.Directory ( doesDirectoryExist ) +import Distribution.Utils.ShortText (ShortText)+import qualified Distribution.Utils.ShortText as ShortText+import qualified Text.Regex.Base as Regex+import qualified Text.Regex.Posix.String as Regex + -- | Return a list of packages matching given search strings. getPkgList :: Verbosity -> PackageDBStack -> RepoContext- -> Compiler- -> ProgramDb+ -> Maybe (Compiler, ProgramDb) -> ListFlags -> [String] -> IO [PackageDisplayInfo]-getPkgList verbosity packageDBs repoCtxt comp progdb listFlags pats = do- installedPkgIndex <- getInstalledPackages verbosity comp packageDBs progdb+getPkgList verbosity packageDBs repoCtxt mcompprogdb listFlags pats = do+ installedPkgIndex <- for mcompprogdb $ \(comp, progdb) ->+ getInstalledPackages verbosity comp packageDBs progdb sourcePkgDb <- getSourcePackages verbosity repoCtxt++ regexps <- for pats $ \pat -> do+ e <- Regex.compile compOption Regex.execBlank pat+ case e of+ Right r -> return r+ Left err -> die' verbosity $ "Failed to compile regex " ++ pat ++ ": " ++ snd err+ let sourcePkgIndex = packageIndex sourcePkgDb prefs name = fromMaybe anyVersion (Map.lookup name (packagePreferences sourcePkgDb)) + pkgsInfoMatching ::+ [(PackageName, [Installed.InstalledPackageInfo], [UnresolvedSourcePackage])]+ pkgsInfoMatching =+ let matchingInstalled = maybe [] (matchingPackages InstalledPackageIndex.searchWithPredicate regexps) installedPkgIndex+ matchingSource = matchingPackages (\ idx n -> concatMap snd (PackageIndex.searchWithPredicate idx n)) regexps sourcePkgIndex+ in mergePackages matchingInstalled matchingSource+ pkgsInfo :: [(PackageName, [Installed.InstalledPackageInfo], [UnresolvedSourcePackage])] pkgsInfo -- gather info for all packages- | null pats = mergePackages- (InstalledPackageIndex.allPackages installedPkgIndex)- ( PackageIndex.allPackages sourcePkgIndex)+ | null regexps = mergePackages+ (maybe [] InstalledPackageIndex.allPackages installedPkgIndex)+ ( PackageIndex.allPackages sourcePkgIndex) -- gather info for packages matching search term | otherwise = pkgsInfoMatching - pkgsInfoMatching ::- [(PackageName, [Installed.InstalledPackageInfo], [UnresolvedSourcePackage])]- pkgsInfoMatching =- let matchingInstalled = matchingPackages- InstalledPackageIndex.searchByNameSubstring- installedPkgIndex- matchingSource = matchingPackages- (\ idx n ->- concatMap snd- (PackageIndex.searchByNameSubstring idx n))- sourcePkgIndex- in mergePackages matchingInstalled matchingSource- matches :: [PackageDisplayInfo] matches = [ mergePackageInfo pref installedPkgs sourcePkgs selectedPkg False@@ -127,28 +138,32 @@ selectedPkg = latestWithPref pref sourcePkgs ] return matches where- onlyInstalled = fromFlag (listInstalled listFlags)- matchingPackages search index =+ onlyInstalled = fromFlagOrDefault False (listInstalled listFlags)+ caseInsensitive = fromFlagOrDefault True (listCaseInsensitive listFlags)++ compOption | caseInsensitive = Regex.compExtended .|. Regex.compIgnoreCase+ | otherwise = Regex.compExtended++ matchingPackages search regexps index = [ pkg- | pat <- pats- , pkg <- search index pat ]+ | re <- regexps+ , pkg <- search index (Regex.matchTest re) ] -- | Show information about packages. list :: Verbosity -> PackageDBStack -> RepoContext- -> Compiler- -> ProgramDb+ -> Maybe (Compiler, ProgramDb) -> ListFlags -> [String] -> IO ()-list verbosity packageDBs repos comp progdb listFlags pats = do- matches <- getPkgList verbosity packageDBs repos comp progdb listFlags pats+list verbosity packageDBs repos mcompProgdb listFlags pats = do+ matches <- getPkgList verbosity packageDBs repos mcompProgdb listFlags pats if simpleOutput then putStr $ unlines- [ display (pkgName pkg) ++ " " ++ display version+ [ prettyShow (pkgName pkg) ++ " " ++ prettyShow version | pkg <- matches , version <- if onlyInstalled then installedVersions pkg@@ -198,7 +213,7 @@ (fromFlag $ globalWorldFile globalFlags) sourcePkgs' userTargets - pkgsinfo <- sequence+ pkgsinfo <- sequenceA [ do pkginfo <- either (die' verbosity) return $ gatherPkgInfo prefs installedPkgIndex sourcePkgIndex@@ -217,9 +232,9 @@ gatherPkgInfo prefs installedPkgIndex sourcePkgIndex (NamedPackage name props) | null (selectedInstalledPkgs) && null (selectedSourcePkgs)- = Left $ "There is no available version of " ++ display name+ = Left $ "There is no available version of " ++ prettyShow name ++ " that satisfies "- ++ display (simplifyVersionRange verConstraint)+ ++ prettyShow (simplifyVersionRange verConstraint) | otherwise = Right $ mergePackageInfo pref installedPkgs@@ -277,17 +292,17 @@ installedVersions :: [Version], sourceVersions :: [Version], preferredVersions :: VersionRange,- homepage :: String,- bugReports :: String,- sourceRepo :: String,- synopsis :: String,- description :: String,- category :: String,+ homepage :: ShortText,+ bugReports :: ShortText,+ sourceRepo :: String, -- TODO+ synopsis :: ShortText,+ description :: ShortText,+ category :: ShortText, license :: Either SPDX.License License,- author :: String,- maintainer :: String,+ author :: ShortText,+ maintainer :: ShortText, dependencies :: [ExtDependency],- flags :: [Flag],+ flags :: [PackageFlag], hasLib :: Bool, hasExe :: Bool, executables :: [UnqualComponentName],@@ -304,38 +319,39 @@ showPackageSummaryInfo :: PackageDisplayInfo -> String showPackageSummaryInfo pkginfo = renderStyle (style {lineLength = 80, ribbonsPerLine = 1}) $- char '*' <+> disp (pkgName pkginfo)+ char '*' <+> pretty (pkgName pkginfo) $+$ (nest 4 $ vcat [- maybeShow (synopsis pkginfo) "Synopsis:" reflowParagraphs+ maybeShowST (synopsis pkginfo) "Synopsis:" reflowParagraphs , text "Default available version:" <+> case selectedSourcePkg pkginfo of Nothing -> text "[ Not available from any configured repository ]"- Just pkg -> disp (packageVersion pkg)+ Just pkg -> pretty (packageVersion pkg) , text "Installed versions:" <+> case installedVersions pkginfo of [] | hasLib pkginfo -> text "[ Not installed ]" | otherwise -> text "[ Unknown ]" versions -> dispTopVersions 4 (preferredVersions pkginfo) versions- , maybeShow (homepage pkginfo) "Homepage:" text+ , maybeShowST (homepage pkginfo) "Homepage:" text , text "License: " <+> either pretty pretty (license pkginfo) ]) $+$ text "" where- maybeShow [] _ _ = empty- maybeShow l s f = text s <+> (f l)+ maybeShowST l s f+ | ShortText.null l = Disp.empty+ | otherwise = text s <+> f (ShortText.fromShortText l) showPackageDetailedInfo :: PackageDisplayInfo -> String showPackageDetailedInfo pkginfo = renderStyle (style {lineLength = 80, ribbonsPerLine = 1}) $- char '*' <+> disp (pkgName pkginfo)- Disp.<> maybe empty (\v -> char '-' Disp.<> disp v) (selectedVersion pkginfo)- <+> text (replicate (16 - length (display (pkgName pkginfo))) ' ')- Disp.<> parens pkgkind+ char '*' <+> pretty (pkgName pkginfo)+ <<>> maybe Disp.empty (\v -> char '-' Disp.<> pretty v) (selectedVersion pkginfo)+ <+> text (replicate (16 - length (prettyShow (pkgName pkginfo))) ' ')+ <<>> parens pkgkind $+$ (nest 4 $ vcat [- entry "Synopsis" synopsis hideIfNull reflowParagraphs+ entryST "Synopsis" synopsis hideIfNull reflowParagraphs , entry "Versions available" sourceVersions (altText null "[ Not available from server ]") (dispTopVersions 9 (preferredVersions pkginfo))@@ -343,32 +359,34 @@ (altText null (if hasLib pkginfo then "[ Not installed ]" else "[ Unknown ]")) (dispTopVersions 4 (preferredVersions pkginfo))- , entry "Homepage" homepage orNotSpecified text- , entry "Bug reports" bugReports orNotSpecified text- , entry "Description" description hideIfNull reflowParagraphs- , entry "Category" category hideIfNull text+ , entryST "Homepage" homepage orNotSpecified text+ , entryST "Bug reports" bugReports orNotSpecified text+ , entryST "Description" description hideIfNull reflowParagraphs+ , entryST "Category" category hideIfNull text , entry "License" license alwaysShow (either pretty pretty)- , entry "Author" author hideIfNull reflowLines- , entry "Maintainer" maintainer hideIfNull reflowLines+ , entryST "Author" author hideIfNull reflowLines+ , entryST "Maintainer" maintainer hideIfNull reflowLines , entry "Source repo" sourceRepo orNotSpecified text- , entry "Executables" executables hideIfNull (commaSep disp)+ , entry "Executables" executables hideIfNull (commaSep pretty) , entry "Flags" flags hideIfNull (commaSep dispFlag) , entry "Dependencies" dependencies hideIfNull (commaSep dispExtDep) , entry "Documentation" haddockHtml showIfInstalled text , entry "Cached" haveTarball alwaysShow dispYesNo- , if not (hasLib pkginfo) then empty else- text "Modules:" $+$ nest 4 (vcat (map disp . sort . modules $ pkginfo))+ , if not (hasLib pkginfo) then mempty else+ text "Modules:" $+$ nest 4 (vcat (map pretty . sort . modules $ pkginfo)) ]) $+$ text "" where entry fname field cond format = case cond (field pkginfo) of Nothing -> label <+> format (field pkginfo)- Just Nothing -> empty+ Just Nothing -> mempty Just (Just other) -> label <+> text other where label = text fname Disp.<> char ':' Disp.<> padding padding = text (replicate (13 - length fname ) ' ') + entryST fname field = entry fname (ShortText.fromShortText . field)+ normal = Nothing hide = Just Nothing replace msg = Just (Just msg)@@ -387,8 +405,8 @@ dispYesNo True = text "Yes" dispYesNo False = text "No" - dispExtDep (SourceDependency dep) = disp dep- dispExtDep (InstalledDependency dep) = disp dep+ dispExtDep (SourceDependency dep) = pretty dep+ dispExtDep (InstalledDependency dep) = pretty dep isInstalled = not (null (installedVersions pkginfo)) hasExes = length (executables pkginfo) >= 2@@ -398,7 +416,7 @@ | hasLib pkginfo = text "library" | hasExes = text "programs" | hasExe pkginfo = text "program"- | otherwise = empty+ | otherwise = mempty reflowParagraphs :: String -> Doc@@ -407,7 +425,7 @@ . intersperse (text "") -- re-insert blank lines . map (fsep . map text . concatMap words) -- reflow paragraphs . filter (/= [""])- . groupBy (\x y -> "" `notElem` [x,y]) -- break on blank lines+ . L.groupBy (\x y -> "" `notElem` [x,y]) -- break on blank lines . lines reflowLines :: String -> Doc@@ -446,14 +464,14 @@ Installed.author installed, homepage = combine Source.homepage source Installed.homepage installed,- bugReports = maybe "" Source.bugReports source,- sourceRepo = fromMaybe "" . join+ bugReports = maybe mempty Source.bugReports source,+ sourceRepo = fromMaybe mempty . join . fmap (uncons Nothing Source.repoLocation . sortBy (comparing Source.repoKind) . Source.sourceRepos) $ source, --TODO: installed package info is missing synopsis- synopsis = maybe "" Source.synopsis source,+ synopsis = maybe mempty Source.synopsis source, description = combine Source.description source Installed.description installed, category = combine Source.category source@@ -489,7 +507,7 @@ sourceSelected | isJust selectedPkg = selectedPkg | otherwise = latestWithPref versionPref sourcePkgs- sourceGeneric = fmap packageDescription sourceSelected+ sourceGeneric = fmap srcpkgDescription sourceSelected source = fmap flattenPackageDescription sourceGeneric uncons :: b -> (a -> b) -> [a] -> b@@ -503,7 +521,7 @@ -- updateFileSystemPackageDetails :: PackageDisplayInfo -> IO PackageDisplayInfo updateFileSystemPackageDetails pkginfo = do- fetched <- maybe (return False) (isFetched . packageSource)+ fetched <- maybe (return False) (isFetched . srcpkgSource) (selectedSourcePkg pkginfo) docsExist <- doesDirectoryExist (haddockHtml pkginfo) return pkginfo {@@ -539,14 +557,14 @@ collect (OnlyInRight (name,as)) = (name, [], as) groupOn :: Ord key => (a -> key) -> [a] -> [(key,[a])]-groupOn key = map (\xs -> (key (head xs), xs))+groupOn key = map (\xs -> (key (head xs), toList xs)) . groupBy (equating key) . sortBy (comparing key) dispTopVersions :: Int -> VersionRange -> [Version] -> Doc dispTopVersions n pref vs = (Disp.fsep . Disp.punctuate (Disp.char ',')- . map (\ver -> if ispref ver then disp ver else parens (disp ver))+ . map (\ver -> if ispref ver then pretty ver else parens (pretty ver)) . sort . take n . interestingVersions ispref $ vs) <+> trailingMessage@@ -577,9 +595,12 @@ . reorderTree (\(Node (v,_) _) -> pref (mkVersion v)) . reverseTree . mkTree- . map versionNumbers+ . map (or0 . versionNumbers) where+ or0 [] = 0 :| []+ or0 (x:xs) = x :| xs+ swizzleTree = unfoldTree (spine []) where spine ts' (Node x []) = (x, ts')@@ -592,12 +613,17 @@ reverseTree (Node x cs) = Node x (reverse (map reverseTree cs)) + mkTree :: forall a. Eq a => [NonEmpty a] -> Tree ([a], Bool) mkTree xs = unfoldTree step (False, [], xs) where+ step :: (Bool, [a], [NonEmpty a]) -> (([a], Bool), [(Bool, [a], [NonEmpty a])]) step (node,ns,vs) = ( (reverse ns, node)- , [ (any null vs', n:ns, filter (not . null) vs')- | (n, vs') <- groups vs ]+ , [ (any null vs', n:ns, mapMaybe nonEmpty (toList vs'))+ | (n, vs') <- groups vs+ ] )- groups = map (\g -> (head (head g), map tail g))++ groups :: [NonEmpty a] -> [(a, NonEmpty [a])]+ groups = map (\g -> (head (head g), fmap tail g)) . groupBy (equating head)
cabal/cabal-install/Distribution/Client/Manpage.hs view
@@ -14,22 +14,63 @@ module Distribution.Client.Manpage ( -- * Manual page generation manpage+ , manpageCmd+ , ManpageFlags+ , defaultManpageFlags+ , manpageOptions ) where +import Distribution.Client.Compat.Prelude+import Prelude ()++import Distribution.Client.ManpageFlags+import Distribution.Client.Setup (globalCommand)+import Distribution.Compat.Process (createProcess) import Distribution.Simple.Command-import Distribution.Client.Setup (globalCommand)+import Distribution.Simple.Flag (fromFlagOrDefault)+import System.IO (hClose, hPutStr) -import Data.Char (toUpper)-import Data.List (intercalate)+import qualified System.Process as Process data FileInfo = FileInfo String String -- ^ path, description +-------------------------------------------------------------------------------+--+-------------------------------------------------------------------------------+ -- | A list of files that should be documented in the manual page. files :: [FileInfo] files = [ (FileInfo "~/.cabal/config" "The defaults that can be overridden with command-line options.") , (FileInfo "~/.cabal/world" "A list of all packages whose installation has been explicitly requested.") ]++manpageCmd :: String -> [CommandSpec a] -> ManpageFlags -> IO ()+manpageCmd pname commands flags+ | fromFlagOrDefault False (manpageRaw flags)+ = putStrLn contents+ | otherwise+ = do+ let cmd = "man"+ args = ["-l", "-"]++ (mb_in, _, _, ph) <- createProcess (Process.proc cmd args)+ { Process.std_in = Process.CreatePipe+ , Process.std_out = Process.Inherit+ , Process.std_err = Process.Inherit+ }++ -- put contents+ for_ mb_in $ \hin -> do+ hPutStr hin contents+ hClose hin++ -- wait for process to exit, propagate exit code+ ec <- Process.waitForProcess ph+ exitWith ec+ where+ contents :: String+ contents = manpage pname commands -- | Produces a manual page with @troff@ markup. manpage :: String -> [CommandSpec a] -> String
+ cabal/cabal-install/Distribution/Client/ManpageFlags.hs view
@@ -0,0 +1,40 @@+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE LambdaCase #-}+module Distribution.Client.ManpageFlags+( ManpageFlags (..)+, defaultManpageFlags+, manpageOptions,+) where++import Distribution.Client.Compat.Prelude++import Distribution.Simple.Command (OptionField (..), ShowOrParseArgs (..), option)+import Distribution.Simple.Setup (Flag (..), toFlag, trueArg, optionVerbosity)+import Distribution.Verbosity (normal)++data ManpageFlags = ManpageFlags+ { manpageVerbosity :: Flag Verbosity+ , manpageRaw :: Flag Bool+ } deriving (Eq, Show, Generic)++instance Monoid ManpageFlags where+ mempty = gmempty+ mappend = (<>)++instance Semigroup ManpageFlags where+ (<>) = gmappend++defaultManpageFlags :: ManpageFlags+defaultManpageFlags = ManpageFlags+ { manpageVerbosity = toFlag normal+ , manpageRaw = toFlag False+ }++manpageOptions :: ShowOrParseArgs -> [OptionField ManpageFlags]+manpageOptions _ =+ [ optionVerbosity manpageVerbosity (\v flags -> flags { manpageVerbosity = v })+ , option "" ["raw"]+ "Output raw troff content"+ manpageRaw (\v flags -> flags { manpageRaw = v })+ trueArg+ ]
cabal/cabal-install/Distribution/Client/Nix.hs view
@@ -6,12 +6,11 @@ , inNixShell , nixInstantiate , nixShell- , nixShellIfSandboxed ) where import Distribution.Client.Compat.Prelude -import Control.Exception (bracket, catch)+import Control.Exception (bracket) import System.Directory ( canonicalizePath, createDirectoryIfMissing, doesDirectoryExist , doesFileExist, removeDirectoryRecursive, removeFile )@@ -25,8 +24,6 @@ import Distribution.Compat.Environment ( lookupEnv, setEnv, unsetEnv ) -import Distribution.Verbosity- import Distribution.Simple.Program ( Program(..), ProgramDb , addKnownProgram, configureProgram, emptyProgramDb, getDbProgramOutput@@ -36,7 +33,6 @@ import Distribution.Client.Config (SavedConfig(..)) import Distribution.Client.GlobalFlags (GlobalFlags(..))-import Distribution.Client.Sandbox.Types (UseSandbox(..)) configureOneProgram :: Verbosity -> Program -> IO ProgramDb@@ -86,7 +82,7 @@ -> GlobalFlags -> SavedConfig -> IO ()-nixInstantiate verb dist force globalFlags config =+nixInstantiate verb dist force' globalFlags config = findNixExpr globalFlags config >>= \case Nothing -> return () Just shellNix -> do@@ -98,7 +94,7 @@ let timestamp = timestampPath dist shellNix upToDate <- existsAndIsMoreRecentThan timestamp shellNix - let ready = alreadyInShell || (instantiated && upToDate && not force)+ let ready = alreadyInShell || (instantiated && upToDate && not force') unless ready $ do let prog = simpleProgram "nix-instantiate"@@ -184,19 +180,3 @@ when exists $ do debug verb ("removing Nix gcroots from " ++ tgt) removeDirectoryRecursive tgt---nixShellIfSandboxed- :: Verbosity- -> FilePath- -> GlobalFlags- -> SavedConfig- -> UseSandbox- -> IO ()- -- ^ The action to perform inside a nix-shell. This is also the action- -- that will be performed immediately if Nix is disabled.- -> IO ()-nixShellIfSandboxed verb dist globalFlags config useSandbox go =- case useSandbox of- NoSandbox -> go- UseSandbox _ -> nixShell verb dist globalFlags config go
+ cabal/cabal-install/Distribution/Client/NixStyleOptions.hs view
@@ -0,0 +1,85 @@+-- | Command line options for nix-style / v2 commands.+--+-- The commands take a lot of the same options, which affect how install plan+-- is constructed.+module Distribution.Client.NixStyleOptions (+ NixStyleFlags (..),+ nixStyleOptions,+ defaultNixStyleFlags,+) where++import Distribution.Client.Compat.Prelude+import Prelude ()++import Distribution.Simple.Command (OptionField (..), ShowOrParseArgs)+import Distribution.Simple.Setup (BenchmarkFlags, HaddockFlags, TestFlags)+import Distribution.Solver.Types.ConstraintSource (ConstraintSource (..))++import Distribution.Client.ProjectFlags+ (ProjectFlags (..), defaultProjectFlags, projectFlagsOptions)+import Distribution.Client.Setup+ (ConfigExFlags, ConfigFlags (..), InstallFlags (..), benchmarkOptions, configureExOptions,+ configureOptions, haddockOptions, installOptions, liftOptions, testOptions)++data NixStyleFlags a = NixStyleFlags+ { configFlags :: ConfigFlags+ , configExFlags :: ConfigExFlags+ , installFlags :: InstallFlags+ , haddockFlags :: HaddockFlags+ , testFlags :: TestFlags+ , benchmarkFlags :: BenchmarkFlags+ , projectFlags :: ProjectFlags+ , extraFlags :: a+ }++nixStyleOptions+ :: (ShowOrParseArgs -> [OptionField a])+ -> ShowOrParseArgs -> [OptionField (NixStyleFlags a)]+nixStyleOptions commandOptions showOrParseArgs =+ liftOptions configFlags set1+ -- Note: [Hidden Flags]+ -- hide "constraint", "dependency", and+ -- "exact-configuration" from the configure options.+ (filter ((`notElem` ["constraint", "dependency"+ , "exact-configuration"])+ . optionName) $ configureOptions showOrParseArgs)+ ++ liftOptions configExFlags set2 (configureExOptions showOrParseArgs+ ConstraintSourceCommandlineFlag)+ ++ liftOptions installFlags set3+ -- hide "target-package-db" and "symlink-bindir" flags from the+ -- install options.+ -- "symlink-bindir" is obsoleted by "installdir" in ClientInstallFlags+ (filter ((`notElem` ["target-package-db", "symlink-bindir"])+ . optionName) $+ installOptions showOrParseArgs)+ ++ liftOptions haddockFlags set4+ -- hide "verbose" and "builddir" flags from the+ -- haddock options.+ (filter ((`notElem` ["v", "verbose", "builddir"])+ . optionName) $+ haddockOptions showOrParseArgs)+ ++ liftOptions testFlags set5 (testOptions showOrParseArgs)+ ++ liftOptions benchmarkFlags set6 (benchmarkOptions showOrParseArgs)+ ++ liftOptions projectFlags set7 (projectFlagsOptions showOrParseArgs)+ ++ liftOptions extraFlags set8 (commandOptions showOrParseArgs)+ where+ set1 x flags = flags { configFlags = x }+ set2 x flags = flags { configExFlags = x }+ set3 x flags = flags { installFlags = x }+ set4 x flags = flags { haddockFlags = x }+ set5 x flags = flags { testFlags = x }+ set6 x flags = flags { benchmarkFlags = x }+ set7 x flags = flags { projectFlags = x }+ set8 x flags = flags { extraFlags = x }++defaultNixStyleFlags :: a -> NixStyleFlags a+defaultNixStyleFlags x = NixStyleFlags+ { configFlags = mempty+ , configExFlags = mempty+ , installFlags = mempty+ , haddockFlags = mempty+ , testFlags = mempty+ , benchmarkFlags = mempty+ , projectFlags = defaultProjectFlags+ , extraFlags = x+ }
cabal/cabal-install/Distribution/Client/Outdated.hs view
@@ -37,22 +37,21 @@ import Distribution.Simple.Utils (die', notice, debug, tryFindPackageDesc) import Distribution.System (Platform)-import Distribution.Deprecated.Text (display) import Distribution.Types.ComponentRequestedSpec (ComponentRequestedSpec(..)) import Distribution.Types.Dependency- (Dependency(..), depPkgName, simplifyDependency)-import Distribution.Verbosity (Verbosity, silent)+ (Dependency(..))+import Distribution.Verbosity (silent) import Distribution.Version (Version, VersionRange, LowerBound(..), UpperBound(..) ,asVersionIntervals, majorBoundVersion) import Distribution.PackageDescription.Parsec (readGenericPackageDescription)+import Distribution.Types.PackageVersionConstraint+ (PackageVersionConstraint (..), simplifyPackageVersionConstraint) import qualified Data.Set as S import System.Directory (getCurrentDirectory)-import System.Exit (exitFailure)-import Control.Exception (throwIO) -- | Entry point for the 'outdated' command. outdated :: Verbosity -> OutdatedFlags -> RepoContext@@ -91,7 +90,7 @@ then depsFromNewFreezeFile verbosity mprojectFile else depsFromPkgDesc verbosity comp platform debug verbosity $ "Dependencies loaded: "- ++ (intercalate ", " $ map display deps)+ ++ (intercalate ", " $ map prettyShow deps) let outdatedDeps = listOutdated deps pkgIndex (ListOutdatedSettings ignorePred minorPred) when (not quiet) $@@ -102,25 +101,25 @@ -- | Print either the list of all outdated dependencies, or a message -- that there are none.-showResult :: Verbosity -> [(Dependency,Version)] -> Bool -> IO ()+showResult :: Verbosity -> [(PackageVersionConstraint,Version)] -> Bool -> IO () showResult verbosity outdatedDeps simpleOutput = if (not . null $ outdatedDeps) then do when (not simpleOutput) $ notice verbosity "Outdated dependencies:"- for_ outdatedDeps $ \(d@(Dependency pn _ _), v) ->- let outdatedDep = if simpleOutput then display pn- else display d ++ " (latest: " ++ display v ++ ")"+ for_ outdatedDeps $ \(d@(PackageVersionConstraint pn _), v) ->+ let outdatedDep = if simpleOutput then prettyShow pn+ else prettyShow d ++ " (latest: " ++ prettyShow v ++ ")" in notice verbosity outdatedDep else notice verbosity "All dependencies are up to date." -- | Convert a list of 'UserConstraint's to a 'Dependency' list.-userConstraintsToDependencies :: [UserConstraint] -> [Dependency]+userConstraintsToDependencies :: [UserConstraint] -> [PackageVersionConstraint] userConstraintsToDependencies ucnstrs = mapMaybe (packageConstraintToDependency . userToPackageConstraint) ucnstrs -- | Read the list of dependencies from the freeze file.-depsFromFreezeFile :: Verbosity -> IO [Dependency]+depsFromFreezeFile :: Verbosity -> IO [PackageVersionConstraint] depsFromFreezeFile verbosity = do cwd <- getCurrentDirectory userConfig <- loadUserConfig verbosity cwd Nothing@@ -131,7 +130,7 @@ return deps -- | Read the list of dependencies from the new-style freeze file.-depsFromNewFreezeFile :: Verbosity -> Maybe FilePath -> IO [Dependency]+depsFromNewFreezeFile :: Verbosity -> Maybe FilePath -> IO [PackageVersionConstraint] depsFromNewFreezeFile verbosity mprojectFile = do projectRoot <- either throwIO return =<< findProjectRoot Nothing mprojectFile@@ -147,7 +146,7 @@ return deps -- | Read the list of dependencies from the package description.-depsFromPkgDesc :: Verbosity -> Compiler -> Platform -> IO [Dependency]+depsFromPkgDesc :: Verbosity -> Compiler -> Platform -> IO [PackageVersionConstraint] depsFromPkgDesc verbosity comp platform = do cwd <- getCurrentDirectory path <- tryFindPackageDesc verbosity cwd@@ -161,7 +160,9 @@ let bd = allBuildDepends pd debug verbosity "Reading the list of dependencies from the package description"- return bd+ return $ map toPVC bd+ where+ toPVC (Dependency pn vr _) = PackageVersionConstraint pn vr -- | Various knobs for customising the behaviour of 'listOutdated'. data ListOutdatedSettings = ListOutdatedSettings {@@ -172,16 +173,16 @@ } -- | Find all outdated dependencies.-listOutdated :: [Dependency]+listOutdated :: [PackageVersionConstraint] -> PackageIndex UnresolvedSourcePackage -> ListOutdatedSettings- -> [(Dependency, Version)]+ -> [(PackageVersionConstraint, Version)] listOutdated deps pkgIndex (ListOutdatedSettings ignorePred minorPred) =- mapMaybe isOutdated $ map simplifyDependency deps+ mapMaybe isOutdated $ map simplifyPackageVersionConstraint deps where- isOutdated :: Dependency -> Maybe (Dependency, Version)- isOutdated dep@(Dependency pname vr _)- | ignorePred (depPkgName dep) = Nothing+ isOutdated :: PackageVersionConstraint -> Maybe (PackageVersionConstraint, Version)+ isOutdated dep@(PackageVersionConstraint pname vr)+ | ignorePred pname = Nothing | otherwise = let this = map packageVersion $ lookupDependency pkgIndex pname vr latest = lookupLatest dep@@ -195,12 +196,12 @@ latest' = maximum latest in if this' < latest' then Just latest' else Nothing - lookupLatest :: Dependency -> [Version]- lookupLatest dep@(Dependency pname vr _)- | minorPred (depPkgName dep) =+ lookupLatest :: PackageVersionConstraint -> [Version]+ lookupLatest (PackageVersionConstraint pname vr)+ | minorPred pname = map packageVersion $ lookupDependency pkgIndex pname (relaxMinor vr)- | otherwise =- map packageVersion $ lookupPackageName pkgIndex (depPkgName dep)+ | otherwise =+ map packageVersion $ lookupPackageName pkgIndex pname relaxMinor :: VersionRange -> VersionRange relaxMinor vr =
cabal/cabal-install/Distribution/Client/PackageHash.hs view
@@ -20,13 +20,6 @@ -- ** Platform-specific variations hashedInstalledPackageIdLong, hashedInstalledPackageIdShort,-- -- * Low level hash choice- HashValue,- hashValue,- showHashValue,- readFileHashValue,- hashFromTUF, ) where import Prelude ()@@ -37,35 +30,23 @@ , PkgconfigName ) import Distribution.System ( Platform, OS(Windows, OSX), buildOS )-import Distribution.PackageDescription- ( FlagAssignment, unFlagAssignment, showFlagValue )+import Distribution.Types.Flag+ ( FlagAssignment, showFlagAssignment ) import Distribution.Simple.Compiler ( CompilerId, OptimisationLevel(..), DebugInfoLevel(..) , ProfDetailLevel(..), showProfDetailLevel ) import Distribution.Simple.InstallDirs ( PathTemplate, fromPathTemplate )-import Distribution.Pretty (prettyShow)-import Distribution.Deprecated.Text- ( display ) import Distribution.Types.PkgconfigVersion (PkgconfigVersion)+import Distribution.Client.HashValue import Distribution.Client.Types ( InstalledPackageId ) import qualified Distribution.Solver.Types.ComponentDeps as CD -import qualified Hackage.Security.Client as Sec--import qualified Crypto.Hash.SHA256 as SHA256-import qualified Data.ByteString.Base16 as Base16-import qualified Data.ByteString.Char8 as BS import qualified Data.ByteString.Lazy.Char8 as LBS import qualified Data.Map as Map import qualified Data.Set as Set -import Data.Function (on)-import Control.Exception (evaluate)-import System.IO (withBinaryFile, IOMode(..))-- ------------------------------- -- Calculating package hashes --@@ -90,11 +71,22 @@ -- without significant path length limitations (ie not Windows). -- hashedInstalledPackageIdLong :: PackageHashInputs -> InstalledPackageId-hashedInstalledPackageIdLong pkghashinputs@PackageHashInputs{pkgHashPkgId} =- mkComponentId $- display pkgHashPkgId -- to be a bit user friendly- ++ "-"- ++ showHashValue (hashPackageHashInputs pkghashinputs)+hashedInstalledPackageIdLong+ pkghashinputs@PackageHashInputs{pkgHashPkgId,pkgHashComponent}+ = mkComponentId $+ prettyShow pkgHashPkgId -- to be a bit user friendly+ ++ maybe "" displayComponent pkgHashComponent+ ++ "-"+ ++ showHashValue (hashPackageHashInputs pkghashinputs)+ where+ displayComponent :: CD.Component -> String+ displayComponent CD.ComponentLib = ""+ displayComponent (CD.ComponentSubLib s) = "-l-" ++ prettyShow s+ displayComponent (CD.ComponentFLib s) = "-f-" ++ prettyShow s+ displayComponent (CD.ComponentExe s) = "-e-" ++ prettyShow s+ displayComponent (CD.ComponentTest s) = "-t-" ++ prettyShow s+ displayComponent (CD.ComponentBench s) = "-b-" ++ prettyShow s+ displayComponent CD.ComponentSetup = "-setup" -- | On Windows we have serious problems with path lengths. Windows imposes a -- maximum path length of 260 chars, and even if we can use the windows long@@ -119,17 +111,13 @@ mkComponentId $ intercalate "-" -- max length now 64- [ truncateStr 14 (display name)- , truncateStr 8 (display version)- , showHashValue (truncateHash (hashPackageHashInputs pkghashinputs))+ [ truncateStr 14 (prettyShow name)+ , truncateStr 8 (prettyShow version)+ , showHashValue (truncateHash 20 (hashPackageHashInputs pkghashinputs)) ] where PackageIdentifier name version = pkgHashPkgId - -- Truncate a 32 byte SHA256 hash to 160bits, 20 bytes :-(- -- It'll render as 40 hex chars.- truncateHash (HashValue h) = HashValue (BS.take 20 h)- -- Truncate a string, with a visual indication that it is truncated. truncateStr n s | length s <= n = s | otherwise = take (n-1) s ++ "_"@@ -161,13 +149,12 @@ hashedInstalledPackageIdVeryShort pkghashinputs@PackageHashInputs{pkgHashPkgId} = mkComponentId $ intercalate "-"- [ filter (not . flip elem "aeiou") (display name)- , display version- , showHashValue (truncateHash (hashPackageHashInputs pkghashinputs))+ [ filter (not . flip elem "aeiou") (prettyShow name)+ , prettyShow version+ , showHashValue (truncateHash 4 (hashPackageHashInputs pkghashinputs)) ] where PackageIdentifier name version = pkgHashPkgId- truncateHash (HashValue h) = HashValue (BS.take 4 h) -- | All the information that contribues to a package's hash, and thus its -- 'InstalledPackageId'.@@ -269,37 +256,37 @@ -- into the ghc-pkg db. At that point this should probably be changed to -- use the config file infrastructure so it can be read back in again. LBS.pack $ unlines $ catMaybes $- [ entry "pkgid" display pkgHashPkgId+ [ entry "pkgid" prettyShow pkgHashPkgId , mentry "component" show pkgHashComponent , entry "src" showHashValue pkgHashSourceHash , entry "pkg-config-deps"- (intercalate ", " . map (\(pn, mb_v) -> display pn +++ (intercalate ", " . map (\(pn, mb_v) -> prettyShow pn ++ case mb_v of Nothing -> "" Just v -> " " ++ prettyShow v) . Set.toList) pkgHashPkgConfigDeps- , entry "deps" (intercalate ", " . map display+ , entry "deps" (intercalate ", " . map prettyShow . Set.toList) pkgHashDirectDeps -- and then all the config- , entry "compilerid" display pkgHashCompilerId- , entry "platform" display pkgHashPlatform+ , entry "compilerid" prettyShow pkgHashCompilerId+ , entry "platform" prettyShow pkgHashPlatform , opt "flags" mempty showFlagAssignment pkgHashFlagAssignment , opt "configure-script" [] unwords pkgHashConfigureScriptArgs- , opt "vanilla-lib" True display pkgHashVanillaLib- , opt "shared-lib" False display pkgHashSharedLib- , opt "dynamic-exe" False display pkgHashDynExe- , opt "fully-static-exe" False display pkgHashFullyStaticExe- , opt "ghci-lib" False display pkgHashGHCiLib- , opt "prof-lib" False display pkgHashProfLib- , opt "prof-exe" False display pkgHashProfExe+ , opt "vanilla-lib" True prettyShow pkgHashVanillaLib+ , opt "shared-lib" False prettyShow pkgHashSharedLib+ , opt "dynamic-exe" False prettyShow pkgHashDynExe+ , opt "fully-static-exe" False prettyShow pkgHashFullyStaticExe+ , opt "ghci-lib" False prettyShow pkgHashGHCiLib+ , opt "prof-lib" False prettyShow pkgHashProfLib+ , opt "prof-exe" False prettyShow pkgHashProfExe , opt "prof-lib-detail" ProfDetailDefault showProfDetailLevel pkgHashProfLibDetail , opt "prof-exe-detail" ProfDetailDefault showProfDetailLevel pkgHashProfExeDetail- , opt "hpc" False display pkgHashCoverage+ , opt "hpc" False prettyShow pkgHashCoverage , opt "optimisation" NormalOptimisation (show . fromEnum) pkgHashOptimization- , opt "split-objs" False display pkgHashSplitObjs- , opt "split-sections" False display pkgHashSplitSections- , opt "stripped-lib" False display pkgHashStripLibs- , opt "stripped-exe" True display pkgHashStripExes+ , opt "split-objs" False prettyShow pkgHashSplitObjs+ , opt "split-sections" False prettyShow pkgHashSplitSections+ , opt "stripped-lib" False prettyShow pkgHashStripLibs+ , opt "stripped-exe" True prettyShow pkgHashStripExes , opt "debug-info" NormalDebugInfo (show . fromEnum) pkgHashDebugInfo , opt "extra-lib-dirs" [] unwords pkgHashExtraLibDirs , opt "extra-framework-dirs" [] unwords pkgHashExtraFrameworkDirs@@ -307,18 +294,18 @@ , opt "prog-prefix" Nothing (maybe "" fromPathTemplate) pkgHashProgPrefix , opt "prog-suffix" Nothing (maybe "" fromPathTemplate) pkgHashProgSuffix - , opt "documentation" False display pkgHashDocumentation- , opt "haddock-hoogle" False display pkgHashHaddockHoogle- , opt "haddock-html" False display pkgHashHaddockHtml+ , opt "documentation" False prettyShow pkgHashDocumentation+ , opt "haddock-hoogle" False prettyShow pkgHashHaddockHoogle+ , opt "haddock-html" False prettyShow pkgHashHaddockHtml , opt "haddock-html-location" Nothing (fromMaybe "") pkgHashHaddockHtmlLocation- , opt "haddock-foreign-libraries" False display pkgHashHaddockForeignLibs- , opt "haddock-executables" False display pkgHashHaddockExecutables- , opt "haddock-tests" False display pkgHashHaddockTestSuites- , opt "haddock-benchmarks" False display pkgHashHaddockBenchmarks- , opt "haddock-internal" False display pkgHashHaddockInternal+ , opt "haddock-foreign-libraries" False prettyShow pkgHashHaddockForeignLibs+ , opt "haddock-executables" False prettyShow pkgHashHaddockExecutables+ , opt "haddock-tests" False prettyShow pkgHashHaddockTestSuites+ , opt "haddock-benchmarks" False prettyShow pkgHashHaddockBenchmarks+ , opt "haddock-internal" False prettyShow pkgHashHaddockInternal , opt "haddock-css" Nothing (fromMaybe "") pkgHashHaddockCss- , opt "haddock-hyperlink-source" False display pkgHashHaddockLinkedSource- , opt "haddock-quickjump" False display pkgHashHaddockQuickJump+ , opt "haddock-hyperlink-source" False prettyShow pkgHashHaddockLinkedSource+ , opt "haddock-quickjump" False prettyShow pkgHashHaddockQuickJump , opt "haddock-contents-location" Nothing (maybe "" fromPathTemplate) pkgHashHaddockContents ] ++ Map.foldrWithKey (\prog args acc -> opt (prog ++ "-options") [] unwords args : acc) [] pkgHashProgramArgs@@ -328,60 +315,3 @@ opt key def format value | value == def = Nothing | otherwise = entry key format value-- showFlagAssignment = unwords . map showFlagValue . sortBy (compare `on` fst) . unFlagAssignment---------------------------------------------------- The specific choice of hash implementation------- Is a crypto hash necessary here? One thing to consider is who controls the--- inputs and what's the result of a hash collision. Obviously we should not--- install packages we don't trust because they can run all sorts of code, but--- if I've checked there's no TH, no custom Setup etc, is there still a--- problem? If someone provided us a tarball that hashed to the same value as--- some other package and we installed it, we could end up re-using that--- installed package in place of another one we wanted. So yes, in general--- there is some value in preventing intentional hash collisions in installed--- package ids.--newtype HashValue = HashValue BS.ByteString- deriving (Eq, Generic, Show, Typeable)--instance Binary HashValue where- put (HashValue digest) = put digest- get = do- digest <- get- -- Cannot do any sensible validation here. Although we use SHA256- -- for stuff we hash ourselves, we can also get hashes from TUF- -- and that can in principle use different hash functions in future.- return (HashValue digest)---- | Hash some data. Currently uses SHA256.----hashValue :: LBS.ByteString -> HashValue-hashValue = HashValue . SHA256.hashlazy--showHashValue :: HashValue -> String-showHashValue (HashValue digest) = BS.unpack (Base16.encode digest)---- | Hash the content of a file. Uses SHA256.----readFileHashValue :: FilePath -> IO HashValue-readFileHashValue tarball =- withBinaryFile tarball ReadMode $ \hnd ->- evaluate . hashValue =<< LBS.hGetContents hnd---- | Convert a hash from TUF metadata into a 'PackageSourceHash'.------ Note that TUF hashes don't neessarily have to be SHA256, since it can--- support new algorithms in future.----hashFromTUF :: Sec.Hash -> HashValue-hashFromTUF (Sec.Hash hashstr) =- --TODO: [code cleanup] either we should get TUF to use raw bytestrings or- -- perhaps we should also just use a base16 string as the internal rep.- case Base16.decode (BS.pack hashstr) of- (hash, trailing) | not (BS.null hash) && BS.null trailing- -> HashValue hash- _ -> error "hashFromTUF: cannot decode base16 hash"
− cabal/cabal-install/Distribution/Client/PackageUtils.hs
@@ -1,38 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Distribution.Client.PackageUtils--- Copyright : (c) Duncan Coutts 2010--- License : BSD-like------ Maintainer : cabal-devel@gmail.com--- Stability : provisional--- Portability : portable------ Various package description utils that should be in the Cabal lib-------------------------------------------------------------------------------module Distribution.Client.PackageUtils (- externalBuildDepends,- ) where--import Distribution.Package (packageName, packageVersion)-import Distribution.PackageDescription- (PackageDescription (..), enabledBuildDepends, libName)-import Distribution.Types.ComponentRequestedSpec (ComponentRequestedSpec)-import Distribution.Types.Dependency-import Distribution.Types.LibraryName-import Distribution.Types.UnqualComponentName-import Distribution.Version (isAnyVersion, withinRange)---- | The list of dependencies that refer to external packages--- rather than internal package components.----externalBuildDepends :: PackageDescription -> ComponentRequestedSpec -> [Dependency]-externalBuildDepends pkg spec = filter (not . internal) (enabledBuildDepends pkg spec)- where- -- True if this dependency is an internal one (depends on a library- -- defined in the same package).- internal (Dependency depName versionRange _) =- (depName == packageName pkg &&- packageVersion pkg `withinRange` versionRange) ||- (LSubLibName (packageNameToUnqualComponentName depName) `elem` map libName (subLibraries pkg) &&- isAnyVersion versionRange)
cabal/cabal-install/Distribution/Client/ParseUtils.hs view
@@ -54,14 +54,14 @@ import Distribution.Simple.Command ( OptionField ) -import Text.PrettyPrint ( (<+>), ($+$) )+import Text.PrettyPrint ( ($+$) ) import qualified Data.Map as Map import qualified Text.PrettyPrint as Disp ( (<>), Doc, text, colon, vcat, empty, isEmpty, nest ) -- For new parser stuff import Distribution.CabalSpecVersion (cabalSpecLatest)-import Distribution.FieldGrammar (FieldGrammar, partitionFields, parseFieldGrammar)+import Distribution.FieldGrammar (partitionFields, parseFieldGrammar) import Distribution.Fields.ParseResult (runParseResult) import Distribution.Parsec.Error (showPError) import Distribution.Parsec.Position (Position (..))@@ -124,9 +124,9 @@ } -- | 'FieldGrammar' section description-data FGSectionDescr a = forall s. FGSectionDescr+data FGSectionDescr g a = forall s. FGSectionDescr { fgSectionName :: String- , fgSectionGrammar :: forall g. (FieldGrammar g, Applicative (g s)) => g s s+ , fgSectionGrammar :: g s s -- todo: add subsections? , fgSectionGet :: a -> [(String, s)] , fgSectionSet :: LineNo -> String -> s -> a -> ParseResult a@@ -219,7 +219,7 @@ parseFieldsAndSections :: [FieldDescr a] -- ^ field -> [SectionDescr a] -- ^ legacy sections- -> [FGSectionDescr a] -- ^ FieldGrammar sections+ -> [FGSectionDescr FG.ParsecFieldGrammar a] -- ^ FieldGrammar sections -> a -> [Field] -> ParseResult a parseFieldsAndSections fieldDescrs sectionDescrs fgSectionDescrs =@@ -286,7 +286,7 @@ -- Note that unlike 'ppFields', at present it does not support printing -- default values. If needed, adding such support would be quite reasonable. ---ppFieldsAndSections :: [FieldDescr a] -> [SectionDescr a] -> [FGSectionDescr a] -> a -> Disp.Doc+ppFieldsAndSections :: [FieldDescr a] -> [SectionDescr a] -> [FGSectionDescr FG.PrettyFieldGrammar a] -> a -> Disp.Doc ppFieldsAndSections fieldDescrs sectionDescrs fgSectionDescrs val = ppFields fieldDescrs Nothing val $+$@@ -313,7 +313,7 @@ -- 'ppFieldsAndSections' and so does not need to be exported. -- ppSectionAndSubsections :: String -> String- -> [FieldDescr a] -> [SectionDescr a] -> [FGSectionDescr a] -> a -> Disp.Doc+ -> [FieldDescr a] -> [SectionDescr a] -> [FGSectionDescr FG.PrettyFieldGrammar a] -> a -> Disp.Doc ppSectionAndSubsections name arg fields sections fgSections cur | Disp.isEmpty fieldsDoc = Disp.empty | otherwise = Disp.text name <+> argDoc@@ -360,7 +360,7 @@ -- -- It accumulates the result on top of a given initial (typically empty) value. ---parseConfig :: [FieldDescr a] -> [SectionDescr a] -> [FGSectionDescr a] -> a+parseConfig :: [FieldDescr a] -> [SectionDescr a] -> [FGSectionDescr FG.ParsecFieldGrammar a] -> a -> String -> ParseResult a parseConfig fieldDescrs sectionDescrs fgSectionDescrs empty str = parseFieldsAndSections fieldDescrs sectionDescrs fgSectionDescrs empty@@ -369,6 +369,6 @@ -- | Render a value in the config file syntax, based on a description of the -- configuration file in terms of its fields and sections. ---showConfig :: [FieldDescr a] -> [SectionDescr a] -> [FGSectionDescr a] -> a -> Disp.Doc+showConfig :: [FieldDescr a] -> [SectionDescr a] -> [FGSectionDescr FG.PrettyFieldGrammar a] -> a -> Disp.Doc showConfig = ppFieldsAndSections
cabal/cabal-install/Distribution/Client/ProjectBuilding.hs view
@@ -38,9 +38,8 @@ BuildFailureReason(..), ) where -#if !MIN_VERSION_base(4,8,0)-import Control.Applicative ((<$>))-#endif+import Distribution.Client.Compat.Prelude+import Prelude () import Distribution.Client.PackageHash (renderPackageHashInputs) import Distribution.Client.RebuildMonad@@ -91,33 +90,21 @@ import Distribution.Simple.Utils import Distribution.Version-import Distribution.Verbosity-import Distribution.Pretty import Distribution.Compat.Graph (IsNode(..)) import qualified Data.List.NonEmpty as NE-import Data.Map (Map) import qualified Data.Map as Map-import Data.Set (Set) import qualified Data.Set as Set+import qualified Data.ByteString as BS import qualified Data.ByteString.Lazy as LBS-import Data.List (isPrefixOf) -import Control.Monad-import Control.Exception-import Data.Function (on)-import Data.Maybe+import Control.Exception (Handler (..), SomeAsyncException, assert, catches, handle)+import System.Directory (canonicalizePath, createDirectoryIfMissing, doesDirectoryExist, doesFileExist, removeFile, renameDirectory)+import System.FilePath (dropDrive, makeRelative, normalise, takeDirectory, (<.>), (</>))+import System.IO (IOMode (AppendMode), withFile) -import System.FilePath-import System.IO-import System.Directory+import Distribution.Compat.Directory (listDirectory) -#if !MIN_VERSION_directory(1,2,5)-listDirectory :: FilePath -> IO [FilePath]-listDirectory path =- (filter f) <$> (getDirectoryContents path)- where f filename = filename /= "." && filename /= ".."-#endif ------------------------------------------------------------------------------ -- * Overall building strategy.@@ -213,13 +200,8 @@ -- artifacts under the shared dist directory. dryRunLocalPkg pkg depsBuildStatus srcdir - Just (RemoteSourceRepoPackage _repo srcdir) ->- -- At this point, source repos are essentially the same as local- -- dirs, since we've already download them.- dryRunLocalPkg pkg depsBuildStatus srcdir-- -- The three tarball cases are handled the same as each other,- -- though depending on the build style.+ -- The rest cases are all tarball cases are,+ -- and handled the same as each other though depending on the build style. Just (LocalTarballPackage tarball) -> dryRunTarballPkg pkg depsBuildStatus tarball @@ -229,6 +211,10 @@ Just (RepoTarballPackage _ _ tarball) -> dryRunTarballPkg pkg depsBuildStatus tarball + Just (RemoteSourceRepoPackage _repo tarball) ->+ dryRunTarballPkg pkg depsBuildStatus tarball++ dryRunTarballPkg :: ElaboratedConfiguredPackage -> [BuildStatus] -> FilePath@@ -296,7 +282,7 @@ -- we go in the right order so the results map has entries for all deps let depresults :: [b] depresults =- map (\ipkgid -> let Just result = Map.lookup ipkgid results+ map (\ipkgid -> let result = Map.findWithDefault (error "foldMInstallPlanDepOrder") ipkgid results in result) (InstallPlan.depends pkg) result <- visit pkg depresults@@ -591,7 +577,7 @@ createDirectoryIfMissingVerbose verbosity True distBuildRootDirectory createDirectoryIfMissingVerbose verbosity True distTempDirectory- mapM_ (createPackageDBIfMissing verbosity compiler progdb) packageDBsToUse+ traverse_ (createPackageDBIfMissing verbosity compiler progdb) packageDBsToUse -- Before traversing the install plan, pre-emptively find all packages that -- will need to be downloaded and start downloading them.@@ -606,7 +592,7 @@ handle (\(e :: BuildFailure) -> return (Left e)) $ fmap Right $ let uid = installedUnitId pkg- Just pkgBuildStatus = Map.lookup uid pkgsBuildStatus in+ pkgBuildStatus = Map.findWithDefault (error "rebuildTargets") uid pkgsBuildStatus in rebuildTarget verbosity@@ -766,7 +752,7 @@ | InstallPlan.Configured elab <- InstallPlan.reverseTopologicalOrder installPlan , let uid = installedUnitId elab- Just pkgBuildStatus = Map.lookup uid pkgsBuildStatus+ pkgBuildStatus = Map.findWithDefault (error "asyncDownloadPackages") uid pkgsBuildStatus , BuildStatusDownload <- [pkgBuildStatus] ] @@ -1014,7 +1000,7 @@ listFilesRecursive :: FilePath -> IO [FilePath] listFilesRecursive path = do files <- fmap (path </>) <$> (listDirectory path)- allFiles <- forM files $ \file -> do+ allFiles <- for files $ \file -> do isDir <- doesDirectoryExist file if isDir then listFilesRecursive file@@ -1236,7 +1222,7 @@ execRebuild srcdir (needElaboratedConfiguredPackage pkg) listSdist = fmap (map monitorFileHashed) $- allPackageSourceFiles verbosity scriptOptions srcdir+ allPackageSourceFiles verbosity srcdir ifNullThen m m' = do xs <- m if null xs then m' else return xs monitors <- case PD.buildType (elabPkgDescription pkg) of@@ -1448,11 +1434,10 @@ ++ show perror readPkgConf pkgConfDir pkgConfFile = do- (warns, ipkg) <-- withUTF8FileContents (pkgConfDir </> pkgConfFile) $ \pkgConfStr ->- case Installed.parseInstalledPackageInfo pkgConfStr of- Left perrors -> pkgConfParseFailed $ unlines $ NE.toList perrors- Right (warns, ipkg) -> return (warns, ipkg)+ pkgConfStr <- BS.readFile (pkgConfDir </> pkgConfFile)+ (warns, ipkg) <- case Installed.parseInstalledPackageInfo pkgConfStr of+ Left perrors -> pkgConfParseFailed $ unlines $ NE.toList perrors+ Right (warns, ipkg) -> return (warns, ipkg) unless (null warns) $ warn verbosity $ unlines warns
cabal/cabal-install/Distribution/Client/ProjectBuilding/Types.hs view
@@ -22,17 +22,15 @@ BuildFailureReason(..), ) where +import Distribution.Client.Compat.Prelude+import Prelude ()+ import Distribution.Client.Types (DocsResult, TestsResult) import Distribution.Client.FileMonitor (MonitorChangedReason(..)) import Distribution.Package (UnitId, PackageId) import Distribution.InstalledPackageInfo (InstalledPackageInfo) import Distribution.Simple.LocalBuildInfo (ComponentName)--import Data.Map (Map)-import Data.Set (Set)-import Data.Typeable (Typeable)-import Control.Exception (Exception, SomeException) ------------------------------------------------------------------------------
cabal/cabal-install/Distribution/Client/ProjectConfig.hs view
@@ -1,6 +1,7 @@ {-# LANGUAGE BangPatterns #-} {-# LANGUAGE CPP #-} {-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE RecordWildCards #-}@@ -87,7 +88,7 @@ ( PackageProperty(..) ) import Distribution.Package- ( PackageName, PackageId, packageId, UnitId )+ ( PackageName, PackageId, UnitId, packageId ) import Distribution.Types.PackageVersionConstraint ( PackageVersionConstraint(..) ) import Distribution.System@@ -98,10 +99,9 @@ ( parseGenericPackageDescription ) import Distribution.Fields ( runParseResult, PError, PWarning, showPWarning)-import Distribution.Pretty () import Distribution.Types.SourceRepo ( RepoType(..) )-import Distribution.Client.SourceRepo+import Distribution.Client.Types.SourceRepo ( SourceRepoList, SourceRepositoryPackage (..), srpFanOut ) import Distribution.Simple.Compiler ( Compiler, compilerInfo )@@ -122,22 +122,20 @@ import Distribution.Utils.NubList ( fromNubList ) import Distribution.Verbosity- ( Verbosity, modifyVerbosity, verbose )+ ( modifyVerbosity, verbose ) import Distribution.Version ( Version )-import Distribution.Deprecated.Text import qualified Distribution.Deprecated.ParseUtils as OldParser ( ParseResult(..), locatedErrorMsg, showPWarning )+import Distribution.Client.SrcDist+ ( packageDirToSdist ) import qualified Codec.Archive.Tar as Tar import qualified Codec.Archive.Tar.Entry as Tar import qualified Distribution.Client.Tar as Tar import qualified Distribution.Client.GZipUtils as GZipUtils -import Control.Monad import Control.Monad.Trans (liftIO)-import Control.Exception-import Data.Either import qualified Data.ByteString as BS import qualified Data.ByteString.Lazy as LBS import qualified Data.Map as Map@@ -184,7 +182,7 @@ withRepoContext' verbosity buildSettingRemoteRepos- buildSettingLocalRepos+ buildSettingLocalNoIndexRepos buildSettingCacheDir buildSettingHttpTransport (Just buildSettingIgnoreExpiry)@@ -206,7 +204,7 @@ withRepoContext' verbosity (fromNubList projectConfigRemoteRepos)- (fromNubList projectConfigLocalRepos)+ (fromNubList projectConfigLocalNoIndexRepos) (fromFlagOrDefault (error "projectConfigWithSolverRepoContext: projectConfigCacheDir")@@ -230,7 +228,7 @@ --TODO: [required eventually] some of these settings need validation, e.g. -- the flag assignments need checking. solverSettingRemoteRepos = fromNubList projectConfigRemoteRepos- solverSettingLocalRepos = fromNubList projectConfigLocalRepos+ solverSettingLocalNoIndexRepos = fromNubList projectConfigLocalNoIndexRepos solverSettingConstraints = projectConfigConstraints solverSettingPreferences = projectConfigPreferences solverSettingFlagAssignment = packageConfigFlagAssignment projectConfigLocalPackages@@ -245,11 +243,13 @@ | otherwise -> Just n solverSettingReorderGoals = fromFlag projectConfigReorderGoals solverSettingCountConflicts = fromFlag projectConfigCountConflicts+ solverSettingFineGrainedConflicts = fromFlag projectConfigFineGrainedConflicts solverSettingMinimizeConflictSet = fromFlag projectConfigMinimizeConflictSet solverSettingStrongFlags = fromFlag projectConfigStrongFlags solverSettingAllowBootLibInstalls = fromFlag projectConfigAllowBootLibInstalls solverSettingOnlyConstrained = fromFlag projectConfigOnlyConstrained solverSettingIndexState = flagToMaybe projectConfigIndexState+ solverSettingActiveRepos = flagToMaybe projectConfigActiveRepos solverSettingIndependentGoals = fromFlag projectConfigIndependentGoals --solverSettingShadowPkgs = fromFlag projectConfigShadowPkgs --solverSettingReinstall = fromFlag projectConfigReinstall@@ -266,6 +266,7 @@ projectConfigMaxBackjumps = Flag defaultMaxBackjumps, projectConfigReorderGoals = Flag (ReorderGoals False), projectConfigCountConflicts = Flag (CountConflicts True),+ projectConfigFineGrainedConflicts = Flag (FineGrainedConflicts True), projectConfigMinimizeConflictSet = Flag (MinimizeConflictSet False), projectConfigStrongFlags = Flag (StrongFlags False), projectConfigAllowBootLibInstalls = Flag (AllowBootLibInstalls False),@@ -293,7 +294,7 @@ ProjectConfig { projectConfigShared = ProjectConfigShared { projectConfigRemoteRepos,- projectConfigLocalRepos,+ projectConfigLocalNoIndexRepos, projectConfigProgPathExtra }, projectConfigBuildOnly@@ -313,7 +314,7 @@ buildSettingOfflineMode = fromFlag projectConfigOfflineMode buildSettingKeepTempFiles = fromFlag projectConfigKeepTempFiles buildSettingRemoteRepos = fromNubList projectConfigRemoteRepos- buildSettingLocalRepos = fromNubList projectConfigLocalRepos+ buildSettingLocalNoIndexRepos = fromNubList projectConfigLocalNoIndexRepos buildSettingCacheDir = fromFlag projectConfigCacheDir buildSettingHttpTransport = flagToMaybe projectConfigHttpTransport buildSettingIgnoreExpiry = fromFlag projectConfigIgnoreExpiry@@ -429,9 +430,6 @@ then return (Right (ProjectRootExplicit dir projectFileName)) else go (takeDirectory dir) - --TODO: [nice to have] add compat support for old style sandboxes-- -- | Errors returned by 'findProjectRoot'. -- data BadProjectRoot = BadProjectRootExplicitFile FilePath@@ -453,12 +451,26 @@ renderBadProjectRoot (BadProjectRootExplicitFile projectFile) = "The given project file '" ++ projectFile ++ "' does not exist." -withProjectOrGlobalConfig :: Verbosity- -> Flag FilePath- -> IO a- -> (ProjectConfig -> IO a)- -> IO a-withProjectOrGlobalConfig verbosity globalConfigFlag with without = do+withProjectOrGlobalConfig+ :: Verbosity -- ^ verbosity+ -> Flag Bool -- ^ whether to ignore local project+ -> Flag FilePath -- ^ @--cabal-config@+ -> IO a -- ^ with project+ -> (ProjectConfig -> IO a) -- ^ without projet+ -> IO a+withProjectOrGlobalConfig verbosity (Flag True) gcf _with without = do+ globalConfig <- runRebuild "" $ readGlobalConfig verbosity gcf+ without globalConfig+withProjectOrGlobalConfig verbosity _ignorePrj gcf with without =+ withProjectOrGlobalConfig' verbosity gcf with without++withProjectOrGlobalConfig'+ :: Verbosity+ -> Flag FilePath+ -> IO a+ -> (ProjectConfig -> IO a)+ -> IO a+withProjectOrGlobalConfig' verbosity globalConfigFlag with without = do globalConfig <- runRebuild "" $ readGlobalConfig verbosity globalConfigFlag let@@ -517,9 +529,6 @@ -- We expect a package in the current directory. projectPackages = [ "./*.cabal" ], - -- This is to automatically pick up deps that we unpack locally.- projectPackagesOptional = [ "./*/*.cabal" ],- projectConfigProvenance = Set.singleton Implicit } @@ -797,7 +806,7 @@ where findPackageLocations required pkglocstr = do (problems, pkglocs) <-- partitionEithers <$> mapM (findPackageLocation required) pkglocstr+ partitionEithers <$> traverse (findPackageLocation required) pkglocstr unless (null problems) $ liftIO $ throwIO $ BadPackageLocations projectConfigProvenance problems return (concat pkglocs)@@ -856,7 +865,7 @@ checkIsFileGlobPackage pkglocstr =- case simpleParse pkglocstr of+ case simpleParsec pkglocstr of Nothing -> return Nothing Just glob -> liftM Just $ do matches <- matchFileGlob glob@@ -869,7 +878,7 @@ _ -> do (failures, pkglocs) <- partitionEithers <$>- mapM checkFilePackageMatch matches+ traverse checkFilePackageMatch matches return $! case (failures, pkglocs) of ([failure], []) | isJust (isTrivialFilePathGlob glob) -> Left (BadPackageLocationFile failure)@@ -977,13 +986,13 @@ pkgLocations = do pkgsLocalDirectory <-- sequence+ sequenceA [ readSourcePackageLocalDirectory verbosity dir cabalFile | location <- pkgLocations , (dir, cabalFile) <- projectPackageLocal location ] pkgsLocalTarball <-- sequence+ sequenceA [ readSourcePackageLocalTarball verbosity path | ProjectPackageLocalTarball path <- pkgLocations ] @@ -991,7 +1000,7 @@ getTransport <- delayInitSharedResource $ configureTransport verbosity progPathExtra preferredHttpTransport- sequence+ sequenceA [ fetchAndReadSourcePackageRemoteTarball verbosity distDirLayout getTransport uri | ProjectPackageRemoteTarball uri <- pkgLocations ]@@ -1057,7 +1066,6 @@ . uncurry (readSourcePackageCabalFile verbosity) =<< extractTarballPackageCabalFile (root </> tarballFile) - -- | A helper for 'fetchAndReadSourcePackages' to handle the case of -- 'ProjectPackageRemoteTarball'. We download the tarball to the dist src dir -- and after that handle it like the local tarball case.@@ -1133,10 +1141,10 @@ --TODO: pass progPathExtra on to 'configureVCS' let _progPathExtra = fromNubList projectConfigProgPathExtra getConfiguredVCS <- delayInitSharedResources $ \repoType ->- let Just vcs = Map.lookup repoType knownVCSs in+ let vcs = Map.findWithDefault (error $ "Unknown VCS: " ++ prettyShow repoType) repoType knownVCSs in configureVCS verbosity {-progPathExtra-} vcs - concat <$> sequence+ concat <$> sequenceA [ rerunIfChanged verbosity monitor repoGroup' $ do vcs' <- getConfiguredVCS repoType syncRepoGroupAndReadSourcePackages vcs' pathStem repoGroup'@@ -1164,10 +1172,11 @@ syncSourceRepos verbosity vcs [ (repo, repoPath) | (repo, _, repoPath) <- repoGroupWithPaths ]+ -- TODO phadej 2020-06-18 add post-sync script -- But for reading we go through each 'SourceRepo' including its subdir -- value and have to know which path each one ended up in.- sequence+ sequenceA [ readPackageFromSourceRepo repoWithSubdir repoPath | (_, reposWithSubdir, repoPath) <- repoGroupWithPaths , repoWithSubdir <- NE.toList reposWithSubdir ]@@ -1193,25 +1202,31 @@ : [ pathStem ++ "-" ++ show (i :: Int) | i <- [2..] ] readPackageFromSourceRepo- :: SourceRepositoryPackage Maybe -> FilePath+ :: SourceRepositoryPackage Maybe+ -> FilePath -> Rebuild (PackageSpecifier (SourcePackage UnresolvedPkgLoc)) readPackageFromSourceRepo repo repoPath = do- let packageDir = maybe repoPath (repoPath </>) (srpSubdir repo)+ let packageDir :: FilePath+ packageDir = maybe repoPath (repoPath </>) (srpSubdir repo)+ entries <- liftIO $ getDirectoryContents packageDir- --TODO: wrap exceptions+ --TODO: dcoutts 2018-06-23: wrap exceptions case filter (\e -> takeExtension e == ".cabal") entries of [] -> liftIO $ throwIO $ NoCabalFileFound packageDir (_:_:_) -> liftIO $ throwIO $ MultipleCabalFilesFound packageDir [cabalFileName] -> do+ let cabalFilePath = packageDir </> cabalFileName monitorFiles [monitorFileHashed cabalFilePath]- liftIO $ fmap (mkSpecificSourcePackage location)- . readSourcePackageCabalFile verbosity cabalFilePath- =<< BS.readFile cabalFilePath- where- cabalFilePath = packageDir </> cabalFileName- location = RemoteSourceRepoPackage repo packageDir+ gpd <- liftIO $ readSourcePackageCabalFile verbosity cabalFilePath =<< BS.readFile cabalFilePath + -- write sdist tarball, to repoPath-pgkid+ tarball <- liftIO $ packageDirToSdist verbosity gpd packageDir+ let tarballPath = repoPath ++ "-" ++ prettyShow (packageId gpd) ++ ".tar.gz"+ liftIO $ LBS.writeFile tarballPath tarball + let location = RemoteSourceRepoPackage repo tarballPath+ return $ mkSpecificSourcePackage location gpd+ reportSourceRepoProblems :: [(SourceRepoList, SourceRepoProblem)] -> Rebuild a reportSourceRepoProblems = liftIO . die' verbosity . renderSourceRepoProblems @@ -1225,16 +1240,14 @@ -- mkSpecificSourcePackage :: PackageLocation FilePath -> GenericPackageDescription- -> PackageSpecifier- (SourcePackage (PackageLocation (Maybe FilePath)))+ -> PackageSpecifier (SourcePackage UnresolvedPkgLoc) mkSpecificSourcePackage location pkg =- SpecificSourcePackage SourcePackage {- packageInfoId = packageId pkg,- packageDescription = pkg,- --TODO: it is silly that we still have to use a Maybe FilePath here- packageSource = fmap Just location,- packageDescrOverride = Nothing- }+ SpecificSourcePackage SourcePackage+ { srcpkgPackageId = packageId pkg+ , srcpkgDescription = pkg+ , srcpkgSource = fmap Just location+ , srcpkgDescrOverride = Nothing+ } -- | Errors reported upon failing to parse a @.cabal@ file.@@ -1422,7 +1435,7 @@ "The path to the compiler program (or programs used by the compiler) " ++ "cannot be specified on a per-package basis in the cabal.project file " ++ "(i.e. setting the '" ++ progname ++ "-location' for package '"- ++ display pkgname ++ "'). All packages have to use the same compiler, so "+ ++ prettyShow pkgname ++ "'). All packages have to use the same compiler, so " ++ "specify the path in a global 'program-locations' section." --TODO: [nice to have] better format control so we can pretty-print the -- offending part of the project file. Currently the line wrapping breaks any
cabal/cabal-install/Distribution/Client/ProjectConfig/Legacy.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE RecordWildCards, NamedFieldPuns, DeriveGeneric #-}+{-# LANGUAGE RecordWildCards, NamedFieldPuns, DeriveGeneric, ConstraintKinds #-} -- | Project configuration, implementation in terms of legacy types. --@@ -23,16 +23,16 @@ import Prelude () import Distribution.Client.Compat.Prelude -import Distribution.Deprecated.ParseUtils (parseFlagAssignment)+import Distribution.Types.Flag (parsecFlagAssignment) import Distribution.Client.ProjectConfig.Types-import Distribution.Client.Types- ( RemoteRepo(..), emptyRemoteRepo- , AllowNewer(..), AllowOlder(..) )-import Distribution.Client.SourceRepo (sourceRepositoryPackageGrammar, SourceRepoList)+import Distribution.Client.Types.RepoName (RepoName (..), unRepoName)+import Distribution.Client.Types.Repo (RemoteRepo(..), LocalRepo (..), emptyRemoteRepo)+import Distribution.Client.Types.AllowNewer (AllowNewer(..), AllowOlder(..))+import Distribution.Client.Types.SourceRepo (sourceRepositoryPackageGrammar, SourceRepoList) import Distribution.Client.Config- ( SavedConfig(..), remoteRepoFields )+ ( SavedConfig(..), remoteRepoFields, postProcessRepo ) import Distribution.Client.CmdInstall.ClientInstallFlags ( ClientInstallFlags(..), defaultClientInstallFlags@@ -40,7 +40,9 @@ import Distribution.Solver.Types.ConstraintSource +import Distribution.FieldGrammar import Distribution.Package+import Distribution.Types.SourceRepo (RepoType) import Distribution.PackageDescription ( dispFlagAssignment ) import Distribution.Simple.Compiler@@ -54,6 +56,8 @@ , BenchmarkFlags(..), benchmarkOptions', defaultBenchmarkFlags , programDbPaths', splitArgs )+import Distribution.Client.NixStyleOptions (NixStyleFlags (..))+import Distribution.Client.ProjectFlags (ProjectFlags (..), projectFlagsOptions, defaultProjectFlags) import Distribution.Client.Setup ( GlobalFlags(..), globalCommand , ConfigExFlags(..), configureExOptions, defaultConfigExFlags@@ -69,27 +73,31 @@ import Distribution.Simple.LocalBuildInfo ( toPathTemplate, fromPathTemplate ) -import Distribution.Deprecated.Text import qualified Distribution.Deprecated.ReadP as Parse import Distribution.Deprecated.ReadP ( ReadP, (+++) ) import qualified Text.PrettyPrint as Disp import Text.PrettyPrint ( Doc, ($+$) )-import qualified Distribution.Deprecated.ParseUtils as ParseUtils (field)+import qualified Distribution.Deprecated.ParseUtils as ParseUtils import Distribution.Deprecated.ParseUtils- ( ParseResult(..), PError(..), syntaxError, PWarning(..), warning- , simpleField, commaNewLineListField, newLineListField, parseTokenQ- , parseHaskellString, showToken )+ ( ParseResult(..), PError(..), syntaxError, PWarning(..)+ , commaNewLineListFieldParsec, newLineListField, parseTokenQ+ , parseHaskellString, showToken + , simpleFieldParsec+ ) import Distribution.Client.ParseUtils import Distribution.Simple.Command ( CommandUI(commandOptions), ShowOrParseArgs(..) , OptionField, option, reqArg' ) import Distribution.Types.PackageVersionConstraint ( PackageVersionConstraint )+import Distribution.Parsec (ParsecParser) import qualified Data.Map as Map +import Network.URI (URI (..))+ ------------------------------------------------------------------ -- Representing the project config file in terms of legacy types --@@ -142,7 +150,8 @@ legacyConfigureShFlags :: ConfigFlags, legacyConfigureExFlags :: ConfigExFlags, legacyInstallFlags :: InstallFlags,- legacyClientInstallFlags:: ClientInstallFlags+ legacyClientInstallFlags:: ClientInstallFlags,+ legacyProjectFlags :: ProjectFlags } deriving Generic instance Monoid LegacySharedConfig where@@ -165,15 +174,10 @@ -- 'LegacyProjectConfig' for an explanation. -- commandLineFlagsToProjectConfig :: GlobalFlags- -> ConfigFlags -> ConfigExFlags- -> InstallFlags -> ClientInstallFlags- -> HaddockFlags- -> TestFlags- -> BenchmarkFlags+ -> NixStyleFlags a+ -> ClientInstallFlags -> ProjectConfig-commandLineFlagsToProjectConfig globalFlags configFlags configExFlags- installFlags clientInstallFlags- haddockFlags testFlags benchmarkFlags =+commandLineFlagsToProjectConfig globalFlags NixStyleFlags {..} clientInstallFlags = mempty { projectConfigBuildOnly = convertLegacyBuildOnlyFlags globalFlags configFlags@@ -181,7 +185,7 @@ haddockFlags testFlags benchmarkFlags, projectConfigShared = convertLegacyAllPackageFlags globalFlags configFlags- configExFlags installFlags,+ configExFlags installFlags projectFlags, projectConfigLocalPackages = localConfig, projectConfigAllPackages = allConfig }@@ -235,7 +239,8 @@ savedReportFlags = _, savedHaddockFlags = haddockFlags, savedTestFlags = testFlags,- savedBenchmarkFlags = benchmarkFlags+ savedBenchmarkFlags = benchmarkFlags,+ savedProjectFlags = projectFlags } = mempty { projectConfigBuildOnly = configBuildOnly,@@ -251,13 +256,14 @@ haddockFlags' = defaultHaddockFlags <> haddockFlags testFlags' = defaultTestFlags <> testFlags benchmarkFlags' = defaultBenchmarkFlags <> benchmarkFlags+ projectFlags' = defaultProjectFlags <> projectFlags configAllPackages = convertLegacyPerPackageFlags configFlags installFlags' haddockFlags' testFlags' benchmarkFlags' configShared = convertLegacyAllPackageFlags globalFlags configFlags- configExFlags' installFlags'+ configExFlags' installFlags' projectFlags' configBuildOnly = convertLegacyBuildOnlyFlags globalFlags configFlags installFlags' clientInstallFlags'@@ -277,7 +283,7 @@ legacyPackagesNamed, legacySharedConfig = LegacySharedConfig globalFlags configShFlags configExFlags installSharedFlags- clientInstallFlags,+ clientInstallFlags projectFlags, legacyAllConfig, legacyLocalConfig = LegacyPackageConfig configFlags installPerPkgFlags haddockFlags testFlags benchmarkFlags,@@ -305,7 +311,7 @@ testFlags benchmarkFlags configPackagesShared= convertLegacyAllPackageFlags globalFlags (configFlags <> configShFlags)- configExFlags installSharedFlags+ configExFlags installSharedFlags projectFlags configBuildOnly = convertLegacyBuildOnlyFlags globalFlags configShFlags installSharedFlags clientInstallFlags@@ -322,18 +328,21 @@ -- | Helper used by other conversion functions that returns the -- 'ProjectConfigShared' subset of the 'ProjectConfig'. ---convertLegacyAllPackageFlags :: GlobalFlags -> ConfigFlags- -> ConfigExFlags -> InstallFlags- -> ProjectConfigShared-convertLegacyAllPackageFlags globalFlags configFlags- configExFlags installFlags =+convertLegacyAllPackageFlags+ :: GlobalFlags+ -> ConfigFlags+ -> ConfigExFlags+ -> InstallFlags+ -> ProjectFlags+ -> ProjectConfigShared+convertLegacyAllPackageFlags globalFlags configFlags configExFlags installFlags projectFlags = ProjectConfigShared{..} where GlobalFlags { globalConfigFile = projectConfigConfigFile,- globalSandboxConfigFile = _, -- ?? globalRemoteRepos = projectConfigRemoteRepos,- globalLocalRepos = projectConfigLocalRepos,+ globalLocalNoIndexRepos = projectConfigLocalNoIndexRepos,+ globalActiveRepos = projectConfigActiveRepos, globalProgPathExtra = projectConfigProgPathExtra, globalStoreDir = projectConfigStoreDir } = globalFlags@@ -361,7 +370,6 @@ } = configExFlags InstallFlags {- installProjectFileName = projectConfigProjectFile, installHaddockIndex = projectConfigHaddockIndex, --installReinstall = projectConfigReinstall, --installAvoidReinstalls = projectConfigAvoidReinstalls,@@ -371,6 +379,7 @@ --installUpgradeDeps = projectConfigUpgradeDeps, installReorderGoals = projectConfigReorderGoals, installCountConflicts = projectConfigCountConflicts,+ installFineGrainedConflicts = projectConfigFineGrainedConflicts, installMinimizeConflictSet = projectConfigMinimizeConflictSet, installPerComponent = projectConfigPerComponent, installIndependentGoals = projectConfigIndependentGoals,@@ -380,7 +389,10 @@ installOnlyConstrained = projectConfigOnlyConstrained } = installFlags -+ ProjectFlags+ { flagProjectFileName = projectConfigProjectFile+ , flagIgnoreProject = projectConfigIgnoreProject+ } = projectFlags -- | Helper used by other conversion functions that returns the -- 'PackageConfig' subset of the 'ProjectConfig'.@@ -551,27 +563,26 @@ } } = - LegacySharedConfig {- legacyGlobalFlags = globalFlags,- legacyConfigureShFlags = configFlags,- legacyConfigureExFlags = configExFlags,- legacyInstallFlags = installFlags,- legacyClientInstallFlags = projectConfigClientInstallFlags- }+ LegacySharedConfig+ { legacyGlobalFlags = globalFlags+ , legacyConfigureShFlags = configFlags+ , legacyConfigureExFlags = configExFlags+ , legacyInstallFlags = installFlags+ , legacyClientInstallFlags = projectConfigClientInstallFlags+ , legacyProjectFlags = projectFlags+ } where globalFlags = GlobalFlags { globalVersion = mempty, globalNumericVersion = mempty, globalConfigFile = projectConfigConfigFile,- globalSandboxConfigFile = mempty, globalConstraintsFile = mempty, globalRemoteRepos = projectConfigRemoteRepos, globalCacheDir = projectConfigCacheDir,- globalLocalRepos = projectConfigLocalRepos,+ globalLocalNoIndexRepos = projectConfigLocalNoIndexRepos,+ globalActiveRepos = projectConfigActiveRepos, globalLogsDir = projectConfigLogsDir, globalWorldFile = mempty,- globalRequireSandbox = mempty,- globalIgnoreSandbox = mempty, globalIgnoreExpiry = projectConfigIgnoreExpiry, globalHttpTransport = projectConfigHttpTransport, globalNix = mempty,@@ -607,6 +618,7 @@ installUpgradeDeps = mempty, --projectConfigUpgradeDeps, installReorderGoals = projectConfigReorderGoals, installCountConflicts = projectConfigCountConflicts,+ installFineGrainedConflicts = projectConfigFineGrainedConflicts, installMinimizeConflictSet = projectConfigMinimizeConflictSet, installIndependentGoals = projectConfigIndependentGoals, installShadowPkgs = mempty, --projectConfigShadowPkgs,@@ -627,11 +639,15 @@ installNumJobs = projectConfigNumJobs, installKeepGoing = projectConfigKeepGoing, installRunTests = mempty,- installOfflineMode = projectConfigOfflineMode,- installProjectFileName = projectConfigProjectFile+ installOfflineMode = projectConfigOfflineMode } + projectFlags = ProjectFlags+ { flagProjectFileName = projectConfigProjectFile+ , flagIgnoreProject = projectConfigIgnoreProject+ } + convertToLegacyAllPackageConfig :: ProjectConfig -> LegacyPackageConfig convertToLegacyAllPackageConfig ProjectConfig {@@ -856,8 +872,8 @@ (Disp.text . renderPackageLocationToken) parsePackageLocationTokenQ legacyPackagesOptional (\v flags -> flags { legacyPackagesOptional = v })- , commaNewLineListField "extra-packages"- disp parse+ , commaNewLineListFieldParsec "extra-packages"+ pretty parsec legacyPackagesNamed (\v flags -> flags { legacyPackagesNamed = v }) ]@@ -925,17 +941,12 @@ legacySharedConfigFieldDescrs :: [FieldDescr LegacySharedConfig]-legacySharedConfigFieldDescrs =-- ( liftFields+legacySharedConfigFieldDescrs = concat+ [ liftFields legacyGlobalFlags (\flags conf -> conf { legacyGlobalFlags = flags }) . addFields- [ newLineListField "local-repo"- showTokenQ parseTokenQ- (fromNubList . globalLocalRepos)- (\v conf -> conf { globalLocalRepos = toNubList v }),- newLineListField "extra-prog-path-shared-only"+ [ newLineListField "extra-prog-path-shared-only" showTokenQ parseTokenQ (fromNubList . globalProgPathExtra) (\v conf -> conf { globalProgPathExtra = toNubList v })@@ -943,36 +954,37 @@ . filterFields [ "remote-repo-cache" , "logs-dir", "store-dir", "ignore-expiry", "http-transport"+ , "active-repositories" ] . commandOptionsToFields- ) (commandOptions (globalCommand []) ParseArgs)- ++- ( liftFields+ $ commandOptions (globalCommand []) ParseArgs++ , liftFields legacyConfigureShFlags (\flags conf -> conf { legacyConfigureShFlags = flags }) . filterFields ["verbose", "builddir" ] . commandOptionsToFields- ) (configureOptions ParseArgs)- ++- ( liftFields+ $ configureOptions ParseArgs++ , liftFields legacyConfigureExFlags (\flags conf -> conf { legacyConfigureExFlags = flags }) . addFields- [ commaNewLineListField "constraints"- (disp . fst) (fmap (\constraint -> (constraint, constraintSrc)) parse)+ [ commaNewLineListFieldParsec "constraints"+ (pretty . fst) (fmap (\constraint -> (constraint, constraintSrc)) parsec) configExConstraints (\v conf -> conf { configExConstraints = v }) - , commaNewLineListField "preferences"- disp parse+ , commaNewLineListFieldParsec "preferences"+ pretty parsec configPreferences (\v conf -> conf { configPreferences = v }) - , monoidField "allow-older"- (maybe mempty disp) (fmap Just parse)+ , monoidFieldParsec "allow-older"+ (maybe mempty pretty) (fmap Just parsec) (fmap unAllowOlder . configAllowOlder) (\v conf -> conf { configAllowOlder = fmap AllowOlder v }) - , monoidField "allow-newer"- (maybe mempty disp) (fmap Just parse)+ , monoidFieldParsec "allow-newer"+ (maybe mempty pretty) (fmap Just parsec) (fmap unAllowNewer . configAllowNewer) (\v conf -> conf { configAllowNewer = fmap AllowNewer v }) ]@@ -981,9 +993,9 @@ -- not "constraint" or "preference", we use our own plural ones above ] . commandOptionsToFields- ) (configureExOptions ParseArgs constraintSrc)- ++- ( liftFields+ $ configureExOptions ParseArgs constraintSrc++ , liftFields legacyInstallFlags (\flags conf -> conf { legacyInstallFlags = flags }) . addFields@@ -1000,19 +1012,28 @@ , "one-shot", "jobs", "keep-going", "offline", "per-component" -- solver flags: , "max-backjumps", "reorder-goals", "count-conflicts"- , "minimize-conflict-set", "independent-goals"- , "strong-flags" , "allow-boot-library-installs", "reject-unconstrained-dependencies", "index-state"+ , "fine-grained-conflicts" , "minimize-conflict-set", "independent-goals"+ , "strong-flags" , "allow-boot-library-installs"+ , "reject-unconstrained-dependencies", "index-state" ] . commandOptionsToFields- ) (installOptions ParseArgs)- ++- ( liftFields+ $ installOptions ParseArgs++ , liftFields legacyClientInstallFlags (\flags conf -> conf { legacyClientInstallFlags = flags }) . commandOptionsToFields- ) (clientInstallOptions ParseArgs)+ $ clientInstallOptions ParseArgs++ , liftFields+ legacyProjectFlags+ (\flags conf -> conf { legacyProjectFlags = flags })+ . commandOptionsToFields+ $ projectFlagsOptions ParseArgs++ ] where- constraintSrc = ConstraintSourceProjectConfig "TODO"+ constraintSrc = ConstraintSourceProjectConfig "TODO" -- TODO: is a filepath legacyPackageConfigFieldDescrs :: [FieldDescr LegacyPackageConfig]@@ -1041,8 +1062,8 @@ showTokenQ parseTokenQ configConfigureArgs (\v conf -> conf { configConfigureArgs = v })- , simpleField "flags"- dispFlagAssignment parseFlagAssignment+ , simpleFieldParsec "flags"+ dispFlagAssignment parsecFlagAssignment configConfigurationsFlags (\v conf -> conf { configConfigurationsFlags = v }) ]@@ -1088,9 +1109,9 @@ . mapFieldNames ("haddock-"++) . addFields- [ simpleField "for-hackage"+ [ simpleFieldParsec "for-hackage" -- TODO: turn this into a library function- (fromFlagOrDefault Disp.empty . fmap disp) (Parse.option mempty (fmap toFlag parse))+ (fromFlagOrDefault Disp.empty . fmap pretty) (toFlag <$> parsec <|> pure mempty) haddockForHackage (\v conf -> conf { haddockForHackage = v }) ] . filterFields@@ -1137,9 +1158,9 @@ where overrideFieldCompiler =- simpleField "compiler"- (fromFlagOrDefault Disp.empty . fmap disp)- (Parse.option mempty (fmap toFlag parse))+ simpleFieldParsec "compiler"+ (fromFlagOrDefault Disp.empty . fmap pretty)+ (toFlag <$> parsec <|> pure mempty) configHcFlavor (\v flags -> flags { configHcFlavor = v }) @@ -1201,7 +1222,11 @@ | otherwise = "test-" ++ name -legacyPackageConfigFGSectionDescrs :: [FGSectionDescr LegacyProjectConfig]+legacyPackageConfigFGSectionDescrs+ :: ( FieldGrammar c g, Applicative (g SourceRepoList)+ , c (Identity RepoType), c (List NoCommaFSep FilePathNT String)+ )+ => [FGSectionDescr g LegacyProjectConfig] legacyPackageConfigFGSectionDescrs = [ packageRepoSectionDescr ]@@ -1226,7 +1251,11 @@ remoteRepoSectionDescr ] -packageRepoSectionDescr :: FGSectionDescr LegacyProjectConfig+packageRepoSectionDescr+ :: ( FieldGrammar c g, Applicative (g SourceRepoList)+ , c (Identity RepoType), c (List NoCommaFSep FilePathNT String)+ )+ => FGSectionDescr g LegacyProjectConfig packageRepoSectionDescr = FGSectionDescr { fgSectionName = "source-repository-package" , fgSectionGrammar = sourceRepositoryPackageGrammar@@ -1273,7 +1302,7 @@ sectionFields = packageSpecificOptionsFieldDescrs, sectionSubsections = [], sectionGet = \projconf ->- [ (display pkgname, pkgconf)+ [ (prettyShow pkgname, pkgconf) | (pkgname, pkgconf) <- Map.toList . getMapMappend . legacySpecificConfig $ projconf ]@@ -1284,7 +1313,7 @@ legacyAllConfig = legacyAllConfig projconf <> pkgconf } _ -> do- pkgname <- case simpleParse pkgnamestr of+ pkgname <- case simpleParsec pkgnamestr of Just pkgname -> return pkgname Nothing -> syntaxError lineno $ "a 'package' section requires a package name "@@ -1385,47 +1414,51 @@ | otherwise = arg +-- The implementation is slight hack: we parse all as remote repository+-- but if the url schema is file+noindex, we switch to local. remoteRepoSectionDescr :: SectionDescr GlobalFlags-remoteRepoSectionDescr =- SectionDescr {- sectionName = "repository",- sectionFields = remoteRepoFields,- sectionSubsections = [],- sectionGet = map (\x->(remoteRepoName x, x)) . fromNubList- . globalRemoteRepos,- sectionSet =- \lineno reponame repo0 conf -> do- when (null reponame) $- syntaxError lineno $ "a 'repository' section requires the "- ++ "repository name as an argument"- let repo = repo0 { remoteRepoName = reponame }- when (remoteRepoKeyThreshold repo- > length (remoteRepoRootKeys repo)) $- warning $ "'key-threshold' for repository "- ++ show (remoteRepoName repo)- ++ " higher than number of keys"- when (not (null (remoteRepoRootKeys repo))- && remoteRepoSecure repo /= Just True) $- warning $ "'root-keys' for repository "- ++ show (remoteRepoName repo)- ++ " non-empty, but 'secure' not set to True."- return conf {- globalRemoteRepos = overNubList (++[repo]) (globalRemoteRepos conf)- },- sectionEmpty = emptyRemoteRepo ""+remoteRepoSectionDescr = SectionDescr+ { sectionName = "repository"+ , sectionEmpty = emptyRemoteRepo (RepoName "")+ , sectionFields = remoteRepoFields+ , sectionSubsections = []+ , sectionGet = getS+ , sectionSet = setS }+ where+ getS :: GlobalFlags -> [(String, RemoteRepo)]+ getS gf =+ map (\x->(unRepoName $ remoteRepoName x, x)) (fromNubList (globalRemoteRepos gf))+ +++ map (\x->(unRepoName $ localRepoName x, localToRemote x)) (fromNubList (globalLocalNoIndexRepos gf)) + setS :: Int -> String -> RemoteRepo -> GlobalFlags -> ParseResult GlobalFlags+ setS lineno reponame repo0 conf = do+ repo1 <- postProcessRepo lineno reponame repo0+ case repo1 of+ Left repo -> return conf+ { globalLocalNoIndexRepos = overNubList (++[repo]) (globalLocalNoIndexRepos conf)+ }+ Right repo -> return conf+ { globalRemoteRepos = overNubList (++[repo]) (globalRemoteRepos conf)+ } + localToRemote :: LocalRepo -> RemoteRepo+ localToRemote (LocalRepo name path sharedCache) = (emptyRemoteRepo name)+ { remoteRepoURI = URI "file+noindex:" Nothing path "" (if sharedCache then "#shared-cache" else "")+ }+ ------------------------------- -- Local field utils -- -- | Parser combinator for simple fields which uses the field type's -- 'Monoid' instance for combining multiple occurrences of the field.-monoidField :: Monoid a => String -> (a -> Doc) -> ReadP a a- -> (b -> a) -> (a -> b -> b) -> FieldDescr b-monoidField name showF readF get' set =- liftField get' set' $ ParseUtils.field name showF readF+monoidFieldParsec+ :: Monoid a => String -> (a -> Doc) -> ParsecParser a+ -> (b -> a) -> (a -> b -> b) -> FieldDescr b+monoidFieldParsec name showF readF get' set =+ liftField get' set' $ ParseUtils.fieldParsec name showF readF where set' xs b = set (get' b `mappend` xs) b
cabal/cabal-install/Distribution/Client/ProjectConfig/Types.hs view
@@ -20,19 +20,24 @@ MapMappend(..), ) where -import Distribution.Client.Types- ( RemoteRepo, AllowNewer(..), AllowOlder(..)- , WriteGhcEnvironmentFilesPolicy )+import Distribution.Client.Compat.Prelude+import Prelude ()++import Distribution.Client.Types.Repo ( RemoteRepo, LocalRepo )+import Distribution.Client.Types.AllowNewer ( AllowNewer(..), AllowOlder(..) )+import Distribution.Client.Types.WriteGhcEnvironmentFilesPolicy ( WriteGhcEnvironmentFilesPolicy ) import Distribution.Client.Dependency.Types ( PreSolver ) import Distribution.Client.Targets ( UserConstraint ) import Distribution.Client.BuildReports.Types ( ReportLevel(..) )-import Distribution.Client.SourceRepo (SourceRepoList)+import Distribution.Client.Types.SourceRepo (SourceRepoList) -import Distribution.Client.IndexUtils.Timestamp- ( IndexState )+import Distribution.Client.IndexUtils.IndexState+ ( TotalIndexState )+import Distribution.Client.IndexUtils.ActiveRepos+ ( ActiveRepos ) import Distribution.Client.CmdInstall.ClientInstallFlags ( ClientInstallFlags(..) )@@ -59,18 +64,9 @@ ( PathTemplate ) import Distribution.Utils.NubList ( NubList )-import Distribution.Verbosity- ( Verbosity ) -import Data.Map (Map) import qualified Data.Map as Map-import Data.Set (Set)-import Distribution.Compat.Binary (Binary)-import Distribution.Compat.Semigroup-import GHC.Generics (Generic)-import Data.Typeable - ------------------------------- -- Project config types --@@ -167,6 +163,7 @@ projectConfigDistDir :: Flag FilePath, projectConfigConfigFile :: Flag FilePath, projectConfigProjectFile :: Flag FilePath,+ projectConfigIgnoreProject :: Flag Bool, projectConfigHcFlavor :: Flag CompilerFlavor, projectConfigHcPath :: Flag FilePath, projectConfigHcPkg :: Flag FilePath,@@ -182,8 +179,9 @@ -- configuration used both by the solver and other phases projectConfigRemoteRepos :: NubList RemoteRepo, -- ^ Available Hackage servers.- projectConfigLocalRepos :: NubList FilePath,- projectConfigIndexState :: Flag IndexState,+ projectConfigLocalNoIndexRepos :: NubList LocalRepo,+ projectConfigActiveRepos :: Flag ActiveRepos,+ projectConfigIndexState :: Flag TotalIndexState, projectConfigStoreDir :: Flag FilePath, -- solver configuration@@ -198,6 +196,7 @@ projectConfigMaxBackjumps :: Flag Int, projectConfigReorderGoals :: Flag ReorderGoals, projectConfigCountConflicts :: Flag CountConflicts,+ projectConfigFineGrainedConflicts :: Flag FineGrainedConflicts, projectConfigMinimizeConflictSet :: Flag MinimizeConflictSet, projectConfigStrongFlags :: Flag StrongFlags, projectConfigAllowBootLibInstalls :: Flag AllowBootLibInstalls,@@ -306,12 +305,19 @@ instance Binary ProjectConfigProvenance instance Binary PackageConfig +instance Structured ProjectConfig+instance Structured ProjectConfigBuildOnly+instance Structured ProjectConfigShared+instance Structured ProjectConfigProvenance+instance Structured PackageConfig -- | Newtype wrapper for 'Map' that provides a 'Monoid' instance that takes -- the last value rather than the first value for overlapping keys. newtype MapLast k v = MapLast { getMapLast :: Map k v } deriving (Eq, Show, Functor, Generic, Binary, Typeable) +instance (Structured k, Structured v) => Structured (MapLast k v)+ instance Ord k => Monoid (MapLast k v) where mempty = MapLast Map.empty mappend = (<>)@@ -326,6 +332,8 @@ newtype MapMappend k v = MapMappend { getMapMappend :: Map k v } deriving (Eq, Show, Functor, Generic, Binary, Typeable) +instance (Structured k, Structured v) => Structured (MapMappend k v)+ instance (Semigroup v, Ord k) => Monoid (MapMappend k v) where mempty = MapMappend Map.empty mappend = (<>)@@ -381,7 +389,7 @@ data SolverSettings = SolverSettings { solverSettingRemoteRepos :: [RemoteRepo], -- ^ Available Hackage servers.- solverSettingLocalRepos :: [FilePath],+ solverSettingLocalNoIndexRepos :: [LocalRepo], solverSettingConstraints :: [(UserConstraint, ConstraintSource)], solverSettingPreferences :: [PackageVersionConstraint], solverSettingFlagAssignment :: FlagAssignment, -- ^ For all local packages@@ -393,11 +401,13 @@ solverSettingMaxBackjumps :: Maybe Int, solverSettingReorderGoals :: ReorderGoals, solverSettingCountConflicts :: CountConflicts,+ solverSettingFineGrainedConflicts :: FineGrainedConflicts, solverSettingMinimizeConflictSet :: MinimizeConflictSet, solverSettingStrongFlags :: StrongFlags, solverSettingAllowBootLibInstalls :: AllowBootLibInstalls, solverSettingOnlyConstrained :: OnlyConstrained,- solverSettingIndexState :: Maybe IndexState,+ solverSettingIndexState :: Maybe TotalIndexState,+ solverSettingActiveRepos :: Maybe ActiveRepos, solverSettingIndependentGoals :: IndependentGoals -- Things that only make sense for manual mode, not --local mode -- too much control!@@ -410,6 +420,7 @@ deriving (Eq, Show, Generic, Typeable) instance Binary SolverSettings+instance Structured SolverSettings -- | Resolved configuration for things that affect how we build and not the@@ -439,7 +450,7 @@ buildSettingOfflineMode :: Bool, buildSettingKeepTempFiles :: Bool, buildSettingRemoteRepos :: [RemoteRepo],- buildSettingLocalRepos :: [FilePath],+ buildSettingLocalNoIndexRepos :: [LocalRepo], buildSettingCacheDir :: FilePath, buildSettingHttpTransport :: Maybe String, buildSettingIgnoreExpiry :: Bool,
+ cabal/cabal-install/Distribution/Client/ProjectFlags.hs view
@@ -0,0 +1,60 @@+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE OverloadedStrings #-}+module Distribution.Client.ProjectFlags (+ ProjectFlags(..),+ defaultProjectFlags,+ projectFlagsOptions,+) where++import Distribution.Client.Compat.Prelude+import Prelude ()++import Distribution.ReadE (succeedReadE)+import Distribution.Simple.Command (MkOptDescr, OptionField, ShowOrParseArgs (..), boolOpt', option, reqArg)+import Distribution.Simple.Setup (Flag (..), flagToList, flagToMaybe, toFlag, trueArg)++data ProjectFlags = ProjectFlags+ { flagProjectFileName :: Flag FilePath+ -- ^ The cabal project file name; defaults to @cabal.project@.+ -- The name itself denotes the cabal project file name, but it also+ -- is the base of auxiliary project files, such as+ -- @cabal.project.local@ and @cabal.project.freeze@ which are also+ -- read and written out in some cases. If the path is not found+ -- in the current working directory, we will successively probe+ -- relative to parent directories until this name is found.++ , flagIgnoreProject :: Flag Bool+ -- ^ Whether to ignore the local project (i.e. don't search for cabal.project)+ -- The exact interpretation might be slightly different per command.+ }+ deriving (Show, Generic)++defaultProjectFlags :: ProjectFlags+defaultProjectFlags = ProjectFlags+ { flagProjectFileName = mempty+ , flagIgnoreProject = toFlag False+ -- Should we use 'Last' here?+ }++projectFlagsOptions :: ShowOrParseArgs -> [OptionField ProjectFlags]+projectFlagsOptions showOrParseArgs =+ [ option [] ["project-file"]+ "Set the name of the cabal.project file to search for in parent directories"+ flagProjectFileName (\pf flags -> flags { flagProjectFileName = pf })+ (reqArg "FILE" (succeedReadE Flag) flagToList)+ , option ['z'] ["ignore-project"]+ "Ignore local project configuration"+ flagIgnoreProject (\v flags -> flags { flagIgnoreProject = v })+ (yesNoOpt showOrParseArgs)+ ]++instance Monoid ProjectFlags where+ mempty = gmempty+ mappend = (<>)++instance Semigroup ProjectFlags where+ (<>) = gmappend++yesNoOpt :: ShowOrParseArgs -> MkOptDescr (b -> Flag Bool) (Flag Bool -> b -> b) b+yesNoOpt ShowArgs sf lf = trueArg sf lf+yesNoOpt _ sf lf = boolOpt' flagToMaybe Flag (sf, lf) ([], map ("no-" ++) lf) sf lf
cabal/cabal-install/Distribution/Client/ProjectOrchestration.hs view
@@ -43,6 +43,7 @@ -- * Discovery phase: what is in the project? CurrentCommand(..), establishProjectBaseContext,+ establishProjectBaseContextWithRoot, ProjectBaseContext(..), BuildTimeSettings(..), commandLineFlagsToProjectConfig,@@ -67,7 +68,6 @@ ComponentKind(..), ComponentTarget(..), SubComponentTarget(..),- TargetProblemCommon(..), selectComponentTargetBasic, distinctTargetComponents, -- ** Utils for selecting targets@@ -95,6 +95,10 @@ -- * Shared CLI utils cmdCommonHelpTextNewBuildBeta,++ -- * Dummy projects+ establishDummyProjectBaseContext,+ establishDummyDistDirLayout, ) where import Prelude ()@@ -110,7 +114,10 @@ import Distribution.Client.ProjectPlanning.Types import Distribution.Client.ProjectBuilding import Distribution.Client.ProjectPlanOutput+import Distribution.Client.RebuildMonad ( runRebuild ) +import Distribution.Client.TargetProblem+ ( TargetProblem (..) ) import Distribution.Client.Types ( GenericReadyPackage(..), UnresolvedSourcePackage , PackageSpecifier(..)@@ -136,35 +143,29 @@ import Distribution.Solver.Types.OptionalStanza import Distribution.Package-import Distribution.PackageDescription- ( FlagAssignment, unFlagAssignment, showFlagValue- , diffFlagAssignment )+import Distribution.Types.Flag+ ( FlagAssignment, showFlagAssignment, diffFlagAssignment ) import Distribution.Simple.LocalBuildInfo ( ComponentName(..), pkgComponents ) import Distribution.Simple.Flag- ( fromFlagOrDefault )+ ( fromFlagOrDefault, flagToMaybe ) import qualified Distribution.Simple.Setup as Setup import Distribution.Simple.Command (commandShowOptions) import Distribution.Simple.Configure (computeEffectiveProfiling) import Distribution.Simple.Utils- ( die', warn, notice, noticeNoWrap, debugNoWrap )+ ( die', warn, notice, noticeNoWrap, debugNoWrap, createDirectoryIfMissingVerbose ) import Distribution.Verbosity import Distribution.Version ( mkVersion )-import Distribution.Pretty- ( prettyShow ) import Distribution.Simple.Compiler ( compilerCompatVersion, showCompilerId , OptimisationLevel(..)) -import qualified Data.Monoid as Mon import qualified Data.List.NonEmpty as NE import qualified Data.Set as Set import qualified Data.Map as Map-import Data.Either-import Control.Exception (Exception(..), throwIO, assert)-import System.Exit (ExitCode(..), exitFailure)+import Control.Exception (assert) #ifdef MIN_VERSION_unix import System.Posix.Signals (sigKILL, sigSEGV) #endif@@ -187,18 +188,29 @@ currentCommand :: CurrentCommand } -establishProjectBaseContext :: Verbosity- -> ProjectConfig- -> CurrentCommand- -> IO ProjectBaseContext+establishProjectBaseContext+ :: Verbosity+ -> ProjectConfig+ -> CurrentCommand+ -> IO ProjectBaseContext establishProjectBaseContext verbosity cliConfig currentCommand = do+ projectRoot <- either throwIO return =<< findProjectRoot Nothing mprojectFile+ establishProjectBaseContextWithRoot verbosity cliConfig projectRoot currentCommand+ where+ mprojectFile = Setup.flagToMaybe projectConfigProjectFile+ ProjectConfigShared { projectConfigProjectFile } = projectConfigShared cliConfig +-- | Like 'establishProjectBaseContext' but doesn't search for project root.+establishProjectBaseContextWithRoot+ :: Verbosity+ -> ProjectConfig+ -> ProjectRoot+ -> CurrentCommand+ -> IO ProjectBaseContext+establishProjectBaseContextWithRoot verbosity cliConfig projectRoot currentCommand = do cabalDir <- getCabalDir- projectRoot <- either throwIO return =<<- findProjectRoot Nothing mprojectFile - let distDirLayout = defaultDistDirLayout projectRoot- mdistDirectory+ let distDirLayout = defaultDistDirLayout projectRoot mdistDirectory (projectConfig, localPackages) <- rebuildProjectConfig verbosity@@ -222,6 +234,10 @@ verbosity cabalDirLayout projectConfig + -- https://github.com/haskell/cabal/issues/6013+ when (null (projectPackages projectConfig) && null (projectPackagesOptional projectConfig)) $+ warn verbosity "There are no packages or optional-packages in the project"+ return ProjectBaseContext { distDirLayout, cabalDirLayout,@@ -232,11 +248,7 @@ } where mdistDirectory = Setup.flagToMaybe projectConfigDistDir- mprojectFile = Setup.flagToMaybe projectConfigProjectFile- ProjectConfigShared {- projectConfigDistDir,- projectConfigProjectFile- } = projectConfigShared cliConfig+ ProjectConfigShared { projectConfigDistDir } = projectConfigShared cliConfig -- | This holds the context between the pre-build, build and post-build phases.@@ -288,7 +300,7 @@ -- everything in the project. This is independent of any specific targets -- the user has asked for. --- (elaboratedPlan, _, elaboratedShared) <-+ (elaboratedPlan, _, elaboratedShared, _, _) <- rebuildInstallPlan verbosity distDirLayout cabalDirLayout projectConfig@@ -313,7 +325,7 @@ -- everything in the project. This is independent of any specific targets -- the user has asked for. --- (elaboratedPlan, _, elaboratedShared) <-+ (elaboratedPlan, _, elaboratedShared, _, _) <- rebuildInstallPlan verbosity distDirLayout cabalDirLayout projectConfig@@ -501,16 +513,15 @@ resolveTargets :: forall err. (forall k. TargetSelector -> [AvailableTarget k]- -> Either err [k])+ -> Either (TargetProblem err) [k]) -> (forall k. SubComponentTarget -> AvailableTarget k- -> Either err k )- -> (TargetProblemCommon -> err)+ -> Either (TargetProblem err) k ) -> ElaboratedInstallPlan -> Maybe (SourcePackageDb) -> [TargetSelector]- -> Either [err] TargetsMap-resolveTargets selectPackageTargets selectComponentTarget liftProblem+ -> Either [TargetProblem err] TargetsMap+resolveTargets selectPackageTargets selectComponentTarget installPlan mPkgDb = fmap mkTargetsMap . either (Left . toList) Right@@ -528,7 +539,7 @@ AvailableTargetIndexes{..} = availableTargetIndexes installPlan - checkTarget :: TargetSelector -> Either err [(UnitId, ComponentTarget)]+ checkTarget :: TargetSelector -> Either (TargetProblem err) [(UnitId, ComponentTarget)] -- We can ask to build any whole package, project-local or a dependency checkTarget bt@(TargetPackage _ [pkgid] mkfilter)@@ -538,7 +549,7 @@ $ selectPackageTargets bt ats | otherwise- = Left (liftProblem (TargetProblemNoSuchPackage pkgid))+ = Left (TargetProblemNoSuchPackage pkgid) checkTarget (TargetPackage _ _ _) = error "TODO: add support for multiple packages in a directory"@@ -564,10 +575,10 @@ $ selectComponentTargets subtarget ats | Map.member pkgid availableTargetsByPackageId- = Left (liftProblem (TargetProblemNoSuchComponent pkgid cname))+ = Left (TargetProblemNoSuchComponent pkgid cname) | otherwise- = Left (liftProblem (TargetProblemNoSuchPackage pkgid))+ = Left (TargetProblemNoSuchPackage pkgid) checkTarget (TargetComponentUnknown pkgname ecname subtarget) | Just ats <- case ecname of@@ -581,10 +592,10 @@ $ selectComponentTargets subtarget ats | Map.member pkgname availableTargetsByPackageName- = Left (liftProblem (TargetProblemUnknownComponent pkgname ecname))+ = Left (TargetProblemUnknownComponent pkgname ecname) | otherwise- = Left (liftProblem (TargetNotInProject pkgname))+ = Left (TargetNotInProject pkgname) checkTarget bt@(TargetPackageNamed pkgname mkfilter) | Just ats <- fmap (maybe id filterTargetsKind mkfilter)@@ -596,10 +607,10 @@ | Just SourcePackageDb{ packageIndex } <- mPkgDb , let pkg = lookupPackageName packageIndex pkgname , not (null pkg)- = Left (liftProblem (TargetAvailableInIndex pkgname))+ = Left (TargetAvailableInIndex pkgname) | otherwise- = Left (liftProblem (TargetNotInProject pkgname))+ = Left (TargetNotInProject pkgname) componentTargets :: SubComponentTarget -> [(b, ComponentName)]@@ -609,7 +620,7 @@ selectComponentTargets :: SubComponentTarget -> [AvailableTarget k]- -> Either err [k]+ -> Either (TargetProblem err) [k] selectComponentTargets subtarget = either (Left . NE.head) Right . checkErrors@@ -748,7 +759,7 @@ -- selectComponentTargetBasic :: SubComponentTarget -> AvailableTarget k- -> Either TargetProblemCommon k+ -> Either (TargetProblem a) k selectComponentTargetBasic subtarget AvailableTarget { availableTargetPackageId = pkgid,@@ -771,32 +782,6 @@ TargetBuildable targetKey _ -> Right targetKey -data TargetProblemCommon- = TargetNotInProject PackageName- | TargetAvailableInIndex PackageName-- | TargetComponentNotProjectLocal- PackageId ComponentName SubComponentTarget-- | TargetComponentNotBuildable- PackageId ComponentName SubComponentTarget-- | TargetOptionalStanzaDisabledByUser- PackageId ComponentName SubComponentTarget-- | TargetOptionalStanzaDisabledBySolver- PackageId ComponentName SubComponentTarget-- | TargetProblemUnknownComponent- PackageName (Either UnqualComponentName ComponentName)-- -- The target matching stuff only returns packages local to the project,- -- so these lookups should never fail, but if 'resolveTargets' is called- -- directly then of course it can.- | TargetProblemNoSuchPackage PackageId- | TargetProblemNoSuchComponent PackageId ComponentName- deriving (Eq, Show)- -- | Wrapper around 'ProjectPlanning.pruneInstallPlanToTargets' that adjusts -- for the extra unneeded info in the 'TargetsMap'. --@@ -867,21 +852,20 @@ | otherwise = "will" showPkgAndReason :: ElaboratedReadyPackage -> String- showPkgAndReason (ReadyPackage elab) =- " - " ++- (if verbosity >= deafening+ showPkgAndReason (ReadyPackage elab) = unwords $ filter (not . null) $+ [ " -"+ , if verbosity >= deafening then prettyShow (installedUnitId elab) else prettyShow (packageId elab)- ) ++- (case elabPkgOrComp elab of+ , case elabPkgOrComp elab of ElabPackage pkg -> showTargets elab ++ ifVerbose (showStanzas pkg) ElabComponent comp ->- " (" ++ showComp elab comp ++ ")"- ) ++- showFlagAssignment (nonDefaultFlags elab) ++- showConfigureFlags elab ++- let buildStatus = pkgsBuildStatus Map.! installedUnitId elab in- " (" ++ showBuildStatus buildStatus ++ ")"+ "(" ++ showComp elab comp ++ ")"+ , showFlagAssignment (nonDefaultFlags elab)+ , showConfigureFlags elab+ , let buildStatus = pkgsBuildStatus Map.! installedUnitId elab+ in "(" ++ showBuildStatus buildStatus ++ ")"+ ] showComp elab comp = maybe "custom" prettyShow (compComponentName comp) ++@@ -906,14 +890,11 @@ showTargets elab | null (elabBuildTargets elab) = "" | otherwise- = " ("+ = "(" ++ intercalate ", " [ showComponentTarget (packageId elab) t | t <- elabBuildTargets elab ] ++ ")" - showFlagAssignment :: FlagAssignment -> String- showFlagAssignment = concatMap ((' ' :) . showFlagValue) . unFlagAssignment- showConfigureFlags elab = let fullConfigureFlags = setupHsConfigureFlags@@ -932,7 +913,7 @@ computeEffectiveProfiling fullConfigureFlags partialConfigureFlags- = Mon.mempty {+ = mempty { configProf = nubFlag False (configProf fullConfigureFlags), configProfExe =@@ -1223,3 +1204,67 @@ ++ "https://github.com/haskell/cabal/issues and if you\nhave any time " ++ "to get involved and help with testing, fixing bugs etc then\nthat " ++ "is very much appreciated.\n"++-------------------------------------------------------------------------------+-- Dummy projects+-------------------------------------------------------------------------------++-- | Create a dummy project context, without a .cabal or a .cabal.project file+-- (a place where to put a temporary dist directory is still needed)+establishDummyProjectBaseContext+ :: Verbosity+ -> ProjectConfig+ -> DistDirLayout+ -- ^ Where to put the dist directory+ -> [PackageSpecifier UnresolvedSourcePackage]+ -- ^ The packages to be included in the project+ -> CurrentCommand+ -> IO ProjectBaseContext+establishDummyProjectBaseContext verbosity cliConfig distDirLayout localPackages currentCommand = do+ cabalDir <- getCabalDir++ globalConfig <- runRebuild ""+ $ readGlobalConfig verbosity+ $ projectConfigConfigFile+ $ projectConfigShared cliConfig+ let projectConfig = globalConfig <> cliConfig++ let ProjectConfigBuildOnly {+ projectConfigLogsDir+ } = projectConfigBuildOnly projectConfig++ ProjectConfigShared {+ projectConfigStoreDir+ } = projectConfigShared projectConfig++ mlogsDir = flagToMaybe projectConfigLogsDir+ mstoreDir = flagToMaybe projectConfigStoreDir+ cabalDirLayout = mkCabalDirLayout cabalDir mstoreDir mlogsDir++ buildSettings = resolveBuildTimeSettings+ verbosity cabalDirLayout+ projectConfig++ return ProjectBaseContext {+ distDirLayout,+ cabalDirLayout,+ projectConfig,+ localPackages,+ buildSettings,+ currentCommand+ }++establishDummyDistDirLayout :: Verbosity -> ProjectConfig -> FilePath -> IO DistDirLayout+establishDummyDistDirLayout verbosity cliConfig tmpDir = do+ let distDirLayout = defaultDistDirLayout projectRoot mdistDirectory++ -- Create the dist directories+ createDirectoryIfMissingVerbose verbosity True $ distDirectory distDirLayout+ createDirectoryIfMissingVerbose verbosity True $ distProjectCacheDirectory distDirLayout++ return distDirLayout+ where+ mdistDirectory = flagToMaybe+ $ projectConfigDistDir+ $ projectConfigShared cliConfig+ projectRoot = ProjectRootImplicit tmpDir
cabal/cabal-install/Distribution/Client/ProjectPlanOutput.hs view
@@ -18,9 +18,12 @@ import Distribution.Client.ProjectPlanning.Types import Distribution.Client.ProjectBuilding.Types import Distribution.Client.DistDirLayout-import Distribution.Client.Types (Repo(..), RemoteRepo(..), PackageLocation(..), confInstId)-import Distribution.Client.PackageHash (showHashValue, hashValue)-import Distribution.Client.SourceRepo (SourceRepoMaybe, SourceRepositoryPackage (..))+import Distribution.Client.Types.Repo (Repo(..), RemoteRepo(..))+import Distribution.Client.Types.PackageLocation (PackageLocation(..))+import Distribution.Client.Types.ConfiguredId (confInstId)+import Distribution.Client.Types.SourceRepo (SourceRepoMaybe, SourceRepositoryPackage (..))+import Distribution.Client.HashValue (showHashValue, hashValue)+import Distribution.Client.Utils (cabalInstallVersion) import qualified Distribution.Client.InstallPlan as InstallPlan import qualified Distribution.Client.Utils.Json as J@@ -41,13 +44,13 @@ ( getImplInfo, GhcImplInfo(supportsPkgEnvFiles) , GhcEnvironmentFileEntry(..), simpleGhcEnvironmentFile , writeGhcEnvironmentFile )-import Distribution.Deprecated.Text+import Distribution.Simple.BuildPaths+ ( dllExtension, exeExtension ) import qualified Distribution.Compat.Graph as Graph import Distribution.Compat.Graph (Graph, Node) import qualified Distribution.Compat.Binary as Binary import Distribution.Simple.Utils import Distribution.Verbosity-import qualified Paths_cabal_install as Our (version) import Prelude () import Distribution.Client.Compat.Prelude@@ -88,7 +91,7 @@ encodePlanAsJson distDirLayout elaboratedInstallPlan elaboratedSharedConfig = --TODO: [nice to have] include all of the sharedPackageConfig and all of -- the parts of the elaboratedInstallPlan- J.object [ "cabal-version" J..= jdisplay Our.version+ J.object [ "cabal-version" J..= jdisplay cabalInstallVersion , "cabal-lib-version" J..= jdisplay cabalVersion , "compiler-id" J..= (J.String . showCompilerId . pkgConfigCompiler) elaboratedSharedConfig@@ -97,7 +100,7 @@ , "install-plan" J..= installPlanToJ elaboratedInstallPlan ] where- Platform arch os = pkgConfigPlatform elaboratedSharedConfig+ plat@(Platform arch os) = pkgConfigPlatform elaboratedSharedConfig installPlanToJ :: ElaboratedInstallPlan -> [J.Value] installPlanToJ = map planPackageToJ . InstallPlan.toList@@ -199,8 +202,8 @@ repoToJ :: Repo -> J.Value repoToJ repo = case repo of- RepoLocal{..} ->- J.object [ "type" J..= J.String "local-repo"+ RepoLocalNoIndex{..} ->+ J.object [ "type" J..= J.String "local-repo-no-index" , "path" J..= J.String repoLocalDir ] RepoRemote{..} ->@@ -229,33 +232,32 @@ ComponentDeps.ComponentExe s -> bin_file' s ComponentDeps.ComponentTest s -> bin_file' s ComponentDeps.ComponentBench s -> bin_file' s+ ComponentDeps.ComponentFLib s -> flib_file' s _ -> [] bin_file' s = ["bin-file" J..= J.String bin] where bin = if elabBuildStyle elab == BuildInplaceOnly- then dist_dir </> "build" </> display s </> display s- else InstallDirs.bindir (elabInstallDirs elab) </> display s+ then dist_dir </> "build" </> prettyShow s </> prettyShow s <.> exeExtension plat+ else InstallDirs.bindir (elabInstallDirs elab) </> prettyShow s <.> exeExtension plat - -- TODO: maybe move this helper to "ComponentDeps" module?- -- Or maybe define a 'Text' instance?+ flib_file' s =+ ["bin-file" J..= J.String bin]+ where+ bin = if elabBuildStyle elab == BuildInplaceOnly+ then dist_dir </> "build" </> prettyShow s </> ("lib" ++ prettyShow s) <.> dllExtension plat+ else InstallDirs.bindir (elabInstallDirs elab) </> ("lib" ++ prettyShow s) <.> dllExtension plat+ comp2str :: ComponentDeps.Component -> String- comp2str c = case c of- ComponentDeps.ComponentLib -> "lib"- ComponentDeps.ComponentSubLib s -> "lib:" <> display s- ComponentDeps.ComponentFLib s -> "flib:" <> display s- ComponentDeps.ComponentExe s -> "exe:" <> display s- ComponentDeps.ComponentTest s -> "test:" <> display s- ComponentDeps.ComponentBench s -> "bench:" <> display s- ComponentDeps.ComponentSetup -> "setup"+ comp2str = prettyShow style2str :: Bool -> BuildStyle -> String style2str True _ = "local" style2str False BuildInplaceOnly = "inplace" style2str False BuildAndInstall = "global" - jdisplay :: Text a => a -> J.Value- jdisplay = J.String . display+ jdisplay :: Pretty a => a -> J.Value+ jdisplay = J.String . prettyShow -----------------------------------------------------------------------------@@ -690,7 +692,7 @@ return currentBuildStatus where- displayPackageIdSet = intercalate ", " . map display . Set.toList+ displayPackageIdSet = intercalate ", " . map prettyShow . Set.toList -- | Helper for reading the cache file. --@@ -834,7 +836,7 @@ selectGhcEnvironmentFilePackageDbs elaboratedInstallPlan -- TODO use proper flags? but packageDbArgsDb is private clearPackageDbStackFlag = ["-clear-package-db", "-global-package-db"]- packageIdFlag uid = ["-package-id", display uid]+ packageIdFlag uid = ["-package-id", prettyShow uid] -- We're producing an environment for users to use in ghci, so of course
cabal/cabal-install/Distribution/Client/ProjectPlanning.hs view
@@ -70,6 +70,7 @@ import Prelude () import Distribution.Client.Compat.Prelude +import Distribution.Client.HashValue import Distribution.Client.ProjectPlanning.Types as Ty import Distribution.Client.PackageHash import Distribution.Client.RebuildMonad@@ -109,6 +110,7 @@ import Distribution.Solver.Types.SourcePackage import Distribution.Solver.Types.Settings +import Distribution.CabalSpecVersion import Distribution.ModuleName import Distribution.Package import Distribution.Types.AnnotatedId@@ -124,7 +126,7 @@ import qualified Distribution.PackageDescription as PD import qualified Distribution.PackageDescription.Configuration as PD import Distribution.Simple.PackageIndex (InstalledPackageIndex)-import Distribution.Simple.Compiler hiding (Flag)+import Distribution.Simple.Compiler import qualified Distribution.Simple.GHC as GHC --TODO: [code cleanup] eliminate import qualified Distribution.Simple.GHCJS as GHCJS --TODO: [code cleanup] eliminate import Distribution.Simple.Program@@ -151,23 +153,18 @@ import Distribution.Simple.Utils import Distribution.Version-import Distribution.Verbosity-import Distribution.Deprecated.Text import qualified Distribution.Compat.Graph as Graph import Distribution.Compat.Graph(IsNode(..)) -import Text.PrettyPrint hiding ((<>))+import Text.PrettyPrint (text, hang, quotes, colon, vcat, ($$), fsep, punctuate, comma) import qualified Text.PrettyPrint as Disp import qualified Data.Map as Map import qualified Data.Set as Set-import Control.Monad-import qualified Data.Traversable as T import Control.Monad.State as State-import Control.Exception+import Control.Exception (assert) import Data.List (groupBy)-import Data.Either-import Data.Function+import qualified Data.List.NonEmpty as NE import System.FilePath ------------------------------------------------------------------------------@@ -394,8 +391,11 @@ -> [PackageSpecifier UnresolvedSourcePackage] -> IO ( ElaboratedInstallPlan -- with store packages , ElaboratedInstallPlan -- with source packages- , ElaboratedSharedConfig )- -- ^ @(improvedPlan, elaboratedPlan, _, _)@+ , ElaboratedSharedConfig+ , IndexUtils.TotalIndexState+ , IndexUtils.ActiveRepos+ )+ -- ^ @(improvedPlan, elaboratedPlan, _, _, _)@ rebuildInstallPlan verbosity distDirLayout@DistDirLayout { distProjectRootDirectory,@@ -415,14 +415,14 @@ (projectConfigMonitored, localPackages, progsearchpath) $ do -- And so is the elaborated plan that the improved plan based on- (elaboratedPlan, elaboratedShared) <-+ (elaboratedPlan, elaboratedShared, totalIndexState, activeRepos) <- rerunIfChanged verbosity fileMonitorElaboratedPlan (projectConfigMonitored, localPackages, progsearchpath) $ do compilerEtc <- phaseConfigureCompiler projectConfig _ <- phaseConfigurePrograms projectConfig compilerEtc- (solverPlan, pkgConfigDB)+ (solverPlan, pkgConfigDB, totalIndexState, activeRepos) <- phaseRunSolver projectConfig compilerEtc localPackages@@ -433,14 +433,14 @@ localPackages phaseMaintainPlanOutputs elaboratedPlan elaboratedShared- return (elaboratedPlan, elaboratedShared)+ return (elaboratedPlan, elaboratedShared, totalIndexState, activeRepos) -- The improved plan changes each time we install something, whereas -- the underlying elaborated plan only changes when input config -- changes, so it's worth caching them separately. improvedPlan <- phaseImprovePlan elaboratedPlan elaboratedShared - return (improvedPlan, elaboratedPlan, elaboratedShared)+ return (improvedPlan, elaboratedPlan, elaboratedShared, totalIndexState, activeRepos) where fileMonitorCompiler = newFileMonitorInCacheDir "compiler"@@ -541,10 +541,11 @@ -- Run the solver to get the initial install plan. -- This is expensive so we cache it independently. --- phaseRunSolver :: ProjectConfig- -> (Compiler, Platform, ProgramDb)- -> [PackageSpecifier UnresolvedSourcePackage]- -> Rebuild (SolverInstallPlan, PkgConfigDb)+ phaseRunSolver+ :: ProjectConfig+ -> (Compiler, Platform, ProgramDb)+ -> [PackageSpecifier UnresolvedSourcePackage]+ -> Rebuild (SolverInstallPlan, PkgConfigDb, IndexUtils.TotalIndexState, IndexUtils.ActiveRepos) phaseRunSolver projectConfig@ProjectConfig { projectConfigShared, projectConfigBuildOnly@@ -559,8 +560,9 @@ installedPkgIndex <- getInstalledPackages verbosity compiler progdb platform corePackageDbs- sourcePkgDb <- getSourcePackages verbosity withRepoCtx- (solverSettingIndexState solverSettings)+ (sourcePkgDb, tis, ar) <- getSourcePackages verbosity withRepoCtx+ (solverSettingIndexState solverSettings)+ (solverSettingActiveRepos solverSettings) pkgConfigDB <- getPkgConfigDb verbosity progdb --TODO: [code cleanup] it'd be better if the Compiler contained the@@ -578,7 +580,7 @@ planPackages verbosity compiler platform solver solverSettings installedPkgIndex sourcePkgDb pkgConfigDB localPackages localPackagesEnabledStanzas- return (plan, pkgConfigDB)+ return (plan, pkgConfigDB, tis, ar) where corePackageDbs = [GlobalPackageDB] withRepoCtx = projectConfigWithSolverRepoContext verbosity@@ -591,6 +593,10 @@ Map.fromList [ (pkgname, stanzas) | pkg <- localPackages+ -- TODO: misnormer: we should separate+ -- builtin/global/inplace/local packages+ -- and packages explicitly mentioned in the project+ -- , let pkgname = pkgSpecifierTarget pkg testsEnabled = lookupLocalPackageConfig packageConfigTests@@ -598,12 +604,14 @@ benchmarksEnabled = lookupLocalPackageConfig packageConfigBenchmarks projectConfig pkgname- stanzas =- Map.fromList $+ isLocal = isJust (shouldBeLocal pkg)+ stanzas+ | isLocal = Map.fromList $ [ (TestStanzas, enabled)- | enabled <- flagToList testsEnabled ]- ++ [ (BenchStanzas , enabled)+ | enabled <- flagToList testsEnabled ] +++ [ (BenchStanzas , enabled) | enabled <- flagToList benchmarksEnabled ]+ | otherwise = Map.fromList [(TestStanzas, False), (BenchStanzas, False) ] ] -- Elaborate the solver's install plan to get a fully detailed plan. This@@ -755,20 +763,23 @@ packagedb progdb -} -getSourcePackages :: Verbosity -> (forall a. (RepoContext -> IO a) -> IO a)- -> Maybe IndexUtils.IndexState -> Rebuild SourcePackageDb-getSourcePackages verbosity withRepoCtx idxState = do- (sourcePkgDb, repos) <-+getSourcePackages+ :: Verbosity+ -> (forall a. (RepoContext -> IO a) -> IO a)+ -> Maybe IndexUtils.TotalIndexState+ -> Maybe IndexUtils.ActiveRepos+ -> Rebuild (SourcePackageDb, IndexUtils.TotalIndexState, IndexUtils.ActiveRepos)+getSourcePackages verbosity withRepoCtx idxState activeRepos = do+ (sourcePkgDbWithTIS, repos) <- liftIO $ withRepoCtx $ \repoctx -> do- sourcePkgDb <- IndexUtils.getSourcePackagesAtIndexState verbosity- repoctx idxState- return (sourcePkgDb, repoContextRepos repoctx)+ sourcePkgDbWithTIS <- IndexUtils.getSourcePackagesAtIndexState verbosity repoctx idxState activeRepos+ return (sourcePkgDbWithTIS, repoContextRepos repoctx) - mapM_ needIfExists+ traverse_ needIfExists . IndexUtils.getSourcePackagesMonitorFiles $ repos- return sourcePkgDb+ return sourcePkgDbWithTIS getPkgConfigDb :: Verbosity -> ProgramDb -> Rebuild PkgConfigDb@@ -776,7 +787,7 @@ dirs <- liftIO $ getPkgConfigDbDirs verbosity progdb -- Just monitor the dirs so we'll notice new .pc files. -- Alternatively we could monitor all the .pc files too.- mapM_ monitorDirectoryStatus dirs+ traverse_ monitorDirectoryStatus dirs liftIO $ readPkgConfigDb verbosity progdb @@ -784,7 +795,7 @@ packageLocationsSignature :: SolverInstallPlan -> [(PackageId, PackageLocation (Maybe FilePath))] packageLocationsSignature solverPlan =- [ (packageId pkg, packageSource pkg)+ [ (packageId pkg, srcpkgSource pkg) | SolverInstallPlan.Configured (SolverPackage { solverPkgSource = pkg}) <- SolverInstallPlan.toList solverPlan ]@@ -805,7 +816,7 @@ -- let allPkgLocations :: [(PackageId, PackageLocation (Maybe FilePath))] allPkgLocations =- [ (packageId pkg, packageSource pkg)+ [ (packageId pkg, srcpkgSource pkg) | SolverInstallPlan.Configured (SolverPackage { solverPkgSource = pkg}) <- SolverInstallPlan.toList solverPlan ] @@ -818,11 +829,15 @@ -- Tarballs from remote URLs. We must have downloaded these already -- (since we extracted the .cabal file earlier)- --TODO: [required eventually] finish remote tarball functionality--- allRemoteTarballPkgs =--- [ (pkgid, )--- | (pkgid, RemoteTarballPackage ) <- allPkgLocations ]+ remoteTarballPkgs =+ [ (pkgid, tarball)+ | (pkgid, RemoteTarballPackage _ (Just tarball)) <- allPkgLocations ] + -- tarballs from source-repository-package stanzas+ sourceRepoTarballPkgs =+ [ (pkgid, tarball)+ | (pkgid, RemoteSourceRepoPackage _ (Just tarball)) <- allPkgLocations ]+ -- Tarballs from repositories, either where the repository provides -- hashes as part of the repo metadata, or where we will have to -- download and hash the tarball.@@ -877,8 +892,8 @@ return (pkgid, hashFromTUF hash) | pkgid <- pkgids ] | (repo, pkgids) <-- map (\grp@((_,repo):_) -> (repo, map fst grp))- . groupBy ((==) `on` (remoteRepoName . repoRemote . snd))+ map (\grp@((_,repo):|_) -> (repo, map fst (NE.toList grp)))+ . NE.groupBy ((==) `on` (remoteRepoName . repoRemote . snd)) . sortBy (compare `on` (remoteRepoName . repoRemote . snd)) $ repoTarballPkgsWithMetadata ]@@ -901,6 +916,8 @@ -- let allTarballFilePkgs :: [(PackageId, FilePath)] allTarballFilePkgs = localTarballPkgs+ ++ remoteTarballPkgs+ ++ sourceRepoTarballPkgs ++ repoTarballPkgsDownloaded ++ repoTarballPkgsNewlyDownloaded hashesFromTarballFiles <- liftIO $@@ -956,6 +973,8 @@ . setCountConflicts solverSettingCountConflicts + . setFineGrainedConflicts solverSettingFineGrainedConflicts+ . setMinimizeConflictSet solverSettingMinimizeConflictSet --TODO: [required eventually] should only be configurable for@@ -988,7 +1007,7 @@ . addDefaultSetupDependencies (defaultSetupDeps comp platform . PD.packageDescription- . packageDescription)+ . srcpkgDescription) . addSetupCabalMinVersionConstraint setupMinCabalVersionConstraint . addSetupCabalMaxVersionConstraint setupMaxCabalVersionConstraint@@ -1094,6 +1113,8 @@ -- TODO: long-term, this compatibility matrix should be -- stored as a field inside 'Distribution.Compiler.Compiler' setupMinCabalVersionConstraint+ | isGHC, compVer >= mkVersion [8,12] = mkVersion [3,4]+ | isGHC, compVer >= mkVersion [8,10] = mkVersion [3,2] | isGHC, compVer >= mkVersion [8,8] = mkVersion [3,0] | isGHC, compVer >= mkVersion [8,6] = mkVersion [2,4] | isGHC, compVer >= mkVersion [8,4] = mkVersion [2,2]@@ -1282,7 +1303,7 @@ let inplace_doc | shouldBuildInplaceOnly pkg = text "inplace" | otherwise = Disp.empty in addProgressCtx (text "In the" <+> inplace_doc <+> text "package" <+>- quotes (disp (packageId pkg))) $+ quotes (pretty (packageId pkg))) $ map InstallPlan.Configured <$> elaborateSolverToComponents mapDep pkg -- NB: We don't INSTANTIATE packages at this point. That's@@ -1295,7 +1316,7 @@ = case mkComponentsGraph (elabEnabledSpec elab0) pd of Right g -> do let src_comps = componentsGraphToList g- infoProgress $ hang (text "Component graph for" <+> disp pkgid <<>> colon)+ infoProgress $ hang (text "Component graph for" <+> pretty pkgid <<>> colon) 4 (dispComponentsWithDeps src_comps) (_, comps) <- mapAccumM buildComponent (Map.empty, Map.empty, Map.empty)@@ -1335,7 +1356,7 @@ -- for now it's easier to just fallback to legacy-mode when specVersion < 1.8 -- see, https://github.com/haskell/cabal/issues/4121 cuz_spec- | PD.specVersion pd >= mkVersion [1,8] = []+ | PD.specVersion pd >= CabalSpecV1_8 = [] | otherwise = cuz "cabal-version is less than 1.8" -- In the odd corner case that a package has no components at all -- then keep it as a whole package, since otherwise it turns into@@ -1456,10 +1477,10 @@ cid = case elabBuildStyle elab0 of BuildInplaceOnly -> mkComponentId $- display pkgid ++ "-inplace" +++ prettyShow pkgid ++ "-inplace" ++ (case Cabal.componentNameString cname of Nothing -> ""- Just s -> "-" ++ display s)+ Just s -> "-" ++ prettyShow s) BuildAndInstall -> hashedInstalledPackageId (packageHashInputs@@ -1472,7 +1493,7 @@ let lookup_uid def_uid = case Map.lookup (unDefUnitId def_uid) preexistingInstantiatedPkgs of Just full -> full- Nothing -> error ("lookup_uid: " ++ display def_uid)+ Nothing -> error ("lookup_uid: " ++ prettyShow def_uid) lc <- toLinkedComponent verbosity lookup_uid (elabPkgSourceId elab0) (Map.union external_lc_map lc_map) cc infoProgress $ dispLinkedComponent lc@@ -1550,8 +1571,8 @@ compPkgConfigDependencies = [ (pn, fromMaybe (error $ "compPkgConfigDependencies: impossible! "- ++ display pn ++ " from "- ++ display (elabPkgSourceId elab0))+ ++ prettyShow pn ++ " from "+ ++ prettyShow (elabPkgSourceId elab0)) (pkgConfigDbPkgVersion pkgConfigDB pn)) | PkgconfigDependency pn _ <- PD.pkgconfigDepends (Cabal.componentBuildInfo comp) ]@@ -1562,7 +1583,7 @@ elaboratedSharedConfig elab $ case Cabal.componentNameString cname of- Just n -> display n+ Just n -> prettyShow n Nothing -> "" @@ -1594,7 +1615,7 @@ ElabComponent comp -> case fmap Cabal.componentNameString (compComponentName comp) of- Just (Just n) -> [display n]+ Just (Just n) -> [prettyShow n] _ -> [""] in binDirectoryFor@@ -1608,7 +1629,7 @@ -> [ElaboratedConfiguredPackage] -> ElaboratedConfiguredPackage elaborateSolverToPackage- pkg@(SolverPackage (SourcePackage pkgid _gdesc _srcloc _descOverride)+ pkg@(SolverPackage (SourcePackage pkgid _gpd _srcloc _descOverride) _flags _stanzas _deps0 _exe_deps0) compGraph comps = -- Knot tying: the final elab includes the@@ -1638,7 +1659,7 @@ pkgInstalledId | shouldBuildInplaceOnly pkg- = mkComponentId (display pkgid ++ "-inplace")+ = mkComponentId (prettyShow pkgid ++ "-inplace") | otherwise = assert (isJust elabPkgSourceHash) $@@ -1649,7 +1670,7 @@ | otherwise = error $ "elaborateInstallPlan: non-inplace package "- ++ " is missing a source hash: " ++ display pkgid+ ++ " is missing a source hash: " ++ prettyShow pkgid -- Need to filter out internal dependencies, because they don't -- correspond to anything real anymore.@@ -1713,12 +1734,12 @@ elabIsCanonical = True elabPkgSourceId = pkgid- elabPkgDescription = let Right (desc, _) =- PD.finalizePD+ elabPkgDescription = case PD.finalizePD flags elabEnabledSpec (const True) platform (compilerInfo compiler)- [] gdesc- in desc+ [] gdesc of+ Right (desc, _) -> desc+ Left _ -> error "Failed to finalizePD in elaborateSolverToCommon" elabFlagAssignment = flags elabFlagDefaults = PD.mkFlagAssignment [ (Cabal.flagName flag, Cabal.flagDefault flag)@@ -1917,16 +1938,6 @@ Set.fromList (catMaybes (map shouldBeLocal localPackages)) --TODO: localPackages is a misnomer, it's all project packages -- here is where we decide which ones will be local!- where- shouldBeLocal :: PackageSpecifier (SourcePackage (PackageLocation loc)) -> Maybe PackageId- shouldBeLocal NamedPackage{} = Nothing- shouldBeLocal (SpecificSourcePackage pkg)- | LocalTarballPackage _ <- packageSource pkg = Nothing- | otherwise = Just (packageId pkg)- -- TODO: Is it only LocalTarballPackages we can know about without- -- them being "local" in the sense meant here?- --- -- Also, review use of SourcePackage's loc vs ProjectPackageLocation pkgsUseSharedLibrary :: Set PackageId pkgsUseSharedLibrary =@@ -1987,6 +1998,12 @@ -- TODO: Drop matchPlanPkg/matchElabPkg in favor of mkCCMapping +shouldBeLocal :: PackageSpecifier (SourcePackage (PackageLocation loc)) -> Maybe PackageId+shouldBeLocal NamedPackage{} = Nothing+shouldBeLocal (SpecificSourcePackage pkg) = case srcpkgSource pkg of+ LocalUnpackedPackage _ -> Just (packageId pkg)+ _ -> Nothing+ -- | Given a 'ElaboratedPlanPackage', report if it matches a 'ComponentName'. matchPlanPkg :: (ComponentName -> Bool) -> ElaboratedPlanPackage -> Bool matchPlanPkg p = InstallPlan.foldPlanPackage (p . ipiComponentName) (matchElabPkg p)@@ -2015,7 +2032,7 @@ (Cabal.pkgBuildableComponents (elabPkgDescription elab)) -- | Given an 'ElaboratedPlanPackage', generate the mapping from 'PackageName'--- and 'ComponentName' to the 'ComponentId' that that should be used+-- and 'ComponentName' to the 'ComponentId' that should be used -- in this case. mkCCMapping :: ElaboratedPlanPackage -> (PackageName, Map ComponentName (AnnotatedId ComponentId))@@ -2082,9 +2099,9 @@ BuildAndInstall -> [installedBinDirectory package] BuildInplaceOnly -> map (root</>) $ case elabPkgOrComp package of ElabComponent comp -> case compSolverName comp of- CD.ComponentExe n -> [display n]+ CD.ComponentExe n -> [prettyShow n] _ -> []- ElabPackage _ -> map (display . PD.exeName)+ ElabPackage _ -> map (prettyShow . PD.exeName) . PD.executables . elabPkgDescription $ package@@ -2150,7 +2167,7 @@ = case planpkg of InstallPlan.Configured (elab0@ElaboratedConfiguredPackage { elabPkgOrComp = ElabComponent comp }) -> do- deps <- mapM (substUnitId insts)+ deps <- traverse (substUnitId insts) (compLinkedLibDependencies comp) let getDep (Module dep_uid _) = [dep_uid] elab1 = elab0 {@@ -2173,7 +2190,7 @@ } return $ InstallPlan.Configured elab _ -> return planpkg- | otherwise = error ("instantiateComponent: " ++ display cid)+ | otherwise = error ("instantiateComponent: " ++ prettyShow cid) substUnitId :: Map ModuleName Module -> OpenUnitId -> InstM DefUnitId substUnitId _ (DefiniteUnitId uid) =@@ -2186,7 +2203,7 @@ substSubst :: Map ModuleName Module -> Map ModuleName OpenModule -> InstM (Map ModuleName Module)- substSubst subst insts = T.mapM (substModule subst) insts+ substSubst subst insts = traverse (substModule subst) insts substModule :: Map ModuleName Module -> OpenModule -> InstM Module substModule subst (OpenModuleVar mod_name)@@ -2223,7 +2240,7 @@ -- we initially created the ElaboratedPlanPackage because -- we have no way of actually refiying the UnitId into a -- DefiniteUnitId (that's what substUnitId does!)- new_deps <- forM (compLinkedLibDependencies elab_comp) $ \uid ->+ new_deps <- for (compLinkedLibDependencies elab_comp) $ \uid -> if Set.null (openUnitIdFreeHoles uid) then fmap DefiniteUnitId (substUnitId Map.empty uid) else return uid@@ -2241,11 +2258,11 @@ } | Just planpkg <- Map.lookup cid cmap = return planpkg- | otherwise = error ("indefiniteComponent: " ++ display cid)+ | otherwise = error ("indefiniteComponent: " ++ prettyShow cid) ready_map = execState work Map.empty - work = forM_ pkgs $ \pkg ->+ work = for_ pkgs $ \pkg -> case pkg of InstallPlan.Configured elab | not (Map.null (elabLinkedInstantiatedWith elab))@@ -2970,10 +2987,11 @@ -- less than 1.23. -- -- In cases 1 and 2 we obviously have to build an external Setup.hs script,--- while in case 4 we can use the internal library API. In case 3 we also have--- to build an external Setup.hs script because the package needs a later--- Cabal lib version than we can support internally.+-- while in case 4 we can use the internal library API. --+-- TODO:In case 3 we should fail. We don't know how to talk to+-- newer ./Setup.hs+-- -- data SetupScriptStyle = ... -- see ProjectPlanning.Types -- | Work out the 'SetupScriptStyle' given the package description.@@ -2994,7 +3012,8 @@ , Nothing <- PD.setupBuildInfo pkg -- we get this case pre-solver = SetupCustomImplicitDeps - | PD.specVersion pkg > cabalVersion -- one cabal-install is built against+ -- here we should fail.+ | PD.specVersion pkg > cabalSpecLatest -- one cabal-install is built against = SetupNonCustomExternalLib | otherwise@@ -3033,9 +3052,9 @@ -- of other packages. SetupCustomImplicitDeps -> Just $- [ Dependency depPkgname anyVersion (Set.singleton LMainLibName)+ [ Dependency depPkgname anyVersion mainLibSet | depPkgname <- legacyCustomSetupPkgs compiler platform ] ++- [ Dependency cabalPkgname cabalConstraint (Set.singleton LMainLibName)+ [ Dependency cabalPkgname cabalConstraint mainLibSet | packageName pkg /= cabalPkgname ] where -- The Cabal dep is slightly special:@@ -3045,7 +3064,7 @@ -- Note: we also add a global constraint to require Cabal >= 1.20 -- for Setup scripts (see use addSetupCabalMinVersionConstraint). --- cabalConstraint = orLaterVersion (PD.specVersion pkg)+ cabalConstraint = orLaterVersion (csvToVersion (PD.specVersion pkg)) `intersectVersionRanges` earlierVersion cabalCompatMaxVer -- The idea here is that at some point we will make significant@@ -3058,10 +3077,10 @@ -- external Setup.hs, it'll be one of the simple ones that only depends -- on Cabal and base. SetupNonCustomExternalLib ->- Just [ Dependency cabalPkgname cabalConstraint (Set.singleton LMainLibName)- , Dependency basePkgname anyVersion (Set.singleton LMainLibName)]+ Just [ Dependency cabalPkgname cabalConstraint mainLibSet+ , Dependency basePkgname anyVersion mainLibSet] where- cabalConstraint = orLaterVersion (PD.specVersion pkg)+ cabalConstraint = orLaterVersion (csvToVersion (PD.specVersion pkg)) -- The internal setup wrapper method has no deps at all. SetupNonCustomInternalLib -> Just []@@ -3070,10 +3089,15 @@ -- above in the SetupCustomImplicitDeps case. SetupCustomExplicitDeps -> error $ "defaultSetupDeps: called for a package with explicit "- ++ "setup deps: " ++ display (packageId pkg)-+ ++ "setup deps: " ++ prettyShow (packageId pkg)+ where+ -- we require one less+ --+ -- This maps e.g. CabalSpecV3_0 to mkVersion [2,5]+ csvToVersion :: CabalSpecVersion -> Version+ csvToVersion = mkVersion . cabalSpecMinimumLibraryVersion --- | Work out which version of the Cabal spec we will be using to talk to the+-- | Work out which version of the Cabal we will be using to talk to the -- Setup.hs interface for this package. -- -- This depends somewhat on the 'SetupScriptStyle' but most cases are a result@@ -3104,7 +3128,7 @@ packageSetupScriptSpecVersion _ pkg libDepGraph deps = case find ((cabalPkgname ==) . packageName) setupLibDeps of Just dep -> packageVersion dep- Nothing -> PD.specVersion pkg+ Nothing -> mkVersion (cabalSpecMinimumLibraryVersion (PD.specVersion pkg)) where setupLibDeps = map packageId $ fromMaybe [] $ Graph.closure libDepGraph (CD.setupDeps deps)@@ -3119,14 +3143,18 @@ legacyCustomSetupPkgs compiler (Platform _ os) = map mkPackageName $ [ "array", "base", "binary", "bytestring", "containers"- , "deepseq", "directory", "filepath", "old-time", "pretty"+ , "deepseq", "directory", "filepath", "pretty" , "process", "time", "transformers" ] ++ [ "Win32" | os == Windows ] ++ [ "unix" | os /= Windows ] ++ [ "ghc-prim" | isGHC ] ++ [ "template-haskell" | isGHC ]+ ++ [ "old-time" | notGHC710 ] where isGHC = compilerCompatFlavor GHC compiler+ notGHC710 = case compilerCompatVersion GHC compiler of+ Nothing -> False+ Just v -> v <= mkVersion [7,9] -- The other aspects of our Setup.hs policy lives here where we decide on -- the 'SetupScriptOptions'.@@ -3286,7 +3314,7 @@ configDeterministic = mempty -- doesn't matter, configIPID/configCID overridese configIPID = case elabPkgOrComp of- ElabPackage pkg -> toFlag (display (pkgInstalledId pkg))+ ElabPackage pkg -> toFlag (prettyShow (pkgInstalledId pkg)) ElabComponent _ -> mempty configCID = case elabPkgOrComp of ElabPackage _ -> mempty@@ -3372,7 +3400,7 @@ configConstraints = case elabPkgOrComp of ElabPackage _ ->- [ thisPackageVersion srcid+ [ thisPackageVersionConstraint srcid | ConfiguredId srcid _ _uid <- elabLibDependencies elab ] ElabComponent _ -> [] @@ -3395,9 +3423,7 @@ configUserInstall = mempty -- don't rely on defaults configPrograms_ = mempty -- never use, shouldn't exist configUseResponseFiles = mempty- -- TODO set to true when the solver can prevent private-library-deps by itself- -- (issue #6039)- configAllowDependingOnPrivateLibs = mempty+ configAllowDependingOnPrivateLibs = Flag $ not $ libraryVisibilitySupported pkgConfigCompiler setupHsConfigureArgs :: ElaboratedConfiguredPackage -> [String]@@ -3666,7 +3692,7 @@ packageHashInputs _ pkg = error $ "packageHashInputs: only for packages with source hashes. "- ++ display (packageId pkg)+ ++ prettyShow (packageId pkg) packageHashConfigInputs :: ElaboratedSharedConfig -> ElaboratedConfiguredPackage
cabal/cabal-install/Distribution/Client/ProjectPlanning/Types.hs view
@@ -60,6 +60,9 @@ SetupScriptStyle(..), ) where +import Distribution.Client.Compat.Prelude+import Prelude ()+ import Distribution.Client.TargetSelector ( SubComponentTarget(..) ) import Distribution.Client.PackageHash@@ -75,8 +78,7 @@ import Distribution.Backpack import Distribution.Backpack.ModuleShape -import Distribution.Pretty-import Distribution.Verbosity+import Distribution.Verbosity (normal) import Distribution.Types.ComponentRequestedSpec import Distribution.Types.PkgconfigVersion import Distribution.Types.PackageDescription (PackageDescription(..))@@ -102,16 +104,9 @@ import Distribution.Compat.Graph (IsNode(..)) import Distribution.Simple.Utils (ordNub) -import Data.Map (Map) import qualified Data.Map as Map-import Data.Maybe (catMaybes)-import Data.Set (Set) import qualified Data.ByteString.Lazy as LBS-import Distribution.Compat.Binary-import GHC.Generics (Generic) import qualified Data.Monoid as Mon-import Data.Typeable-import Control.Monad import System.FilePath ((</>)) @@ -158,6 +153,7 @@ --TODO: [code cleanup] no Eq instance instance Binary ElaboratedSharedConfig+instance Structured ElaboratedSharedConfig data ElaboratedConfiguredPackage = ElaboratedConfiguredPackage {@@ -309,6 +305,9 @@ -- | The version of the Cabal command line interface that we are using -- for this package. This is typically the version of the Cabal lib -- that the Setup.hs is built against.+ --+ -- TODO: We might want to turn this into a enum,+ -- yet different enum than 'CabalSpecVersion'. elabSetupScriptCliVersion :: Version, -- Build time related:@@ -463,6 +462,7 @@ nodeNeighbors = elabOrderDependencies instance Binary ElaboratedConfiguredPackage+instance Structured ElaboratedConfiguredPackage data ElaboratedPackageOrComponent = ElabPackage ElaboratedPackage@@ -470,6 +470,7 @@ deriving (Eq, Show, Generic) instance Binary ElaboratedPackageOrComponent+instance Structured ElaboratedPackageOrComponent elabComponentName :: ElaboratedConfiguredPackage -> Maybe ComponentName elabComponentName elab =@@ -661,6 +662,7 @@ deriving (Eq, Show, Generic) instance Binary ElaboratedComponent+instance Structured ElaboratedComponent -- | See 'elabOrderDependencies'. compOrderDependencies :: ElaboratedComponent -> [UnitId]@@ -709,6 +711,7 @@ deriving (Eq, Show, Generic) instance Binary ElaboratedPackage+instance Structured ElaboratedPackage -- | See 'elabOrderDependencies'. This gives the unflattened version, -- which can be useful in some circumstances.@@ -740,6 +743,7 @@ deriving (Eq, Show, Generic) instance Binary BuildStyle+instance Structured BuildStyle type CabalFileText = LBS.ByteString @@ -757,6 +761,7 @@ deriving (Eq, Ord, Show, Generic) instance Binary ComponentTarget+instance Structured ComponentTarget -- | Unambiguously render a 'ComponentTarget', e.g., to pass -- to a Cabal Setup script.@@ -832,3 +837,4 @@ deriving (Eq, Show, Generic, Typeable) instance Binary SetupScriptStyle+instance Structured SetupScriptStyle
cabal/cabal-install/Distribution/Client/RebuildMonad.hs view
@@ -63,7 +63,6 @@ import qualified Distribution.Client.Glob as Glob (matchFileGlob) import Distribution.Simple.Utils (debug)-import Distribution.Verbosity (Verbosity) import qualified Data.Map.Strict as Map import Control.Monad.State as State@@ -116,7 +115,7 @@ -- -- Do not share 'FileMonitor's between different uses of 'rerunIfChanged'. ---rerunIfChanged :: (Binary a, Binary b)+rerunIfChanged :: (Binary a, Structured a, Binary b, Structured b) => Verbosity -> FileMonitor a b -> a
cabal/cabal-install/Distribution/Client/Reconfigure.hs view
@@ -5,8 +5,6 @@ import Data.Monoid ( Any(..) ) import System.Directory ( doesFileExist ) -import Distribution.Verbosity- import Distribution.Simple.Configure ( localBuildInfoFile ) import Distribution.Simple.Setup ( Flag, flagToMaybe, toFlag ) import Distribution.Simple.Utils@@ -15,16 +13,11 @@ import Distribution.Client.Config ( SavedConfig(..) ) import Distribution.Client.Configure ( readConfigFlags ) import Distribution.Client.Nix ( findNixExpr, inNixShell, nixInstantiate )-import Distribution.Client.Sandbox- ( WereDepsReinstalled(..), findSavedDistPref, getSandboxConfigFilePath- , maybeReinstallAddSourceDeps, updateInstallDirs )+import Distribution.Client.Sandbox ( findSavedDistPref, updateInstallDirs ) import Distribution.Client.Sandbox.PackageEnvironment ( userPackageEnvironmentFile )-import Distribution.Client.Sandbox.Types ( UseSandbox(..) ) import Distribution.Client.Setup- ( ConfigFlags(..), ConfigExFlags, GlobalFlags(..)- , SkipAddSourceDepsCheck(..) )-+ ( ConfigFlags(..), ConfigExFlags, GlobalFlags(..) ) -- | @Check@ represents a function to check some condition on type @a@. The -- returned 'Any' is 'True' if any part of the condition failed.@@ -82,10 +75,6 @@ -- ^ Verbosity setting -> FilePath -- ^ \"dist\" prefix- -> UseSandbox- -> SkipAddSourceDepsCheck- -- ^ Should we skip the timestamp check for modified- -- add-source dependencies? -> Flag (Maybe Int) -- ^ -j flag for reinstalling add-source deps. -> Check (ConfigFlags, ConfigExFlags)@@ -100,9 +89,7 @@ configureAction verbosity dist- useSandbox- skipAddSourceDepsCheck- numJobsFlag+ _numJobsFlag check extraArgs globalFlags@@ -137,15 +124,11 @@ <> checkDist <> checkOutdated <> check- <> checkAddSourceDeps- (Any force, flags@(configFlags, _)) <- runCheck checks mempty savedFlags+ (Any frc, flags@(configFlags, _)) <- runCheck checks mempty savedFlags - let (_, config') =- updateInstallDirs- (configUserInstall configFlags)- (useSandbox, config)+ let config' = updateInstallDirs (configUserInstall configFlags) config - when force $ configureAction flags extraArgs globalFlags+ when frc $ configureAction flags extraArgs globalFlags return config' where@@ -174,13 +157,6 @@ configured <- doesFileExist buildConfig unless configured $ info verbosity "package has never been configured" - -- Is the configuration older than the sandbox configuration file?- -- If so, reconfiguration is required.- sandboxConfig <- getSandboxConfigFilePath globalFlags- sandboxConfigNewer <- existsAndIsMoreRecentThan sandboxConfig buildConfig- when sandboxConfigNewer $- info verbosity "sandbox was created after the package was configured"- -- Is the @cabal.config@ file newer than @dist/setup.config@? Then we need -- to force reconfigure. Note that it's possible to use @cabal.config@ -- even without sandboxes.@@ -199,35 +175,5 @@ let failed = Any outdated <> Any userPackageEnvironmentFileModified- <> Any sandboxConfigNewer <> Any (not configured) return (failed, flags)-- checkAddSourceDeps = Check $ \(Any force') flags@(configFlags, _) -> do- let (_, config') =- updateInstallDirs- (configUserInstall configFlags)- (useSandbox, config)-- skipAddSourceDepsCheck'- | force' = SkipAddSourceDepsCheck- | otherwise = skipAddSourceDepsCheck-- when (skipAddSourceDepsCheck' == SkipAddSourceDepsCheck) $- info verbosity "skipping add-source deps check"-- -- Were any add-source dependencies reinstalled in the sandbox?- depsReinstalled <-- case skipAddSourceDepsCheck' of- DontSkipAddSourceDepsCheck ->- maybeReinstallAddSourceDeps- verbosity numJobsFlag configFlags globalFlags- (useSandbox, config')- SkipAddSourceDepsCheck -> do- return NoDepsReinstalled-- case depsReinstalled of- NoDepsReinstalled -> return (mempty, flags)- ReinstalledSomeDeps -> do- info verbosity "some add-source dependencies were reinstalled"- return (Any True, flags)
cabal/cabal-install/Distribution/Client/Run.hs view
@@ -34,8 +34,6 @@ rawSystemExitWithEnv, addLibraryPath) import Distribution.System (Platform (..))-import Distribution.Verbosity (Verbosity)-import Distribution.Deprecated.Text (display) import qualified Distribution.Simple.GHCJS as GHCJS @@ -91,16 +89,16 @@ where components :: [(UnqualComponentName, String)] -- Component name, message. components =- [ (name, "The executable '" ++ display name ++ "' is disabled.")+ [ (name, "The executable '" ++ prettyShow name ++ "' is disabled.") | e <- executables pkg_descr , not . buildable . buildInfo $ e, let name = exeName e] - ++ [ (name, "There is a test-suite '" ++ display name ++ "',"+ ++ [ (name, "There is a test-suite '" ++ prettyShow name ++ "'," ++ " but the `run` command is only for executables.") | t <- testSuites pkg_descr , let name = testName t] - ++ [ (name, "There is a benchmark '" ++ display name ++ "',"+ ++ [ (name, "There is a benchmark '" ++ prettyShow name ++ "'," ++ " but the `run` command is only for executables.") | b <- benchmarks pkg_descr , let name = benchmarkName b]@@ -115,7 +113,7 @@ curDir </> dataDir pkg_descr) (path, runArgs) <-- let exeName' = display $ exeName exe+ let exeName' = prettyShow $ exeName exe in case compilerFlavor (compiler lbi) of GHCJS -> do let (script, cmd, cmdArgs) =@@ -139,5 +137,5 @@ paths <- depLibraryPaths True False lbi clbi return (addLibraryPath os paths env) else return env- notice verbosity $ "Running " ++ display (exeName exe) ++ "..."+ notice verbosity $ "Running " ++ prettyShow (exeName exe) ++ "..." rawSystemExitWithEnv verbosity path (runArgs++exeArgs) env'
cabal/cabal-install/Distribution/Client/Sandbox.hs view
@@ -1,5 +1,6 @@ {-# LANGUAGE CPP #-} {-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-} ----------------------------------------------------------------------------- -- | -- Module : Distribution.Client.Sandbox@@ -10,33 +11,9 @@ ----------------------------------------------------------------------------- module Distribution.Client.Sandbox (- sandboxInit,- sandboxDelete,- sandboxAddSource,- sandboxAddSourceSnapshot,- sandboxDeleteSource,- sandboxListSources,- sandboxHcPkg,- dumpPackageEnvironment,- withSandboxBinDirOnSearchPath,-- getSandboxConfigFilePath, loadConfigOrSandboxConfig, findSavedDistPref,- initPackageDBIfNeeded,- maybeWithSandboxDirOnSearchPath, - WereDepsReinstalled(..),- reinstallAddSourceDeps,- maybeReinstallAddSourceDeps,-- SandboxPackageInfo(..),- maybeWithSandboxPackageInfo,-- tryGetIndexFilePath,- sandboxBuildDir,- getInstalledPackagesInSandbox,- updateSandboxConfigFileFlag, updateInstallDirs, getPersistOrConfigCompiler@@ -44,529 +21,41 @@ import Prelude () import Distribution.Client.Compat.Prelude-import Distribution.Utils.Generic(safeLast) import Distribution.Client.Setup- ( SandboxFlags(..), ConfigFlags(..), ConfigExFlags(..), InstallFlags(..)- , GlobalFlags(..), configCompilerAux', configPackageDB'- , defaultConfigExFlags, defaultInstallFlags- , defaultSandboxLocation, withRepoContext )-import Distribution.Client.Sandbox.Timestamp ( listModifiedDeps- , maybeAddCompilerTimestampRecord- , withAddTimestamps- , removeTimestamps )+ ( ConfigFlags(..), GlobalFlags(..), configCompilerAux' ) import Distribution.Client.Config ( SavedConfig(..), defaultUserInstall, loadConfig )-import Distribution.Client.Dependency ( foldProgress )-import Distribution.Client.IndexUtils ( BuildTreeRefType(..) )-import Distribution.Client.Install ( InstallArgs,- makeInstallContext,- makeInstallPlan,- processInstallPlan )-import Distribution.Utils.NubList ( fromNubList ) import Distribution.Client.Sandbox.PackageEnvironment- ( PackageEnvironment(..), PackageEnvironmentType(..)- , createPackageEnvironmentFile, classifyPackageEnvironment- , tryLoadSandboxPackageEnvironmentFile, loadUserConfig- , commentPackageEnvironment, showPackageEnvironmentWithComments- , sandboxPackageEnvironmentFile, userPackageEnvironmentFile- , sandboxPackageDBPath )-import Distribution.Client.Sandbox.Types ( SandboxPackageInfo(..)- , UseSandbox(..) )+ ( PackageEnvironmentType(..)+ , classifyPackageEnvironment+ , loadUserConfig+ ) import Distribution.Client.SetupWrapper ( SetupScriptOptions(..), defaultSetupScriptOptions )-import Distribution.Client.Types ( PackageLocation(..) )-import Distribution.Client.Utils ( inDir, tryCanonicalizePath- , tryFindAddSourcePackageDesc)-import Distribution.PackageDescription.Configuration- ( flattenPackageDescription )-import Distribution.PackageDescription.Parsec ( readGenericPackageDescription )-import Distribution.Simple.Compiler ( Compiler(..), PackageDB(..) )-import Distribution.Simple.Configure ( configCompilerAuxEx- , getPackageDBContents- , maybeGetPersistBuildConfig+import Distribution.Simple.Compiler ( Compiler(..) )+import Distribution.Simple.Configure ( maybeGetPersistBuildConfig , findDistPrefOrDefault , findDistPref ) import qualified Distribution.Simple.LocalBuildInfo as LocalBuildInfo-import Distribution.Simple.PreProcess ( knownSuffixHandlers ) import Distribution.Simple.Program ( ProgramDb )-import Distribution.Simple.Setup ( Flag(..), HaddockFlags(..)- , emptyTestFlags, emptyBenchmarkFlags+import Distribution.Simple.Setup ( Flag(..) , fromFlagOrDefault, flagToMaybe )-import Distribution.Simple.SrcDist ( prepareTree )-import Distribution.Simple.Utils ( die', debug, notice, info, warn- , debugNoWrap, defaultPackageDesc- , topHandlerWith- , createDirectoryIfMissingVerbose )-import Distribution.Package ( Package(..) ) import Distribution.System ( Platform )-import Distribution.Deprecated.Text ( display )-import Distribution.Verbosity ( Verbosity )-import Distribution.Compat.Environment ( lookupEnv, setEnv )-import Distribution.Client.Compat.FilePerms ( setFileHidden )-import qualified Distribution.Client.Sandbox.Index as Index-import Distribution.Simple.PackageIndex ( InstalledPackageIndex )-import qualified Distribution.Simple.PackageIndex as InstalledPackageIndex-import qualified Distribution.Simple.Register as Register -import Distribution.Solver.Types.SourcePackage+import System.Directory ( getCurrentDirectory ) -import qualified Data.Map as M-import qualified Data.Set as S-import Data.Either (partitionEithers)-import Control.Exception ( assert, bracket_ )-import Control.Monad ( forM, mapM, mapM_ )-import Data.Bits ( shiftL, shiftR, xor )-import Data.IORef ( newIORef, writeIORef, readIORef )-import Data.List ( delete- , groupBy )-import Data.Maybe ( fromJust )-import Numeric ( showHex )-import System.Directory ( canonicalizePath- , createDirectory- , doesDirectoryExist- , doesFileExist- , getCurrentDirectory- , removeDirectoryRecursive- , removeFile- , renameDirectory )-import System.FilePath ( (</>), equalFilePath- , getSearchPath- , searchPathSeparator- , splitSearchPath- , takeDirectory ) ------ * Constants------- | The name of the sandbox subdirectory where we keep snapshots of add-source--- dependencies.-snapshotDirectoryName :: FilePath-snapshotDirectoryName = "snapshots"---- | Non-standard build dir that is used for building add-source deps instead of--- "dist". Fixes surprising behaviour in some cases (see issue #1281).-sandboxBuildDir :: FilePath -> FilePath-sandboxBuildDir sandboxDir = "dist/dist-sandbox-" ++ showHex sandboxDirHash ""- where- sandboxDirHash = jenkins sandboxDir-- -- See http://en.wikipedia.org/wiki/Jenkins_hash_function- jenkins :: String -> Word32- jenkins str = loop_finish $ foldl' loop 0 str- where- loop :: Word32 -> Char -> Word32- loop hash key_i' = hash'''- where- key_i = toEnum . ord $ key_i'- hash' = hash + key_i- hash'' = hash' + (shiftL hash' 10)- hash''' = hash'' `xor` (shiftR hash'' 6)-- loop_finish :: Word32 -> Word32- loop_finish hash = hash'''- where- hash' = hash + (shiftL hash 3)- hash'' = hash' `xor` (shiftR hash' 11)- hash''' = hash'' + (shiftL hash'' 15)---- -- * Basic sandbox functions. -- --- | If @--sandbox-config-file@ wasn't given on the command-line, set it to the--- value of the @CABAL_SANDBOX_CONFIG@ environment variable, or else to--- 'NoFlag'.-updateSandboxConfigFileFlag :: GlobalFlags -> IO GlobalFlags-updateSandboxConfigFileFlag globalFlags =- case globalSandboxConfigFile globalFlags of- Flag _ -> return globalFlags- NoFlag -> do- f' <- fmap (maybe NoFlag Flag) . lookupEnv $ "CABAL_SANDBOX_CONFIG"- return globalFlags { globalSandboxConfigFile = f' }---- | Return the path to the sandbox config file - either the default or the one--- specified with @--sandbox-config-file@.-getSandboxConfigFilePath :: GlobalFlags -> IO FilePath-getSandboxConfigFilePath globalFlags = do- let sandboxConfigFileFlag = globalSandboxConfigFile globalFlags- case sandboxConfigFileFlag of- NoFlag -> do pkgEnvDir <- getCurrentDirectory- return (pkgEnvDir </> sandboxPackageEnvironmentFile)- Flag path -> return path---- | Load the @cabal.sandbox.config@ file (and possibly the optional--- @cabal.config@). In addition to a @PackageEnvironment@, also return a--- canonical path to the sandbox. Exit with error if the sandbox directory or--- the package environment file do not exist.-tryLoadSandboxConfig :: Verbosity -> GlobalFlags- -> IO (FilePath, PackageEnvironment)-tryLoadSandboxConfig verbosity globalFlags = do- path <- getSandboxConfigFilePath globalFlags- tryLoadSandboxPackageEnvironmentFile verbosity path- (globalConfigFile globalFlags)---- | Return the name of the package index file for this package environment.-tryGetIndexFilePath :: Verbosity -> SavedConfig -> IO FilePath-tryGetIndexFilePath verbosity config = tryGetIndexFilePath' verbosity (savedGlobalFlags config)---- | The same as 'tryGetIndexFilePath', but takes 'GlobalFlags' instead of--- 'SavedConfig'.-tryGetIndexFilePath' :: Verbosity -> GlobalFlags -> IO FilePath-tryGetIndexFilePath' verbosity globalFlags = do- let paths = fromNubList $ globalLocalRepos globalFlags- case safeLast paths of- Nothing -> die' verbosity $ "Distribution.Client.Sandbox.tryGetIndexFilePath: " ++- "no local repos found. " ++ checkConfiguration- Just lp -> return $ lp </> Index.defaultIndexFileName- where- checkConfiguration = "Please check your configuration ('"- ++ userPackageEnvironmentFile ++ "')."---- | Try to extract a 'PackageDB' from 'ConfigFlags'. Gives a better error--- message than just pattern-matching.-getSandboxPackageDB :: Verbosity -> ConfigFlags -> IO PackageDB-getSandboxPackageDB verbosity configFlags = do- case configPackageDBs configFlags of- [Just sandboxDB@(SpecificPackageDB _)] -> return sandboxDB- -- TODO: should we allow multiple package DBs (e.g. with 'inherit')?-- [] ->- die' verbosity $ "Sandbox package DB is not specified. " ++ sandboxConfigCorrupt- [_] ->- die' verbosity $ "Unexpected contents of the 'package-db' field. "- ++ sandboxConfigCorrupt- _ ->- die' verbosity $ "Too many package DBs provided. " ++ sandboxConfigCorrupt-- where- sandboxConfigCorrupt = "Your 'cabal.sandbox.config' is probably corrupt."----- | Which packages are installed in the sandbox package DB?-getInstalledPackagesInSandbox :: Verbosity -> ConfigFlags- -> Compiler -> ProgramDb- -> IO InstalledPackageIndex-getInstalledPackagesInSandbox verbosity configFlags comp progdb = do- sandboxDB <- getSandboxPackageDB verbosity configFlags- getPackageDBContents verbosity comp sandboxDB progdb---- | Temporarily add $SANDBOX_DIR/bin to $PATH.-withSandboxBinDirOnSearchPath :: FilePath -> IO a -> IO a-withSandboxBinDirOnSearchPath sandboxDir = bracket_ addBinDir rmBinDir- where- -- TODO: Instead of modifying the global process state, it'd be better to- -- set the environment individually for each subprocess invocation. This- -- will have to wait until the Shell monad is implemented; without it the- -- required changes are too intrusive.- addBinDir :: IO ()- addBinDir = do- mbOldPath <- lookupEnv "PATH"- let newPath = maybe sandboxBin ((++) sandboxBin . (:) searchPathSeparator)- mbOldPath- setEnv "PATH" newPath-- rmBinDir :: IO ()- rmBinDir = do- oldPath <- getSearchPath- let newPath = intercalate [searchPathSeparator]- (delete sandboxBin oldPath)- setEnv "PATH" newPath-- sandboxBin = sandboxDir </> "bin"---- | Initialise a package DB for this compiler if it doesn't exist.-initPackageDBIfNeeded :: Verbosity -> ConfigFlags- -> Compiler -> ProgramDb- -> IO ()-initPackageDBIfNeeded verbosity configFlags comp progdb = do- SpecificPackageDB dbPath <- getSandboxPackageDB verbosity configFlags- packageDBExists <- doesDirectoryExist dbPath- unless packageDBExists $- Register.initPackageDB verbosity comp progdb dbPath- when packageDBExists $- debug verbosity $ "The package database already exists: " ++ dbPath---- | Entry point for the 'cabal sandbox dump-pkgenv' command.-dumpPackageEnvironment :: Verbosity -> SandboxFlags -> GlobalFlags -> IO ()-dumpPackageEnvironment verbosity _sandboxFlags globalFlags = do- (sandboxDir, pkgEnv) <- tryLoadSandboxConfig verbosity globalFlags- commentPkgEnv <- commentPackageEnvironment sandboxDir- putStrLn . showPackageEnvironmentWithComments (Just commentPkgEnv) $ pkgEnv---- | Entry point for the 'cabal sandbox init' command.-sandboxInit :: Verbosity -> SandboxFlags -> GlobalFlags -> IO ()-sandboxInit verbosity sandboxFlags globalFlags = do- -- Warn if there's a 'cabal-dev' sandbox.- isCabalDevSandbox <- liftM2 (&&) (doesDirectoryExist "cabal-dev")- (doesFileExist $ "cabal-dev" </> "cabal.config")- when isCabalDevSandbox $- warn verbosity $- "You are apparently using a legacy (cabal-dev) sandbox. "- ++ "Legacy sandboxes may interact badly with native Cabal sandboxes. "- ++ "You may want to delete the 'cabal-dev' directory to prevent issues."-- -- Create the sandbox directory.- let sandboxDir' = fromFlagOrDefault defaultSandboxLocation- (sandboxLocation sandboxFlags)- createDirectoryIfMissingVerbose verbosity True sandboxDir'- sandboxDir <- tryCanonicalizePath sandboxDir'- setFileHidden sandboxDir-- -- Determine which compiler to use (using the value from ~/.cabal/config).- userConfig <- loadConfig verbosity (globalConfigFile globalFlags)- (comp, platform, progdb) <- configCompilerAuxEx (savedConfigureFlags userConfig)-- -- Create the package environment file.- pkgEnvFile <- getSandboxConfigFilePath globalFlags- createPackageEnvironmentFile verbosity sandboxDir pkgEnvFile comp platform- (_sandboxDir, pkgEnv) <- tryLoadSandboxConfig verbosity globalFlags- let config = pkgEnvSavedConfig pkgEnv- configFlags = savedConfigureFlags config-- -- Create the index file if it doesn't exist.- indexFile <- tryGetIndexFilePath verbosity config- indexFileExists <- doesFileExist indexFile- if indexFileExists- then notice verbosity $ "Using an existing sandbox located at " ++ sandboxDir- else notice verbosity $ "Creating a new sandbox at " ++ sandboxDir- Index.createEmpty verbosity indexFile-- -- Create the package DB for the default compiler.- initPackageDBIfNeeded verbosity configFlags comp progdb- maybeAddCompilerTimestampRecord verbosity sandboxDir indexFile- (compilerId comp) platform---- | Entry point for the 'cabal sandbox delete' command.-sandboxDelete :: Verbosity -> SandboxFlags -> GlobalFlags -> IO ()-sandboxDelete verbosity _sandboxFlags globalFlags = do- (useSandbox, _) <- loadConfigOrSandboxConfig- verbosity- globalFlags { globalRequireSandbox = Flag False }- case useSandbox of- NoSandbox -> warn verbosity "Not in a sandbox."- UseSandbox sandboxDir -> do- curDir <- getCurrentDirectory- pkgEnvFile <- getSandboxConfigFilePath globalFlags-- -- Remove the @cabal.sandbox.config@ file, unless it's in a non-standard- -- location.- let isNonDefaultConfigLocation = not $ equalFilePath pkgEnvFile $- curDir </> sandboxPackageEnvironmentFile-- if isNonDefaultConfigLocation- then warn verbosity $ "Sandbox config file is in non-default location: '"- ++ pkgEnvFile ++ "'.\n Please delete manually."- else removeFile pkgEnvFile-- -- Remove the sandbox directory, unless we're using a shared sandbox.- let isNonDefaultSandboxLocation = not $ equalFilePath sandboxDir $- curDir </> defaultSandboxLocation-- when isNonDefaultSandboxLocation $- die' verbosity $ "Non-default sandbox location used: '" ++ sandboxDir- ++ "'.\nAssuming a shared sandbox. Please delete '"- ++ sandboxDir ++ "' manually."-- absSandboxDir <- canonicalizePath sandboxDir- notice verbosity $ "Deleting the sandbox located at " ++ absSandboxDir- removeDirectoryRecursive absSandboxDir-- let- pathInsideSandbox = isPrefixOf absSandboxDir-- -- Warn the user if deleting the sandbox deleted a package database- -- referenced in the current environment.- checkPackagePaths var = do- let- checkPath path = do- absPath <- canonicalizePath path- (when (pathInsideSandbox absPath) . warn verbosity)- (var ++ " refers to package database " ++ path- ++ " inside the deleted sandbox.")- liftM (maybe [] splitSearchPath) (lookupEnv var) >>= mapM_ checkPath-- checkPackagePaths "CABAL_SANDBOX_PACKAGE_PATH"- checkPackagePaths "GHC_PACKAGE_PATH"- checkPackagePaths "GHCJS_PACKAGE_PATH"---- Common implementation of 'sandboxAddSource' and 'sandboxAddSourceSnapshot'.-doAddSource :: Verbosity -> [FilePath] -> FilePath -> PackageEnvironment- -> BuildTreeRefType- -> IO ()-doAddSource verbosity buildTreeRefs sandboxDir pkgEnv refType = do- let savedConfig = pkgEnvSavedConfig pkgEnv- indexFile <- tryGetIndexFilePath verbosity savedConfig-- -- If we're running 'sandbox add-source' for the first time for this compiler,- -- we need to create an initial timestamp record.- (comp, platform, _) <- configCompilerAuxEx . savedConfigureFlags $ savedConfig- maybeAddCompilerTimestampRecord verbosity sandboxDir indexFile- (compilerId comp) platform-- withAddTimestamps verbosity sandboxDir $ do- -- Path canonicalisation is done in addBuildTreeRefs, but we do it- -- twice because of the timestamps file.- buildTreeRefs' <- mapM tryCanonicalizePath buildTreeRefs- Index.addBuildTreeRefs verbosity indexFile buildTreeRefs' refType- return buildTreeRefs'---- | Entry point for the 'cabal sandbox add-source' command.-sandboxAddSource :: Verbosity -> [FilePath] -> SandboxFlags -> GlobalFlags- -> IO ()-sandboxAddSource verbosity buildTreeRefs sandboxFlags globalFlags = do- (sandboxDir, pkgEnv) <- tryLoadSandboxConfig verbosity globalFlags-- if fromFlagOrDefault False (sandboxSnapshot sandboxFlags)- then sandboxAddSourceSnapshot verbosity buildTreeRefs sandboxDir pkgEnv- else doAddSource verbosity buildTreeRefs sandboxDir pkgEnv LinkRef---- | Entry point for the 'cabal sandbox add-source --snapshot' command.-sandboxAddSourceSnapshot :: Verbosity -> [FilePath] -> FilePath- -> PackageEnvironment- -> IO ()-sandboxAddSourceSnapshot verbosity buildTreeRefs sandboxDir pkgEnv = do- let snapshotDir = sandboxDir </> snapshotDirectoryName-- -- Use 'D.S.SrcDist.prepareTree' to copy each package's files to our private- -- location.- createDirectoryIfMissingVerbose verbosity True snapshotDir-- -- Collect the package descriptions first, so that if some path does not refer- -- to a cabal package, we fail immediately.- pkgs <- forM buildTreeRefs $ \buildTreeRef ->- inDir (Just buildTreeRef) $- return . flattenPackageDescription- =<< readGenericPackageDescription verbosity- =<< defaultPackageDesc verbosity-- -- Copy the package sources to "snapshots/$PKGNAME-$VERSION-tmp". If- -- 'prepareTree' throws an error at any point, the old snapshots will still be- -- in consistent state.- tmpDirs <- forM (zip buildTreeRefs pkgs) $ \(buildTreeRef, pkg) ->- inDir (Just buildTreeRef) $ do- let targetDir = snapshotDir </> (display . packageId $ pkg)- targetTmpDir = targetDir ++ "-tmp"- dirExists <- doesDirectoryExist targetTmpDir- when dirExists $- removeDirectoryRecursive targetDir- createDirectory targetTmpDir- prepareTree verbosity pkg Nothing targetTmpDir knownSuffixHandlers- return (targetTmpDir, targetDir)-- -- Now rename the "snapshots/$PKGNAME-$VERSION-tmp" dirs to- -- "snapshots/$PKGNAME-$VERSION".- snapshots <- forM tmpDirs $ \(targetTmpDir, targetDir) -> do- dirExists <- doesDirectoryExist targetDir- when dirExists $- removeDirectoryRecursive targetDir- renameDirectory targetTmpDir targetDir- return targetDir-- -- Once the packages are copied, just 'add-source' them as usual.- doAddSource verbosity snapshots sandboxDir pkgEnv SnapshotRef---- | Entry point for the 'cabal sandbox delete-source' command.-sandboxDeleteSource :: Verbosity -> [FilePath] -> SandboxFlags -> GlobalFlags- -> IO ()-sandboxDeleteSource verbosity buildTreeRefs _sandboxFlags globalFlags = do- (sandboxDir, pkgEnv) <- tryLoadSandboxConfig verbosity globalFlags- indexFile <- tryGetIndexFilePath verbosity (pkgEnvSavedConfig pkgEnv)-- (results, convDict) <-- Index.removeBuildTreeRefs verbosity indexFile buildTreeRefs-- let (failedPaths, removedPaths) = partitionEithers results- removedRefs = fmap convDict removedPaths-- unless (null removedPaths) $ do- removeTimestamps verbosity sandboxDir removedPaths-- notice verbosity $ "Success deleting sources: " ++- showL removedRefs ++ "\n\n"-- unless (null failedPaths) $ do- let groupedFailures = groupBy errorType failedPaths- mapM_ handleErrors groupedFailures- die' verbosity $ "The sources with the above errors were skipped. (" ++- showL (fmap getPath failedPaths) ++ ")"-- notice verbosity $ "Note: 'sandbox delete-source' only unregisters the " ++- "source dependency, but does not remove the package " ++- "from the sandbox package DB.\n\n" ++- "Use 'sandbox hc-pkg -- unregister' to do that."- where- getPath (Index.ErrNonregisteredSource p) = p- getPath (Index.ErrNonexistentSource p) = p-- showPaths f = concat . intersperse " " . fmap (show . f)-- showL = showPaths id-- showE [] = return ' '- showE errs = showPaths getPath errs-- errorType Index.ErrNonregisteredSource{} Index.ErrNonregisteredSource{} =- True- errorType Index.ErrNonexistentSource{} Index.ErrNonexistentSource{} = True- errorType _ _ = False-- handleErrors [] = return ()- handleErrors errs@(Index.ErrNonregisteredSource{}:_) =- warn verbosity ("Sources not registered: " ++ showE errs ++ "\n\n")- handleErrors errs@(Index.ErrNonexistentSource{}:_) =- warn verbosity- ("Source directory not found for paths: " ++ showE errs ++ "\n"- ++ "If you are trying to delete a reference to a removed directory, "- ++ "please provide the full absolute path "- ++ "(as given by `sandbox list-sources`).\n\n")---- | Entry point for the 'cabal sandbox list-sources' command.-sandboxListSources :: Verbosity -> SandboxFlags -> GlobalFlags- -> IO ()-sandboxListSources verbosity _sandboxFlags globalFlags = do- (sandboxDir, pkgEnv) <- tryLoadSandboxConfig verbosity globalFlags- indexFile <- tryGetIndexFilePath verbosity (pkgEnvSavedConfig pkgEnv)-- refs <- Index.listBuildTreeRefs verbosity- Index.ListIgnored Index.LinksAndSnapshots indexFile- when (null refs) $- notice verbosity $ "Index file '" ++ indexFile- ++ "' has no references to local build trees."- when (not . null $ refs) $ do- notice verbosity $ "Source dependencies registered "- ++ "in the current sandbox ('" ++ sandboxDir ++ "'):\n\n"- mapM_ putStrLn refs- notice verbosity $ "\nTo unregister source dependencies, "- ++ "use the 'sandbox delete-source' command."---- | Entry point for the 'cabal sandbox hc-pkg' command. Invokes the @hc-pkg@--- tool with provided arguments, restricted to the sandbox.-sandboxHcPkg :: Verbosity -> SandboxFlags -> GlobalFlags -> [String] -> IO ()-sandboxHcPkg verbosity _sandboxFlags globalFlags extraArgs = do- (sandboxDir, pkgEnv) <- tryLoadSandboxConfig verbosity globalFlags- let configFlags = savedConfigureFlags . pkgEnvSavedConfig $ pkgEnv- -- Invoke hc-pkg for the most recently configured compiler (if any),- -- using the right package-db for the compiler (see #1935).- (comp, platform, progdb) <- getPersistOrConfigCompiler configFlags- let dir = sandboxPackageDBPath sandboxDir comp platform- dbStack = [GlobalPackageDB, SpecificPackageDB dir]- Register.invokeHcPkg verbosity comp progdb dbStack extraArgs--updateInstallDirs :: Flag Bool- -> (UseSandbox, SavedConfig) -> (UseSandbox, SavedConfig)-updateInstallDirs userInstallFlag (useSandbox, savedConfig) =- case useSandbox of- NoSandbox ->- let savedConfig' = savedConfig {- savedConfigureFlags = configureFlags {- configInstallDirs = installDirs- }- }- in (useSandbox, savedConfig')- _ -> (useSandbox, savedConfig)+updateInstallDirs :: Flag Bool -> SavedConfig -> SavedConfig+updateInstallDirs userInstallFlag savedConfig = savedConfig+ { savedConfigureFlags = configureFlags+ { configInstallDirs = installDirs+ }+ } where configureFlags = savedConfigureFlags savedConfig userInstallDirs = savedUserInstallDirs savedConfig@@ -582,30 +71,19 @@ loadConfigOrSandboxConfig :: Verbosity -> GlobalFlags -- ^ For @--config-file@ and -- @--sandbox-config-file@.- -> IO (UseSandbox, SavedConfig)+ -> IO SavedConfig loadConfigOrSandboxConfig verbosity globalFlags = do let configFileFlag = globalConfigFile globalFlags- sandboxConfigFileFlag = globalSandboxConfigFile globalFlags- ignoreSandboxFlag = globalIgnoreSandbox globalFlags - pkgEnvDir <- getPkgEnvDir sandboxConfigFileFlag- pkgEnvType <- classifyPackageEnvironment pkgEnvDir sandboxConfigFileFlag- ignoreSandboxFlag+ pkgEnvDir <- getCurrentDirectory+ pkgEnvType <- classifyPackageEnvironment pkgEnvDir case pkgEnvType of- -- A @cabal.sandbox.config@ file (and possibly @cabal.config@) is present.- SandboxPackageEnvironment -> do- (sandboxDir, pkgEnv) <- tryLoadSandboxConfig verbosity globalFlags- -- Prints an error message and exits on error.- let config = pkgEnvSavedConfig pkgEnv- return (UseSandbox sandboxDir, config)- -- Only @cabal.config@ is present. UserPackageEnvironment -> do config <- loadConfig verbosity configFileFlag userConfig <- loadUserConfig verbosity pkgEnvDir Nothing let config' = config `mappend` userConfig- dieIfSandboxRequired config'- return (NoSandbox, config')+ return config' -- Neither @cabal.sandbox.config@ nor @cabal.config@ are present. AmbientPackageEnvironment -> do@@ -615,30 +93,7 @@ globalConstraintConfig <- loadUserConfig verbosity pkgEnvDir globalConstraintsOpt let config' = config `mappend` globalConstraintConfig- dieIfSandboxRequired config- return (NoSandbox, config')-- where- -- Return the path to the package environment directory - either the- -- current directory or the one that @--sandbox-config-file@ resides in.- getPkgEnvDir :: (Flag FilePath) -> IO FilePath- getPkgEnvDir sandboxConfigFileFlag = do- case sandboxConfigFileFlag of- NoFlag -> getCurrentDirectory- Flag path -> tryCanonicalizePath . takeDirectory $ path-- -- Die if @--require-sandbox@ was specified and we're not inside a sandbox.- dieIfSandboxRequired :: SavedConfig -> IO ()- dieIfSandboxRequired config = checkFlag flag- where- flag = (globalRequireSandbox . savedGlobalFlags $ config)- `mappend` (globalRequireSandbox globalFlags)- checkFlag (Flag True) =- die' verbosity $ "'require-sandbox' is set to True, but no sandbox is present. "- ++ "Use '--no-require-sandbox' if you want to override "- ++ "'require-sandbox' temporarily."- checkFlag (Flag False) = return ()- checkFlag (NoFlag) = return ()+ return config' -- | Return the saved \"dist/\" prefix, or the default prefix. findSavedDistPref :: SavedConfig -> Flag FilePath -> IO FilePath@@ -648,208 +103,6 @@ `mappend` flagDistPref findDistPref defDistPref flagDistPref' --- | If we're in a sandbox, call @withSandboxBinDirOnSearchPath@, otherwise do--- nothing.-maybeWithSandboxDirOnSearchPath :: UseSandbox -> IO a -> IO a-maybeWithSandboxDirOnSearchPath NoSandbox act = act-maybeWithSandboxDirOnSearchPath (UseSandbox sandboxDir) act =- withSandboxBinDirOnSearchPath sandboxDir $ act---- | Had reinstallAddSourceDeps actually reinstalled any dependencies?-data WereDepsReinstalled = ReinstalledSomeDeps | NoDepsReinstalled---- | Reinstall those add-source dependencies that have been modified since--- we've last installed them. Assumes that we're working inside a sandbox.-reinstallAddSourceDeps :: Verbosity- -> ConfigFlags -> ConfigExFlags- -> InstallFlags -> GlobalFlags- -> FilePath- -> IO WereDepsReinstalled-reinstallAddSourceDeps verbosity configFlags' configExFlags- installFlags globalFlags sandboxDir = topHandler' $ do- let sandboxDistPref = sandboxBuildDir sandboxDir- configFlags = configFlags'- { configDistPref = Flag sandboxDistPref }- haddockFlags = mempty- { haddockDistPref = Flag sandboxDistPref }- (comp, platform, progdb) <- configCompilerAux' configFlags- retVal <- newIORef NoDepsReinstalled-- withSandboxPackageInfo verbosity configFlags globalFlags- comp platform progdb sandboxDir $ \sandboxPkgInfo ->- unless (null $ modifiedAddSourceDependencies sandboxPkgInfo) $ do-- withRepoContext verbosity globalFlags $ \repoContext -> do- let args :: InstallArgs- args = ((configPackageDB' configFlags)- ,repoContext- ,comp, platform, progdb- ,UseSandbox sandboxDir, Just sandboxPkgInfo- ,globalFlags, configFlags, configExFlags, installFlags- ,haddockFlags, emptyTestFlags, emptyBenchmarkFlags)-- -- This can actually be replaced by a call to 'install', but we use a- -- lower-level API because of layer separation reasons. Additionally, we- -- might want to use some lower-level features this in the future.- withSandboxBinDirOnSearchPath sandboxDir $ do- installContext <- makeInstallContext verbosity args Nothing- installPlan <- foldProgress logMsg die'' return =<<- makeInstallPlan verbosity args installContext-- processInstallPlan verbosity args installContext installPlan- writeIORef retVal ReinstalledSomeDeps-- readIORef retVal-- where- die'' message = die' verbosity (message ++ installFailedInSandbox)- -- TODO: use a better error message, remove duplication.- installFailedInSandbox =- "Note: when using a sandbox, all packages are required to have "- ++ "consistent dependencies. Try reinstalling/unregistering the "- ++ "offending packages or recreating the sandbox."- logMsg message rest = debugNoWrap verbosity message >> rest-- topHandler' = topHandlerWith $ \_ -> do- warn verbosity "Couldn't reinstall some add-source dependencies."- -- Here we can't know whether any deps have been reinstalled, so we have- -- to be conservative.- return ReinstalledSomeDeps---- | Produce a 'SandboxPackageInfo' and feed it to the given action. Note that--- we don't update the timestamp file here - this is done in--- 'postInstallActions'.-withSandboxPackageInfo :: Verbosity -> ConfigFlags -> GlobalFlags- -> Compiler -> Platform -> ProgramDb- -> FilePath- -> (SandboxPackageInfo -> IO ())- -> IO ()-withSandboxPackageInfo verbosity configFlags globalFlags- comp platform progdb sandboxDir cont = do- -- List all add-source deps.- indexFile <- tryGetIndexFilePath' verbosity globalFlags- buildTreeRefs <- Index.listBuildTreeRefs verbosity- Index.DontListIgnored Index.OnlyLinks indexFile- let allAddSourceDepsSet = S.fromList buildTreeRefs-- -- List all packages installed in the sandbox.- installedPkgIndex <- getInstalledPackagesInSandbox verbosity- configFlags comp progdb- let err = "Error reading sandbox package information."- -- Get the package descriptions for all add-source deps.- depsCabalFiles <- mapM (flip (tryFindAddSourcePackageDesc verbosity) err) buildTreeRefs- depsPkgDescs <- mapM (readGenericPackageDescription verbosity) depsCabalFiles- let depsMap = M.fromList (zip buildTreeRefs depsPkgDescs)- isInstalled pkgid = not . null- . InstalledPackageIndex.lookupSourcePackageId installedPkgIndex $ pkgid- installedDepsMap = M.filter (isInstalled . packageId) depsMap-- -- Get the package ids of modified (and installed) add-source deps.- modifiedAddSourceDeps <- listModifiedDeps verbosity sandboxDir- (compilerId comp) platform installedDepsMap- -- 'fromJust' here is safe because 'modifiedAddSourceDeps' are guaranteed to- -- be a subset of the keys of 'depsMap'.- let modifiedDeps = [ (modDepPath, fromJust $ M.lookup modDepPath depsMap)- | modDepPath <- modifiedAddSourceDeps ]- modifiedDepsMap = M.fromList modifiedDeps-- assert (all (`S.member` allAddSourceDepsSet) modifiedAddSourceDeps) (return ())- if (null modifiedDeps)- then info verbosity $ "Found no modified add-source deps."- else notice verbosity $ "Some add-source dependencies have been modified. "- ++ "They will be reinstalled..."-- -- Get the package ids of the remaining add-source deps (some are possibly not- -- installed).- let otherDeps = M.assocs (depsMap `M.difference` modifiedDepsMap)-- -- Finally, assemble a 'SandboxPackageInfo'.- cont $ SandboxPackageInfo (map toSourcePackage modifiedDeps)- (map toSourcePackage otherDeps) installedPkgIndex allAddSourceDepsSet-- where- toSourcePackage (path, pkgDesc) = SourcePackage- (packageId pkgDesc) pkgDesc (LocalUnpackedPackage path) Nothing---- | Same as 'withSandboxPackageInfo' if we're inside a sandbox and the--- identity otherwise.-maybeWithSandboxPackageInfo :: Verbosity -> ConfigFlags -> GlobalFlags- -> Compiler -> Platform -> ProgramDb- -> UseSandbox- -> (Maybe SandboxPackageInfo -> IO ())- -> IO ()-maybeWithSandboxPackageInfo verbosity configFlags globalFlags- comp platform progdb useSandbox cont =- case useSandbox of- NoSandbox -> cont Nothing- UseSandbox sandboxDir -> withSandboxPackageInfo verbosity- configFlags globalFlags- comp platform progdb sandboxDir- (\spi -> cont (Just spi))---- | Check if a sandbox is present and call @reinstallAddSourceDeps@ in that--- case.-maybeReinstallAddSourceDeps :: Verbosity- -> Flag (Maybe Int) -- ^ The '-j' flag- -> ConfigFlags -- ^ Saved configure flags- -- (from dist/setup-config)- -> GlobalFlags- -> (UseSandbox, SavedConfig)- -> IO WereDepsReinstalled-maybeReinstallAddSourceDeps verbosity numJobsFlag configFlags'- globalFlags' (useSandbox, config) = do- case useSandbox of- NoSandbox -> return NoDepsReinstalled- UseSandbox sandboxDir -> do- -- Reinstall the modified add-source deps.- let configFlags = savedConfigureFlags config- `mappendSomeSavedFlags`- configFlags'- configExFlags = defaultConfigExFlags- `mappend` savedConfigureExFlags config- installFlags' = defaultInstallFlags- `mappend` savedInstallFlags config- installFlags = installFlags' {- installNumJobs = installNumJobs installFlags'- `mappend` numJobsFlag- }- globalFlags = savedGlobalFlags config- -- This makes it possible to override things like 'remote-repo-cache'- -- from the command line. These options are hidden, and are only- -- useful for debugging, so this should be fine.- `mappend` globalFlags'- reinstallAddSourceDeps- verbosity configFlags configExFlags- installFlags globalFlags sandboxDir-- where-- -- NOTE: we can't simply do @sandboxConfigFlags `mappend` savedFlags@- -- because we don't want to auto-enable things like 'library-profiling' for- -- all add-source dependencies even if the user has passed- -- '--enable-library-profiling' to 'cabal configure'. These options are- -- supposed to be set in 'cabal.config'.- mappendSomeSavedFlags :: ConfigFlags -> ConfigFlags -> ConfigFlags- mappendSomeSavedFlags sandboxConfigFlags savedFlags =- sandboxConfigFlags {- configHcFlavor = configHcFlavor sandboxConfigFlags- `mappend` configHcFlavor savedFlags,- configHcPath = configHcPath sandboxConfigFlags- `mappend` configHcPath savedFlags,- configHcPkg = configHcPkg sandboxConfigFlags- `mappend` configHcPkg savedFlags,- configProgramPaths = configProgramPaths sandboxConfigFlags- `mappend` configProgramPaths savedFlags,- configProgramArgs = configProgramArgs sandboxConfigFlags- `mappend` configProgramArgs savedFlags,- -- NOTE: Unconditionally choosing the value from- -- 'dist/setup-config'. Sandbox package DB location may have been- -- changed by 'configure -w'.- configPackageDBs = configPackageDBs savedFlags- -- FIXME: Is this compatible with the 'inherit' feature?- }---- -- Utils (transitionary) --
− cabal/cabal-install/Distribution/Client/Sandbox/Index.hs
@@ -1,285 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Distribution.Client.Sandbox.Index--- Maintainer : cabal-devel@haskell.org--- Portability : portable------ Querying and modifying local build tree references in the package index.--------------------------------------------------------------------------------module Distribution.Client.Sandbox.Index (- createEmpty,- addBuildTreeRefs,- removeBuildTreeRefs,- ListIgnoredBuildTreeRefs(..), RefTypesToList(..),- DeleteSourceError(..),- listBuildTreeRefs,- validateIndexPath,-- defaultIndexFileName- ) where--import qualified Codec.Archive.Tar as Tar-import qualified Codec.Archive.Tar.Entry as Tar-import qualified Codec.Archive.Tar.Index as Tar-import qualified Distribution.Client.Tar as Tar-import Distribution.Client.IndexUtils ( BuildTreeRefType(..)- , refTypeFromTypeCode- , typeCodeFromRefType- , updatePackageIndexCacheFile- , readCacheStrict- , Index(..) )-import qualified Distribution.Client.IndexUtils as IndexUtils-import Distribution.Client.Utils ( byteStringToFilePath, filePathToByteString- , makeAbsoluteToCwd, tryCanonicalizePath- , tryFindAddSourcePackageDesc )--import Distribution.Simple.Utils ( die', debug )-import Distribution.Compat.Exception ( tryIO )-import Distribution.Verbosity ( Verbosity )--import qualified Data.ByteString.Lazy as BS-import Control.DeepSeq ( NFData(rnf) )-import Control.Exception ( evaluate, throw, Exception )-import Control.Monad ( liftM, unless )-import Control.Monad.Writer.Lazy (WriterT(..), runWriterT, tell)-import Data.List ( (\\), intersect, nub, find )-import Data.Maybe ( catMaybes )-import Data.Either (partitionEithers)-import System.Directory ( createDirectoryIfMissing,- doesDirectoryExist, doesFileExist,- renameFile, canonicalizePath)-import System.FilePath ( (</>), (<.>), takeDirectory, takeExtension )-import System.IO ( IOMode(..), withBinaryFile )---- | A reference to a local build tree.-data BuildTreeRef = BuildTreeRef {- buildTreeRefType :: !BuildTreeRefType,- buildTreePath :: !FilePath- }--instance NFData BuildTreeRef where- rnf (BuildTreeRef _ fp) = rnf fp--defaultIndexFileName :: FilePath-defaultIndexFileName = "00-index.tar"---- | Given a path, ensure that it refers to a local build tree.-buildTreeRefFromPath :: Verbosity -> BuildTreeRefType -> FilePath -> IO (Maybe BuildTreeRef)-buildTreeRefFromPath verbosity refType dir = do- dirExists <- doesDirectoryExist dir- unless dirExists $- die' verbosity $ "directory '" ++ dir ++ "' does not exist"- _ <- tryFindAddSourcePackageDesc verbosity dir "Error adding source reference."- return . Just $ BuildTreeRef refType dir---- | Given a tar archive entry, try to parse it as a local build tree reference.-readBuildTreeRef :: Tar.Entry -> Maybe BuildTreeRef-readBuildTreeRef entry = case Tar.entryContent entry of- (Tar.OtherEntryType typeCode bs size)- | (Tar.isBuildTreeRefTypeCode typeCode)- && (size == BS.length bs) -> Just $! BuildTreeRef- (refTypeFromTypeCode typeCode)- (byteStringToFilePath bs)- | otherwise -> Nothing- _ -> Nothing---- | Given a sequence of tar archive entries, extract all references to local--- build trees.-readBuildTreeRefs :: Exception e => Tar.Entries e -> [BuildTreeRef]-readBuildTreeRefs =- catMaybes- . Tar.foldEntries (\e r -> readBuildTreeRef e : r)- [] throw---- | Given a path to a tar archive, extract all references to local build trees.-readBuildTreeRefsFromFile :: FilePath -> IO [BuildTreeRef]-readBuildTreeRefsFromFile = liftM (readBuildTreeRefs . Tar.read) . BS.readFile---- | Read build tree references from an index cache-readBuildTreeRefsFromCache :: Verbosity -> FilePath -> IO [BuildTreeRef]-readBuildTreeRefsFromCache verbosity indexPath = do- (mRefs, _prefs) <- readCacheStrict verbosity (SandboxIndex indexPath) buildTreeRef- return (catMaybes mRefs)- where- buildTreeRef pkgEntry =- case pkgEntry of- IndexUtils.NormalPackage _ _ _ _ -> Nothing- IndexUtils.BuildTreeRef typ _ _ path _ -> Just $ BuildTreeRef typ path---- | Given a local build tree ref, serialise it to a tar archive entry.-writeBuildTreeRef :: BuildTreeRef -> Tar.Entry-writeBuildTreeRef (BuildTreeRef refType path) = Tar.simpleEntry tarPath content- where- bs = filePathToByteString path- -- Provide a filename for tools that treat custom entries as ordinary files.- tarPath' = "local-build-tree-reference"- -- fromRight can't fail because the path is shorter than 255 characters.- tarPath = fromRight $ Tar.toTarPath True tarPath'- content = Tar.OtherEntryType (typeCodeFromRefType refType) bs (BS.length bs)-- -- TODO: Move this to D.C.Utils?- fromRight (Left err) = error err- fromRight (Right a) = a---- | Check that the provided path is either an existing directory, or a tar--- archive in an existing directory.-validateIndexPath :: Verbosity -> FilePath -> IO FilePath-validateIndexPath verbosity path' = do- path <- makeAbsoluteToCwd path'- if (== ".tar") . takeExtension $ path- then return path- else do dirExists <- doesDirectoryExist path- unless dirExists $- die' verbosity $ "directory does not exist: '" ++ path ++ "'"- return $ path </> defaultIndexFileName---- | Create an empty index file.-createEmpty :: Verbosity -> FilePath -> IO ()-createEmpty verbosity path = do- indexExists <- doesFileExist path- if indexExists- then debug verbosity $ "Package index already exists: " ++ path- else do- debug verbosity $ "Creating the index file '" ++ path ++ "'"- createDirectoryIfMissing True (takeDirectory path)- -- Equivalent to 'tar cvf empty.tar --files-from /dev/null'.- let zeros = BS.replicate (512*20) 0- BS.writeFile path zeros---- | Add given local build tree references to the index.-addBuildTreeRefs :: Verbosity -> FilePath -> [FilePath] -> BuildTreeRefType- -> IO ()-addBuildTreeRefs _ _ [] _ =- error "Distribution.Client.Sandbox.Index.addBuildTreeRefs: unexpected"-addBuildTreeRefs verbosity path l' refType = do- checkIndexExists verbosity path- l <- liftM nub . mapM tryCanonicalizePath $ l'- treesInIndex <- fmap (map buildTreePath) (readBuildTreeRefsFromFile path)- -- Add only those paths that aren't already in the index.- treesToAdd <- mapM (buildTreeRefFromPath verbosity refType) (l \\ treesInIndex)- let entries = map writeBuildTreeRef (catMaybes treesToAdd)- unless (null entries) $ do- withBinaryFile path ReadWriteMode $ \h -> do- block <- Tar.hSeekEndEntryOffset h Nothing- debug verbosity $ "Writing at tar block: " ++ show block- BS.hPut h (Tar.write entries)- debug verbosity $ "Successfully appended to '" ++ path ++ "'"- updatePackageIndexCacheFile verbosity $ SandboxIndex path--data DeleteSourceError = ErrNonregisteredSource { nrPath :: FilePath }- | ErrNonexistentSource { nePath :: FilePath } deriving Show---- | Remove given local build tree references from the index.------ Returns a tuple with either removed build tree refs or errors and a function--- that converts from a provided build tree ref to corresponding full directory path.-removeBuildTreeRefs :: Verbosity -> FilePath -> [FilePath]- -> IO ([Either DeleteSourceError FilePath],- (FilePath -> FilePath))-removeBuildTreeRefs _ _ [] =- error "Distribution.Client.Sandbox.Index.removeBuildTreeRefs: unexpected"-removeBuildTreeRefs verbosity indexPath l = do- checkIndexExists verbosity indexPath- let tmpFile = indexPath <.> "tmp"-- canonRes <- mapM (\btr -> do res <- tryIO $ canonicalizePath btr- return $ case res of- Right pth -> Right (btr, pth)- Left _ -> Left $ ErrNonexistentSource btr) l- let (failures, convDict) = partitionEithers canonRes- allRefs = fmap snd convDict-- -- Performance note: on my system, it takes 'index --remove-source'- -- approx. 3,5s to filter a 65M file. Real-life indices are expected to be- -- much smaller.- removedRefs <- doRemove convDict tmpFile-- renameFile tmpFile indexPath- debug verbosity $ "Successfully renamed '" ++ tmpFile- ++ "' to '" ++ indexPath ++ "'"-- unless (null removedRefs) $- updatePackageIndexCacheFile verbosity $ SandboxIndex indexPath-- let results = fmap Right removedRefs- ++ fmap Left failures- ++ fmap (Left . ErrNonregisteredSource)- (fmap (convertWith convDict) (allRefs \\ removedRefs))-- return (results, convertWith convDict)-- where- doRemove :: [(FilePath, FilePath)] -> FilePath -> IO [FilePath]- doRemove srcRefs tmpFile = do- (newIdx, changedPaths) <-- Tar.read `fmap` BS.readFile indexPath- >>= runWriterT . Tar.filterEntriesM (p $ fmap snd srcRefs)- BS.writeFile tmpFile . Tar.write . Tar.entriesToList $ newIdx- return changedPaths-- p :: [FilePath] -> Tar.Entry -> WriterT [FilePath] IO Bool- p refs entry = case readBuildTreeRef entry of- Nothing -> return True- -- FIXME: removing snapshot deps is done with `delete-source- -- .cabal-sandbox/snapshots/$SNAPSHOT_NAME`. Perhaps we also want to- -- support removing snapshots by providing the original path.- (Just (BuildTreeRef _ pth)) -> if pth `elem` refs- then tell [pth] >> return False- else return True-- convertWith dict pth = maybe pth fst $ find ((==pth) . snd) dict---- | A build tree ref can become ignored if the user later adds a build tree ref--- with the same package ID. We display ignored build tree refs when the user--- runs 'cabal sandbox list-sources', but do not look at their timestamps in--- 'reinstallAddSourceDeps'.-data ListIgnoredBuildTreeRefs = ListIgnored | DontListIgnored---- | Which types of build tree refs should be listed?-data RefTypesToList = OnlySnapshots | OnlyLinks | LinksAndSnapshots---- | List the local build trees that are referred to from the index.-listBuildTreeRefs :: Verbosity -> ListIgnoredBuildTreeRefs -> RefTypesToList- -> FilePath- -> IO [FilePath]-listBuildTreeRefs verbosity listIgnored refTypesToList path = do- checkIndexExists verbosity path- buildTreeRefs <-- case listIgnored of- DontListIgnored -> do- paths <- listWithoutIgnored- case refTypesToList of- LinksAndSnapshots -> return paths- _ -> do- allPathsFiltered <- fmap (map buildTreePath . filter predicate)- listWithIgnored- _ <- evaluate (length allPathsFiltered)- return (paths `intersect` allPathsFiltered)-- ListIgnored -> fmap (map buildTreePath . filter predicate) listWithIgnored-- _ <- evaluate (length buildTreeRefs)- return buildTreeRefs-- where- predicate :: BuildTreeRef -> Bool- predicate = case refTypesToList of- OnlySnapshots -> (==) SnapshotRef . buildTreeRefType- OnlyLinks -> (==) LinkRef . buildTreeRefType- LinksAndSnapshots -> const True-- listWithIgnored :: IO [BuildTreeRef]- listWithIgnored = readBuildTreeRefsFromFile path-- listWithoutIgnored :: IO [FilePath]- listWithoutIgnored = fmap (map buildTreePath)- $ readBuildTreeRefsFromCache verbosity path----- | Check that the package index file exists and exit with error if it does not.-checkIndexExists :: Verbosity -> FilePath -> IO ()-checkIndexExists verbosity path = do- indexExists <- doesFileExist path- unless indexExists $- die' verbosity $ "index does not exist: '" ++ path ++ "'"
cabal/cabal-install/Distribution/Client/Sandbox/PackageEnvironment.hs view
@@ -14,71 +14,47 @@ PackageEnvironment(..) , PackageEnvironmentType(..) , classifyPackageEnvironment- , createPackageEnvironmentFile- , tryLoadSandboxPackageEnvironmentFile , readPackageEnvironmentFile , showPackageEnvironment , showPackageEnvironmentWithComments- , setPackageDB- , sandboxPackageDBPath , loadUserConfig - , basePackageEnvironment- , initialPackageEnvironment- , commentPackageEnvironment- , sandboxPackageEnvironmentFile , userPackageEnvironmentFile ) where -import Distribution.Client.Config ( SavedConfig(..), commentSavedConfig- , loadConfig, configFieldDescriptions+import Distribution.Client.Compat.Prelude+import Prelude ()++import Distribution.Client.Config ( SavedConfig(..) + , configFieldDescriptions , haddockFlagsFields , installDirsFields, withProgramsFields , withProgramOptionsFields- , defaultCompiler )+ ) import Distribution.Client.ParseUtils ( parseFields, ppFields, ppSection )-import Distribution.Client.Setup ( GlobalFlags(..), ConfigExFlags(..)- , InstallFlags(..)- , defaultSandboxLocation )+import Distribution.Client.Setup ( ConfigExFlags(..)+ ) import Distribution.Client.Targets ( userConstraintPackageName )-import Distribution.Utils.NubList ( toNubList )-import Distribution.Simple.Compiler ( Compiler, PackageDB(..)- , compilerFlavor, showCompilerIdWithAbi )-import Distribution.Simple.InstallDirs ( InstallDirs(..), PathTemplate- , defaultInstallDirs, combineInstallDirs- , fromPathTemplate, toPathTemplate )+import Distribution.Simple.InstallDirs ( InstallDirs(..), PathTemplate ) import Distribution.Simple.Setup ( Flag(..) , ConfigFlags(..), HaddockFlags(..)- , fromFlagOrDefault, toFlag, flagToMaybe )-import Distribution.Simple.Utils ( die', info, notice, warn, debug )+ )+import Distribution.Simple.Utils ( warn, debug ) import Distribution.Solver.Types.ConstraintSource import Distribution.Deprecated.ParseUtils ( FieldDescr(..), ParseResult(..)- , commaListField, commaNewLineListField+ , commaListFieldParsec, commaNewLineListFieldParsec , liftField, lineNo, locatedErrorMsg- , parseFilePathQ, readFields- , showPWarning, simpleField+ , readFields+ , showPWarning , syntaxError, warning )-import Distribution.System ( Platform )-import Distribution.Verbosity ( Verbosity, normal )-import Control.Monad ( foldM, liftM2, unless )-import Data.List ( partition, sortBy )-import Data.Maybe ( isJust )-import Data.Ord ( comparing )-import Distribution.Compat.Exception ( catchIO )-import Distribution.Compat.Semigroup-import System.Directory ( doesDirectoryExist, doesFileExist- , renameFile )-import System.FilePath ( (<.>), (</>), takeDirectory )+import System.Directory ( doesFileExist )+import System.FilePath ( (</>) ) import System.IO.Error ( isDoesNotExistError ) import Text.PrettyPrint ( ($+$) ) import qualified Text.PrettyPrint as Disp-import qualified Distribution.Deprecated.ReadP as Parse import qualified Distribution.Deprecated.ParseUtils as ParseUtils ( Field(..) )-import qualified Distribution.Deprecated.Text as Text-import GHC.Generics ( Generic ) - -- -- * Configuration saved in the package environment file --@@ -86,9 +62,6 @@ -- TODO: would be nice to remove duplication between -- D.C.Sandbox.PackageEnvironment and D.C.Config. data PackageEnvironment = PackageEnvironment {- -- The 'inherit' feature is not used ATM, but could be useful in the future- -- for constructing nested sandboxes (see discussion in #1196).- pkgEnvInherit :: Flag FilePath, pkgEnvSavedConfig :: SavedConfig } deriving Generic @@ -99,182 +72,29 @@ instance Semigroup PackageEnvironment where (<>) = gmappend --- | The automatically-created package environment file that should not be--- touched by the user.-sandboxPackageEnvironmentFile :: FilePath-sandboxPackageEnvironmentFile = "cabal.sandbox.config"- -- | Optional package environment file that can be used to customize the default -- settings. Created by the user. userPackageEnvironmentFile :: FilePath userPackageEnvironmentFile = "cabal.config" -- | Type of the current package environment.-data PackageEnvironmentType =- SandboxPackageEnvironment -- ^ './cabal.sandbox.config'- | UserPackageEnvironment -- ^ './cabal.config'+data PackageEnvironmentType+ = UserPackageEnvironment -- ^ './cabal.config' | AmbientPackageEnvironment -- ^ '~/.cabal/config' --- | Is there a 'cabal.sandbox.config' or 'cabal.config' in this--- directory?-classifyPackageEnvironment :: FilePath -> Flag FilePath -> Flag Bool- -> IO PackageEnvironmentType-classifyPackageEnvironment pkgEnvDir sandboxConfigFileFlag ignoreSandboxFlag =- do isSandbox <- liftM2 (||) (return forceSandboxConfig)- (configExists sandboxPackageEnvironmentFile)- isUser <- configExists userPackageEnvironmentFile- return (classify isSandbox isUser)+-- | Is there a 'cabal.config' in this directory?+classifyPackageEnvironment :: FilePath -> IO PackageEnvironmentType+classifyPackageEnvironment pkgEnvDir = do+ isUser <- configExists userPackageEnvironmentFile+ return (classify isUser) where configExists fname = doesFileExist (pkgEnvDir </> fname)- ignoreSandbox = fromFlagOrDefault False ignoreSandboxFlag- forceSandboxConfig = isJust . flagToMaybe $ sandboxConfigFileFlag - classify :: Bool -> Bool -> PackageEnvironmentType- classify True _- | not ignoreSandbox = SandboxPackageEnvironment- classify _ True = UserPackageEnvironment- classify _ False = AmbientPackageEnvironment+ classify :: Bool -> PackageEnvironmentType+ classify True = UserPackageEnvironment+ classify False = AmbientPackageEnvironment --- | Defaults common to 'initialPackageEnvironment' and--- 'commentPackageEnvironment'.-commonPackageEnvironmentConfig :: FilePath -> SavedConfig-commonPackageEnvironmentConfig sandboxDir =- mempty {- savedConfigureFlags = mempty {- -- TODO: Currently, we follow cabal-dev and set 'user-install: False' in- -- the config file. In the future we may want to distinguish between- -- global, sandbox and user install types.- configUserInstall = toFlag False,- configInstallDirs = installDirs- },- savedUserInstallDirs = installDirs,- savedGlobalInstallDirs = installDirs,- savedGlobalFlags = mempty {- globalLogsDir = toFlag $ sandboxDir </> "logs",- -- Is this right? cabal-dev uses the global world file.- globalWorldFile = toFlag $ sandboxDir </> "world"- }- }- where- installDirs = sandboxInstallDirs sandboxDir --- | 'commonPackageEnvironmentConfig' wrapped inside a 'PackageEnvironment'.-commonPackageEnvironment :: FilePath -> PackageEnvironment-commonPackageEnvironment sandboxDir = mempty {- pkgEnvSavedConfig = commonPackageEnvironmentConfig sandboxDir- }---- | Given a path to a sandbox, return the corresponding InstallDirs record.-sandboxInstallDirs :: FilePath -> InstallDirs (Flag PathTemplate)-sandboxInstallDirs sandboxDir = mempty {- prefix = toFlag (toPathTemplate sandboxDir)- }---- | These are the absolute basic defaults, the fields that must be--- initialised. When we load the package environment from the file we layer the--- loaded values over these ones.-basePackageEnvironment :: PackageEnvironment-basePackageEnvironment =- mempty {- pkgEnvSavedConfig = mempty {- savedConfigureFlags = mempty {- configHcFlavor = toFlag defaultCompiler,- configVerbosity = toFlag normal- }- }- }---- | Initial configuration that we write out to the package environment file if--- it does not exist. When the package environment gets loaded this--- configuration gets layered on top of 'basePackageEnvironment'.-initialPackageEnvironment :: FilePath -> Compiler -> Platform- -> IO PackageEnvironment-initialPackageEnvironment sandboxDir compiler platform = do- defInstallDirs <- defaultInstallDirs (compilerFlavor compiler)- {- userInstall= -} False {- _hasLibs= -} False- let initialConfig = commonPackageEnvironmentConfig sandboxDir- installDirs = combineInstallDirs (\d f -> Flag $ fromFlagOrDefault d f)- defInstallDirs (savedUserInstallDirs initialConfig)- return $ mempty {- pkgEnvSavedConfig = initialConfig {- savedUserInstallDirs = installDirs,- savedGlobalInstallDirs = installDirs,- savedGlobalFlags = (savedGlobalFlags initialConfig) {- globalLocalRepos = toNubList [sandboxDir </> "packages"]- },- savedConfigureFlags = setPackageDB sandboxDir compiler platform- (savedConfigureFlags initialConfig),- savedInstallFlags = (savedInstallFlags initialConfig) {- installSummaryFile = toNubList [toPathTemplate (sandboxDir </>- "logs" </> "build.log")]- }- }- }---- | Return the path to the sandbox package database.-sandboxPackageDBPath :: FilePath -> Compiler -> Platform -> String-sandboxPackageDBPath sandboxDir compiler platform =- sandboxDir- </> (Text.display platform ++ "-"- ++ showCompilerIdWithAbi compiler- ++ "-packages.conf.d")--- The path in sandboxPackageDBPath should be kept in sync with the--- path in the bootstrap.sh which is used to bootstrap cabal-install--- into a sandbox.---- | Use the package DB location specific for this compiler.-setPackageDB :: FilePath -> Compiler -> Platform -> ConfigFlags -> ConfigFlags-setPackageDB sandboxDir compiler platform configFlags =- configFlags {- configPackageDBs = [Just (SpecificPackageDB $ sandboxPackageDBPath- sandboxDir- compiler- platform)]- }---- | Almost the same as 'savedConf `mappend` pkgEnv', but some settings are--- overridden instead of mappend'ed.-overrideSandboxSettings :: PackageEnvironment -> PackageEnvironment ->- PackageEnvironment-overrideSandboxSettings pkgEnv0 pkgEnv =- pkgEnv {- pkgEnvSavedConfig = mappendedConf {- savedConfigureFlags = (savedConfigureFlags mappendedConf) {- configPackageDBs = configPackageDBs pkgEnvConfigureFlags- }- , savedInstallFlags = (savedInstallFlags mappendedConf) {- installSummaryFile = installSummaryFile pkgEnvInstallFlags- }- },- pkgEnvInherit = pkgEnvInherit pkgEnv0- }- where- pkgEnvConf = pkgEnvSavedConfig pkgEnv- mappendedConf = (pkgEnvSavedConfig pkgEnv0) `mappend` pkgEnvConf- pkgEnvConfigureFlags = savedConfigureFlags pkgEnvConf- pkgEnvInstallFlags = savedInstallFlags pkgEnvConf---- | Default values that get used if no value is given. Used here to include in--- comments when we write out the initial package environment.-commentPackageEnvironment :: FilePath -> IO PackageEnvironment-commentPackageEnvironment sandboxDir = do- commentConf <- commentSavedConfig- let baseConf = commonPackageEnvironmentConfig sandboxDir- return $ mempty {- pkgEnvSavedConfig = commentConf `mappend` baseConf- }---- | If this package environment inherits from some other package environment,--- return that package environment; otherwise return mempty.-inheritedPackageEnvironment :: Verbosity -> PackageEnvironment- -> IO PackageEnvironment-inheritedPackageEnvironment verbosity pkgEnv = do- case (pkgEnvInherit pkgEnv) of- NoFlag -> return mempty- confPathFlag@(Flag _) -> do- conf <- loadConfig verbosity confPathFlag- return $ mempty { pkgEnvSavedConfig = conf }- -- | Load the user package environment if it exists (the optional "cabal.config" -- file). If it does not exist locally, attempt to load an optional global one. userPackageEnvironment :: Verbosity -> FilePath -> Maybe FilePath@@ -312,121 +132,26 @@ fmap pkgEnvSavedConfig $ userPackageEnvironment verbosity pkgEnvDir globalConfigLocation --- | Common error handling code used by 'tryLoadSandboxPackageEnvironment' and--- 'updatePackageEnvironment'.-handleParseResult :: Verbosity -> FilePath- -> Maybe (ParseResult PackageEnvironment)- -> IO PackageEnvironment-handleParseResult verbosity path minp =- case minp of- Nothing -> die' verbosity $- "The package environment file '" ++ path ++ "' doesn't exist"- Just (ParseOk warns parseResult) -> do- unless (null warns) $ warn verbosity $- unlines (map (showPWarning path) warns)- return parseResult- Just (ParseFailed err) -> do- let (line, msg) = locatedErrorMsg err- die' verbosity $ "Error parsing package environment file " ++ path- ++ maybe "" (\n -> ":" ++ show n) line ++ ":\n" ++ msg --- | Try to load the given package environment file, exiting with error if it--- doesn't exist. Also returns the path to the sandbox directory. The path--- parameter should refer to an existing file.-tryLoadSandboxPackageEnvironmentFile :: Verbosity -> FilePath -> (Flag FilePath)- -> IO (FilePath, PackageEnvironment)-tryLoadSandboxPackageEnvironmentFile verbosity pkgEnvFile configFileFlag = do- let pkgEnvDir = takeDirectory pkgEnvFile- minp <- readPackageEnvironmentFile- (ConstraintSourceSandboxConfig pkgEnvFile) mempty pkgEnvFile- pkgEnv <- handleParseResult verbosity pkgEnvFile minp - -- Get the saved sandbox directory.- -- TODO: Use substPathTemplate with- -- compilerTemplateEnv ++ platformTemplateEnv ++ abiTemplateEnv.- let sandboxDir = fromFlagOrDefault defaultSandboxLocation- . fmap fromPathTemplate . prefix . savedUserInstallDirs- . pkgEnvSavedConfig $ pkgEnv-- -- Do some sanity checks- dirExists <- doesDirectoryExist sandboxDir- -- TODO: Also check for an initialised package DB?- unless dirExists $- die' verbosity ("No sandbox exists at " ++ sandboxDir)- info verbosity $ "Using a sandbox located at " ++ sandboxDir-- let base = basePackageEnvironment- let common = commonPackageEnvironment sandboxDir- user <- userPackageEnvironment verbosity pkgEnvDir Nothing --TODO- inherited <- inheritedPackageEnvironment verbosity user-- -- Layer the package environment settings over settings from ~/.cabal/config.- cabalConfig <- fmap unsetSymlinkBinDir $ loadConfig verbosity configFileFlag- return (sandboxDir,- updateInstallDirs $- (base `mappend` (toPkgEnv cabalConfig) `mappend`- common `mappend` inherited `mappend` user)- `overrideSandboxSettings` pkgEnv)- where- toPkgEnv config = mempty { pkgEnvSavedConfig = config }-- updateInstallDirs pkgEnv =- let config = pkgEnvSavedConfig pkgEnv- configureFlags = savedConfigureFlags config- installDirs = savedUserInstallDirs config- in pkgEnv {- pkgEnvSavedConfig = config {- savedConfigureFlags = configureFlags {- configInstallDirs = installDirs- }- }- }-- -- We don't want to inherit the value of 'symlink-bindir' from- -- '~/.cabal/config'. See #1514.- unsetSymlinkBinDir config =- let installFlags = savedInstallFlags config- in config {- savedInstallFlags = installFlags {- installSymlinkBinDir = NoFlag- }- }---- | Create a new package environment file, replacing the existing one if it--- exists. Note that the path parameters should point to existing directories.-createPackageEnvironmentFile :: Verbosity -> FilePath -> FilePath- -> Compiler- -> Platform- -> IO ()-createPackageEnvironmentFile verbosity sandboxDir pkgEnvFile compiler platform = do- notice verbosity $ "Writing a default package environment file to " ++ pkgEnvFile- initialPkgEnv <- initialPackageEnvironment sandboxDir compiler platform- writePackageEnvironmentFile pkgEnvFile initialPkgEnv- -- | Descriptions of all fields in the package environment file. pkgEnvFieldDescrs :: ConstraintSource -> [FieldDescr PackageEnvironment]-pkgEnvFieldDescrs src = [- simpleField "inherit"- (fromFlagOrDefault Disp.empty . fmap Disp.text) (optional parseFilePathQ)- pkgEnvInherit (\v pkgEnv -> pkgEnv { pkgEnvInherit = v })-- , commaNewLineListField "constraints"- (Text.disp . fst) ((\pc -> (pc, src)) `fmap` Text.parse)+pkgEnvFieldDescrs src =+ [ commaNewLineListFieldParsec "constraints"+ (pretty . fst) ((\pc -> (pc, src)) `fmap` parsec) (sortConstraints . configExConstraints . savedConfigureExFlags . pkgEnvSavedConfig) (\v pkgEnv -> updateConfigureExFlags pkgEnv (\flags -> flags { configExConstraints = v })) - , commaListField "preferences"- Text.disp Text.parse+ , commaListFieldParsec "preferences"+ pretty parsec (configPreferences . savedConfigureExFlags . pkgEnvSavedConfig) (\v pkgEnv -> updateConfigureExFlags pkgEnv (\flags -> flags { configPreferences = v })) ] ++ map toPkgEnv configFieldDescriptions' where- optional = Parse.option mempty . fmap toFlag- configFieldDescriptions' :: [FieldDescr SavedConfig] configFieldDescriptions' = filter (\(FieldDescr name _ _) -> name /= "preference" && name /= "constraint")@@ -538,21 +263,7 @@ type SectionsAccum = (HaddockFlags, InstallDirs (Flag PathTemplate) , [(String, FilePath)], [(String, [String])]) --- | Write out the package environment file.-writePackageEnvironmentFile :: FilePath -> PackageEnvironment -> IO ()-writePackageEnvironmentFile path pkgEnv = do- let tmpPath = (path <.> "tmp")- writeFile tmpPath $ explanation ++ pkgEnvStr ++ "\n"- renameFile tmpPath path- where- pkgEnvStr = showPackageEnvironment pkgEnv- explanation = unlines- ["-- This is a Cabal package environment file."- ,"-- THIS FILE IS AUTO-GENERATED. DO NOT EDIT DIRECTLY."- ,"-- Please create a 'cabal.config' file in the same directory"- ,"-- if you want to change the default settings for this sandbox."- ,"",""- ]+ -- | Pretty-print the package environment. showPackageEnvironment :: PackageEnvironment -> String
− cabal/cabal-install/Distribution/Client/Sandbox/Timestamp.hs
@@ -1,273 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Distribution.Client.Sandbox.Timestamp--- Maintainer : cabal-devel@haskell.org--- Portability : portable------ Timestamp file handling (for add-source dependencies).--------------------------------------------------------------------------------module Distribution.Client.Sandbox.Timestamp (- AddSourceTimestamp,- withAddTimestamps,- withUpdateTimestamps,- maybeAddCompilerTimestampRecord,- listModifiedDeps,- removeTimestamps,-- -- * For testing- TimestampFileRecord,- readTimestampFile,- writeTimestampFile- ) where--import Control.Monad (filterM, forM, when)-import Data.Char (isSpace)-import Data.List (partition)-import System.Directory (renameFile)-import System.FilePath ((<.>), (</>))-import qualified Data.Map as M--import Distribution.Compiler (CompilerId)-import Distribution.Simple.Utils (debug, die', warn)-import Distribution.System (Platform)-import Distribution.Deprecated.Text (display)-import Distribution.Verbosity (Verbosity)--import Distribution.Client.SrcDist (allPackageSourceFiles)-import Distribution.Client.Sandbox.Index- (ListIgnoredBuildTreeRefs (ListIgnored), RefTypesToList(OnlyLinks)- ,listBuildTreeRefs)-import Distribution.Client.SetupWrapper--import Distribution.Compat.Exception (catchIO)-import Distribution.Compat.Time (ModTime, getCurTime,- getModTime,- posixSecondsToModTime)----- | Timestamp of an add-source dependency.-type AddSourceTimestamp = (FilePath, ModTime)--- | Timestamp file record - a string identifying the compiler & platform plus a--- list of add-source timestamps.-type TimestampFileRecord = (String, [AddSourceTimestamp])--timestampRecordKey :: CompilerId -> Platform -> String-timestampRecordKey compId platform = display platform ++ "-" ++ display compId---- | The 'add-source-timestamps' file keeps the timestamps of all add-source--- dependencies. It is initially populated by 'sandbox add-source' and kept--- current by 'reinstallAddSourceDeps' and 'configure -w'. The user can install--- add-source deps manually with 'cabal install' after having edited them, so we--- can err on the side of caution sometimes.--- FIXME: We should keep this info in the index file, together with build tree--- refs.-timestampFileName :: FilePath-timestampFileName = "add-source-timestamps"---- | Read the timestamp file. Exits with error if the timestamp file is--- corrupted. Returns an empty list if the file doesn't exist.-readTimestampFile :: Verbosity -> FilePath -> IO [TimestampFileRecord]-readTimestampFile verbosity timestampFile = do- timestampString <- readFile timestampFile `catchIO` \_ -> return "[]"- case reads timestampString of- [(version, s)]- | version == (2::Int) ->- case reads s of- [(timestamps, s')] | all isSpace s' -> return timestamps- _ -> dieCorrupted- | otherwise -> dieWrongFormat-- -- Old format (timestamps are POSIX seconds). Convert to new format.- [] ->- case reads timestampString of- [(timestamps, s)] | all isSpace s -> do- let timestamps' = map (\(i, ts) ->- (i, map (\(p, t) ->- (p, posixSecondsToModTime t)) ts))- timestamps- writeTimestampFile timestampFile timestamps'- return timestamps'- _ -> dieCorrupted- _ -> dieCorrupted- where- dieWrongFormat = die' verbosity $ wrongFormat ++ deleteAndRecreate- dieCorrupted = die' verbosity $ corrupted ++ deleteAndRecreate- wrongFormat = "The timestamps file is in the wrong format."- corrupted = "The timestamps file is corrupted."- deleteAndRecreate = " Please delete and recreate the sandbox."---- | Write the timestamp file, atomically.-writeTimestampFile :: FilePath -> [TimestampFileRecord] -> IO ()-writeTimestampFile timestampFile timestamps = do- writeFile timestampTmpFile "2\n" -- version- appendFile timestampTmpFile (show timestamps ++ "\n")- renameFile timestampTmpFile timestampFile- where- timestampTmpFile = timestampFile <.> "tmp"---- | Read, process and write the timestamp file in one go.-withTimestampFile :: Verbosity -> FilePath- -> ([TimestampFileRecord] -> IO [TimestampFileRecord])- -> IO ()-withTimestampFile verbosity sandboxDir process = do- let timestampFile = sandboxDir </> timestampFileName- timestampRecords <- readTimestampFile verbosity timestampFile >>= process- writeTimestampFile timestampFile timestampRecords---- | Given a list of 'AddSourceTimestamp's, a list of paths to add-source deps--- we've added and an initial timestamp, add an 'AddSourceTimestamp' to the list--- for each path. If a timestamp for a given path already exists in the list,--- update it.-addTimestamps :: ModTime -> [AddSourceTimestamp] -> [FilePath]- -> [AddSourceTimestamp]-addTimestamps initial timestamps newPaths =- [ (p, initial) | p <- newPaths ] ++ oldTimestamps- where- (oldTimestamps, _toBeUpdated) =- partition (\(path, _) -> path `notElem` newPaths) timestamps---- | Given a list of 'AddSourceTimestamp's, a list of paths to add-source deps--- we've reinstalled and a new timestamp value, update the timestamp value for--- the deps in the list. If there are new paths in the list, ignore them.-updateTimestamps :: [AddSourceTimestamp] -> [FilePath] -> ModTime- -> [AddSourceTimestamp]-updateTimestamps timestamps pathsToUpdate newTimestamp =- foldr updateTimestamp [] timestamps- where- updateTimestamp t@(path, _oldTimestamp) rest- | path `elem` pathsToUpdate = (path, newTimestamp) : rest- | otherwise = t : rest---- | Given a list of 'TimestampFileRecord's and a list of paths to add-source--- deps we've removed, remove those deps from the list.-removeTimestamps' :: [AddSourceTimestamp] -> [FilePath] -> [AddSourceTimestamp]-removeTimestamps' l pathsToRemove = foldr removeTimestamp [] l- where- removeTimestamp t@(path, _oldTimestamp) rest =- if path `elem` pathsToRemove- then rest- else t : rest---- | If a timestamp record for this compiler doesn't exist, add a new one.-maybeAddCompilerTimestampRecord :: Verbosity -> FilePath -> FilePath- -> CompilerId -> Platform- -> IO ()-maybeAddCompilerTimestampRecord verbosity sandboxDir indexFile- compId platform = do- let key = timestampRecordKey compId platform- withTimestampFile verbosity sandboxDir $ \timestampRecords -> do- case lookup key timestampRecords of- Just _ -> return timestampRecords- Nothing -> do- buildTreeRefs <- listBuildTreeRefs verbosity ListIgnored OnlyLinks- indexFile- now <- getCurTime- let timestamps = map (\p -> (p, now)) buildTreeRefs- return $ (key, timestamps):timestampRecords---- | Given an IO action that returns a list of build tree refs, add those--- build tree refs to the timestamps file (for all compilers).-withAddTimestamps :: Verbosity -> FilePath -> IO [FilePath] -> IO ()-withAddTimestamps verbosity sandboxDir act = do- let initialTimestamp = minBound- withActionOnAllTimestamps (addTimestamps initialTimestamp) verbosity sandboxDir act---- | Given a list of build tree refs, remove those--- build tree refs from the timestamps file (for all compilers).-removeTimestamps :: Verbosity -> FilePath -> [FilePath] -> IO ()-removeTimestamps verbosity idxFile =- withActionOnAllTimestamps removeTimestamps' verbosity idxFile . return---- | Given an IO action that returns a list of build tree refs, update the--- timestamps of the returned build tree refs to the current time (only for the--- given compiler & platform).-withUpdateTimestamps :: Verbosity -> FilePath -> CompilerId -> Platform- ->([AddSourceTimestamp] -> IO [FilePath])- -> IO ()-withUpdateTimestamps =- withActionOnCompilerTimestamps updateTimestamps---- | Helper for implementing 'withAddTimestamps' and--- 'withRemoveTimestamps'. Runs a given action on the list of--- 'AddSourceTimestamp's for all compilers, applies 'f' to the result and then--- updates the timestamp file. The IO action is run only once.-withActionOnAllTimestamps :: ([AddSourceTimestamp] -> [FilePath]- -> [AddSourceTimestamp])- -> Verbosity- -> FilePath- -> IO [FilePath]- -> IO ()-withActionOnAllTimestamps f verbosity sandboxDir act =- withTimestampFile verbosity sandboxDir $ \timestampRecords -> do- paths <- act- return [(key, f timestamps paths) | (key, timestamps) <- timestampRecords]---- | Helper for implementing 'withUpdateTimestamps'. Runs a given action on the--- list of 'AddSourceTimestamp's for this compiler, applies 'f' to the result--- and then updates the timestamp file record. The IO action is run only once.-withActionOnCompilerTimestamps :: ([AddSourceTimestamp]- -> [FilePath] -> ModTime- -> [AddSourceTimestamp])- -> Verbosity- -> FilePath- -> CompilerId- -> Platform- -> ([AddSourceTimestamp] -> IO [FilePath])- -> IO ()-withActionOnCompilerTimestamps f verbosity sandboxDir compId platform act = do- let needle = timestampRecordKey compId platform- withTimestampFile verbosity sandboxDir $ \timestampRecords -> do- timestampRecords' <- forM timestampRecords $ \r@(key, timestamps) ->- if key == needle- then do paths <- act timestamps- now <- getCurTime- return (key, f timestamps paths now)- else return r- return timestampRecords'---- | Has this dependency been modified since we have last looked at it?-isDepModified :: Verbosity -> ModTime -> AddSourceTimestamp -> IO Bool-isDepModified verbosity now (packageDir, timestamp) = do- debug verbosity ("Checking whether the dependency is modified: " ++ packageDir)- -- TODO: we should properly plumb the correct options through- -- instead of using defaultSetupScriptOptions- depSources <- allPackageSourceFiles verbosity defaultSetupScriptOptions packageDir- go depSources-- where- go [] = return False- go (dep0:rest) = do- -- FIXME: What if the clock jumps backwards at any point? For now we only- -- print a warning.- let dep = packageDir </> dep0- modTime <- getModTime dep- when (modTime > now) $- warn verbosity $ "File '" ++ dep- ++ "' has a modification time that is in the future."- if modTime >= timestamp- then do- debug verbosity ("Dependency has a modified source file: " ++ dep)- return True- else go rest---- | List all modified dependencies.-listModifiedDeps :: Verbosity -> FilePath -> CompilerId -> Platform- -> M.Map FilePath a- -- ^ The set of all installed add-source deps.- -> IO [FilePath]-listModifiedDeps verbosity sandboxDir compId platform installedDepsMap = do- timestampRecords <- readTimestampFile verbosity (sandboxDir </> timestampFileName)- let needle = timestampRecordKey compId platform- timestamps <- maybe noTimestampRecord return- (lookup needle timestampRecords)- now <- getCurTime- fmap (map fst) . filterM (isDepModified verbosity now)- . filter (\ts -> fst ts `M.member` installedDepsMap)- $ timestamps-- where- noTimestampRecord = die' verbosity $ "Сouldn't find a timestamp record for the given "- ++ "compiler/platform pair. "- ++ "Please report this on the Cabal bug tracker: "- ++ "https://github.com/haskell/cabal/issues/new ."
− cabal/cabal-install/Distribution/Client/Sandbox/Types.hs
@@ -1,65 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Distribution.Client.Sandbox.Types--- Maintainer : cabal-devel@haskell.org--- Portability : portable------ Helpers for writing code that works both inside and outside a sandbox.--------------------------------------------------------------------------------module Distribution.Client.Sandbox.Types (- UseSandbox(..), isUseSandbox, whenUsingSandbox,- SandboxPackageInfo(..)- ) where--import Prelude ()-import Distribution.Client.Compat.Prelude--import qualified Distribution.Simple.PackageIndex as InstalledPackageIndex-import Distribution.Client.Types (UnresolvedSourcePackage)--import qualified Data.Set as S---- | Are we using a sandbox?-data UseSandbox = UseSandbox FilePath | NoSandbox--instance Monoid UseSandbox where- mempty = NoSandbox- mappend = (<>)--instance Semigroup UseSandbox where- NoSandbox <> s = s- u0@(UseSandbox _) <> NoSandbox = u0- (UseSandbox _) <> u1@(UseSandbox _) = u1---- | Convert a @UseSandbox@ value to a boolean. Useful in conjunction with--- @when@.-isUseSandbox :: UseSandbox -> Bool-isUseSandbox (UseSandbox _) = True-isUseSandbox NoSandbox = False---- | Execute an action only if we're in a sandbox, feeding to it the path to the--- sandbox directory.-whenUsingSandbox :: UseSandbox -> (FilePath -> IO ()) -> IO ()-whenUsingSandbox NoSandbox _ = return ()-whenUsingSandbox (UseSandbox sandboxDir) act = act sandboxDir---- | Data about the packages installed in the sandbox that is passed from--- 'reinstallAddSourceDeps' to the solver.-data SandboxPackageInfo = SandboxPackageInfo {- modifiedAddSourceDependencies :: ![UnresolvedSourcePackage],- -- ^ Modified add-source deps that we want to reinstall. These are guaranteed- -- to be already installed in the sandbox.-- otherAddSourceDependencies :: ![UnresolvedSourcePackage],- -- ^ Remaining add-source deps. Some of these may be not installed in the- -- sandbox.-- otherInstalledSandboxPackages :: !InstalledPackageIndex.InstalledPackageIndex,- -- ^ All packages installed in the sandbox. Intersection with- -- 'modifiedAddSourceDependencies' and/or 'otherAddSourceDependencies' can be- -- non-empty.-- allAddSourceDependencies :: !(S.Set FilePath)- -- ^ A set of paths to all add-source dependencies, for convenience.- }
cabal/cabal-install/Distribution/Client/SavedFlags.hs view
@@ -5,17 +5,15 @@ , readSavedArgs, writeSavedArgs ) where +import Distribution.Client.Compat.Prelude+import Prelude ()+ import Distribution.Simple.Command import Distribution.Simple.UserHooks ( Args ) import Distribution.Simple.Utils ( createDirectoryIfMissingVerbose, unintersperse ) import Distribution.Verbosity -import Control.Exception ( Exception, throwIO )-import Control.Monad ( liftM )-import Data.List ( intercalate )-import Data.Maybe ( fromMaybe )-import Data.Typeable import System.Directory ( doesFileExist ) import System.FilePath ( takeDirectory ) @@ -41,7 +39,7 @@ readSavedArgs path = do exists <- doesFileExist path if exists- then liftM (Just . unintersperse '\0') (readFile path)+ then fmap (Just . unintersperse '\0') (readFile path) else return Nothing @@ -49,7 +47,7 @@ -- Returns the default flags if the file does not exist. readCommandFlags :: FilePath -> CommandUI flags -> IO flags readCommandFlags path command = do- savedArgs <- liftM (fromMaybe []) (readSavedArgs path)+ savedArgs <- fmap (fromMaybe []) (readSavedArgs path) case (commandParseArgs command True savedArgs) of CommandHelp _ -> throwIO (SavedArgsErrorHelp savedArgs) CommandList _ -> throwIO (SavedArgsErrorList savedArgs)
cabal/cabal-install/Distribution/Client/Security/DNS.hs view
@@ -8,12 +8,8 @@ import Prelude () import Distribution.Client.Compat.Prelude import Network.URI (URI(..), URIAuth(..), parseURI)-import Distribution.Verbosity-import Control.Monad-import Control.DeepSeq (force)-import Control.Exception (SomeException, evaluate, try)+import Control.Exception (try) import Distribution.Simple.Utils-import Distribution.Compat.Exception (displayException) #if defined(MIN_VERSION_resolv) || defined(MIN_VERSION_windns) import Network.DNS (queryTXT, Name(..), CharStr(..))@@ -71,7 +67,7 @@ then warn verbosity ("No mirrors found for " ++ show repoUri) else do info verbosity ("located " ++ show (length mirrors) ++ " mirrors for " ++ show repoUri ++ " :")- forM_ mirrors $ \url -> info verbosity ("- " ++ show url)+ for_ mirrors $ \url -> info verbosity ("- " ++ show url) return mirrors @@ -118,7 +114,7 @@ then warn verbosity ("No mirrors found for " ++ show repoUri) else do info verbosity ("located " ++ show (length mirrors) ++ " mirrors for " ++ show repoUri ++ " :")- forM_ mirrors $ \url -> info verbosity ("- " ++ show url)+ for_ mirrors $ \url -> info verbosity ("- " ++ show url) return mirrors
cabal/cabal-install/Distribution/Client/Security/HTTP.hs view
@@ -8,13 +8,10 @@ -- | Implementation of 'HttpLib' using cabal-install's own 'HttpTransport' module Distribution.Client.Security.HTTP (HttpLib, transportAdapter) where +import Distribution.Solver.Compat.Prelude+import Prelude ()+ -- stdlibs-import Control.Exception- ( Exception(..), IOException )-import Data.List- ( intercalate )-import Data.Typeable- ( Typeable ) import System.Directory ( getTemporaryDirectory ) import Network.URI@@ -31,10 +28,11 @@ ( withTempFileName ) -- hackage-security-import Hackage.Security.Client-import Hackage.Security.Client.Repository.HttpLib-import Hackage.Security.Util.Checked-import Hackage.Security.Util.Pretty+import Hackage.Security.Client.Repository.HttpLib (HttpLib (..))+import qualified Hackage.Security.Client as HC+import qualified Hackage.Security.Client.Repository.HttpLib as HC+import qualified Hackage.Security.Util.Checked as HC+import qualified Hackage.Security.Util.Pretty as HC {------------------------------------------------------------------------------- 'HttpLib' implementation@@ -62,49 +60,50 @@ transportAdapter verbosity getTransport = HttpLib{ httpGet = \headers uri callback -> do transport <- getTransport- get verbosity transport headers uri callback+ httpGetImpl verbosity transport headers uri callback , httpGetRange = \headers uri range callback -> do transport <- getTransport getRange verbosity transport headers uri range callback } -get :: Throws SomeRemoteError+httpGetImpl+ :: HC.Throws HC.SomeRemoteError => Verbosity -> HttpTransport- -> [HttpRequestHeader] -> URI- -> ([HttpResponseHeader] -> BodyReader -> IO a)+ -> [HC.HttpRequestHeader] -> URI+ -> ([HC.HttpResponseHeader] -> HC.BodyReader -> IO a) -> IO a-get verbosity transport reqHeaders uri callback = wrapCustomEx $ do+httpGetImpl verbosity transport reqHeaders uri callback = wrapCustomEx $ do get' verbosity transport reqHeaders uri Nothing $ \code respHeaders br -> case code of 200 -> callback respHeaders br- _ -> throwChecked $ UnexpectedResponse uri code+ _ -> HC.throwChecked $ UnexpectedResponse uri code -getRange :: Throws SomeRemoteError+getRange :: HC.Throws HC.SomeRemoteError => Verbosity -> HttpTransport- -> [HttpRequestHeader] -> URI -> (Int, Int)- -> (HttpStatus -> [HttpResponseHeader] -> BodyReader -> IO a)+ -> [HC.HttpRequestHeader] -> URI -> (Int, Int)+ -> (HC.HttpStatus -> [HC.HttpResponseHeader] -> HC.BodyReader -> IO a) -> IO a getRange verbosity transport reqHeaders uri range callback = wrapCustomEx $ do get' verbosity transport reqHeaders uri (Just range) $ \code respHeaders br -> case code of- 200 -> callback HttpStatus200OK respHeaders br- 206 -> callback HttpStatus206PartialContent respHeaders br- _ -> throwChecked $ UnexpectedResponse uri code+ 200 -> callback HC.HttpStatus200OK respHeaders br+ 206 -> callback HC.HttpStatus206PartialContent respHeaders br+ _ -> HC.throwChecked $ UnexpectedResponse uri code -- | Internal generalization of 'get' and 'getRange' get' :: Verbosity -> HttpTransport- -> [HttpRequestHeader] -> URI -> Maybe (Int, Int)- -> (HttpCode -> [HttpResponseHeader] -> BodyReader -> IO a)+ -> [HC.HttpRequestHeader] -> URI -> Maybe (Int, Int)+ -> (HttpCode -> [HC.HttpResponseHeader] -> HC.BodyReader -> IO a) -> IO a get' verbosity transport reqHeaders uri mRange callback = do tempDir <- getTemporaryDirectory withTempFileName tempDir "transportAdapterGet" $ \temp -> do (code, _etag) <- getHttp transport verbosity uri Nothing temp reqHeaders'- br <- bodyReaderFromBS =<< BS.L.readFile temp- callback code [HttpResponseAcceptRangesBytes] br+ br <- HC.bodyReaderFromBS =<< BS.L.readFile temp+ callback code [HC.HttpResponseAcceptRangesBytes] br where reqHeaders' = mkReqHeaders reqHeaders mRange @@ -119,31 +118,31 @@ -- See <http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html> rangeHeader = "bytes=" ++ show from ++ "-" ++ show (to - 1) -mkReqHeaders :: [HttpRequestHeader] -> Maybe (Int, Int) -> [HTTP.Header]+mkReqHeaders :: [HC.HttpRequestHeader] -> Maybe (Int, Int) -> [HTTP.Header] mkReqHeaders reqHeaders mRange = concat [ tr [] reqHeaders , [mkRangeHeader fr to | Just (fr, to) <- [mRange]] ] where- tr :: [(HTTP.HeaderName, [String])] -> [HttpRequestHeader] -> [HTTP.Header]+ tr :: [(HTTP.HeaderName, [String])] -> [HC.HttpRequestHeader] -> [HTTP.Header] tr acc [] = concatMap finalize acc- tr acc (HttpRequestMaxAge0:os) =+ tr acc (HC.HttpRequestMaxAge0:os) = tr (insert HTTP.HdrCacheControl ["max-age=0"] acc) os- tr acc (HttpRequestNoTransform:os) =+ tr acc (HC.HttpRequestNoTransform:os) = tr (insert HTTP.HdrCacheControl ["no-transform"] acc) os -- Some headers are comma-separated, others need multiple headers for -- multiple options. --- -- TODO: Right we we just comma-separate all of them.+ -- TODO: Right we just comma-separate all of them. finalize :: (HTTP.HeaderName, [String]) -> [HTTP.Header] finalize (name, strs) = [HTTP.Header name (intercalate ", " (reverse strs))] insert :: Eq a => a -> [b] -> [(a, [b])] -> [(a, [b])] insert x y = modifyAssocList x (++ y) - -- modify the first maching element+ -- modify the first matching element modifyAssocList :: Eq a => a -> (b -> b) -> [(a, b)] -> [(a, b)] modifyAssocList a f = go where go [] = []@@ -157,24 +156,24 @@ data UnexpectedResponse = UnexpectedResponse URI Int deriving (Typeable) -instance Pretty UnexpectedResponse where+instance HC.Pretty UnexpectedResponse where pretty (UnexpectedResponse uri code) = "Unexpected response " ++ show code ++ " for " ++ show uri #if MIN_VERSION_base(4,8,0) deriving instance Show UnexpectedResponse-instance Exception UnexpectedResponse where displayException = pretty+instance Exception UnexpectedResponse where displayException = HC.pretty #else-instance Show UnexpectedResponse where show = pretty+instance Show UnexpectedResponse where show = HC.pretty instance Exception UnexpectedResponse #endif -wrapCustomEx :: ( ( Throws UnexpectedResponse- , Throws IOException+wrapCustomEx :: ( ( HC.Throws UnexpectedResponse+ , HC.Throws IOException ) => IO a)- -> (Throws SomeRemoteError => IO a)-wrapCustomEx act = handleChecked (\(ex :: UnexpectedResponse) -> go ex)- $ handleChecked (\(ex :: IOException) -> go ex)+ -> (HC.Throws HC.SomeRemoteError => IO a)+wrapCustomEx act = HC.handleChecked (\(ex :: UnexpectedResponse) -> go ex)+ $ HC.handleChecked (\(ex :: IOException) -> go ex) $ act where- go ex = throwChecked (SomeRemoteError ex)+ go ex = HC.throwChecked (HC.SomeRemoteError ex)
cabal/cabal-install/Distribution/Client/Setup.hs view
@@ -21,17 +21,15 @@ , configureCommand, ConfigFlags(..), configureOptions, filterConfigureFlags , configPackageDB', configCompilerAux' , configureExCommand, ConfigExFlags(..), defaultConfigExFlags- , buildCommand, BuildFlags(..), BuildExFlags(..), SkipAddSourceDepsCheck(..)+ , buildCommand, BuildFlags(..) , filterTestFlags , replCommand, testCommand, benchmarkCommand, testOptions, benchmarkOptions , configureExOptions, reconfigureCommand , installCommand, InstallFlags(..), installOptions, defaultInstallFlags , filterHaddockArgs, filterHaddockFlags, haddockOptions , defaultSolver, defaultMaxBackjumps- , listCommand, ListFlags(..)+ , listCommand, ListFlags(..), listNeedsCompiler , updateCommand, UpdateFlags(..), defaultUpdateFlags- , upgradeCommand- , uninstallCommand , infoCommand, InfoFlags(..) , fetchCommand, FetchFlags(..) , freezeCommand, FreezeFlags(..)@@ -44,10 +42,7 @@ , reportCommand, ReportFlags(..) , runCommand , initCommand, initOptions, IT.InitFlags(..)- , sdistCommand, SDistFlags(..)- , win32SelfUpgradeCommand, Win32SelfUpgradeFlags(..) , actAsSetupCommand, ActAsSetupFlags(..)- , sandboxCommand, defaultSandboxLocation, SandboxFlags(..) , execCommand, ExecFlags(..), defaultExecFlags , userConfigCommand, UserConfigFlags(..) , manpageCommand@@ -60,30 +55,26 @@ , parsePackageArgs , liftOptions , yesNoOpt- --TODO: stop exporting these:- , showRepo- , parseRepo- , readRepo ) where import Prelude () import Distribution.Client.Compat.Prelude hiding (get) -import Distribution.Deprecated.ReadP (readP_to_E)+import Distribution.Client.Types.Credentials (Username (..), Password (..))+import Distribution.Client.Types.Repo (RemoteRepo(..), LocalRepo (..))+import Distribution.Client.Types.AllowNewer (AllowNewer(..), AllowOlder(..), RelaxDeps(..))+import Distribution.Client.Types.WriteGhcEnvironmentFilesPolicy -import Distribution.Client.Types- ( Username(..), Password(..), RemoteRepo(..)- , AllowNewer(..), AllowOlder(..), RelaxDeps(..)- , WriteGhcEnvironmentFilesPolicy(..)- ) import Distribution.Client.BuildReports.Types ( ReportLevel(..) ) import Distribution.Client.Dependency.Types ( PreSolver(..) )-import Distribution.Client.IndexUtils.Timestamp- ( IndexState(..) )+import Distribution.Client.IndexUtils.ActiveRepos+ ( ActiveRepos )+import Distribution.Client.IndexUtils.IndexState+ ( TotalIndexState, headTotalIndexState ) import qualified Distribution.Client.Init.Types as IT- ( InitFlags(..), PackageType(..) )+ ( InitFlags(..), PackageType(..), defaultInitFlags ) import Distribution.Client.Targets ( UserConstraint, readUserConstraint ) import Distribution.Utils.NubList@@ -99,14 +90,17 @@ import Distribution.Simple.Configure ( configCompilerAuxEx, interpretPackageDbFlags, computeEffectiveProfiling ) import qualified Distribution.Simple.Setup as Cabal+import Distribution.Simple.Flag+ ( Flag(..), toFlag, flagToMaybe, flagToList, maybeToFlag+ , flagElim, fromFlagOrDefault+ ) import Distribution.Simple.Setup ( ConfigFlags(..), BuildFlags(..), ReplFlags , TestFlags, BenchmarkFlags- , SDistFlags(..), HaddockFlags(..)+ , HaddockFlags(..) , CleanFlags(..), DoctestFlags(..) , CopyFlags(..), RegisterFlags(..) , readPackageDbList, showPackageDbList- , Flag(..), toFlag, flagToMaybe, flagToList, maybeToFlag , BooleanFlag(..), optionVerbosity , boolOpt, boolOpt', trueArg, falseArg , optionNumJobs )@@ -114,10 +108,9 @@ ( PathTemplate, InstallDirs(..) , toPathTemplate, fromPathTemplate, combinePathTemplate ) import Distribution.Version- ( Version, mkVersion, nullVersion, anyVersion, thisVersion )+ ( Version, mkVersion ) import Distribution.Package- ( PackageName, PackageIdentifier, packageName, packageVersion )-import Distribution.Types.Dependency+ ( PackageName ) import Distribution.Types.GivenComponent ( GivenComponent(..) ) import Distribution.Types.PackageVersionConstraint@@ -127,30 +120,24 @@ import Distribution.PackageDescription ( BuildType(..), RepoKind(..), LibraryName(..) ) import Distribution.System ( Platform )-import Distribution.Deprecated.Text- ( Text(..), display ) import Distribution.ReadE- ( ReadE(..), succeedReadE )-import qualified Distribution.Deprecated.ReadP as Parse- ( ReadP, char, munch1, pfail, sepBy1, (+++) )-import Distribution.Deprecated.ParseUtils- ( readPToMaybe )+ ( ReadE(..), succeedReadE, parsecToReadE )+import qualified Distribution.Compat.CharParsing as P import Distribution.Verbosity- ( Verbosity, lessVerbose, normal, verboseNoFlags, verboseNoTimestamp )+ ( lessVerbose, normal, verboseNoFlags, verboseNoTimestamp ) import Distribution.Simple.Utils- ( wrapText, wrapLine )+ ( wrapText ) import Distribution.Client.GlobalFlags ( GlobalFlags(..), defaultGlobalFlags , RepoContext(..), withRepoContext )+import Distribution.Client.ManpageFlags (ManpageFlags, defaultManpageFlags, manpageOptions)+import Distribution.FieldGrammar.Newtypes (SpecVersion (..)) import Data.List ( deleteFirstsBy )-import qualified Data.Set as Set import System.FilePath ( (</>) )-import Network.URI- ( parseAbsoluteURI, uriToString ) globalCommand :: [Command action] -> CommandUI GlobalFlags globalCommand commands = CommandUI {@@ -211,6 +198,7 @@ , "new-install" , "new-clean" , "new-sdist"+ , "list-bin" -- v1 commands, stateful style , "v1-build" , "v1-configure"@@ -229,7 +217,6 @@ , "v1-copy" , "v1-register" , "v1-reconfigure"- , "v1-sandbox" -- v2 commands, nix-style , "v2-build" , "v2-configure"@@ -289,21 +276,7 @@ , addCmd "haddock" , addCmd "hscolour" , addCmd "exec"- , par- , startGroup "new-style projects (beta)"- , addCmd "new-build"- , addCmd "new-configure"- , addCmd "new-repl"- , addCmd "new-run"- , addCmd "new-test"- , addCmd "new-bench"- , addCmd "new-freeze"- , addCmd "new-haddock"- , addCmd "new-exec"- , addCmd "new-update"- , addCmd "new-install"- , addCmd "new-clean"- , addCmd "new-sdist"+ , addCmd "list-bin" , par , startGroup "new-style projects (forwards-compatible aliases)" , addCmd "v2-build"@@ -338,7 +311,6 @@ , addCmd "v1-copy" , addCmd "v1-register" , addCmd "v1-reconfigure"- , addCmd "v1-sandbox" ] ++ if null otherCmds then [] else par :startGroup "other" :[addCmd n | n <- otherCmds])@@ -379,26 +351,11 @@ globalConfigFile (\v flags -> flags { globalConfigFile = v }) (reqArgFlag "FILE") - ,option [] ["sandbox-config-file"]- "Set an alternate location for the sandbox config file (default: './cabal.sandbox.config')"- globalSandboxConfigFile (\v flags -> flags { globalSandboxConfigFile = v })- (reqArgFlag "FILE")- ,option [] ["default-user-config"] "Set a location for a cabal.config file for projects without their own cabal.config freeze file." globalConstraintsFile (\v flags -> flags {globalConstraintsFile = v}) (reqArgFlag "FILE") - ,option [] ["require-sandbox"]- "requiring the presence of a sandbox for sandbox-aware commands"- globalRequireSandbox (\v flags -> flags { globalRequireSandbox = v })- (boolOpt' ([], ["require-sandbox"]) ([], ["no-require-sandbox"]))-- ,option [] ["ignore-sandbox"]- "Ignore any existing sandbox"- globalIgnoreSandbox (\v flags -> flags { globalIgnoreSandbox = v })- trueArg- ,option [] ["ignore-expiry"] "Ignore expiry dates on signed metadata (use only in exceptional circumstances)" globalIgnoreExpiry (\v flags -> flags { globalIgnoreExpiry = v })@@ -412,6 +369,7 @@ "Nix integration: run commands through nix-shell if a 'shell.nix' file exists" globalNix (\v flags -> flags { globalNix = v }) (boolOpt [] [])+ ] -- arguments we don't want shown in the help@@ -420,18 +378,18 @@ option [] ["remote-repo"] "The name and url for a remote repository" globalRemoteRepos (\v flags -> flags { globalRemoteRepos = v })- (reqArg' "NAME:URL" (toNubList . maybeToList . readRepo) (map showRepo . fromNubList))+ (reqArg' "NAME:URL" (toNubList . maybeToList . readRemoteRepo) (map showRemoteRepo . fromNubList)) + ,option [] ["local-no-index-repo"]+ "The name and a path for a local no-index repository"+ globalLocalNoIndexRepos (\v flags -> flags { globalLocalNoIndexRepos = v })+ (reqArg' "NAME:PATH" (toNubList . maybeToList . readLocalRepo) (map showLocalRepo . fromNubList))+ ,option [] ["remote-repo-cache"] "The location where downloads from all remote repos are cached" globalCacheDir (\v flags -> flags { globalCacheDir = v }) (reqArgFlag "DIR") - ,option [] ["local-repo"]- "The location of a local repository"- globalLocalRepos (\v flags -> flags { globalLocalRepos = v })- (reqArg' "DIR" (\x -> toNubList [x]) fromNubList)- ,option [] ["logs-dir", "logsdir"] "The location to put log files" globalLogsDir (\v flags -> flags { globalLogsDir = v })@@ -446,6 +404,13 @@ "The location of the nix-local-build store" globalStoreDir (\v flags -> flags { globalStoreDir = v }) (reqArgFlag "DIR")++ , option [] ["active-repositories"]+ "The active package repositories"+ globalActiveRepos (\v flags -> flags { globalActiveRepos = v })+ (reqArg "REPOS" (parsecToReadE (\err -> "Error parsing active-repositories: " ++ err)+ (toFlag `fmap` parsec))+ (map prettyShow . flagToList)) ] -- ------------------------------------------------------------@@ -534,6 +499,8 @@ convertToLegacyInternalDep (GivenComponent pn LMainLibName cid) = Just $ GivenComponent pn LMainLibName cid in catMaybes $ convertToLegacyInternalDep <$> configDependencies flags+ -- Cabal < 2.5 doesn't know about '--allow-depending-on-private-libs'.+ , configAllowDependingOnPrivateLibs = NoFlag -- Cabal < 2.5 doesn't know about '--enable/disable-executable-static'. , configFullyStaticExe = NoFlag }@@ -643,7 +610,7 @@ configWriteGhcEnvironmentFilesPolicy :: Flag WriteGhcEnvironmentFilesPolicy }- deriving (Eq, Generic)+ deriving (Eq, Show, Generic) defaultConfigExFlags :: ConfigExFlags defaultConfigExFlags = mempty { configSolver = Flag defaultSolver }@@ -670,23 +637,23 @@ ("Select which version of the Cabal lib to use to build packages " ++ "(useful for testing).") configCabalVersion (\v flags -> flags { configCabalVersion = v })- (reqArg "VERSION" (readP_to_E ("Cannot parse cabal lib version: "++)- (fmap toFlag parse))- (map display . flagToList))+ (reqArg "VERSION" (parsecToReadE ("Cannot parse cabal lib version: "++)+ (fmap toFlag parsec))+ (map prettyShow. flagToList)) , option [] ["constraint"] "Specify constraints on a package (version, installed/source, flags)" configExConstraints (\v flags -> flags { configExConstraints = v }) (reqArg "CONSTRAINT" ((\x -> [(x, src)]) `fmap` ReadE readUserConstraint)- (map $ display . fst))+ (map $ prettyShow . fst)) , option [] ["preference"] "Specify preferences (soft constraints) on the version of a package" configPreferences (\v flags -> flags { configPreferences = v }) (reqArg "CONSTRAINT"- (readP_to_E (const "dependency expected")- (fmap (\x -> [x]) parse))- (map display))+ (parsecToReadE (const "dependency expected")+ (fmap (\x -> [x]) parsec))+ (map prettyShow)) , optionSolver configSolver (\v flags -> flags { configSolver = v }) @@ -695,7 +662,7 @@ (fmap unAllowOlder . configAllowOlder) (\v flags -> flags { configAllowOlder = fmap AllowOlder v}) (optArg "DEPS"- (readP_to_E ("Cannot parse the list of packages: " ++) relaxDepsParser)+ (parsecToReadE ("Cannot parse the list of packages: " ++) relaxDepsParser) (Just RelaxDepsAll) relaxDepsPrinter) , option [] ["allow-newer"]@@ -703,7 +670,7 @@ (fmap unAllowNewer . configAllowNewer) (\v flags -> flags { configAllowNewer = fmap AllowNewer v}) (optArg "DEPS"- (readP_to_E ("Cannot parse the list of packages: " ++) relaxDepsParser)+ (parsecToReadE ("Cannot parse the list of packages: " ++) relaxDepsParser) (Just RelaxDepsAll) relaxDepsPrinter) , option [] ["write-ghc-environment-files"]@@ -734,14 +701,14 @@ NoFlag -> [] -relaxDepsParser :: Parse.ReadP r (Maybe RelaxDeps)+relaxDepsParser :: CabalParsing m => m (Maybe RelaxDeps) relaxDepsParser =- (Just . RelaxDepsSome) `fmap` Parse.sepBy1 parse (Parse.char ',')+ (Just . RelaxDepsSome . toList) `fmap` P.sepByNonEmpty parsec (P.char ',') relaxDepsPrinter :: (Maybe RelaxDeps) -> [Maybe String] relaxDepsPrinter Nothing = [] relaxDepsPrinter (Just RelaxDepsAll) = [Nothing]-relaxDepsPrinter (Just (RelaxDepsSome pkgs)) = map (Just . display) $ pkgs+relaxDepsPrinter (Just (RelaxDepsSome pkgs)) = map (Just . prettyShow) $ pkgs instance Monoid ConfigExFlags where@@ -777,39 +744,18 @@ -- * Build flags -- ------------------------------------------------------------ -data SkipAddSourceDepsCheck =- SkipAddSourceDepsCheck | DontSkipAddSourceDepsCheck- deriving Eq--data BuildExFlags = BuildExFlags {- buildOnly :: Flag SkipAddSourceDepsCheck-} deriving Generic--buildExOptions :: ShowOrParseArgs -> [OptionField BuildExFlags]-buildExOptions _showOrParseArgs =- option [] ["only"]- "Don't reinstall add-source dependencies (sandbox-only)"- buildOnly (\v flags -> flags { buildOnly = v })- (noArg (Flag SkipAddSourceDepsCheck))-- : []--buildCommand :: CommandUI (BuildFlags, BuildExFlags)+buildCommand :: CommandUI BuildFlags buildCommand = parent { commandName = "build", commandDescription = Just $ \_ -> wrapText $ "Components encompass executables, tests, and benchmarks.\n" ++ "\n" ++ "Affected by configuration options, see `v1-configure`.\n",- commandDefaultFlags = (commandDefaultFlags parent, mempty),+ commandDefaultFlags = commandDefaultFlags parent, commandUsage = usageAlternatives "v1-build" $ [ "[FLAGS]", "COMPONENTS [FLAGS]" ],- commandOptions =- \showOrParseArgs -> liftOptions fst setFst- (commandOptions parent showOrParseArgs)- ++- liftOptions snd setSnd (buildExOptions showOrParseArgs)- , commandNotes = Just $ \pname ->+ commandOptions = commandOptions parent+ , commandNotes = Just $ \pname -> "Examples:\n" ++ " " ++ pname ++ " v1-build " ++ " All the components in the package\n"@@ -818,18 +764,8 @@ ++ Cabal.programFlagsDescription defaultProgramDb } where- setFst a (_,b) = (a,b)- setSnd b (a,_) = (a,b)- parent = Cabal.buildCommand defaultProgramDb -instance Monoid BuildExFlags where- mempty = gmempty- mappend = (<>)--instance Semigroup BuildExFlags where- (<>) = gmappend- -- ------------------------------------------------------------ -- * Test flags -- ------------------------------------------------------------@@ -865,13 +801,12 @@ -- * Repl command -- ------------------------------------------------------------ -replCommand :: CommandUI (ReplFlags, BuildExFlags)+replCommand :: CommandUI ReplFlags replCommand = parent { commandName = "repl", commandDescription = Just $ \pname -> wrapText $ "If the current directory contains no package, ignores COMPONENT "- ++ "parameters and opens an interactive interpreter session; if a "- ++ "sandbox is present, its package database will be used.\n"+ ++ "parameters and opens an interactive interpreter session;\n" ++ "\n" ++ "Otherwise, (re)configures with the given or default flags, and " ++ "loads the interpreter with the relevant modules. For executables, "@@ -887,12 +822,8 @@ ++ "not (re)configure and you will have to specify the location of " ++ "other modules, if required.\n", commandUsage = \pname -> "Usage: " ++ pname ++ " v1-repl [COMPONENT] [FLAGS]\n",- commandDefaultFlags = (commandDefaultFlags parent, mempty),- commandOptions =- \showOrParseArgs -> liftOptions fst setFst- (commandOptions parent showOrParseArgs)- ++- liftOptions snd setSnd (buildExOptions showOrParseArgs),+ commandDefaultFlags = commandDefaultFlags parent,+ commandOptions = commandOptions parent, commandNotes = Just $ \pname -> "Examples:\n" ++ " " ++ pname ++ " v1-repl "@@ -903,16 +834,13 @@ ++ " Specifying flags for interpreter\n" } where- setFst a (_,b) = (a,b)- setSnd b (a,_) = (a,b)- parent = Cabal.replCommand defaultProgramDb -- ------------------------------------------------------------ -- * Test command -- ------------------------------------------------------------ -testCommand :: CommandUI (TestFlags, BuildFlags, BuildExFlags)+testCommand :: CommandUI (BuildFlags, TestFlags) testCommand = parent { commandName = "test", commandDescription = Just $ \pname -> wrapText $@@ -927,21 +855,17 @@ ++ " define actions to be executed before and after running tests.\n", commandUsage = usageAlternatives "v1-test" [ "[FLAGS]", "TESTCOMPONENTS [FLAGS]" ],- commandDefaultFlags = (commandDefaultFlags parent,- Cabal.defaultBuildFlags, mempty),+ commandDefaultFlags = (Cabal.defaultBuildFlags, commandDefaultFlags parent), commandOptions = \showOrParseArgs -> liftOptions get1 set1- (commandOptions parent showOrParseArgs)- ++- liftOptions get2 set2 (Cabal.buildOptions progDb showOrParseArgs) ++- liftOptions get3 set3 (buildExOptions showOrParseArgs)+ liftOptions get2 set2+ (commandOptions parent showOrParseArgs) } where- get1 (a,_,_) = a; set1 a (_,b,c) = (a,b,c)- get2 (_,b,_) = b; set2 b (a,_,c) = (a,b,c)- get3 (_,_,c) = c; set3 c (a,b,_) = (a,b,c)+ get1 (a,_) = a; set1 a (_,b) = (a,b)+ get2 (_,b) = b; set2 b (a,_) = (a,b) parent = Cabal.testCommand progDb = defaultProgramDb@@ -950,7 +874,7 @@ -- * Bench command -- ------------------------------------------------------------ -benchmarkCommand :: CommandUI (BenchmarkFlags, BuildFlags, BuildExFlags)+benchmarkCommand :: CommandUI (BuildFlags, BenchmarkFlags) benchmarkCommand = parent { commandName = "bench", commandUsage = usageAlternatives "v1-bench"@@ -966,21 +890,17 @@ ++ "By defining UserHooks in a custom Setup.hs, the package can" ++ " define actions to be executed before and after running" ++ " benchmarks.\n",- commandDefaultFlags = (commandDefaultFlags parent,- Cabal.defaultBuildFlags, mempty),+ commandDefaultFlags = (Cabal.defaultBuildFlags, commandDefaultFlags parent), commandOptions = \showOrParseArgs -> liftOptions get1 set1- (commandOptions parent showOrParseArgs)- ++- liftOptions get2 set2 (Cabal.buildOptions progDb showOrParseArgs) ++- liftOptions get3 set3 (buildExOptions showOrParseArgs)+ liftOptions get2 set2+ (commandOptions parent showOrParseArgs) } where- get1 (a,_,_) = a; set1 a (_,b,c) = (a,b,c)- get2 (_,b,_) = b; set2 b (a,_,c) = (a,b,c)- get3 (_,_,c) = c; set3 c (a,b,_) = (a,b,c)+ get1 (a,_) = a; set1 a (_,b) = (a,b)+ get2 (_,b) = b; set2 b (a,_) = (a,b) parent = Cabal.benchmarkCommand progDb = defaultProgramDb@@ -997,6 +917,7 @@ fetchMaxBackjumps :: Flag Int, fetchReorderGoals :: Flag ReorderGoals, fetchCountConflicts :: Flag CountConflicts,+ fetchFineGrainedConflicts :: Flag FineGrainedConflicts, fetchMinimizeConflictSet :: Flag MinimizeConflictSet, fetchIndependentGoals :: Flag IndependentGoals, fetchShadowPkgs :: Flag ShadowPkgs,@@ -1017,6 +938,7 @@ fetchMaxBackjumps = Flag defaultMaxBackjumps, fetchReorderGoals = Flag (ReorderGoals False), fetchCountConflicts = Flag (CountConflicts True),+ fetchFineGrainedConflicts = Flag (FineGrainedConflicts True), fetchMinimizeConflictSet = Flag (MinimizeConflictSet False), fetchIndependentGoals = Flag (IndependentGoals False), fetchShadowPkgs = Flag (ShadowPkgs False),@@ -1079,6 +1001,7 @@ fetchMaxBackjumps (\v flags -> flags { fetchMaxBackjumps = v }) fetchReorderGoals (\v flags -> flags { fetchReorderGoals = v }) fetchCountConflicts (\v flags -> flags { fetchCountConflicts = v })+ fetchFineGrainedConflicts (\v flags -> flags { fetchFineGrainedConflicts = v }) fetchMinimizeConflictSet (\v flags -> flags { fetchMinimizeConflictSet = v }) fetchIndependentGoals (\v flags -> flags { fetchIndependentGoals = v }) fetchShadowPkgs (\v flags -> flags { fetchShadowPkgs = v })@@ -1100,6 +1023,7 @@ freezeMaxBackjumps :: Flag Int, freezeReorderGoals :: Flag ReorderGoals, freezeCountConflicts :: Flag CountConflicts,+ freezeFineGrainedConflicts :: Flag FineGrainedConflicts, freezeMinimizeConflictSet :: Flag MinimizeConflictSet, freezeIndependentGoals :: Flag IndependentGoals, freezeShadowPkgs :: Flag ShadowPkgs,@@ -1118,6 +1042,7 @@ freezeMaxBackjumps = Flag defaultMaxBackjumps, freezeReorderGoals = Flag (ReorderGoals False), freezeCountConflicts = Flag (CountConflicts True),+ freezeFineGrainedConflicts = Flag (FineGrainedConflicts True), freezeMinimizeConflictSet = Flag (MinimizeConflictSet False), freezeIndependentGoals = Flag (IndependentGoals False), freezeShadowPkgs = Flag (ShadowPkgs False),@@ -1171,6 +1096,7 @@ freezeMaxBackjumps (\v flags -> flags { freezeMaxBackjumps = v }) freezeReorderGoals (\v flags -> flags { freezeReorderGoals = v }) freezeCountConflicts (\v flags -> flags { freezeCountConflicts = v })+ freezeFineGrainedConflicts (\v flags -> flags { freezeFineGrainedConflicts = v }) freezeMinimizeConflictSet (\v flags -> flags { freezeMinimizeConflictSet = v }) freezeIndependentGoals (\v flags -> flags { freezeIndependentGoals = v }) freezeShadowPkgs (\v flags -> flags { freezeShadowPkgs = v })@@ -1293,7 +1219,7 @@ ,option [] ["ignore"] "Packages to ignore" outdatedIgnore (\v flags -> flags { outdatedIgnore = v })- (reqArg "PKGS" pkgNameListParser (map display))+ (reqArg "PKGS" pkgNameListParser (map prettyShow)) ,option [] ["minor"] "Ignore major version bumps for these packages"@@ -1309,14 +1235,14 @@ ignoreMajorVersionBumpsPrinter (Just IgnoreMajorVersionBumpsNone)= [] ignoreMajorVersionBumpsPrinter (Just IgnoreMajorVersionBumpsAll) = [Nothing] ignoreMajorVersionBumpsPrinter (Just (IgnoreMajorVersionBumpsSome pkgs)) =- map (Just . display) $ pkgs+ map (Just . prettyShow) $ pkgs ignoreMajorVersionBumpsParser = (Just . IgnoreMajorVersionBumpsSome) `fmap` pkgNameListParser - pkgNameListParser = readP_to_E+ pkgNameListParser = parsecToReadE ("Couldn't parse the list of package names: " ++)- (Parse.sepBy1 parse (Parse.char ','))+ (fmap toList (P.sepByNonEmpty parsec (P.char ','))) -- ------------------------------------------------------------ -- * Update command@@ -1325,14 +1251,14 @@ data UpdateFlags = UpdateFlags { updateVerbosity :: Flag Verbosity,- updateIndexState :: Flag IndexState+ updateIndexState :: Flag TotalIndexState } deriving Generic defaultUpdateFlags :: UpdateFlags defaultUpdateFlags = UpdateFlags { updateVerbosity = toFlag normal,- updateIndexState = toFlag IndexStateHead+ updateIndexState = toFlag headTotalIndexState } updateCommand :: CommandUI UpdateFlags@@ -1354,12 +1280,12 @@ "Accepts unix-timestamps (e.g. '@1474732068'), ISO8601 UTC timestamps " ++ "(e.g. '2016-09-24T17:47:48Z'), or 'HEAD' (default: 'HEAD').") updateIndexState (\v flags -> flags { updateIndexState = v })- (reqArg "STATE" (readP_to_E (const $ "index-state must be a " +++ (reqArg "STATE" (parsecToReadE (const $ "index-state must be a " ++ "unix-timestamps (e.g. '@1474732068'), " ++ "a ISO8601 UTC timestamp " ++ "(e.g. '2016-09-24T17:47:48Z'), or 'HEAD'")- (toFlag `fmap` parse))- (flagToList . fmap display))+ (toFlag `fmap` parsec))+ (flagToList . fmap prettyShow)) ] } @@ -1367,18 +1293,6 @@ -- * Other commands -- ------------------------------------------------------------ -upgradeCommand :: CommandUI ( ConfigFlags, ConfigExFlags, InstallFlags- , HaddockFlags, TestFlags, BenchmarkFlags- )-upgradeCommand = configureCommand {- commandName = "upgrade",- commandSynopsis = "(command disabled, use install instead)",- commandDescription = Nothing,- commandUsage = usageFlagsOrPackages "upgrade",- commandDefaultFlags = (mempty, mempty, mempty, mempty, mempty, mempty),- commandOptions = commandOptions installCommand- }- cleanCommand :: CommandUI CleanFlags cleanCommand = Cabal.cleanCommand { commandUsage = \pname ->@@ -1412,30 +1326,19 @@ commandOptions = \_ -> [] } -uninstallCommand :: CommandUI (Flag Verbosity)-uninstallCommand = CommandUI {- commandName = "uninstall",- commandSynopsis = "Warn about 'uninstall' not being implemented.",- commandDescription = Nothing,- commandNotes = Nothing,- commandUsage = usageAlternatives "uninstall" ["PACKAGES"],- commandDefaultFlags = toFlag normal,- commandOptions = \_ -> []- }--manpageCommand :: CommandUI (Flag Verbosity)+manpageCommand :: CommandUI ManpageFlags manpageCommand = CommandUI {- commandName = "manpage",+ commandName = "man", commandSynopsis = "Outputs manpage source.", commandDescription = Just $ \_ -> "Output manpage source to STDOUT.\n", commandNotes = Nothing,- commandUsage = usageFlags "manpage",- commandDefaultFlags = toFlag normal,- commandOptions = \_ -> [optionVerbosity id const]+ commandUsage = usageFlags "man",+ commandDefaultFlags = defaultManpageFlags,+ commandOptions = manpageOptions } -runCommand :: CommandUI (BuildFlags, BuildExFlags)+runCommand :: CommandUI BuildFlags runCommand = CommandUI { commandName = "run", commandSynopsis = "Builds and runs an executable.",@@ -1455,17 +1358,9 @@ commandUsage = usageAlternatives "v1-run" ["[FLAGS] [EXECUTABLE] [-- EXECUTABLE_FLAGS]"], commandDefaultFlags = mempty,- commandOptions =- \showOrParseArgs -> liftOptions fst setFst- (commandOptions parent showOrParseArgs)- ++- liftOptions snd setSnd- (buildExOptions showOrParseArgs)+ commandOptions = commandOptions parent } where- setFst a (_,b) = (a,b)- setSnd b (a,_) = (a,b)- parent = Cabal.buildCommand defaultProgramDb -- ------------------------------------------------------------@@ -1525,7 +1420,8 @@ data GetFlags = GetFlags { getDestDir :: Flag FilePath, getPristine :: Flag Bool,- getIndexState :: Flag IndexState,+ getIndexState :: Flag TotalIndexState,+ getActiveRepos :: Flag ActiveRepos, getSourceRepository :: Flag (Maybe RepoKind), getVerbosity :: Flag Verbosity } deriving Generic@@ -1535,6 +1431,7 @@ getDestDir = mempty, getPristine = mempty, getIndexState = mempty,+ getActiveRepos = mempty, getSourceRepository = mempty, getVerbosity = toFlag normal }@@ -1567,8 +1464,8 @@ ,option "s" ["source-repository"] "Copy the package's source repository (ie git clone, darcs get, etc as appropriate)." getSourceRepository (\v flags -> flags { getSourceRepository = v })- (optArg "[head|this|...]" (readP_to_E (const "invalid source-repository")- (fmap (toFlag . Just) parse))+ (optArg "[head|this|...]" (parsecToReadE (const "invalid source-repository")+ (fmap (toFlag . Just) parsec)) (Flag Nothing) (map (fmap show) . flagToList)) @@ -1579,12 +1476,12 @@ "This determines which package versions are available as well as " ++ ".cabal file revision is selected (unless --pristine is used).") getIndexState (\v flags -> flags { getIndexState = v })- (reqArg "STATE" (readP_to_E (const $ "index-state must be a " +++ (reqArg "STATE" (parsecToReadE (const $ "index-state must be a " ++ "unix-timestamps (e.g. '@1474732068'), " ++ "a ISO8601 UTC timestamp " ++ "(e.g. '2016-09-24T17:47:48Z'), or 'HEAD'")- (toFlag `fmap` parse))- (flagToList . fmap display))+ (toFlag `fmap` parsec))+ (flagToList . fmap prettyShow)) , option [] ["pristine"] ("Unpack the original pristine tarball, rather than updating the "@@ -1612,20 +1509,25 @@ -- * List flags -- ------------------------------------------------------------ -data ListFlags = ListFlags {- listInstalled :: Flag Bool,- listSimpleOutput :: Flag Bool,- listVerbosity :: Flag Verbosity,- listPackageDBs :: [Maybe PackageDB]- } deriving Generic+data ListFlags = ListFlags+ { listInstalled :: Flag Bool+ , listSimpleOutput :: Flag Bool+ , listCaseInsensitive :: Flag Bool+ , listVerbosity :: Flag Verbosity+ , listPackageDBs :: [Maybe PackageDB]+ , listHcPath :: Flag FilePath+ }+ deriving Generic defaultListFlags :: ListFlags-defaultListFlags = ListFlags {- listInstalled = Flag False,- listSimpleOutput = Flag False,- listVerbosity = toFlag normal,- listPackageDBs = []- }+defaultListFlags = ListFlags+ { listInstalled = Flag False+ , listSimpleOutput = Flag False+ , listCaseInsensitive = Flag True+ , listVerbosity = toFlag normal+ , listPackageDBs = []+ , listHcPath = mempty+ } listCommand :: CommandUI ListFlags listCommand = CommandUI {@@ -1635,9 +1537,7 @@ "List all packages, or all packages matching one of the search" ++ " strings.\n" ++ "\n"- ++ "If there is a sandbox in the current directory and "- ++ "config:ignore-sandbox is False, use the sandbox package database. "- ++ "Otherwise, use the package database specified with --package-db. "+ ++ "Use the package database specified with --package-db. " ++ "If not specified, use the user package database.\n", commandNotes = Just $ \pname -> "Examples:\n"@@ -1646,32 +1546,48 @@ commandUsage = usageAlternatives "list" [ "[FLAGS]" , "[FLAGS] STRINGS"], commandDefaultFlags = defaultListFlags,- commandOptions = \_ -> [- optionVerbosity listVerbosity (\v flags -> flags { listVerbosity = v })+ commandOptions = const listOptions+ } - , option [] ["installed"]- "Only print installed packages"- listInstalled (\v flags -> flags { listInstalled = v })- trueArg+listOptions :: [OptionField ListFlags]+listOptions =+ [ optionVerbosity listVerbosity (\v flags -> flags { listVerbosity = v }) - , option [] ["simple-output"]- "Print in a easy-to-parse format"- listSimpleOutput (\v flags -> flags { listSimpleOutput = v })- trueArg+ , option [] ["installed"]+ "Only print installed packages"+ listInstalled (\v flags -> flags { listInstalled = v })+ trueArg - , option "" ["package-db"]- ( "Append the given package database to the list of package"- ++ " databases used (to satisfy dependencies and register into)."- ++ " May be a specific file, 'global' or 'user'. The initial list"- ++ " is ['global'], ['global', 'user'], or ['global', $sandbox],"- ++ " depending on context. Use 'clear' to reset the list to empty."- ++ " See the user guide for details.")- listPackageDBs (\v flags -> flags { listPackageDBs = v })- (reqArg' "DB" readPackageDbList showPackageDbList)+ , option [] ["simple-output"]+ "Print in a easy-to-parse format"+ listSimpleOutput (\v flags -> flags { listSimpleOutput = v })+ trueArg+ , option ['i'] ["ignore-case"]+ "Ignore case destictions"+ listCaseInsensitive (\v flags -> flags { listCaseInsensitive = v })+ (boolOpt' (['i'], ["ignore-case"]) (['I'], ["strict-case"])) - ]- }+ , option "" ["package-db"]+ ( "Append the given package database to the list of package"+ ++ " databases used (to satisfy dependencies and register into)."+ ++ " May be a specific file, 'global' or 'user'. The initial list"+ ++ " is ['global'], ['global', 'user'],"+ ++ " depending on context. Use 'clear' to reset the list to empty."+ ++ " See the user guide for details.")+ listPackageDBs (\v flags -> flags { listPackageDBs = v })+ (reqArg' "DB" readPackageDbList showPackageDbList) + , option "w" ["with-compiler"]+ "give the path to a particular compiler"+ listHcPath (\v flags -> flags { listHcPath = v })+ (reqArgFlag "PATH")+ ]++listNeedsCompiler :: ListFlags -> Bool+listNeedsCompiler f =+ flagElim False (const True) (listHcPath f)+ || fromFlagOrDefault False (listInstalled f)+ instance Monoid ListFlags where mempty = gmempty mappend = (<>)@@ -1699,9 +1615,7 @@ commandName = "info", commandSynopsis = "Display detailed information about a particular package.", commandDescription = Just $ \_ -> wrapText $- "If there is a sandbox in the current directory and "- ++ "config:ignore-sandbox is False, use the sandbox package database. "- ++ "Otherwise, use the package database specified with --package-db. "+ "Use the package database specified with --package-db. " ++ "If not specified, use the user package database.\n", commandNotes = Nothing, commandUsage = usageAlternatives "info" ["[FLAGS] PACKAGES"],@@ -1713,7 +1627,7 @@ ( "Append the given package database to the list of package" ++ " databases used (to satisfy dependencies and register into)." ++ " May be a specific file, 'global' or 'user'. The initial list"- ++ " is ['global'], ['global', 'user'], or ['global', $sandbox],"+ ++ " is ['global'], ['global', 'user']," ++ " depending on context. Use 'clear' to reset the list to empty." ++ " See the user guide for details.") infoPackageDBs (\v flags -> flags { infoPackageDBs = v })@@ -1743,6 +1657,7 @@ installMaxBackjumps :: Flag Int, installReorderGoals :: Flag ReorderGoals, installCountConflicts :: Flag CountConflicts,+ installFineGrainedConflicts :: Flag FineGrainedConflicts, installMinimizeConflictSet :: Flag MinimizeConflictSet, installIndependentGoals :: Flag IndependentGoals, installShadowPkgs :: Flag ShadowPkgs,@@ -1755,7 +1670,7 @@ installUpgradeDeps :: Flag Bool, installOnly :: Flag Bool, installOnlyDeps :: Flag Bool,- installIndexState :: Flag IndexState,+ installIndexState :: Flag TotalIndexState, installRootCmd :: Flag String, installSummaryFile :: NubList PathTemplate, installLogFile :: Flag PathTemplate,@@ -1769,17 +1684,9 @@ installNumJobs :: Flag (Maybe Int), installKeepGoing :: Flag Bool, installRunTests :: Flag Bool,- installOfflineMode :: Flag Bool,- -- | The cabal project file name; defaults to @cabal.project@.- -- Th name itself denotes the cabal project file name, but it also- -- is the base of auxiliary project files, such as- -- @cabal.project.local@ and @cabal.project.freeze@ which are also- -- read and written out in some cases. If the path is not found- -- in the current working directory, we will successively probe- -- relative to parent directories until this name is found.- installProjectFileName :: Flag FilePath+ installOfflineMode :: Flag Bool }- deriving (Eq, Generic)+ deriving (Eq, Show, Generic) instance Binary InstallFlags @@ -1792,6 +1699,7 @@ installMaxBackjumps = Flag defaultMaxBackjumps, installReorderGoals = Flag (ReorderGoals False), installCountConflicts = Flag (CountConflicts True),+ installFineGrainedConflicts = Flag (FineGrainedConflicts True), installMinimizeConflictSet = Flag (MinimizeConflictSet False), installIndependentGoals= Flag (IndependentGoals False), installShadowPkgs = Flag (ShadowPkgs False),@@ -1816,8 +1724,7 @@ installNumJobs = mempty, installKeepGoing = Flag False, installRunTests = mempty,- installOfflineMode = Flag False,- installProjectFileName = mempty+ installOfflineMode = Flag False } where docIndexFile = toPathTemplate ("$datadir" </> "doc"@@ -1830,7 +1737,7 @@ defaultSolver = AlwaysModular allSolvers :: String-allSolvers = intercalate ", " (map display ([minBound .. maxBound] :: [PreSolver]))+allSolvers = intercalate ", " (map prettyShow ([minBound .. maxBound] :: [PreSolver])) installCommand :: CommandUI ( ConfigFlags, ConfigExFlags, InstallFlags , HaddockFlags, TestFlags, BenchmarkFlags@@ -1843,31 +1750,22 @@ ], commandDescription = Just $ \_ -> wrapText $ "Installs one or more packages. By default, the installed package"- ++ " will be registered in the user's package database or, if a sandbox"- ++ " is present in the current directory, inside the sandbox.\n"+ ++ " will be registered in the user's package database." ++ "\n" ++ "If PACKAGES are specified, downloads and installs those packages." ++ " Otherwise, install the package in the current directory (and/or its" ++ " dependencies) (there must be exactly one .cabal file in the current" ++ " directory).\n" ++ "\n"- ++ "When using a sandbox, the flags for `v1-install` only affect the"- ++ " current command and have no effect on future commands. (To achieve"- ++ " that, `v1-configure` must be used.)\n"- ++ " In contrast, without a sandbox, the flags to `v1-install` are saved and"+ ++ "The flags to `v1-install` are saved and" ++ " affect future commands such as `v1-build` and `v1-repl`. See the help for" ++ " `v1-configure` for a list of commands being affected.\n" ++ "\n"- ++ "Installed executables will by default (and without a sandbox)"+ ++ "Installed executables will by default" ++ " be put into `~/.cabal/bin/`." ++ " If you want installed executable to be available globally, make" ++ " sure that the PATH environment variable contains that directory.\n"- ++ "When using a sandbox, executables will be put into"- ++ " `$SANDBOX/bin/` (by default: `./.cabal-sandbox/bin/`).\n"- ++ "\n"- ++ "When specifying --bindir, consider also specifying --datadir;"- ++ " this way the sandbox can be deleted and the executable should"- ++ " continue working as long as bindir and datadir are left untouched.",+ ++ "\n", commandNotes = Just $ \pname -> ( case commandNotes $ Cabal.configureCommand defaultProgramDb@@ -2022,6 +1920,7 @@ installMaxBackjumps (\v flags -> flags { installMaxBackjumps = v }) installReorderGoals (\v flags -> flags { installReorderGoals = v }) installCountConflicts (\v flags -> flags { installCountConflicts = v })+ installFineGrainedConflicts (\v flags -> flags { installFineGrainedConflicts = v }) installMinimizeConflictSet (\v flags -> flags { installMinimizeConflictSet = v }) installIndependentGoals (\v flags -> flags { installIndependentGoals = v }) installShadowPkgs (\v flags -> flags { installShadowPkgs = v })@@ -2065,12 +1964,12 @@ "Accepts unix-timestamps (e.g. '@1474732068'), ISO8601 UTC timestamps " ++ "(e.g. '2016-09-24T17:47:48Z'), or 'HEAD' (default: 'HEAD').") installIndexState (\v flags -> flags { installIndexState = v })- (reqArg "STATE" (readP_to_E (const $ "index-state must be a " +++ (reqArg "STATE" (parsecToReadE (const $ "index-state must be a " ++ "unix-timestamps (e.g. '@1474732068'), " ++ "a ISO8601 UTC timestamp " ++ "(e.g. '2016-09-24T17:47:48Z'), or 'HEAD'")- (toFlag `fmap` parse))- (flagToList . fmap display))+ (toFlag `fmap` parsec))+ (flagToList . fmap prettyShow)) , option [] ["root-cmd"] "(No longer supported, do not use.)"@@ -2096,10 +1995,10 @@ , option [] ["remote-build-reporting"] "Generate build reports to send to a remote server (none, anonymous or detailed)." installBuildReports (\v flags -> flags { installBuildReports = v })- (reqArg "LEVEL" (readP_to_E (const $ "report level must be 'none', "+ (reqArg "LEVEL" (parsecToReadE (const $ "report level must be 'none', " ++ "'anonymous' or 'detailed'")- (toFlag `fmap` parse))- (flagToList . fmap display))+ (toFlag `fmap` parsec))+ (flagToList . fmap prettyShow)) , option [] ["report-planning-failure"] "Generate build reports when the dependency solver fails. This is used by the Hackage build bot."@@ -2134,10 +2033,6 @@ installOfflineMode (\v flags -> flags { installOfflineMode = v }) (yesNoOpt showOrParseArgs) - , option [] ["project-file"]- "Set the name of the cabal.project file to search for in parent directories"- installProjectFileName (\v flags -> flags {installProjectFileName = v})- (reqArgFlag "FILE") ] ++ case showOrParseArgs of -- TODO: remove when "cabal install" -- avoids ParseArgs ->@@ -2189,7 +2084,7 @@ commandDescription = Nothing, commandNotes = Just $ \_ -> "You can store your Hackage login in the ~/.cabal/config file\n"- ++ relevantConfigValuesText ["username", "password"],+ ++ relevantConfigValuesText ["username", "password", "password-command"], commandUsage = \pname -> "Usage: " ++ pname ++ " upload [FLAGS] TARFILES\n", commandDefaultFlags = defaultUploadFlags,@@ -2240,12 +2135,6 @@ -- * Init flags -- ------------------------------------------------------------ -emptyInitFlags :: IT.InitFlags-emptyInitFlags = mempty--defaultInitFlags :: IT.InitFlags-defaultInitFlags = emptyInitFlags { IT.initVerbosity = toFlag normal }- initCommand :: CommandUI IT.InitFlags initCommand = CommandUI { commandName = "init",@@ -2263,7 +2152,7 @@ commandNotes = Nothing, commandUsage = \pname -> "Usage: " ++ pname ++ " init [FLAGS]\n",- commandDefaultFlags = defaultInitFlags,+ commandDefaultFlags = IT.defaultInitFlags, commandOptions = initOptions } @@ -2302,30 +2191,30 @@ , option ['p'] ["package-name"] "Name of the Cabal package to create." IT.packageName (\v flags -> flags { IT.packageName = v })- (reqArg "PACKAGE" (readP_to_E ("Cannot parse package name: "++)- (toFlag `fmap` parse))- (flagToList . fmap display))+ (reqArg "PACKAGE" (parsecToReadE ("Cannot parse package name: "++)+ (toFlag `fmap` parsec))+ (flagToList . fmap prettyShow)) , option [] ["version"] "Initial version of the package." IT.version (\v flags -> flags { IT.version = v })- (reqArg "VERSION" (readP_to_E ("Cannot parse package version: "++)- (toFlag `fmap` parse))- (flagToList . fmap display))+ (reqArg "VERSION" (parsecToReadE ("Cannot parse package version: "++)+ (toFlag `fmap` parsec))+ (flagToList . fmap prettyShow)) , option [] ["cabal-version"] "Version of the Cabal specification." IT.cabalVersion (\v flags -> flags { IT.cabalVersion = v })- (reqArg "VERSION_RANGE" (readP_to_E ("Cannot parse Cabal specification version: "++)- (toFlag `fmap` parse))- (flagToList . fmap display))+ (reqArg "CABALSPECVERSION" (parsecToReadE ("Cannot parse Cabal specification version: "++)+ (fmap (toFlag . getSpecVersion) parsec))+ (flagToList . fmap (prettyShow . SpecVersion))) , option ['l'] ["license"] "Project license." IT.license (\v flags -> flags { IT.license = v })- (reqArg "LICENSE" (readP_to_E ("Cannot parse license: "++)- (toFlag `fmap` parse))- (flagToList . fmap display))+ (reqArg "LICENSE" (parsecToReadE ("Cannot parse license: "++)+ (toFlag `fmap` parsec))+ (flagToList . fmap prettyShow)) , option ['a'] ["author"] "Name of the project's author."@@ -2404,32 +2293,32 @@ "Specify the default language." IT.language (\v flags -> flags { IT.language = v })- (reqArg "LANGUAGE" (readP_to_E ("Cannot parse language: "++)- (toFlag `fmap` parse))- (flagToList . fmap display))+ (reqArg "LANGUAGE" (parsecToReadE ("Cannot parse language: "++)+ (toFlag `fmap` parsec))+ (flagToList . fmap prettyShow)) , option ['o'] ["expose-module"] "Export a module from the package." IT.exposedModules (\v flags -> flags { IT.exposedModules = v })- (reqArg "MODULE" (readP_to_E ("Cannot parse module name: "++)- ((Just . (:[])) `fmap` parse))- (maybe [] (fmap display)))+ (reqArg "MODULE" (parsecToReadE ("Cannot parse module name: "++)+ ((Just . (:[])) `fmap` parsec))+ (maybe [] (fmap prettyShow))) , option [] ["extension"] "Use a LANGUAGE extension (in the other-extensions field)." IT.otherExts (\v flags -> flags { IT.otherExts = v })- (reqArg "EXTENSION" (readP_to_E ("Cannot parse extension: "++)- ((Just . (:[])) `fmap` parse))- (maybe [] (fmap display)))+ (reqArg "EXTENSION" (parsecToReadE ("Cannot parse extension: "++)+ ((Just . (:[])) `fmap` parsec))+ (maybe [] (fmap prettyShow))) , option ['d'] ["dependency"] "Package dependency." IT.dependencies (\v flags -> flags { IT.dependencies = v })- (reqArg "PACKAGE" (readP_to_E ("Cannot parse dependency: "++)- ((Just . (:[])) `fmap` parse))- (maybe [] (fmap display)))+ (reqArg "PACKAGE" (parsecToReadE ("Cannot parse dependency: "++)+ ((Just . (:[])) `fmap` parsec))+ (maybe [] (fmap prettyShow))) , option [] ["application-dir"] "Directory containing package application executable."@@ -2464,18 +2353,6 @@ -- * SDist flags -- ------------------------------------------------------------ --- | Extra flags to @sdist@ beyond runghc Setup sdist----sdistCommand :: CommandUI SDistFlags-sdistCommand = Cabal.sdistCommand {- commandUsage = \pname ->- "Usage: " ++ pname ++ " v1-sdist [FLAGS]\n",- commandDefaultFlags = (commandDefaultFlags Cabal.sdistCommand)- }------ doctestCommand :: CommandUI DoctestFlags doctestCommand = Cabal.doctestCommand { commandUsage = \pname -> "Usage: " ++ pname ++ " v1-doctest [FLAGS]\n" }@@ -2499,41 +2376,6 @@ { commandUsage = \pname -> "Usage: " ++ pname ++ " v1-register [FLAGS]\n" } -- --------------------------------------------------------------- * Win32SelfUpgrade flags--- --------------------------------------------------------------data Win32SelfUpgradeFlags = Win32SelfUpgradeFlags {- win32SelfUpgradeVerbosity :: Flag Verbosity-} deriving Generic--defaultWin32SelfUpgradeFlags :: Win32SelfUpgradeFlags-defaultWin32SelfUpgradeFlags = Win32SelfUpgradeFlags {- win32SelfUpgradeVerbosity = toFlag normal-}--win32SelfUpgradeCommand :: CommandUI Win32SelfUpgradeFlags-win32SelfUpgradeCommand = CommandUI {- commandName = "win32selfupgrade",- commandSynopsis = "Self-upgrade the executable on Windows",- commandDescription = Nothing,- commandNotes = Nothing,- commandUsage = \pname ->- "Usage: " ++ pname ++ " win32selfupgrade PID PATH\n",- commandDefaultFlags = defaultWin32SelfUpgradeFlags,- commandOptions = \_ ->- [optionVerbosity win32SelfUpgradeVerbosity- (\v flags -> flags { win32SelfUpgradeVerbosity = v})- ]-}--instance Monoid Win32SelfUpgradeFlags where- mempty = gmempty- mappend = (<>)--instance Semigroup Win32SelfUpgradeFlags where- (<>) = gmappend---- ------------------------------------------------------------ -- * ActAsSetup flags -- ------------------------------------------------------------ @@ -2559,9 +2401,9 @@ [option "" ["build-type"] "Use the given build type." actAsSetupBuildType (\v flags -> flags { actAsSetupBuildType = v })- (reqArg "BUILD-TYPE" (readP_to_E ("Cannot parse build type: "++)- (fmap toFlag parse))- (map display . flagToList))+ (reqArg "BUILD-TYPE" (parsecToReadE ("Cannot parse build type: "++)+ (fmap toFlag parsec))+ (map prettyShow . flagToList)) ] } @@ -2573,128 +2415,6 @@ (<>) = gmappend -- --------------------------------------------------------------- * Sandbox-related flags--- --------------------------------------------------------------data SandboxFlags = SandboxFlags {- sandboxVerbosity :: Flag Verbosity,- sandboxSnapshot :: Flag Bool, -- FIXME: this should be an 'add-source'-only- -- flag.- sandboxLocation :: Flag FilePath-} deriving Generic--defaultSandboxLocation :: FilePath-defaultSandboxLocation = ".cabal-sandbox"--defaultSandboxFlags :: SandboxFlags-defaultSandboxFlags = SandboxFlags {- sandboxVerbosity = toFlag normal,- sandboxSnapshot = toFlag False,- sandboxLocation = toFlag defaultSandboxLocation- }--sandboxCommand :: CommandUI SandboxFlags-sandboxCommand = CommandUI {- commandName = "sandbox",- commandSynopsis = "Create/modify/delete a sandbox.",- commandDescription = Just $ \pname -> concat- [ paragraph $ "Sandboxes are isolated package databases that can be used"- ++ " to prevent dependency conflicts that arise when many different"- ++ " packages are installed in the same database (i.e. the user's"- ++ " database in the home directory)."- , paragraph $ "A sandbox in the current directory (created by"- ++ " `v1-sandbox init`) will be used instead of the user's database for"- ++ " commands such as `v1-install` and `v1-build`. Note that (a directly"- ++ " invoked) GHC will not automatically be aware of sandboxes;"- ++ " only if called via appropriate " ++ pname- ++ " commands, e.g. `v1-repl`, `v1-build`, `v1-exec`."- , paragraph $ "Currently, " ++ pname ++ " will not search for a sandbox"- ++ " in folders above the current one, so cabal will not see the sandbox"- ++ " if you are in a subfolder of a sandbox."- , paragraph "Subcommands:"- , headLine "init:"- , indentParagraph $ "Initialize a sandbox in the current directory."- ++ " An existing package database will not be modified, but settings"- ++ " (such as the location of the database) can be modified this way."- , headLine "delete:"- , indentParagraph $ "Remove the sandbox; deleting all the packages"- ++ " installed inside."- , headLine "add-source:"- , indentParagraph $ "Make one or more local packages available in the"- ++ " sandbox. PATHS may be relative or absolute."- ++ " Typical usecase is when you need"- ++ " to make a (temporary) modification to a dependency: You download"- ++ " the package into a different directory, make the modification,"- ++ " and add that directory to the sandbox with `add-source`."- , indentParagraph $ "Unless given `--snapshot`, any add-source'd"- ++ " dependency that was modified since the last build will be"- ++ " re-installed automatically."- , headLine "delete-source:"- , indentParagraph $ "Remove an add-source dependency; however, this will"- ++ " not delete the package(s) that have been installed in the sandbox"- ++ " from this dependency. You can either unregister the package(s) via"- ++ " `" ++ pname ++ " v1-sandbox hc-pkg unregister` or re-create the"- ++ " sandbox (`v1-sandbox delete; v1-sandbox init`)."- , headLine "list-sources:"- , indentParagraph $ "List the directories of local packages made"- ++ " available via `" ++ pname ++ " v1-sandbox add-source`."- , headLine "hc-pkg:"- , indentParagraph $ "Similar to `ghc-pkg`, but for the sandbox package"- ++ " database. Can be used to list specific/all packages that are"- ++ " installed in the sandbox. For subcommands, see the help for"- ++ " ghc-pkg. Affected by the compiler version specified by `v1-configure`."- ],- commandNotes = Just $ \pname ->- relevantConfigValuesText ["require-sandbox"- ,"ignore-sandbox"]- ++ "\n"- ++ "Examples:\n"- ++ " Set up a sandbox with one local dependency, located at ../foo:\n"- ++ " " ++ pname ++ " v1-sandbox init\n"- ++ " " ++ pname ++ " v1-sandbox add-source ../foo\n"- ++ " " ++ pname ++ " v1-install --only-dependencies\n"- ++ " Reset the sandbox:\n"- ++ " " ++ pname ++ " v1-sandbox delete\n"- ++ " " ++ pname ++ " v1-sandbox init\n"- ++ " " ++ pname ++ " v1-install --only-dependencies\n"- ++ " List the packages in the sandbox:\n"- ++ " " ++ pname ++ " v1-sandbox hc-pkg list\n"- ++ " Unregister the `broken` package from the sandbox:\n"- ++ " " ++ pname ++ " v1-sandbox hc-pkg -- --force unregister broken\n",- commandUsage = usageAlternatives "v1-sandbox"- [ "init [FLAGS]"- , "delete [FLAGS]"- , "add-source [FLAGS] PATHS"- , "delete-source [FLAGS] PATHS"- , "list-sources [FLAGS]"- , "hc-pkg [FLAGS] [--] COMMAND [--] [ARGS]"- ],-- commandDefaultFlags = defaultSandboxFlags,- commandOptions = \_ ->- [ optionVerbosity sandboxVerbosity- (\v flags -> flags { sandboxVerbosity = v })-- , option [] ["snapshot"]- "Take a snapshot instead of creating a link (only applies to 'add-source')"- sandboxSnapshot (\v flags -> flags { sandboxSnapshot = v })- trueArg-- , option [] ["sandbox"]- "Sandbox location (default: './.cabal-sandbox')."- sandboxLocation (\v flags -> flags { sandboxLocation = v })- (reqArgFlag "DIR")- ]- }--instance Monoid SandboxFlags where- mempty = gmempty- mappend = (<>)--instance Semigroup SandboxFlags where- (<>) = gmappend---- ------------------------------------------------------------ -- * Exec Flags -- ------------------------------------------------------------ @@ -2844,16 +2564,17 @@ -> OptionField flags optionSolver get set = option [] ["solver"]- ("Select dependency solver to use (default: " ++ display defaultSolver ++ "). Choices: " ++ allSolvers ++ ".")+ ("Select dependency solver to use (default: " ++ prettyShow defaultSolver ++ "). Choices: " ++ allSolvers ++ ".") get set- (reqArg "SOLVER" (readP_to_E (const $ "solver must be one of: " ++ allSolvers)- (toFlag `fmap` parse))- (flagToList . fmap display))+ (reqArg "SOLVER" (parsecToReadE (const $ "solver must be one of: " ++ allSolvers)+ (toFlag `fmap` parsec))+ (flagToList . fmap prettyShow)) optionSolverFlags :: ShowOrParseArgs -> (flags -> Flag Int ) -> (Flag Int -> flags -> flags) -> (flags -> Flag ReorderGoals) -> (Flag ReorderGoals -> flags -> flags) -> (flags -> Flag CountConflicts) -> (Flag CountConflicts -> flags -> flags)+ -> (flags -> Flag FineGrainedConflicts) -> (Flag FineGrainedConflicts -> flags -> flags) -> (flags -> Flag MinimizeConflictSet) -> (Flag MinimizeConflictSet -> flags -> flags) -> (flags -> Flag IndependentGoals) -> (Flag IndependentGoals -> flags -> flags) -> (flags -> Flag ShadowPkgs) -> (Flag ShadowPkgs -> flags -> flags)@@ -2862,12 +2583,12 @@ -> (flags -> Flag OnlyConstrained) -> (Flag OnlyConstrained -> flags -> flags) -> [OptionField flags] optionSolverFlags showOrParseArgs getmbj setmbj getrg setrg getcc setcc- getmc setmc getig setig getsip setsip getstrfl setstrfl- getib setib getoc setoc =+ getfgc setfgc getmc setmc getig setig getsip setsip+ getstrfl setstrfl getib setib getoc setoc = [ option [] ["max-backjumps"] ("Maximum number of backjumps allowed while solving (default: " ++ show defaultMaxBackjumps ++ "). Use a negative number to enable unlimited backtracking. Use 0 to disable backtracking completely.") getmbj setmbj- (reqArg "NUM" (readP_to_E ("Cannot parse number: "++) (fmap toFlag parse))+ (reqArg "NUM" (parsecToReadE ("Cannot parse number: "++) (fmap toFlag P.signedIntegral)) (map show . flagToList)) , option [] ["reorder-goals"] "Try to reorder goals according to certain heuristics. Slows things down on average, but may make backtracking faster for some packages."@@ -2879,6 +2600,11 @@ (fmap asBool . getcc) (setcc . fmap CountConflicts) (yesNoOpt showOrParseArgs)+ , option [] ["fine-grained-conflicts"]+ "Skip a version of a package if it does not resolve the conflicts encountered in the last version, as a solver optimization (default)."+ (fmap asBool . getfgc)+ (setfgc . fmap FineGrainedConflicts)+ (yesNoOpt showOrParseArgs) , option [] ["minimize-conflict-set"] ("When there is no solution, try to improve the error message by finding " ++ "a minimal conflict set (default: false). May increase run time "@@ -2911,18 +2637,13 @@ getoc setoc (reqArg "none|all"- (readP_to_E+ (parsecToReadE (const "reject-unconstrained-dependencies must be 'none' or 'all'")- (toFlag `fmap` parse))- (flagToList . fmap display))+ (toFlag `fmap` parsec))+ (flagToList . fmap prettyShow)) ] -usageFlagsOrPackages :: String -> String -> String-usageFlagsOrPackages name pname =- "Usage: " ++ pname ++ " " ++ name ++ " [FLAGS]\n"- ++ " or: " ++ pname ++ " " ++ name ++ " [PACKAGES]\n"- usagePackages :: String -> String -> String usagePackages name pname = "Usage: " ++ pname ++ " " ++ name ++ " [PACKAGES]\n"@@ -2932,70 +2653,29 @@ "Usage: " ++ pname ++ " " ++ name ++ " [FLAGS]\n" --TODO: do we want to allow per-package flags?-parsePackageArgs :: [String] -> Either String [Dependency]-parsePackageArgs = parsePkgArgs []- where- parsePkgArgs ds [] = Right (reverse ds)- parsePkgArgs ds (arg:args) =- case readPToMaybe parseDependencyOrPackageId arg of- Just dep -> parsePkgArgs (dep:ds) args- Nothing -> Left $- show arg ++ " is not valid syntax for a package name or"- ++ " package dependency."+parsePackageArgs :: [String] -> Either String [PackageVersionConstraint]+parsePackageArgs = traverse p where+ p arg = case eitherParsec arg of+ Right pvc -> Right pvc+ Left err -> Left $+ show arg ++ " is not valid syntax for a package name or"+ ++ " package dependency. " ++ err -parseDependencyOrPackageId :: Parse.ReadP r Dependency-parseDependencyOrPackageId = parse Parse.+++ liftM pkgidToDependency parse- where- pkgidToDependency :: PackageIdentifier -> Dependency- pkgidToDependency p = case packageVersion p of- v | v == nullVersion -> Dependency (packageName p) anyVersion (Set.singleton LMainLibName)- | otherwise -> Dependency (packageName p) (thisVersion v) (Set.singleton LMainLibName)+showRemoteRepo :: RemoteRepo -> String+showRemoteRepo = prettyShow -showRepo :: RemoteRepo -> String-showRepo repo = remoteRepoName repo ++ ":"- ++ uriToString id (remoteRepoURI repo) []+readRemoteRepo :: String -> Maybe RemoteRepo+readRemoteRepo = simpleParsec -readRepo :: String -> Maybe RemoteRepo-readRepo = readPToMaybe parseRepo+showLocalRepo :: LocalRepo -> String+showLocalRepo = prettyShow -parseRepo :: Parse.ReadP r RemoteRepo-parseRepo = do- name <- Parse.munch1 (\c -> isAlphaNum c || c `elem` "_-.")- _ <- Parse.char ':'- uriStr <- Parse.munch1 (\c -> isAlphaNum c || c `elem` "+-=._/*()@'$:;&!?~")- uri <- maybe Parse.pfail return (parseAbsoluteURI uriStr)- return RemoteRepo {- remoteRepoName = name,- remoteRepoURI = uri,- remoteRepoSecure = Nothing,- remoteRepoRootKeys = [],- remoteRepoKeyThreshold = 0,- remoteRepoShouldTryHttps = False- }+readLocalRepo :: String -> Maybe LocalRepo+readLocalRepo = simpleParsec -- ------------------------------------------------------------ -- * Helpers for Documentation -- --------------------------------------------------------------headLine :: String -> String-headLine = unlines- . map unwords- . wrapLine 79- . words--paragraph :: String -> String-paragraph = (++"\n")- . unlines- . map unwords- . wrapLine 79- . words--indentParagraph :: String -> String-indentParagraph = unlines- . (flip (++)) [""]- . map ((" "++).unwords)- . wrapLine 77- . words relevantConfigValuesText :: [String] -> String relevantConfigValuesText vs =
cabal/cabal-install/Distribution/Client/SetupWrapper.hs view
@@ -1,5 +1,6 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE OverloadedStrings #-} ----------------------------------------------------------------------------- -- | -- Module : Distribution.Client.SetupWrapper@@ -25,6 +26,7 @@ import Prelude () import Distribution.Client.Compat.Prelude +import Distribution.CabalSpecVersion (cabalSpecMinimumLibraryVersion) import qualified Distribution.Make as Make import qualified Distribution.Simple as Simple import Distribution.Version@@ -39,7 +41,8 @@ import Distribution.PackageDescription ( GenericPackageDescription(packageDescription) , PackageDescription(..), specVersion, buildType- , BuildType(..), defaultRenaming )+ , BuildType(..) )+import Distribution.Types.ModuleRenaming (defaultRenaming) import Distribution.PackageDescription.Parsec ( readGenericPackageDescription ) import Distribution.Simple.Configure@@ -85,9 +88,9 @@ ( safeHead ) import Distribution.Simple.Utils ( die', debug, info, infoNoWrap- , cabalVersion, tryFindPackageDesc, comparing+ , cabalVersion, tryFindPackageDesc , createDirectoryIfMissingVerbose, installExecutableFile- , copyFileVerbose, rewriteFileEx )+ , copyFileVerbose, rewriteFileEx, rewriteFileLBS ) import Distribution.Client.Utils ( inDir, tryCanonicalizePath, withExtraPathEnv , existsAndIsMoreRecentThan, moreRecentFile, withEnv, withEnvOverrides@@ -98,25 +101,23 @@ import Distribution.ReadE import Distribution.System ( Platform(..), buildPlatform )-import Distribution.Deprecated.Text- ( display ) import Distribution.Utils.NubList ( toNubListR ) import Distribution.Verbosity-import Distribution.Compat.Exception- ( catchIO ) import Distribution.Compat.Stack import System.Directory ( doesFileExist ) import System.FilePath ( (</>), (<.>) ) import System.IO ( Handle, hPutStr )-import System.Exit ( ExitCode(..), exitWith )-import System.Process ( createProcess, StdStream(..), proc, waitForProcess+import Distribution.Compat.Process (createProcess)+import System.Process ( StdStream(..), proc, waitForProcess , ProcessHandle ) import qualified System.Process as Process import Data.List ( foldl1' ) import Distribution.Client.Compat.ExecutablePath ( getExecutablePath ) +import qualified Data.ByteString.Lazy as BS+ #ifdef mingw32_HOST_OS import Distribution.Simple.Utils ( withTempDirectory )@@ -301,7 +302,7 @@ let options' = options { useCabalVersion = intersectVersionRanges (useCabalVersion options)- (orLaterVersion (specVersion pkg))+ (orLaterVersion (mkVersion (cabalSpecMinimumLibraryVersion (specVersion pkg)))) } buildType' = buildType pkg (version, method, options'') <-@@ -464,6 +465,7 @@ mbToStd :: Maybe Handle -> StdStream mbToStd Nothing = Inherit mbToStd (Just hdl) = UseHandle hdl+ -- ------------------------------------------------------------ -- * Self-Exec SetupMethod -- ------------------------------------------------------------@@ -471,7 +473,7 @@ selfExecSetupMethod :: SetupRunner selfExecSetupMethod verbosity options bt args0 = do let args = ["act-as-setup",- "--build-type=" ++ display bt,+ "--build-type=" ++ prettyShow bt, "--"] ++ args0 info verbosity $ "Using self-exec internal setup method with build-type " ++ show bt ++ " and args:\n " ++ show args@@ -564,7 +566,7 @@ ++ show (useDependenciesExclusive options) createDirectoryIfMissingVerbose verbosity True setupDir (cabalLibVersion, mCabalLibInstalledPkgId, options') <- cabalLibVersionToUse- debug verbosity $ "Using Cabal library version " ++ display cabalLibVersion+ debug verbosity $ "Using Cabal library version " ++ prettyShow cabalLibVersion path <- if useCachedSetupExecutable then getCachedSetupExecutable options' cabalLibVersion mCabalLibInstalledPkgId@@ -700,17 +702,15 @@ customSetupLhs = workingDir options </> "Setup.lhs" updateSetupScript cabalLibVersion _ =- rewriteFileEx verbosity setupHs (buildTypeScript cabalLibVersion)+ rewriteFileLBS verbosity setupHs (buildTypeScript cabalLibVersion) - buildTypeScript :: Version -> String+ buildTypeScript :: Version -> BS.ByteString buildTypeScript cabalLibVersion = case bt of- Simple -> "import Distribution.Simple; main = defaultMain\n"- Configure -> "import Distribution.Simple; main = defaultMainWithHooks "- ++ if cabalLibVersion >= mkVersion [1,3,10]- then "autoconfUserHooks\n"- else "defaultUserHooks\n"- Make -> "import Distribution.Make; main = defaultMain\n"- Custom -> error "buildTypeScript Custom"+ Simple -> "import Distribution.Simple; main = defaultMain\n"+ Configure | cabalLibVersion >= mkVersion [1,3,10] -> "import Distribution.Simple; main = defaultMainWithHooks autoconfUserHooks\n"+ | otherwise -> "import Distribution.Simple; main = defaultMainWithHooks defaultUserHooks\n"+ Make -> "import Distribution.Make; main = defaultMain\n"+ Custom -> error "buildTypeScript Custom" installedCabalVersion :: SetupScriptOptions -> Compiler -> ProgramDb -> IO (Version, Maybe InstalledPackageId@@ -724,9 +724,9 @@ cabalDepVersion = useCabalVersion options' options'' = options' { usePackageIndex = Just index } case PackageIndex.lookupDependency index cabalDepName cabalDepVersion of- [] -> die' verbosity $ "The package '" ++ display (packageName pkg)+ [] -> die' verbosity $ "The package '" ++ prettyShow (packageName pkg) ++ "' requires Cabal library version "- ++ display (useCabalVersion options)+ ++ prettyShow (useCabalVersion options) ++ " but no suitable version is installed." pkgs -> let ipkginfo = fromMaybe err $ safeHead . snd . bestVersion fst $ pkgs err = error "Distribution.Client.installedCabalVersion: empty version list"@@ -795,11 +795,11 @@ return (setupCacheDir, cachedSetupProgFile) where buildTypeString = show bt- cabalVersionString = "Cabal-" ++ (display cabalLibVersion)- compilerVersionString = display $+ cabalVersionString = "Cabal-" ++ prettyShow cabalLibVersion+ compilerVersionString = prettyShow $ maybe buildCompilerId compilerId $ useCompiler options'- platformString = display platform+ platformString = prettyShow platform -- | Look up the setup executable in the cache; update the cache if the setup -- executable is not found.@@ -903,7 +903,7 @@ let ghcCmdLine = renderGhcOptions compiler platform ghcOptions when (useVersionMacros options') $ rewriteFileEx verbosity cppMacrosFile- (generatePackageVersionMacros (map snd selectedDeps))+ $ generatePackageVersionMacros (pkgVersion $ package pkg) (map snd selectedDeps) case useLoggingHandle options of Nothing -> runDbProgram verbosity program progdb ghcCmdLine
cabal/cabal-install/Distribution/Client/SolverInstallPlan.hs view
@@ -51,12 +51,14 @@ reverseTopologicalOrder, ) where +import Distribution.Client.Compat.Prelude hiding (toList)+import Prelude ()+ import Distribution.Package ( PackageIdentifier(..), Package(..), PackageName , HasUnitId(..), PackageId, packageVersion, packageName )+import Distribution.Types.Flag (nullFlagAssignment) import qualified Distribution.Solver.Types.ComponentDeps as CD-import Distribution.Deprecated.Text- ( display ) import Distribution.Client.Types ( UnresolvedPkgLoc )@@ -66,20 +68,14 @@ import Distribution.Solver.Types.Settings import Distribution.Solver.Types.ResolverPackage import Distribution.Solver.Types.SolverId+import Distribution.Solver.Types.SolverPackage -import Data.List- ( intercalate )-import Data.Maybe- ( fromMaybe, mapMaybe )-import Distribution.Compat.Binary (Binary(..)) import Distribution.Compat.Graph (Graph, IsNode(..)) import qualified Data.Foldable as Foldable import qualified Data.Graph as OldGraph import qualified Distribution.Compat.Graph as Graph import qualified Data.Map as Map-import Data.Map (Map) import Data.Array ((!))-import Data.Typeable type SolverPlanPackage = ResolverPackage UnresolvedPkgLoc @@ -89,7 +85,7 @@ planIndex :: !SolverPlanIndex, planIndepGoals :: !IndependentGoals }- deriving (Typeable)+ deriving (Typeable, Generic) {- -- | Much like 'planPkgIdOf', but mapping back to full packages.@@ -103,24 +99,10 @@ Nothing -> error "InstallPlan: internal error: planPkgOf lookup failed" -} -mkInstallPlan :: SolverPlanIndex- -> IndependentGoals- -> SolverInstallPlan-mkInstallPlan index indepGoals =- SolverInstallPlan {- planIndex = index,- planIndepGoals = indepGoals- } -instance Binary SolverInstallPlan where- put SolverInstallPlan {- planIndex = index,- planIndepGoals = indepGoals- } = put (index, indepGoals) - get = do- (index, indepGoals) <- get- return $! mkInstallPlan index indepGoals+instance Binary SolverInstallPlan+instance Structured SolverInstallPlan showPlanIndex :: [SolverPlanPackage] -> String showPlanIndex = intercalate "\n" . map showPlanPackage@@ -129,11 +111,24 @@ showInstallPlan = showPlanIndex . toList showPlanPackage :: SolverPlanPackage -> String-showPlanPackage (PreExisting ipkg) = "PreExisting " ++ display (packageId ipkg)- ++ " (" ++ display (installedUnitId ipkg)+showPlanPackage (PreExisting ipkg) = "PreExisting " ++ prettyShow (packageId ipkg)+ ++ " (" ++ prettyShow (installedUnitId ipkg) ++ ")"-showPlanPackage (Configured spkg) = "Configured " ++ display (packageId spkg)+showPlanPackage (Configured spkg) =+ "Configured " ++ prettyShow (packageId spkg) ++ flags ++ comps+ where+ flags+ | nullFlagAssignment fa = ""+ | otherwise = " " ++ prettyShow (solverPkgFlags spkg)+ where+ fa = solverPkgFlags spkg + comps | null deps = ""+ | otherwise = " " ++ unwords (map prettyShow $ Foldable.toList deps)+ where+ deps = CD.components (solverPkgLibDeps spkg)+ <> CD.components (solverPkgExeDeps spkg)+ -- | Build an installation plan from a valid set of resolved packages. -- new :: IndependentGoals@@ -141,7 +136,7 @@ -> Either [SolverPlanProblem] SolverInstallPlan new indepGoals index = case problems indepGoals index of- [] -> Right (mkInstallPlan index indepGoals)+ [] -> Right (SolverInstallPlan index indepGoals) probs -> Left probs toList :: SolverInstallPlan -> [SolverPlanPackage]@@ -191,26 +186,26 @@ showPlanProblem :: SolverPlanProblem -> String showPlanProblem (PackageMissingDeps pkg missingDeps) =- "Package " ++ display (packageId pkg)+ "Package " ++ prettyShow (packageId pkg) ++ " depends on the following packages which are missing from the plan: "- ++ intercalate ", " (map display missingDeps)+ ++ intercalate ", " (map prettyShow missingDeps) showPlanProblem (PackageCycle cycleGroup) = "The following packages are involved in a dependency cycle "- ++ intercalate ", " (map (display.packageId) cycleGroup)+ ++ intercalate ", " (map (prettyShow.packageId) cycleGroup) showPlanProblem (PackageInconsistency name inconsistencies) =- "Package " ++ display name+ "Package " ++ prettyShow name ++ " is required by several packages," ++ " but they require inconsistent versions:\n"- ++ unlines [ " package " ++ display pkg ++ " requires "- ++ display (PackageIdentifier name ver)+ ++ unlines [ " package " ++ prettyShow pkg ++ " requires "+ ++ prettyShow (PackageIdentifier name ver) | (pkg, ver) <- inconsistencies ] showPlanProblem (PackageStateInvalid pkg pkg') =- "Package " ++ display (packageId pkg)+ "Package " ++ prettyShow (packageId pkg) ++ " is in the " ++ showPlanState pkg- ++ " state but it depends on package " ++ display (packageId pkg')+ ++ " state but it depends on package " ++ prettyShow (packageId pkg') ++ " which is in the " ++ showPlanState pkg' ++ " state" where@@ -339,7 +334,7 @@ ] where -- For each package name (of a dependency, somewhere)- -- and each installed ID of that that package+ -- and each installed ID of that package -- the associated package instance -- and a list of reverse dependencies (as source IDs) inverseIndex :: Map PackageName (Map SolverId (SolverPlanPackage, [PackageId]))
cabal/cabal-install/Distribution/Client/SourceFiles.hs view
@@ -37,7 +37,6 @@ import Distribution.Client.Compat.Prelude import System.FilePath-import Control.Monad import qualified Data.Set as Set needElaboratedConfiguredPackage :: ElaboratedConfiguredPackage -> Rebuild ()@@ -48,7 +47,7 @@ needElaboratedPackage :: ElaboratedConfiguredPackage -> ElaboratedPackage -> Rebuild () needElaboratedPackage elab epkg =- mapM_ (needComponent pkg_descr) (enabledComponents pkg_descr enabled)+ traverse_ (needComponent pkg_descr) (enabledComponents pkg_descr enabled) where pkg_descr = elabPkgDescription elab enabled_stanzas = pkgStanzasEnabled epkg@@ -89,7 +88,7 @@ needForeignLib :: PackageDescription -> ForeignLib -> Rebuild () needForeignLib pkg_descr (ForeignLib { foreignLibModDefFile = fs , foreignLibBuildInfo = bi })- = do mapM_ needIfExists fs+ = do traverse_ needIfExists fs needBuildInfo pkg_descr bi [] needExecutable :: PackageDescription -> Executable -> Rebuild ()@@ -145,21 +144,21 @@ -- A.hs-boot; need to track both. findNeededModules ["hs", "lhs", "hsig", "lhsig"] findNeededModules ["hs-boot", "lhs-boot"]- mapM_ needIfExists (cSources bi ++ jsSources bi)- -- A MASSIVE HACK to (1) make sure we rebuild when header- -- files change, but (2) not have to rebuild when anything- -- in extra-src-files changes (most of these won't affect- -- compilation). It would be even better if we knew on a- -- per-component basis which headers would be used but that- -- seems to be too difficult.- mapM_ needIfExists (filter ((==".h").takeExtension) (extraSrcFiles pkg_descr))- forM_ (installIncludes bi) $ \f ->+ traverse_ needIfExists $ concat+ [ cSources bi+ , cxxSources bi+ , jsSources bi+ , cmmSources bi+ , asmSources bi+ , extraSrcFiles pkg_descr+ ]+ for_ (installIncludes bi) $ \f -> findFileMonitored ("." : includeDirs bi) f >>= maybe (return ()) need where- findNeededModules exts =- mapM_ (findNeededModule exts)- (modules ++ otherModules bi)+ findNeededModules exts = traverse_+ (findNeededModule exts)+ (modules ++ otherModules bi) findNeededModule exts m = findFileWithExtensionMonitored (ppSuffixes knownSuffixHandlers ++ exts)
− cabal/cabal-install/Distribution/Client/SourceRepo.hs
@@ -1,96 +0,0 @@-{-# LANGUAGE DeriveAnyClass #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE StandaloneDeriving #-}-{-# LANGUAGE UndecidableInstances #-}-module Distribution.Client.SourceRepo where--import Distribution.Client.Compat.Prelude-import Prelude ()-import Distribution.Compat.Lens (Lens, Lens')--import Distribution.Types.SourceRepo- ( RepoType(..))-import Distribution.FieldGrammar (FieldGrammar, ParsecFieldGrammar', PrettyFieldGrammar', uniqueField, uniqueFieldAla, optionalFieldAla, monoidalFieldAla)-import Distribution.Parsec.Newtypes (Token (..), FilePathNT (..), alaList', NoCommaFSep (..))---- | @source-repository-package@ definition----data SourceRepositoryPackage f = SourceRepositoryPackage- { srpType :: !RepoType- , srpLocation :: !String- , srpTag :: !(Maybe String)- , srpBranch :: !(Maybe String)- , srpSubdir :: !(f FilePath)- }- deriving (Generic)--deriving instance (Eq (f FilePath)) => Eq (SourceRepositoryPackage f)-deriving instance (Ord (f FilePath)) => Ord (SourceRepositoryPackage f)-deriving instance (Show (f FilePath)) => Show (SourceRepositoryPackage f)-deriving instance (Binary (f FilePath)) => Binary (SourceRepositoryPackage f)---- | Read from @cabal.project@-type SourceRepoList = SourceRepositoryPackage []---- | Distilled from 'Distribution.Types.SourceRepo.SourceRepo'-type SourceRepoMaybe = SourceRepositoryPackage Maybe---- | 'SourceRepositoryPackage' without subdir. Used in clone errors. Cloning doesn't care about subdirectory.-type SourceRepoProxy = SourceRepositoryPackage Proxy--srpHoist :: (forall x. f x -> g x) -> SourceRepositoryPackage f -> SourceRepositoryPackage g-srpHoist nt s = s { srpSubdir = nt (srpSubdir s) }--srpToProxy :: SourceRepositoryPackage f -> SourceRepositoryPackage Proxy-srpToProxy s = s { srpSubdir = Proxy }---- | Split single @source-repository-package@ declaration with multiple subdirs,--- into multiple ones with at most single subdir.-srpFanOut :: SourceRepositoryPackage [] -> NonEmpty (SourceRepositoryPackage Maybe)-srpFanOut s@SourceRepositoryPackage { srpSubdir = [] } =- s { srpSubdir = Nothing } :| []-srpFanOut s@SourceRepositoryPackage { srpSubdir = d:ds } = f d :| map f ds where- f subdir = s { srpSubdir = Just subdir }------------------------------------------------------------------------------------ Lens----------------------------------------------------------------------------------srpTypeLens :: Lens' (SourceRepositoryPackage f) RepoType-srpTypeLens f s = fmap (\x -> s { srpType = x }) (f (srpType s))-{-# INLINE srpTypeLens #-}--srpLocationLens :: Lens' (SourceRepositoryPackage f) String-srpLocationLens f s = fmap (\x -> s { srpLocation = x }) (f (srpLocation s))-{-# INLINE srpLocationLens #-}--srpTagLens :: Lens' (SourceRepositoryPackage f) (Maybe String)-srpTagLens f s = fmap (\x -> s { srpTag = x }) (f (srpTag s))-{-# INLINE srpTagLens #-}--srpBranchLens :: Lens' (SourceRepositoryPackage f) (Maybe String)-srpBranchLens f s = fmap (\x -> s { srpBranch = x }) (f (srpBranch s))-{-# INLINE srpBranchLens #-}--srpSubdirLens :: Lens (SourceRepositoryPackage f) (SourceRepositoryPackage g) (f FilePath) (g FilePath)-srpSubdirLens f s = fmap (\x -> s { srpSubdir = x }) (f (srpSubdir s))-{-# INLINE srpSubdirLens #-}------------------------------------------------------------------------------------ Parser & PPrinter----------------------------------------------------------------------------------sourceRepositoryPackageGrammar- :: (FieldGrammar g, Applicative (g SourceRepoList))- => g SourceRepoList SourceRepoList-sourceRepositoryPackageGrammar = SourceRepositoryPackage- <$> uniqueField "type" srpTypeLens- <*> uniqueFieldAla "location" Token srpLocationLens- <*> optionalFieldAla "tag" Token srpTagLens- <*> optionalFieldAla "branch" Token srpBranchLens- <*> monoidalFieldAla "subdir" (alaList' NoCommaFSep FilePathNT) srpSubdirLens -- note: NoCommaFSep is somewhat important for roundtrip, as "." is there...-{-# SPECIALIZE sourceRepositoryPackageGrammar :: ParsecFieldGrammar' SourceRepoList #-}-{-# SPECIALIZE sourceRepositoryPackageGrammar :: PrettyFieldGrammar' SourceRepoList #-}
cabal/cabal-install/Distribution/Client/SrcDist.hs view
@@ -1,155 +1,93 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE NondecreasingIndentation #-}-{-# LANGUAGE FlexibleContexts #-}--- Implements the \"@.\/cabal sdist@\" command, which creates a source--- distribution for this package. That is, packs up the source code--- into a tarball, making use of the corresponding Cabal module.+{-# LANGUAGE OverloadedStrings #-}+-- | Utilities to implemenet cabal @v2-sdist@. module Distribution.Client.SrcDist (- sdist,- allPackageSourceFiles- ) where---import Distribution.Client.SetupWrapper- ( SetupScriptOptions(..), defaultSetupScriptOptions, setupWrapper )-import Distribution.Client.Tar (createTarGzFile)--import Distribution.Package- ( Package(..), packageName )-import Distribution.PackageDescription- ( PackageDescription )-import Distribution.PackageDescription.Configuration- ( flattenPackageDescription )-import Distribution.PackageDescription.Parsec- ( readGenericPackageDescription )-import Distribution.Simple.Utils- ( createDirectoryIfMissingVerbose, defaultPackageDesc- , warn, notice, withTempDirectory )-import Distribution.Client.Setup- ( SDistFlags(..) )-import Distribution.Simple.Setup- ( Flag(..), sdistCommand, flagToList, fromFlag, fromFlagOrDefault- , defaultSDistFlags )-import Distribution.Simple.BuildPaths ( srcPref)-import Distribution.Deprecated.Text ( display )-import Distribution.Verbosity (Verbosity, normal, lessVerbose)-import Distribution.Version (mkVersion, orLaterVersion, intersectVersionRanges)--import Distribution.Client.Utils- (tryFindAddSourcePackageDesc)-import Distribution.Compat.Exception (catchIO)--import System.FilePath ((</>), (<.>))-import Control.Monad (when, unless, liftM)-import System.Directory (getTemporaryDirectory)-import Control.Exception (IOException, evaluate)---- |Create a source distribution.-sdist :: SDistFlags -> IO ()-sdist flags = do- pkg <- liftM flattenPackageDescription- (readGenericPackageDescription verbosity =<< defaultPackageDesc verbosity)- let withDir :: (FilePath -> IO a) -> IO a- withDir = if not needMakeArchive then \f -> f tmpTargetDir- else withTempDirectory verbosity tmpTargetDir "sdist."- -- 'withTempDir' fails if we don't create 'tmpTargetDir'...- when needMakeArchive $- createDirectoryIfMissingVerbose verbosity True tmpTargetDir- withDir $ \tmpDir -> do- let outDir = if isOutDirectory then tmpDir else tmpDir </> tarBallName pkg- flags' = (if not needMakeArchive then flags- else flags { sDistDirectory = Flag outDir })- unless isListSources $- createDirectoryIfMissingVerbose verbosity True outDir-- -- Run 'setup sdist --output-directory=tmpDir' (or- -- '--list-source'/'--output-directory=someOtherDir') in case we were passed- -- those options.- setupWrapper verbosity setupOpts (Just pkg) sdistCommand (const flags') (const [])-- -- Unless we were given --list-sources or --output-directory ourselves,- -- create an archive.- when needMakeArchive $- createTarGzArchive verbosity pkg tmpDir distPref-- when isOutDirectory $- notice verbosity $ "Source directory created: " ++ tmpTargetDir-- when isListSources $- notice verbosity $ "List of package sources written to file '"- ++ (fromFlag . sDistListSources $ flags) ++ "'"+ allPackageSourceFiles,+ packageDirToSdist,+) where - where- flagEnabled f = not . null . flagToList . f $ flags+import Distribution.Client.Compat.Prelude+import Prelude () - isListSources = flagEnabled sDistListSources- isOutDirectory = flagEnabled sDistDirectory- needMakeArchive = not (isListSources || isOutDirectory)- verbosity = fromFlag (sDistVerbosity flags)- distPref = fromFlag (sDistDistPref flags)- tmpTargetDir = fromFlagOrDefault (srcPref distPref) (sDistDirectory flags)- setupOpts = defaultSetupScriptOptions {- useDistPref = distPref,- -- The '--output-directory' sdist flag was introduced in Cabal 1.12, and- -- '--list-sources' in 1.17.- useCabalVersion = if isListSources- then orLaterVersion $ mkVersion [1,17,0]- else orLaterVersion $ mkVersion [1,12,0]- }+import Control.Monad.State.Lazy (StateT, evalStateT, gets, modify)+import Control.Monad.Trans (liftIO)+import Control.Monad.Writer.Lazy (WriterT, execWriterT, tell)+import System.FilePath (normalise, takeDirectory, (</>)) -tarBallName :: PackageDescription -> String-tarBallName = display . packageId+import Distribution.Client.Utils (tryFindAddSourcePackageDesc)+import Distribution.Package (Package (packageId))+import Distribution.PackageDescription.Configuration (flattenPackageDescription)+import Distribution.PackageDescription.Parsec (readGenericPackageDescription)+import Distribution.Simple.PreProcess (knownSuffixHandlers)+import Distribution.Simple.SrcDist (listPackageSources)+import Distribution.Simple.SrcDist (listPackageSourcesWithDie)+import Distribution.Simple.Utils (die')+import Distribution.Types.GenericPackageDescription (GenericPackageDescription) --- | Create a tar.gz archive from a tree of source files.-createTarGzArchive :: Verbosity -> PackageDescription -> FilePath -> FilePath- -> IO ()-createTarGzArchive verbosity pkg tmpDir targetPref = do- createTarGzFile tarBallFilePath tmpDir (tarBallName pkg)- notice verbosity $ "Source tarball created: " ++ tarBallFilePath- where- tarBallFilePath = targetPref </> tarBallName pkg <.> "tar.gz"+import qualified Codec.Archive.Tar as Tar+import qualified Codec.Archive.Tar.Entry as Tar+import qualified Codec.Compression.GZip as GZip+import qualified Data.ByteString as BS+import qualified Data.ByteString.Lazy as BSL+import qualified Data.Set as Set -- | List all source files of a given add-source dependency. Exits with error if -- something is wrong (e.g. there is no .cabal file in the given directory).-allPackageSourceFiles :: Verbosity -> SetupScriptOptions -> FilePath- -> IO [FilePath]-allPackageSourceFiles verbosity setupOpts0 packageDir = do- pkg <- do+--+-- Used in sandbox and projectbuilding.+-- TODO: when sandboxes are removed, move to ProjectBuilding.+--+allPackageSourceFiles :: Verbosity -> FilePath -> IO [FilePath]+allPackageSourceFiles verbosity packageDir = do+ pd <- do let err = "Error reading source files of package." desc <- tryFindAddSourcePackageDesc verbosity packageDir err flattenPackageDescription `fmap` readGenericPackageDescription verbosity desc- globalTmp <- getTemporaryDirectory- withTempDirectory verbosity globalTmp "cabal-list-sources." $ \tempDir -> do- let file = tempDir </> "cabal-sdist-list-sources"- flags = defaultSDistFlags {- sDistVerbosity = Flag $ if verbosity == normal- then lessVerbose verbosity else verbosity,- sDistListSources = Flag file- }- setupOpts = setupOpts0 {- -- 'sdist --list-sources' was introduced in Cabal 1.18.- useCabalVersion = intersectVersionRanges- (orLaterVersion $ mkVersion [1,18,0])- (useCabalVersion setupOpts0),- useWorkingDir = Just packageDir- } - doListSources :: IO [FilePath]- doListSources = do- setupWrapper verbosity setupOpts (Just pkg) sdistCommand (const flags) (const [])- fmap lines . readFile $ file+ listPackageSourcesWithDie verbosity (\_ _ -> return []) packageDir pd knownSuffixHandlers - onFailedListSources :: IOException -> IO ()- onFailedListSources e = do- warn verbosity $- "Could not list sources of the package '"- ++ display (packageName pkg) ++ "'."- warn verbosity $- "Exception was: " ++ show e+-- | Create a tarball for a package in a directory+packageDirToSdist+ :: Verbosity+ -> GenericPackageDescription -- ^ read in GPD+ -> FilePath -- ^ directory containing that GPD+ -> IO BSL.ByteString -- ^ resulting sdist tarball+packageDirToSdist verbosity gpd dir = do+ files' <- listPackageSources verbosity dir (flattenPackageDescription gpd) knownSuffixHandlers+ let files = nub $ sort $ map normalise files' - -- Run setup sdist --list-sources=TMPFILE- r <- doListSources `catchIO` (\e -> onFailedListSources e >> return [])- -- Ensure that we've closed the 'readFile' handle before we exit the- -- temporary directory.- _ <- evaluate (length r)- return r+ let entriesM :: StateT (Set.Set FilePath) (WriterT [Tar.Entry] IO) ()+ entriesM = do+ let prefix = prettyShow (packageId gpd)+ modify (Set.insert prefix)+ case Tar.toTarPath True prefix of+ Left err -> liftIO $ die' verbosity ("Error packing sdist: " ++ err)+ Right path -> tell [Tar.directoryEntry path]++ for_ files $ \file -> do+ let fileDir = takeDirectory (prefix </> file)+ needsEntry <- gets (Set.notMember fileDir)++ when needsEntry $ do+ modify (Set.insert fileDir)+ case Tar.toTarPath True fileDir of+ Left err -> liftIO $ die' verbosity ("Error packing sdist: " ++ err)+ Right path -> tell [Tar.directoryEntry path]++ contents <- liftIO . fmap BSL.fromStrict . BS.readFile $ dir </> file+ case Tar.toTarPath False (prefix </> file) of+ Left err -> liftIO $ die' verbosity ("Error packing sdist: " ++ err)+ Right path -> tell [(Tar.fileEntry path contents) { Tar.entryPermissions = Tar.ordinaryFilePermissions }]++ entries <- execWriterT (evalStateT entriesM mempty)+ let -- Pretend our GZip file is made on Unix.+ normalize bs = BSL.concat [pfx, "\x03", rest']+ where+ (pfx, rest) = BSL.splitAt 9 bs+ rest' = BSL.tail rest+ -- The Unix epoch, which is the default value, is+ -- unsuitable because it causes unpacking problems on+ -- Windows; we need a post-1980 date. One gigasecond+ -- after the epoch is during 2001-09-09, so that does+ -- nicely. See #5596.+ setModTime entry = entry { Tar.entryTime = 1000000000 }+ return . normalize . GZip.compress . Tar.write $ fmap setModTime entries
cabal/cabal-install/Distribution/Client/Store.hs view
@@ -33,11 +33,10 @@ import Distribution.Simple.Utils ( withTempDirectory, debug, info ) import Distribution.Verbosity-import Distribution.Deprecated.Text+ ( silent ) import qualified Data.Set as Set import Control.Exception-import Control.Monad (forM_) import System.FilePath import System.Directory @@ -203,7 +202,7 @@ then do info verbosity $ "Concurrent build race: abandoning build in favour of existing "- ++ "store entry " ++ display compid </> display unitid+ ++ "store entry " ++ prettyShow compid </> prettyShow unitid return UseExistingStoreEntry -- If the entry does not exist then we won the race and can proceed.@@ -214,13 +213,13 @@ -- Atomically rename the temp dir to the final store entry location. renameDirectory incomingEntryDir finalEntryDir- forM_ otherFiles $ \file -> do+ for_ otherFiles $ \file -> do let finalStoreFile = storeDirectory compid </> makeRelative (incomingTmpDir </> (dropDrive (storeDirectory compid))) file createDirectoryIfMissing True (takeDirectory finalStoreFile) renameFile file finalStoreFile debug verbosity $- "Installed store entry " ++ display compid </> display unitid+ "Installed store entry " ++ prettyShow compid </> prettyShow unitid return UseNewStoreEntry where finalEntryDir = storePackageDirectory compid unitid@@ -249,7 +248,7 @@ gotLock <- fdTryLock fd ExclusiveLock unless gotLock $ do info verbosity $ "Waiting for file lock on store entry "- ++ display compid </> display unitid+ ++ prettyShow compid </> prettyShow unitid fdLock fd ExclusiveLock return fd @@ -269,7 +268,7 @@ gotlock <- hTryLock h ExclusiveLock unless gotlock $ do info verbosity $ "Waiting for file lock on store entry "- ++ display compid </> display unitid+ ++ prettyShow compid </> prettyShow unitid hLock h ExclusiveLock return h
cabal/cabal-install/Distribution/Client/Tar.hs view
@@ -28,6 +28,9 @@ entriesToList, ) where +import Distribution.Client.Compat.Prelude+import Prelude ()+ import qualified Data.ByteString.Lazy as BS import qualified Codec.Archive.Tar as Tar import qualified Codec.Archive.Tar.Entry as Tar@@ -35,7 +38,8 @@ import qualified Codec.Compression.GZip as GZip import qualified Distribution.Client.GZipUtils as GZipUtils -import Control.Exception (Exception(..), throw)+-- for foldEntries...+import Control.Exception (throw) -- -- * High level operations
+ cabal/cabal-install/Distribution/Client/TargetProblem.hs view
@@ -0,0 +1,55 @@+{-# LANGUAGE DeriveFunctor #-}+module Distribution.Client.TargetProblem (+ TargetProblem(..),+ TargetProblem',+) where++import Distribution.Client.Compat.Prelude+import Prelude ()++import Distribution.Client.ProjectPlanning (AvailableTarget)+import Distribution.Client.TargetSelector (SubComponentTarget, TargetSelector)+import Distribution.Package (PackageId, PackageName)+import Distribution.Simple.LocalBuildInfo (ComponentName (..))+import Distribution.Types.UnqualComponentName (UnqualComponentName)++-- | Target problems that occur during project orchestration.+data TargetProblem a+ = TargetNotInProject PackageName+ | TargetAvailableInIndex PackageName++ | TargetComponentNotProjectLocal+ PackageId ComponentName SubComponentTarget++ | TargetComponentNotBuildable+ PackageId ComponentName SubComponentTarget++ | TargetOptionalStanzaDisabledByUser+ PackageId ComponentName SubComponentTarget++ | TargetOptionalStanzaDisabledBySolver+ PackageId ComponentName SubComponentTarget++ | TargetProblemUnknownComponent+ PackageName (Either UnqualComponentName ComponentName)++ | TargetProblemNoneEnabled TargetSelector [AvailableTarget ()]+ -- ^ The 'TargetSelector' matches component (test/benchmark/...) but none are buildable++ | TargetProblemNoTargets TargetSelector+ -- ^ There are no targets at all++ -- The target matching stuff only returns packages local to the project,+ -- so these lookups should never fail, but if 'resolveTargets' is called+ -- directly then of course it can.+ | TargetProblemNoSuchPackage PackageId+ | TargetProblemNoSuchComponent PackageId ComponentName++ -- | A custom target problem+ | CustomTargetProblem a+ deriving (Eq, Show, Functor)++-- | Type alias for a 'TargetProblem' with no user-defined problems/errors.+--+-- Can use the utilities below for reporting/rendering problems.+type TargetProblem' = TargetProblem Void
cabal/cabal-install/Distribution/Client/TargetSelector.hs view
@@ -1,5 +1,7 @@ {-# LANGUAGE CPP, DeriveGeneric, DeriveFunctor, RecordWildCards, NamedFieldPuns #-}+-- TODO+{-# OPTIONS_GHC -fno-warn-incomplete-uni-patterns #-} ----------------------------------------------------------------------------- -- | -- Module : Distribution.Client.TargetSelector@@ -47,7 +49,6 @@ import Distribution.Client.Types ( PackageLocation(..), PackageSpecifier(..) ) -import Distribution.Verbosity import Distribution.PackageDescription ( PackageDescription , Executable(..)@@ -65,26 +66,19 @@ , pkgComponents, componentName, componentBuildInfo ) import Distribution.Types.ForeignLib -import Distribution.Deprecated.Text- ( Text, display, simpleParse ) import Distribution.Simple.Utils ( die', lowercase, ordNub ) import Distribution.Client.Utils ( makeRelativeCanonical ) -import Data.Either- ( partitionEithers )-import Data.Function- ( on ) import Data.List- ( stripPrefix, partition, groupBy )-import Data.Ord- ( comparing )+ ( stripPrefix, groupBy )+import qualified Data.List.NonEmpty as NE import qualified Data.Map.Lazy as Map.Lazy import qualified Data.Map.Strict as Map import qualified Data.Set as Set import Control.Arrow ((&&&))-import Control.Monad +import Control.Monad hiding ( mfilter ) import qualified Distribution.Deprecated.ReadP as Parse import Distribution.Deprecated.ReadP@@ -186,11 +180,13 @@ -- | A specific module within a component. | ModuleTarget ModuleName - -- | A specific file within a component.+ -- | A specific file within a component. Note that this does not carry the+ -- file extension. | FileTarget FilePath deriving (Eq, Ord, Show, Generic) instance Binary SubComponentTarget+instance Structured SubComponentTarget -- ------------------------------------------------------------@@ -218,10 +214,10 @@ -> Maybe ComponentKindFilter -> [String] -> m (Either [TargetSelectorProblem] [TargetSelector])-readTargetSelectorsWith dirActions@DirActions{..} pkgs mfilter targetStrs =+readTargetSelectorsWith dirActions@DirActions{} pkgs mfilter targetStrs = case parseTargetStrings targetStrs of ([], usertargets) -> do- usertargets' <- mapM (getTargetStringFileStatus dirActions) usertargets+ usertargets' <- traverse (getTargetStringFileStatus dirActions) usertargets knowntargets <- getKnownTargets dirActions pkgs case resolveTargetSelectors knowntargets usertargets' mfilter of ([], btargets) -> return (Right btargets)@@ -433,7 +429,24 @@ TargetStringFileStatus7 s1 s2 s3 s4 s5 s6 s7 -> TargetString7 s1 s2 s3 s4 s5 s6 s7 +getFileStatus :: TargetStringFileStatus -> Maybe FileStatus+getFileStatus (TargetStringFileStatus1 _ f) = Just f+getFileStatus (TargetStringFileStatus2 _ f _) = Just f+getFileStatus (TargetStringFileStatus3 _ f _ _) = Just f+getFileStatus _ = Nothing +setFileStatus :: FileStatus -> TargetStringFileStatus -> TargetStringFileStatus+setFileStatus f (TargetStringFileStatus1 s1 _) = TargetStringFileStatus1 s1 f+setFileStatus f (TargetStringFileStatus2 s1 _ s2) = TargetStringFileStatus2 s1 f s2+setFileStatus f (TargetStringFileStatus3 s1 _ s2 s3) = TargetStringFileStatus3 s1 f s2 s3+setFileStatus _ t = t++copyFileStatus :: TargetStringFileStatus -> TargetStringFileStatus -> TargetStringFileStatus+copyFileStatus src dst =+ case getFileStatus src of+ Just f -> setFileStatus f dst+ Nothing -> dst+ -- ------------------------------------------------------------ -- * Resolving target strings to target selectors -- ------------------------------------------------------------@@ -502,9 +515,9 @@ projectIsEmpty = null knownPackagesAll classifyMatchErrors errs- | not (null expected)- = let (things, got:_) = unzip expected in- TargetSelectorExpected targetStr things got+ | Just expectedNE <- NE.nonEmpty expected+ = let (things, got:|_) = NE.unzip expectedNE in+ TargetSelectorExpected targetStr (NE.toList things) got | not (null nosuch) = TargetSelectorNoSuch targetStr nosuch@@ -581,7 +594,12 @@ | TargetSelectorNoTargetsInProject deriving (Show, Eq) -data QualLevel = QL1 | QL2 | QL3 | QLFull+-- | Qualification levels.+-- Given the filepath src/F, executable component A, and package foo:+data QualLevel = QL1 -- ^ @src/F@+ | QL2 -- ^ @foo:src/F | A:src/F@+ | QL3 -- ^ @foo:A:src/F | exe:A:src/F@+ | QLFull -- ^ @pkg:foo:exe:A:file:src/F@ deriving (Eq, Enum, Show) disambiguateTargetSelectors@@ -598,12 +616,19 @@ -- So, here's the strategy. We take the original match results, and make a -- table of all their renderings at all qualification levels. -- Note there can be multiple renderings at each qualification level.++ -- Note that renderTargetSelector won't immediately work on any file syntax+ -- When rendering syntax, the FileStatus is always FileStatusNotExists,+ -- which will never match on syntaxForm1File!+ -- Because matchPackageDirectoryPrefix expects a FileStatusExistsFile.+ -- So we need to copy over the file status from the input+ -- TargetStringFileStatus, onto the new rendered TargetStringFileStatus matchResultsRenderings :: [(TargetSelector, [TargetStringFileStatus])] matchResultsRenderings = [ (matchResult, matchRenderings) | matchResult <- matchResults , let matchRenderings =- [ rendering+ [ copyFileStatus matchInput rendering | ql <- [QL1 .. QLFull] , rendering <- renderTargetSelector ql matchResult ] ]@@ -620,6 +645,8 @@ then Map.insert matchInput (Match Exact 0 matchResults) else id) $ Map.Lazy.fromList+ -- (matcher rendering) should *always* be a Match! Otherwise we will hit+ -- the internal error later on. [ (rendering, matcher rendering) | rendering <- concatMap snd matchResultsRenderings ] @@ -1033,7 +1060,7 @@ (pkgfile, ~KnownPackage{pinfoId, pinfoComponents}) -- always returns the KnownPackage case <- matchPackageDirectoryPrefix ps fstatus1- orNoThingIn "package" (display (packageName pinfoId)) $ do+ orNoThingIn "package" (prettyShow (packageName pinfoId)) $ do (filepath, c) <- matchComponentFile pinfoComponents pkgfile return (TargetComponent pinfoId (cinfoName c) (FileTarget filepath)) where@@ -1131,7 +1158,7 @@ p <- matchPackage ps str1 fstatus1 case p of KnownPackage{pinfoId, pinfoComponents} ->- orNoThingIn "package" (display (packageName pinfoId)) $ do+ orNoThingIn "package" (prettyShow (packageName pinfoId)) $ do c <- matchComponentName pinfoComponents str2 return (TargetComponent pinfoId (cinfoName c) WholeComponent) --TODO: the error here ought to say there's no component by that name in@@ -1143,7 +1170,7 @@ render (TargetComponent p c WholeComponent) = [TargetStringFileStatus2 (dispP p) noFileStatus (dispC p c)] render (TargetComponentUnknown pn (Left cn) WholeComponent) =- [TargetStringFileStatus2 (dispPN pn) noFileStatus (display cn)]+ [TargetStringFileStatus2 (dispPN pn) noFileStatus (prettyShow cn)] render _ = [] -- | Syntax: namespace : component@@ -1176,7 +1203,7 @@ p <- matchPackage ps str1 fstatus1 case p of KnownPackage{pinfoId, pinfoComponents} ->- orNoThingIn "package" (display (packageName pinfoId)) $ do+ orNoThingIn "package" (prettyShow (packageName pinfoId)) $ do let ms = [ (m,c) | c <- pinfoComponents, m <- cinfoModules c ] (m,c) <- matchModuleNameAnd ms str2 return (TargetComponent pinfoId (cinfoName c) (ModuleTarget m))@@ -1222,7 +1249,7 @@ p <- matchPackage ps str1 fstatus1 case p of KnownPackage{pinfoId, pinfoComponents} ->- orNoThingIn "package" (display (packageName pinfoId)) $ do+ orNoThingIn "package" (prettyShow (packageName pinfoId)) $ do (filepath, c) <- matchComponentFile pinfoComponents str2 return (TargetComponent pinfoId (cinfoName c) (FileTarget filepath)) KnownPackageName pn ->@@ -1321,7 +1348,7 @@ p <- matchPackage ps str1 fstatus1 case p of KnownPackage{pinfoId, pinfoComponents} ->- orNoThingIn "package" (display (packageName pinfoId)) $ do+ orNoThingIn "package" (prettyShow (packageName pinfoId)) $ do c <- matchComponentKindAndName pinfoComponents ckind str3 return (TargetComponent pinfoId (cinfoName c) WholeComponent) KnownPackageName pn ->@@ -1349,7 +1376,7 @@ p <- matchPackage ps str1 fstatus1 case p of KnownPackage{pinfoId, pinfoComponents} ->- orNoThingIn "package" (display (packageName pinfoId)) $ do+ orNoThingIn "package" (prettyShow (packageName pinfoId)) $ do c <- matchComponentName pinfoComponents str2 orNoThingIn "component" (cinfoStrName c) $ do let ms = cinfoModules c@@ -1401,7 +1428,7 @@ p <- matchPackage ps str1 fstatus1 case p of KnownPackage{pinfoId, pinfoComponents} ->- orNoThingIn "package" (display (packageName pinfoId)) $ do+ orNoThingIn "package" (prettyShow (packageName pinfoId)) $ do c <- matchComponentName pinfoComponents str2 orNoThingIn "component" (cinfoStrName c) $ do (filepath, _) <- matchComponentFile [c] str3@@ -1492,7 +1519,7 @@ p <- matchPackage ps str3 noFileStatus case p of KnownPackage{pinfoId, pinfoComponents} ->- orNoThingIn "package" (display (packageName pinfoId)) $ do+ orNoThingIn "package" (prettyShow (packageName pinfoId)) $ do c <- matchComponentKindAndName pinfoComponents ckind str5 return (TargetComponent pinfoId (cinfoName c) WholeComponent) KnownPackageName pn ->@@ -1522,7 +1549,7 @@ p <- matchPackage ps str3 noFileStatus case p of KnownPackage{pinfoId, pinfoComponents} ->- orNoThingIn "package" (display (packageName pinfoId)) $ do+ orNoThingIn "package" (prettyShow (packageName pinfoId)) $ do c <- matchComponentKindAndName pinfoComponents ckind str5 orNoThingIn "component" (cinfoStrName c) $ do let ms = cinfoModules c@@ -1560,7 +1587,7 @@ p <- matchPackage ps str3 noFileStatus case p of KnownPackage{pinfoId, pinfoComponents} ->- orNoThingIn "package" (display (packageName pinfoId)) $ do+ orNoThingIn "package" (prettyShow (packageName pinfoId)) $ do c <- matchComponentKindAndName pinfoComponents ckind str5 orNoThingIn "component" (cinfoStrName c) $ do (filepath,_) <- matchComponentFile [c] str7@@ -1644,10 +1671,10 @@ match _ = mzero dispP :: Package p => p -> String-dispP = display . packageName+dispP = prettyShow . packageName dispPN :: PackageName -> String-dispPN = display+dispPN = prettyShow dispC :: PackageId -> ComponentName -> String dispC = componentStringName . packageName@@ -1656,7 +1683,7 @@ dispC' = componentStringName dispCN :: UnqualComponentName -> String-dispCN = display+dispCN = prettyShow dispK :: ComponentKind -> String dispK = showComponentKindShort@@ -1668,7 +1695,7 @@ dispF = showComponentKindFilterShort dispM :: ModuleName -> String-dispM = display+dispM = prettyShow -------------------------------@@ -1723,7 +1750,7 @@ -> [PackageSpecifier (SourcePackage (PackageLocation a))] -> m KnownTargets getKnownTargets dirActions@DirActions{..} pkgs = do- pinfo <- mapM (collectKnownPackageInfo dirActions) pkgs+ pinfo <- traverse (collectKnownPackageInfo dirActions) pkgs cwd <- getCurrentDirectory let (ppinfo, opinfo) = selectPrimaryPackage cwd pinfo return KnownTargets {@@ -1754,8 +1781,8 @@ return (KnownPackageName pkgname) collectKnownPackageInfo dirActions@DirActions{..} (SpecificSourcePackage SourcePackage {- packageDescription = pkg,- packageSource = loc+ srcpkgDescription = pkg,+ srcpkgSource = loc }) = do (pkgdir, pkgfile) <- case loc of@@ -1764,8 +1791,8 @@ dirabs <- canonicalizePath dir dirrel <- makeRelativeToCwd dirActions dirabs --TODO: ought to get this earlier in project reading- let fileabs = dirabs </> display (packageName pkg) <.> "cabal"- filerel = dirrel </> display (packageName pkg) <.> "cabal"+ let fileabs = dirabs </> prettyShow (packageName pkg) <.> "cabal"+ filerel = dirrel </> prettyShow (packageName pkg) <.> "cabal" exists <- doesFileExist fileabs return ( Just (dirabs, dirrel) , if exists then Just (fileabs, filerel) else Nothing@@ -1799,7 +1826,7 @@ componentStringName :: PackageName -> ComponentName -> ComponentStringName-componentStringName pkgname (CLibName LMainLibName) = display pkgname+componentStringName pkgname (CLibName LMainLibName) = prettyShow pkgname componentStringName _ (CLibName (LSubLibName name)) = unUnqualComponentName name componentStringName _ (CFLibName name) = unUnqualComponentName name componentStringName _ (CExeName name) = unUnqualComponentName name@@ -1971,9 +1998,9 @@ matchPackageName ps = \str -> do guard (validPackageName str) orNoSuchThing "package" str- (map (display . knownPackageName) ps) $+ (map (prettyShow . knownPackageName) ps) $ increaseConfidenceFor $- matchInexactly caseFold (display . knownPackageName) ps str+ matchInexactly caseFold (prettyShow . knownPackageName) ps str matchPackageNameUnknown :: String -> Match KnownPackage@@ -2056,7 +2083,7 @@ guardModuleName :: String -> Match () guardModuleName s =- case simpleParse s :: Maybe ModuleName of+ case simpleParsec s :: Maybe ModuleName of Just _ -> increaseConfidence _ | all validModuleChar s && not (null s) -> return ()@@ -2067,16 +2094,16 @@ matchModuleName :: [ModuleName] -> String -> Match ModuleName matchModuleName ms str =- orNoSuchThing "module" str (map display ms)+ orNoSuchThing "module" str (map prettyShow ms) $ increaseConfidenceFor- $ matchInexactly caseFold display ms str+ $ matchInexactly caseFold prettyShow ms str matchModuleNameAnd :: [(ModuleName, a)] -> String -> Match (ModuleName, a) matchModuleNameAnd ms str =- orNoSuchThing "module" str (map (display . fst) ms)+ orNoSuchThing "module" str (map (prettyShow . fst) ms) $ increaseConfidenceFor- $ matchInexactly caseFold (display . fst) ms str+ $ matchInexactly caseFold (prettyShow . fst) ms str matchModuleNameUnknown :: String -> Match ModuleName@@ -2113,12 +2140,14 @@ -> Match (FilePath, KnownComponent) matchComponentOtherFile cs = matchFile- [ (file, c)- | c <- cs- , file <- cinfoHsFiles c- ++ cinfoCFiles c- ++ cinfoJsFiles c+ [ (normalise (srcdir </> file), c)+ | c <- cs+ , srcdir <- cinfoSrcDirs c+ , file <- cinfoHsFiles c+ ++ cinfoCFiles c+ ++ cinfoJsFiles c ]+ . normalise matchComponentModuleFile :: [KnownComponent] -> String@@ -2130,7 +2159,8 @@ , d <- cinfoSrcDirs c , m <- cinfoModules c ]- (dropExtension (normalise str))+ (dropExtension (normalise str)) -- Drop the extension because FileTarget+ -- is stored without the extension -- utils @@ -2366,8 +2396,8 @@ -- the map of canonicalised keys to groups of inexact matches m' = Map.mapKeysWith (++) cannonicalise m -matchParse :: Text a => String -> Match a-matchParse = maybe mzero return . simpleParse+matchParse :: Parsec a => String -> Match a+matchParse = maybe mzero return . simpleParsec ------------------------------
cabal/cabal-install/Distribution/Client/Targets.hs view
@@ -1,5 +1,5 @@ {-# LANGUAGE CPP #-}-{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE DeriveFunctor, DeriveFoldable, DeriveTraversable #-} @@ -50,13 +50,10 @@ import Prelude () import Distribution.Client.Compat.Prelude -import Distribution.Deprecated.ParseUtils (parseFlagAssignment)- import Distribution.Package ( Package(..), PackageName, unPackageName, mkPackageName- , PackageIdentifier(..), packageName, packageVersion )+ , packageName ) import Distribution.Types.Dependency-import Distribution.Types.LibraryName import Distribution.Client.Types ( PackageLocation(..), ResolvedPkgLoc, UnresolvedSourcePackage , PackageSpecifier(..) )@@ -76,33 +73,25 @@ import Distribution.Client.Utils ( tryFindPackageDesc ) import Distribution.Client.GlobalFlags ( RepoContext(..) )+import Distribution.Types.PackageVersionConstraint+ ( PackageVersionConstraint (..) ) import Distribution.PackageDescription- ( GenericPackageDescription, nullFlagAssignment)+ ( GenericPackageDescription )+import Distribution.Types.Flag+ ( nullFlagAssignment, parsecFlagAssignmentNonEmpty ) import Distribution.Version- ( nullVersion, thisVersion, anyVersion, isAnyVersion )-import Distribution.Deprecated.Text- ( Text(..), display )-import Distribution.Verbosity (Verbosity)+ ( anyVersion, isAnyVersion ) import Distribution.Simple.Utils ( die', warn, lowercase ) import Distribution.PackageDescription.Parsec ( readGenericPackageDescription, parseGenericPackageDescriptionMaybe ) --- import Data.List ( find, nub )-import Data.Either- ( partitionEithers ) import qualified Data.Map as Map-import qualified Data.Set as Set import qualified Data.ByteString.Lazy as BS import qualified Distribution.Client.GZipUtils as GZipUtils-import Control.Monad (mapM)-import qualified Distribution.Deprecated.ReadP as Parse-import Distribution.Deprecated.ReadP- ( (+++), (<++) )-import Distribution.Deprecated.ParseUtils- ( readPToMaybe )+import qualified Distribution.Compat.CharParsing as P import System.FilePath ( takeExtension, dropExtension, takeDirectory, splitPath ) import System.Directory@@ -125,7 +114,7 @@ -- > cabal install foo-1.0 -- > cabal install 'foo < 2' --- UserTargetNamed Dependency+ UserTargetNamed PackageVersionConstraint -- | A special virtual package that refers to the collection of packages -- recorded in the world file that the user specifically installed.@@ -174,7 +163,7 @@ readUserTargets :: Verbosity -> [String] -> IO [UserTarget] readUserTargets verbosity targetStrs = do (problems, targets) <- liftM partitionEithers- (mapM readUserTarget targetStrs)+ (traverse readUserTarget targetStrs) reportUserTargetProblems verbosity problems return targets @@ -190,14 +179,14 @@ readUserTarget :: String -> IO (Either UserTargetProblem UserTarget) readUserTarget targetstr =- case testNamedTargets targetstr of- Just (Dependency pkgn verrange _)+ case eitherParsec targetstr of+ Right (PackageVersionConstraint pkgn verrange) | pkgn == mkPackageName "world" -> return $ if verrange == anyVersion then Right UserTargetWorld else Left UserTargetBadWorldPkg- Just dep -> return (Right (UserTargetNamed dep))- Nothing -> do+ Right dep -> return (Right (UserTargetNamed dep))+ Left _err -> do fileTarget <- testFileTargets targetstr case fileTarget of Just target -> return target@@ -206,8 +195,6 @@ Just target -> return target Nothing -> return (Left (UserTargetUnrecognised targetstr)) where- testNamedTargets = readPToMaybe parseDependencyOrPackageId- testFileTargets filename = do isDir <- doesDirectoryExist filename isFile <- doesFileExist filename@@ -253,16 +240,6 @@ extensionIsTarGz f = takeExtension f == ".gz" && takeExtension (dropExtension f) == ".tar" - parseDependencyOrPackageId :: Parse.ReadP r Dependency- parseDependencyOrPackageId = parse- +++ liftM pkgidToDependency parse- where- pkgidToDependency :: PackageIdentifier -> Dependency- pkgidToDependency p = case packageVersion p of- v | v == nullVersion -> Dependency (packageName p) anyVersion (Set.singleton LMainLibName)- | otherwise -> Dependency (packageName p) (thisVersion v) (Set.singleton LMainLibName)-- reportUserTargetProblems :: Verbosity -> [UserTargetProblem] -> IO () reportUserTargetProblems verbosity problems = do case [ target | UserTargetUnrecognised target <- problems ] of@@ -332,9 +309,9 @@ -- given the user targets, get a list of fully or partially resolved -- package references- packageTargets <- mapM (readPackageTarget verbosity)- =<< mapM (fetchPackageTarget verbosity repoCtxt) . concat- =<< mapM (expandUserTarget verbosity worldFile) userTargets+ packageTargets <- traverse (readPackageTarget verbosity)+ =<< traverse (fetchPackageTarget verbosity repoCtxt) . concat+ =<< traverse (expandUserTarget verbosity worldFile) userTargets -- users are allowed to give package names case-insensitively, so we must -- disambiguate named package references@@ -380,7 +357,7 @@ -> IO [PackageTarget (PackageLocation ())] expandUserTarget verbosity worldFile userTarget = case userTarget of - UserTargetNamed (Dependency name vrange _cs) ->+ UserTargetNamed (PackageVersionConstraint name vrange) -> let props = [ PackagePropertyVersion vrange | not (isAnyVersion vrange) ] in return [PackageTargetNamedFuzzy name props userTarget]@@ -442,12 +419,12 @@ LocalUnpackedPackage dir -> do pkg <- tryFindPackageDesc verbosity dir (localPackageError dir) >>= readGenericPackageDescription verbosity- return $ SourcePackage {- packageInfoId = packageId pkg,- packageDescription = pkg,- packageSource = fmap Just location,- packageDescrOverride = Nothing- }+ return SourcePackage+ { srcpkgPackageId = packageId pkg+ , srcpkgDescription = pkg+ , srcpkgSource = fmap Just location+ , srcpkgDescrOverride = Nothing+ } LocalTarballPackage tarballFile -> readTarballPackageTarget location tarballFile tarballFile@@ -474,12 +451,12 @@ Nothing -> die' verbosity $ "Could not parse the cabal file " ++ filename ++ " in " ++ tarballFile Just pkg ->- return $ SourcePackage {- packageInfoId = packageId pkg,- packageDescription = pkg,- packageSource = fmap Just location,- packageDescrOverride = Nothing- }+ return SourcePackage+ { srcpkgPackageId = packageId pkg+ , srcpkgDescription = pkg+ , srcpkgSource = fmap Just location+ , srcpkgDescrOverride = Nothing+ } extractTarballPackageCabalFile :: FilePath -> String -> IO (FilePath, BS.ByteString)@@ -515,7 +492,7 @@ _ -> False parsePackageDescription' :: BS.ByteString -> Maybe GenericPackageDescription- parsePackageDescription' bs = + parsePackageDescription' bs = parseGenericPackageDescriptionMaybe (BS.toStrict bs) -- ------------------------------------------------------------@@ -571,7 +548,7 @@ , not (isUserTagetWorld originalTarget) ] of [] -> return () pkgs -> die' verbosity $ unlines- [ "There is no package named '" ++ display name ++ "'. "+ [ "There is no package named '" ++ prettyShow name ++ "'. " | name <- pkgs ] ++ "You may need to run 'hackport update' to get the latest " ++ "list of available packages."@@ -579,11 +556,11 @@ case [ (pkg, matches) | PackageNameAmbiguous pkg matches _ <- problems ] of [] -> return () ambiguities -> die' verbosity $ unlines- [ "There is no package named '" ++ display name ++ "'. "+ [ "There is no package named '" ++ prettyShow name ++ "'. " ++ (if length matches > 1 then "However, the following package names exist: " else "However, the following package name exists: ")- ++ intercalate ", " [ "'" ++ display m ++ "'" | m <- matches]+ ++ intercalate ", " [ "'" ++ prettyShow m ++ "'" | m <- matches] ++ "." | (name, matches) <- ambiguities ] @@ -592,7 +569,7 @@ pkgs -> warn verbosity $ "The following 'world' packages will be ignored because " ++ "they refer to packages that cannot be found: "- ++ intercalate ", " (map display pkgs) ++ "\n"+ ++ intercalate ", " (map prettyShow pkgs) ++ "\n" ++ "You can suppress this warning by correcting the world file." where isUserTagetWorld UserTargetWorld = True; isUserTagetWorld _ = False@@ -669,6 +646,7 @@ deriving (Eq, Show, Generic) instance Binary UserQualifier+instance Structured UserQualifier -- | Version of 'ConstraintScope' that a user may specify on the -- command line.@@ -684,6 +662,7 @@ deriving (Eq, Show, Generic) instance Binary UserConstraintScope+instance Structured UserConstraintScope fromUserQualifier :: UserQualifier -> Qualifier fromUserQualifier UserQualToplevel = QualToplevel@@ -701,8 +680,9 @@ data UserConstraint = UserConstraint UserConstraintScope PackageProperty deriving (Eq, Show, Generic)- + instance Binary UserConstraint+instance Structured UserConstraint userConstraintPackageName :: UserConstraint -> PackageName userConstraintPackageName (UserConstraint scope _) = scopePN scope@@ -717,69 +697,50 @@ readUserConstraint :: String -> Either String UserConstraint readUserConstraint str =- case readPToMaybe parse str of- Nothing -> Left msgCannotParse- Just c -> Right c+ case explicitEitherParsec parsec str of+ Left err -> Left $ msgCannotParse ++ err+ Right c -> Right c where msgCannotParse = "expected a (possibly qualified) package name followed by a " ++ "constraint, which is either a version range, 'installed', " ++- "'source', 'test', 'bench', or flags"+ "'source', 'test', 'bench', or flags. " -instance Text UserConstraint where- disp (UserConstraint scope prop) =+instance Pretty UserConstraint where+ pretty (UserConstraint scope prop) = dispPackageConstraint $ PackageConstraint (fromUserConstraintScope scope) prop- - parse =- let parseConstraintScope :: Parse.ReadP a UserConstraintScope- parseConstraintScope =- do- _ <- Parse.string "any."- pn <- parse- return (UserAnyQualifier pn)- +++- do- _ <- Parse.string "setup."- pn <- parse- return (UserAnySetupQualifier pn)- +++- do- -- Qualified name- pn <- parse- (return (UserQualified UserQualToplevel pn)- +++- do _ <- Parse.string ":setup."- pn2 <- parse- return (UserQualified (UserQualSetup pn) pn2)) - -- -- TODO: Re-enable parsing of UserQualExe once we decide on a syntax.- --- -- +++- -- do _ <- Parse.string ":"- -- pn2 <- parse- -- _ <- Parse.string ":exe."- -- pn3 <- parse- -- return (UserQualExe pn pn2, pn3)- in do- scope <- parseConstraintScope- - -- Package property- let keyword str x = Parse.skipSpaces1 >> Parse.string str >> return x- prop <- ((parse >>= return . PackagePropertyVersion)- +++- keyword "installed" PackagePropertyInstalled- +++- keyword "source" PackagePropertySource- +++- keyword "test" (PackagePropertyStanzas [TestStanzas])- +++- keyword "bench" (PackagePropertyStanzas [BenchStanzas]))- -- Note: the parser is left-biased here so that we- -- don't get an ambiguous parse from 'installed',- -- 'source', etc. being regarded as flags.- <++- (Parse.skipSpaces1 >> parseFlagAssignment- >>= return . PackagePropertyFlags)- - -- Result- return (UserConstraint scope prop)+instance Parsec UserConstraint where+ parsec = do+ scope <- parseConstraintScope+ P.spaces+ prop <- P.choice+ [ PackagePropertyFlags <$> parsecFlagAssignmentNonEmpty -- headed by "+-"+ , PackagePropertyVersion <$> parsec -- headed by "<=>" (will be)+ , PackagePropertyInstalled <$ P.string "installed"+ , PackagePropertySource <$ P.string "source"+ , PackagePropertyStanzas [TestStanzas] <$ P.string "test"+ , PackagePropertyStanzas [BenchStanzas] <$ P.string "bench"+ ]+ return (UserConstraint scope prop)++ where+ parseConstraintScope :: forall m. CabalParsing m => m UserConstraintScope+ parseConstraintScope = do+ pn <- parsec+ P.choice+ [ P.char '.' *> withDot pn+ , P.char ':' *> withColon pn+ , return (UserQualified UserQualToplevel pn)+ ]+ where+ withDot :: PackageName -> m UserConstraintScope+ withDot pn+ | pn == mkPackageName "any" = UserAnyQualifier <$> parsec+ | pn == mkPackageName "setup" = UserAnySetupQualifier <$> parsec+ | otherwise = P.unexpected $ "constraint scope: " ++ unPackageName pn++ withColon :: PackageName -> m UserConstraintScope+ withColon pn = UserQualified (UserQualSetup pn)+ <$ P.string "setup."+ <*> parsec
cabal/cabal-install/Distribution/Client/Types.hs view
@@ -1,10 +1,9 @@ {-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE BangPatterns #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TypeFamilies #-}-{-# OPTIONS_GHC -fno-warn-orphans #-} ----------------------------------------------------------------------------- -- | -- Module : Distribution.Client.Types@@ -18,592 +17,29 @@ -- -- Various common data types for the entire cabal-install system ------------------------------------------------------------------------------module Distribution.Client.Types where--import Prelude ()-import Distribution.Client.Compat.Prelude--import Distribution.Package- ( Package(..), HasMungedPackageId(..), HasUnitId(..)- , PackageIdentifier(..), packageVersion, packageName- , PackageInstalled(..), newSimpleUnitId )-import Distribution.InstalledPackageInfo- ( InstalledPackageInfo, installedComponentId, sourceComponentName )-import Distribution.PackageDescription- ( FlagAssignment )-import Distribution.Version- ( VersionRange, nullVersion, thisVersion )-import Distribution.Types.ComponentId- ( ComponentId )-import Distribution.Types.MungedPackageId- ( computeCompatPackageId )-import Distribution.Types.PackageId- ( PackageId )-import Distribution.Types.AnnotatedId-import Distribution.Types.UnitId- ( UnitId )-import Distribution.Types.PackageName- ( PackageName, mkPackageName )-import Distribution.Types.ComponentName- ( ComponentName(..) )-import Distribution.Types.LibraryName- ( LibraryName(..) )-import Distribution.Client.SourceRepo- ( SourceRepoMaybe )--import Distribution.Solver.Types.PackageIndex- ( PackageIndex )-import qualified Distribution.Solver.Types.ComponentDeps as CD-import Distribution.Solver.Types.ComponentDeps- ( ComponentDeps )-import Distribution.Solver.Types.ConstraintSource-import Distribution.Solver.Types.LabeledPackageConstraint-import Distribution.Solver.Types.OptionalStanza-import Distribution.Solver.Types.PackageConstraint-import Distribution.Solver.Types.PackageFixedDeps-import Distribution.Solver.Types.SourcePackage-import Distribution.Compat.Graph (IsNode(..))-import qualified Distribution.Deprecated.ReadP as Parse-import Distribution.Deprecated.ParseUtils (parseOptCommaList)-import Distribution.Simple.Utils (ordNub)-import Distribution.Deprecated.Text (Text(..))--import Network.URI (URI(..), URIAuth(..), nullURI)-import Control.Exception- ( Exception, SomeException )-import qualified Text.PrettyPrint as Disp---newtype Username = Username { unUsername :: String }-newtype Password = Password { unPassword :: String }---- | This is the information we get from a @00-index.tar.gz@ hackage index.----data SourcePackageDb = SourcePackageDb {- packageIndex :: PackageIndex UnresolvedSourcePackage,- packagePreferences :: Map PackageName VersionRange-}- deriving (Eq, Generic)--instance Binary SourcePackageDb---- --------------------------------------------------------------- * Various kinds of information about packages--- ---------------------------------------------------------------- | Within Cabal the library we no longer have a @InstalledPackageId@ type.--- That's because it deals with the compilers' notion of a registered library,--- and those really are libraries not packages. Those are now named units.------ The package management layer does however deal with installed packages, as--- whole packages not just as libraries. So we do still need a type for--- installed package ids. At the moment however we track instaled packages via--- their primary library, which is a unit id. In future this may change--- slightly and we may distinguish these two types and have an explicit--- conversion when we register units with the compiler.----type InstalledPackageId = ComponentId----- | A 'ConfiguredPackage' is a not-yet-installed package along with the--- total configuration information. The configuration information is total in--- the sense that it provides all the configuration information and so the--- final configure process will be independent of the environment.------ 'ConfiguredPackage' is assumed to not support Backpack. Only the--- @v2-build@ codepath supports Backpack.----data ConfiguredPackage loc = ConfiguredPackage {- confPkgId :: InstalledPackageId,- confPkgSource :: SourcePackage loc, -- package info, including repo- confPkgFlags :: FlagAssignment, -- complete flag assignment for the package- confPkgStanzas :: [OptionalStanza], -- list of enabled optional stanzas for the package- confPkgDeps :: ComponentDeps [ConfiguredId]- -- set of exact dependencies (installed or source).- -- These must be consistent with the 'buildDepends'- -- in the 'PackageDescription' that you'd get by- -- applying the flag assignment and optional stanzas.- }- deriving (Eq, Show, Generic)---- | 'HasConfiguredId' indicates data types which have a 'ConfiguredId'.--- This type class is mostly used to conveniently finesse between--- 'ElaboratedPackage' and 'ElaboratedComponent'.----instance HasConfiguredId (ConfiguredPackage loc) where- configuredId pkg = ConfiguredId (packageId pkg) (Just (CLibName LMainLibName)) (confPkgId pkg)---- 'ConfiguredPackage' is the legacy codepath, we are guaranteed--- to never have a nontrivial 'UnitId'-instance PackageFixedDeps (ConfiguredPackage loc) where- depends = fmap (map (newSimpleUnitId . confInstId)) . confPkgDeps--instance IsNode (ConfiguredPackage loc) where- type Key (ConfiguredPackage loc) = UnitId- nodeKey = newSimpleUnitId . confPkgId- -- TODO: if we update ConfiguredPackage to support order-only- -- dependencies, need to include those here.- -- NB: have to deduplicate, otherwise the planner gets confused- nodeNeighbors = ordNub . CD.flatDeps . depends--instance (Binary loc) => Binary (ConfiguredPackage loc)----- | A ConfiguredId is a package ID for a configured package.------ Once we configure a source package we know its UnitId. It is still--- however useful in lots of places to also know the source ID for the package.--- We therefore bundle the two.------ An already installed package of course is also "configured" (all its--- configuration parameters and dependencies have been specified).-data ConfiguredId = ConfiguredId {- confSrcId :: PackageId- , confCompName :: Maybe ComponentName- , confInstId :: ComponentId- }- deriving (Eq, Ord, Generic)--annotatedIdToConfiguredId :: AnnotatedId ComponentId -> ConfiguredId-annotatedIdToConfiguredId aid = ConfiguredId {- confSrcId = ann_pid aid,- confCompName = Just (ann_cname aid),- confInstId = ann_id aid- }--instance Binary ConfiguredId--instance Show ConfiguredId where- show cid = show (confInstId cid)--instance Package ConfiguredId where- packageId = confSrcId--instance Package (ConfiguredPackage loc) where- packageId cpkg = packageId (confPkgSource cpkg)--instance HasMungedPackageId (ConfiguredPackage loc) where- mungedId cpkg = computeCompatPackageId (packageId cpkg) LMainLibName---- Never has nontrivial UnitId-instance HasUnitId (ConfiguredPackage loc) where- installedUnitId = newSimpleUnitId . confPkgId--instance PackageInstalled (ConfiguredPackage loc) where- installedDepends = CD.flatDeps . depends--class HasConfiguredId a where- configuredId :: a -> ConfiguredId---- NB: This instance is slightly dangerous, in that you'll lose--- information about the specific UnitId you depended on.-instance HasConfiguredId InstalledPackageInfo where- configuredId ipkg = ConfiguredId (packageId ipkg)- (Just (sourceComponentName ipkg))- (installedComponentId ipkg)---- | Like 'ConfiguredPackage', but with all dependencies guaranteed to be--- installed already, hence itself ready to be installed.-newtype GenericReadyPackage srcpkg = ReadyPackage srcpkg -- see 'ConfiguredPackage'.- deriving (Eq, Show, Generic, Package, PackageFixedDeps,- HasMungedPackageId, HasUnitId, PackageInstalled, Binary)---- Can't newtype derive this-instance IsNode srcpkg => IsNode (GenericReadyPackage srcpkg) where- type Key (GenericReadyPackage srcpkg) = Key srcpkg- nodeKey (ReadyPackage spkg) = nodeKey spkg- nodeNeighbors (ReadyPackage spkg) = nodeNeighbors spkg--type ReadyPackage = GenericReadyPackage (ConfiguredPackage UnresolvedPkgLoc)---- | Convenience alias for 'SourcePackage UnresolvedPkgLoc'.-type UnresolvedSourcePackage = SourcePackage UnresolvedPkgLoc----- --------------------------------------------------------------- * Package specifier--- ---------------------------------------------------------------- | A fully or partially resolved reference to a package.----data PackageSpecifier pkg =-- -- | A partially specified reference to a package (either source or- -- installed). It is specified by package name and optionally some- -- required properties. Use a dependency resolver to pick a specific- -- package satisfying these properties.- --- NamedPackage PackageName [PackageProperty]-- -- | A fully specified source package.- --- | SpecificSourcePackage pkg- deriving (Eq, Show, Functor, Generic)--instance Binary pkg => Binary (PackageSpecifier pkg)--pkgSpecifierTarget :: Package pkg => PackageSpecifier pkg -> PackageName-pkgSpecifierTarget (NamedPackage name _) = name-pkgSpecifierTarget (SpecificSourcePackage pkg) = packageName pkg--pkgSpecifierConstraints :: Package pkg- => PackageSpecifier pkg -> [LabeledPackageConstraint]-pkgSpecifierConstraints (NamedPackage name props) = map toLpc props- where- toLpc prop = LabeledPackageConstraint- (PackageConstraint (scopeToplevel name) prop)- ConstraintSourceUserTarget-pkgSpecifierConstraints (SpecificSourcePackage pkg) =- [LabeledPackageConstraint pc ConstraintSourceUserTarget]- where- pc = PackageConstraint- (ScopeTarget $ packageName pkg)- (PackagePropertyVersion $ thisVersion (packageVersion pkg))----- --------------------------------------------------------------- * Package locations and repositories--- --------------------------------------------------------------type UnresolvedPkgLoc = PackageLocation (Maybe FilePath)--type ResolvedPkgLoc = PackageLocation FilePath--data PackageLocation local =-- -- | An unpacked package in the given dir, or current dir- LocalUnpackedPackage FilePath-- -- | A package as a tarball that's available as a local tarball- | LocalTarballPackage FilePath-- -- | A package as a tarball from a remote URI- | RemoteTarballPackage URI local-- -- | A package available as a tarball from a repository.- --- -- It may be from a local repository or from a remote repository, with a- -- locally cached copy. ie a package available from hackage- | RepoTarballPackage Repo PackageId local-- -- | A package available from a version control system source repository- | RemoteSourceRepoPackage SourceRepoMaybe local- deriving (Show, Functor, Eq, Ord, Generic, Typeable)--instance Binary local => Binary (PackageLocation local)---- note, network-uri-2.6.0.3+ provide a Generic instance but earlier--- versions do not, so we use manual Binary instances here-instance Binary URI where- put (URI a b c d e) = do put a; put b; put c; put d; put e- get = do !a <- get; !b <- get; !c <- get; !d <- get; !e <- get- return (URI a b c d e)--instance Binary URIAuth where- put (URIAuth a b c) = do put a; put b; put c- get = do !a <- get; !b <- get; !c <- get; return (URIAuth a b c)--data RemoteRepo =- RemoteRepo {- remoteRepoName :: String,- remoteRepoURI :: URI,-- -- | Enable secure access?- --- -- 'Nothing' here represents "whatever the default is"; this is important- -- to allow for a smooth transition from opt-in to opt-out security- -- (once we switch to opt-out, all access to the central Hackage- -- repository should be secure by default)- remoteRepoSecure :: Maybe Bool,-- -- | Root key IDs (for bootstrapping)- remoteRepoRootKeys :: [String],-- -- | Threshold for verification during bootstrapping- remoteRepoKeyThreshold :: Int,-- -- | Normally a repo just specifies an HTTP or HTTPS URI, but as a- -- special case we may know a repo supports both and want to try HTTPS- -- if we can, but still allow falling back to HTTP.- --- -- This field is not currently stored in the config file, but is filled- -- in automagically for known repos.- remoteRepoShouldTryHttps :: Bool- }-- deriving (Show, Eq, Ord, Generic)--instance Binary RemoteRepo---- | Construct a partial 'RemoteRepo' value to fold the field parser list over.-emptyRemoteRepo :: String -> RemoteRepo-emptyRemoteRepo name = RemoteRepo name nullURI Nothing [] 0 False---- | Different kinds of repositories------ NOTE: It is important that this type remains serializable.-data Repo =- -- | Local repositories- RepoLocal {- repoLocalDir :: FilePath- }-- -- | Standard (unsecured) remote repositores- | RepoRemote {- repoRemote :: RemoteRepo- , repoLocalDir :: FilePath- }-- -- | Secure repositories- --- -- Although this contains the same fields as 'RepoRemote', we use a separate- -- constructor to avoid confusing the two.- --- -- Not all access to a secure repo goes through the hackage-security- -- library currently; code paths that do not still make use of the- -- 'repoRemote' and 'repoLocalDir' fields directly.- | RepoSecure {- repoRemote :: RemoteRepo- , repoLocalDir :: FilePath- }- deriving (Show, Eq, Ord, Generic)--instance Binary Repo---- | Check if this is a remote repo-isRepoRemote :: Repo -> Bool-isRepoRemote RepoLocal{} = False-isRepoRemote _ = True---- | Extract @RemoteRepo@ from @Repo@ if remote.-maybeRepoRemote :: Repo -> Maybe RemoteRepo-maybeRepoRemote (RepoLocal _localDir) = Nothing-maybeRepoRemote (RepoRemote r _localDir) = Just r-maybeRepoRemote (RepoSecure r _localDir) = Just r---- --------------------------------------------------------------- * Build results--- ---------------------------------------------------------------- | A summary of the outcome for building a single package.----type BuildOutcome = Either BuildFailure BuildResult---- | A summary of the outcome for building a whole set of packages.----type BuildOutcomes = Map UnitId BuildOutcome--data BuildFailure = PlanningFailed- | DependentFailed PackageId- | DownloadFailed SomeException- | UnpackFailed SomeException- | ConfigureFailed SomeException- | BuildFailed SomeException- | TestsFailed SomeException- | InstallFailed SomeException- deriving (Show, Typeable, Generic)--instance Exception BuildFailure---- Note that the @Maybe InstalledPackageInfo@ is a slight hack: we only--- the public library's 'InstalledPackageInfo' is stored here, even if--- there were 'InstalledPackageInfo' from internal libraries. This--- 'InstalledPackageInfo' is not used anyway, so it makes no difference.-data BuildResult = BuildResult DocsResult TestsResult- (Maybe InstalledPackageInfo)- deriving (Show, Generic)--data DocsResult = DocsNotTried | DocsFailed | DocsOk- deriving (Show, Generic, Typeable)-data TestsResult = TestsNotTried | TestsOk- deriving (Show, Generic, Typeable)--instance Binary BuildFailure-instance Binary BuildResult-instance Binary DocsResult-instance Binary TestsResult----FIXME: this is a total cheat-instance Binary SomeException where- put _ = return ()- get = fail "cannot serialise exceptions"+module Distribution.Client.Types (+ module Distribution.Client.Types.AllowNewer,+ module Distribution.Client.Types.ConfiguredId,+ module Distribution.Client.Types.ConfiguredPackage,+ module Distribution.Client.Types.BuildResults,+ module Distribution.Client.Types.PackageLocation,+ module Distribution.Client.Types.PackageSpecifier,+ module Distribution.Client.Types.ReadyPackage,+ module Distribution.Client.Types.Repo,+ module Distribution.Client.Types.RepoName,+ module Distribution.Client.Types.SourcePackageDb,+ module Distribution.Client.Types.WriteGhcEnvironmentFilesPolicy,+) where --- --------------------------------------------------------------- * --allow-newer/--allow-older--- ---------------------------------------------------------------- TODO: When https://github.com/haskell/cabal/issues/4203 gets tackled,--- it may make sense to move these definitions to the Solver.Types--- module---- | 'RelaxDeps' in the context of upper bounds (i.e. for @--allow-newer@ flag)-newtype AllowNewer = AllowNewer { unAllowNewer :: RelaxDeps }- deriving (Eq, Read, Show, Generic)---- | 'RelaxDeps' in the context of lower bounds (i.e. for @--allow-older@ flag)-newtype AllowOlder = AllowOlder { unAllowOlder :: RelaxDeps }- deriving (Eq, Read, Show, Generic)---- | Generic data type for policy when relaxing bounds in dependencies.--- Don't use this directly: use 'AllowOlder' or 'AllowNewer' depending--- on whether or not you are relaxing an lower or upper bound--- (respectively).-data RelaxDeps =-- -- | Ignore upper (resp. lower) bounds in some (or no) dependencies on the given packages.- --- -- @RelaxDepsSome []@ is the default, i.e. honor the bounds in all- -- dependencies, never choose versions newer (resp. older) than allowed.- RelaxDepsSome [RelaxedDep]-- -- | Ignore upper (resp. lower) bounds in dependencies on all packages.- --- -- __Note__: This is should be semantically equivalent to- --- -- > RelaxDepsSome [RelaxedDep RelaxDepScopeAll RelaxDepModNone RelaxDepSubjectAll]- --- -- (TODO: consider normalising 'RelaxDeps' and/or 'RelaxedDep')- | RelaxDepsAll- deriving (Eq, Read, Show, Generic)---- | Dependencies can be relaxed either for all packages in the install plan, or--- only for some packages.-data RelaxedDep = RelaxedDep !RelaxDepScope !RelaxDepMod !RelaxDepSubject- deriving (Eq, Read, Show, Generic)---- | Specify the scope of a relaxation, i.e. limit which depending--- packages are allowed to have their version constraints relaxed.-data RelaxDepScope = RelaxDepScopeAll- -- ^ Apply relaxation in any package- | RelaxDepScopePackage !PackageName- -- ^ Apply relaxation to in all versions of a package- | RelaxDepScopePackageId !PackageId- -- ^ Apply relaxation to a specific version of a package only- deriving (Eq, Read, Show, Generic)---- | Modifier for dependency relaxation-data RelaxDepMod = RelaxDepModNone -- ^ Default semantics- | RelaxDepModCaret -- ^ Apply relaxation only to @^>=@ constraints- deriving (Eq, Read, Show, Generic)---- | Express whether to relax bounds /on/ @all@ packages, or a single package-data RelaxDepSubject = RelaxDepSubjectAll- | RelaxDepSubjectPkg !PackageName- deriving (Eq, Ord, Read, Show, Generic)--instance Text RelaxedDep where- disp (RelaxedDep scope rdmod subj) = case scope of- RelaxDepScopeAll -> Disp.text "all:" Disp.<> modDep- RelaxDepScopePackage p0 -> disp p0 Disp.<> Disp.colon Disp.<> modDep- RelaxDepScopePackageId p0 -> disp p0 Disp.<> Disp.colon Disp.<> modDep- where- modDep = case rdmod of- RelaxDepModNone -> disp subj- RelaxDepModCaret -> Disp.char '^' Disp.<> disp subj-- parse = RelaxedDep <$> scopeP <*> modP <*> parse- where- -- "greedy" choices- scopeP = (pure RelaxDepScopeAll <* Parse.char '*' <* Parse.char ':')- Parse.<++ (pure RelaxDepScopeAll <* Parse.string "all:")- Parse.<++ (RelaxDepScopePackageId <$> pidP <* Parse.char ':')- Parse.<++ (RelaxDepScopePackage <$> parse <* Parse.char ':')- Parse.<++ (pure RelaxDepScopeAll)-- modP = (pure RelaxDepModCaret <* Parse.char '^')- Parse.<++ (pure RelaxDepModNone)-- -- | Stricter 'PackageId' parser which doesn't overlap with 'PackageName' parser- pidP = do- p0 <- parse- when (pkgVersion p0 == nullVersion) Parse.pfail- pure p0--instance Text RelaxDepSubject where- disp RelaxDepSubjectAll = Disp.text "all"- disp (RelaxDepSubjectPkg pn) = disp pn-- parse = (pure RelaxDepSubjectAll <* Parse.char '*') Parse.<++ pkgn- where- pkgn = do- pn <- parse- pure (if (pn == mkPackageName "all")- then RelaxDepSubjectAll- else RelaxDepSubjectPkg pn)--instance Text RelaxDeps where- disp rd | not (isRelaxDeps rd) = Disp.text "none"- disp (RelaxDepsSome pkgs) = Disp.fsep .- Disp.punctuate Disp.comma .- map disp $ pkgs- disp RelaxDepsAll = Disp.text "all"-- parse = (const mempty <$> ((Parse.string "none" Parse.+++- Parse.string "None") <* Parse.eof))- Parse.<++ (const RelaxDepsAll <$> ((Parse.string "all" Parse.+++- Parse.string "All" Parse.+++- Parse.string "*") <* Parse.eof))- Parse.<++ ( RelaxDepsSome <$> parseOptCommaList parse)--instance Binary RelaxDeps-instance Binary RelaxDepMod-instance Binary RelaxDepScope-instance Binary RelaxDepSubject-instance Binary RelaxedDep-instance Binary AllowNewer-instance Binary AllowOlder---- | Return 'True' if 'RelaxDeps' specifies a non-empty set of relaxations------ Equivalent to @isRelaxDeps = (/= 'mempty')@-isRelaxDeps :: RelaxDeps -> Bool-isRelaxDeps (RelaxDepsSome []) = False-isRelaxDeps (RelaxDepsSome (_:_)) = True-isRelaxDeps RelaxDepsAll = True---- | 'RelaxDepsAll' is the /absorbing element/-instance Semigroup RelaxDeps where- -- identity element- RelaxDepsSome [] <> r = r- l@(RelaxDepsSome _) <> RelaxDepsSome [] = l- -- absorbing element- l@RelaxDepsAll <> _ = l- (RelaxDepsSome _) <> r@RelaxDepsAll = r- -- combining non-{identity,absorbing} elements- (RelaxDepsSome a) <> (RelaxDepsSome b) = RelaxDepsSome (a ++ b)---- | @'RelaxDepsSome' []@ is the /identity element/-instance Monoid RelaxDeps where- mempty = RelaxDepsSome []- mappend = (<>)--instance Semigroup AllowNewer where- AllowNewer x <> AllowNewer y = AllowNewer (x <> y)--instance Semigroup AllowOlder where- AllowOlder x <> AllowOlder y = AllowOlder (x <> y)--instance Monoid AllowNewer where- mempty = AllowNewer mempty- mappend = (<>)--instance Monoid AllowOlder where- mempty = AllowOlder mempty- mappend = (<>)---- --------------------------------------------------------------- * --write-ghc-environment-file--- ---------------------------------------------------------------- | Whether 'v2-build' should write a .ghc.environment file after--- success. Possible values: 'always', 'never' (the default), 'ghc8.4.4+'--- (8.4.4 is the earliest version that supports--- '-package-env -').-data WriteGhcEnvironmentFilesPolicy- = AlwaysWriteGhcEnvironmentFiles- | NeverWriteGhcEnvironmentFiles- | WriteGhcEnvironmentFilesOnlyForGhc844AndNewer- deriving (Eq, Enum, Bounded, Generic, Show)--instance Binary WriteGhcEnvironmentFilesPolicy+import Distribution.Client.Types.AllowNewer+import Distribution.Client.Types.BuildResults+import Distribution.Client.Types.ConfiguredId+import Distribution.Client.Types.ConfiguredPackage+import Distribution.Client.Types.PackageLocation+import Distribution.Client.Types.PackageSpecifier+import Distribution.Client.Types.Repo+import Distribution.Client.Types.RepoName+import Distribution.Client.Types.ReadyPackage+import Distribution.Client.Types.SourcePackageDb+import Distribution.Client.Types.WriteGhcEnvironmentFilesPolicy
+ cabal/cabal-install/Distribution/Client/Types/AllowNewer.hs view
@@ -0,0 +1,241 @@+{-# LANGUAGE DeriveGeneric #-}+module Distribution.Client.Types.AllowNewer (+ AllowNewer (..),+ AllowOlder (..),+ RelaxDeps (..),+ mkRelaxDepSome,+ RelaxDepMod (..),+ RelaxDepScope (..),+ RelaxDepSubject (..),+ RelaxedDep (..),+ isRelaxDeps,+) where++import Distribution.Client.Compat.Prelude+import Prelude ()++import Distribution.Parsec (parsecLeadingCommaNonEmpty)+import Distribution.Types.PackageId (PackageId, PackageIdentifier (..))+import Distribution.Types.PackageName (PackageName, mkPackageName)+import Distribution.Types.Version (nullVersion)++import qualified Distribution.Compat.CharParsing as P+import qualified Text.PrettyPrint as Disp++-- $setup+-- >>> import Distribution.Parsec++-- TODO: When https://github.com/haskell/cabal/issues/4203 gets tackled,+-- it may make sense to move these definitions to the Solver.Types+-- module++-- | 'RelaxDeps' in the context of upper bounds (i.e. for @--allow-newer@ flag)+newtype AllowNewer = AllowNewer { unAllowNewer :: RelaxDeps }+ deriving (Eq, Read, Show, Generic)++-- | 'RelaxDeps' in the context of lower bounds (i.e. for @--allow-older@ flag)+newtype AllowOlder = AllowOlder { unAllowOlder :: RelaxDeps }+ deriving (Eq, Read, Show, Generic)++-- | Generic data type for policy when relaxing bounds in dependencies.+-- Don't use this directly: use 'AllowOlder' or 'AllowNewer' depending+-- on whether or not you are relaxing an lower or upper bound+-- (respectively).+data RelaxDeps =++ -- | Ignore upper (resp. lower) bounds in some (or no) dependencies on the given packages.+ --+ -- @RelaxDepsSome []@ is the default, i.e. honor the bounds in all+ -- dependencies, never choose versions newer (resp. older) than allowed.+ RelaxDepsSome [RelaxedDep]++ -- | Ignore upper (resp. lower) bounds in dependencies on all packages.+ --+ -- __Note__: This is should be semantically equivalent to+ --+ -- > RelaxDepsSome [RelaxedDep RelaxDepScopeAll RelaxDepModNone RelaxDepSubjectAll]+ --+ -- (TODO: consider normalising 'RelaxDeps' and/or 'RelaxedDep')+ | RelaxDepsAll+ deriving (Eq, Read, Show, Generic)++-- | Dependencies can be relaxed either for all packages in the install plan, or+-- only for some packages.+data RelaxedDep = RelaxedDep !RelaxDepScope !RelaxDepMod !RelaxDepSubject+ deriving (Eq, Read, Show, Generic)++-- | Specify the scope of a relaxation, i.e. limit which depending+-- packages are allowed to have their version constraints relaxed.+data RelaxDepScope = RelaxDepScopeAll+ -- ^ Apply relaxation in any package+ | RelaxDepScopePackage !PackageName+ -- ^ Apply relaxation to in all versions of a package+ | RelaxDepScopePackageId !PackageId+ -- ^ Apply relaxation to a specific version of a package only+ deriving (Eq, Read, Show, Generic)++-- | Modifier for dependency relaxation+data RelaxDepMod = RelaxDepModNone -- ^ Default semantics+ | RelaxDepModCaret -- ^ Apply relaxation only to @^>=@ constraints+ deriving (Eq, Read, Show, Generic)++-- | Express whether to relax bounds /on/ @all@ packages, or a single package+data RelaxDepSubject = RelaxDepSubjectAll+ | RelaxDepSubjectPkg !PackageName+ deriving (Eq, Ord, Read, Show, Generic)++instance Pretty RelaxedDep where+ pretty (RelaxedDep scope rdmod subj) = case scope of+ RelaxDepScopeAll -> Disp.text "*:" Disp.<> modDep+ RelaxDepScopePackage p0 -> pretty p0 Disp.<> Disp.colon Disp.<> modDep+ RelaxDepScopePackageId p0 -> pretty p0 Disp.<> Disp.colon Disp.<> modDep+ where+ modDep = case rdmod of+ RelaxDepModNone -> pretty subj+ RelaxDepModCaret -> Disp.char '^' Disp.<> pretty subj++instance Parsec RelaxedDep where+ parsec = P.char '*' *> relaxedDepStarP <|> (parsec >>= relaxedDepPkgidP)++-- continuation after *+relaxedDepStarP :: CabalParsing m => m RelaxedDep+relaxedDepStarP =+ RelaxedDep RelaxDepScopeAll <$ P.char ':' <*> modP <*> parsec+ <|> pure (RelaxedDep RelaxDepScopeAll RelaxDepModNone RelaxDepSubjectAll)++-- continuation after package identifier+relaxedDepPkgidP :: CabalParsing m => PackageIdentifier -> m RelaxedDep+relaxedDepPkgidP pid@(PackageIdentifier pn v)+ | pn == mkPackageName "all"+ , v == nullVersion+ = RelaxedDep RelaxDepScopeAll <$ P.char ':' <*> modP <*> parsec+ <|> pure (RelaxedDep RelaxDepScopeAll RelaxDepModNone RelaxDepSubjectAll)++ | v == nullVersion+ = RelaxedDep (RelaxDepScopePackage pn) <$ P.char ':' <*> modP <*> parsec+ <|> pure (RelaxedDep RelaxDepScopeAll RelaxDepModNone (RelaxDepSubjectPkg pn))++ | otherwise+ = RelaxedDep (RelaxDepScopePackageId pid) <$ P.char ':' <*> modP <*> parsec++modP :: P.CharParsing m => m RelaxDepMod+modP = RelaxDepModCaret <$ P.char '^' <|> pure RelaxDepModNone++instance Pretty RelaxDepSubject where+ pretty RelaxDepSubjectAll = Disp.text "*"+ pretty (RelaxDepSubjectPkg pn) = pretty pn++instance Parsec RelaxDepSubject where+ parsec = RelaxDepSubjectAll <$ P.char '*' <|> pkgn+ where+ pkgn = do+ pn <- parsec+ pure $ if pn == mkPackageName "all"+ then RelaxDepSubjectAll+ else RelaxDepSubjectPkg pn++instance Pretty RelaxDeps where+ pretty rd | not (isRelaxDeps rd) = Disp.text "none"+ pretty (RelaxDepsSome pkgs) = Disp.fsep .+ Disp.punctuate Disp.comma .+ map pretty $ pkgs+ pretty RelaxDepsAll = Disp.text "all"++-- |+--+-- >>> simpleParsec "all" :: Maybe RelaxDeps+-- Just RelaxDepsAll+--+-- >>> simpleParsec "none" :: Maybe RelaxDeps+-- Just (RelaxDepsSome [])+--+-- >>> simpleParsec "*, *" :: Maybe RelaxDeps+-- Just RelaxDepsAll+--+-- >>> simpleParsec "*:*" :: Maybe RelaxDeps+-- Just RelaxDepsAll+--+-- >>> simpleParsec "foo:bar, quu:puu" :: Maybe RelaxDeps+-- Just (RelaxDepsSome [RelaxedDep (RelaxDepScopePackage (PackageName "foo")) RelaxDepModNone (RelaxDepSubjectPkg (PackageName "bar")),RelaxedDep (RelaxDepScopePackage (PackageName "quu")) RelaxDepModNone (RelaxDepSubjectPkg (PackageName "puu"))])+--+-- This is not a glitch, even it looks like:+--+-- >>> simpleParsec ", all" :: Maybe RelaxDeps+-- Just RelaxDepsAll+--+-- >>> simpleParsec "" :: Maybe RelaxDeps+-- Nothing+--+instance Parsec RelaxDeps where+ parsec = do+ xs <- parsecLeadingCommaNonEmpty parsec+ pure $ case toList xs of+ [RelaxedDep RelaxDepScopeAll RelaxDepModNone RelaxDepSubjectAll]+ -> RelaxDepsAll+ [RelaxedDep RelaxDepScopeAll RelaxDepModNone (RelaxDepSubjectPkg pn)]+ | pn == mkPackageName "none"+ -> mempty+ xs' -> mkRelaxDepSome xs'++instance Binary RelaxDeps+instance Binary RelaxDepMod+instance Binary RelaxDepScope+instance Binary RelaxDepSubject+instance Binary RelaxedDep+instance Binary AllowNewer+instance Binary AllowOlder++instance Structured RelaxDeps+instance Structured RelaxDepMod+instance Structured RelaxDepScope+instance Structured RelaxDepSubject+instance Structured RelaxedDep+instance Structured AllowNewer+instance Structured AllowOlder++-- | Return 'True' if 'RelaxDeps' specifies a non-empty set of relaxations+--+-- Equivalent to @isRelaxDeps = (/= 'mempty')@+isRelaxDeps :: RelaxDeps -> Bool+isRelaxDeps (RelaxDepsSome []) = False+isRelaxDeps (RelaxDepsSome (_:_)) = True+isRelaxDeps RelaxDepsAll = True++-- | A smarter 'RelaxedDepsSome', @*:*@ is the same as @all@.+mkRelaxDepSome :: [RelaxedDep] -> RelaxDeps+mkRelaxDepSome xs+ | any (== RelaxedDep RelaxDepScopeAll RelaxDepModNone RelaxDepSubjectAll) xs+ = RelaxDepsAll++ | otherwise+ = RelaxDepsSome xs++-- | 'RelaxDepsAll' is the /absorbing element/+instance Semigroup RelaxDeps where+ -- identity element+ RelaxDepsSome [] <> r = r+ l@(RelaxDepsSome _) <> RelaxDepsSome [] = l+ -- absorbing element+ l@RelaxDepsAll <> _ = l+ (RelaxDepsSome _) <> r@RelaxDepsAll = r+ -- combining non-{identity,absorbing} elements+ (RelaxDepsSome a) <> (RelaxDepsSome b) = RelaxDepsSome (a ++ b)++-- | @'RelaxDepsSome' []@ is the /identity element/+instance Monoid RelaxDeps where+ mempty = RelaxDepsSome []+ mappend = (<>)++instance Semigroup AllowNewer where+ AllowNewer x <> AllowNewer y = AllowNewer (x <> y)++instance Semigroup AllowOlder where+ AllowOlder x <> AllowOlder y = AllowOlder (x <> y)++instance Monoid AllowNewer where+ mempty = AllowNewer mempty+ mappend = (<>)++instance Monoid AllowOlder where+ mempty = AllowOlder mempty+ mappend = (<>)
+ cabal/cabal-install/Distribution/Client/Types/BuildResults.hs view
@@ -0,0 +1,59 @@+{-# LANGUAGE DeriveGeneric #-}+module Distribution.Client.Types.BuildResults (+ BuildOutcome,+ BuildOutcomes,+ BuildFailure (..),+ BuildResult (..),+ TestsResult (..),+ DocsResult (..),+) where++import Distribution.Client.Compat.Prelude+import Prelude ()++import Distribution.Types.InstalledPackageInfo (InstalledPackageInfo)+import Distribution.Types.PackageId (PackageId)+import Distribution.Types.UnitId (UnitId)++-- | A summary of the outcome for building a single package.+--+type BuildOutcome = Either BuildFailure BuildResult++-- | A summary of the outcome for building a whole set of packages.+--+type BuildOutcomes = Map UnitId BuildOutcome++data BuildFailure = PlanningFailed+ | DependentFailed PackageId+ | DownloadFailed SomeException+ | UnpackFailed SomeException+ | ConfigureFailed SomeException+ | BuildFailed SomeException+ | TestsFailed SomeException+ | InstallFailed SomeException+ deriving (Show, Typeable, Generic)++instance Exception BuildFailure++-- Note that the @Maybe InstalledPackageInfo@ is a slight hack: we only+-- the public library's 'InstalledPackageInfo' is stored here, even if+-- there were 'InstalledPackageInfo' from internal libraries. This+-- 'InstalledPackageInfo' is not used anyway, so it makes no difference.+data BuildResult = BuildResult DocsResult TestsResult+ (Maybe InstalledPackageInfo)+ deriving (Show, Generic)++data DocsResult = DocsNotTried | DocsFailed | DocsOk+ deriving (Show, Generic, Typeable)+data TestsResult = TestsNotTried | TestsOk+ deriving (Show, Generic, Typeable)++instance Binary BuildFailure+instance Binary BuildResult+instance Binary DocsResult+instance Binary TestsResult++instance Structured BuildFailure+instance Structured BuildResult+instance Structured DocsResult+instance Structured TestsResult
+ cabal/cabal-install/Distribution/Client/Types/ConfiguredId.hs view
@@ -0,0 +1,83 @@+{-# LANGUAGE DeriveGeneric #-}+module Distribution.Client.Types.ConfiguredId (+ InstalledPackageId,+ ConfiguredId (..),+ annotatedIdToConfiguredId,+ HasConfiguredId (..),+) where++import Distribution.Client.Compat.Prelude+import Prelude ()++import Distribution.InstalledPackageInfo (InstalledPackageInfo, sourceComponentName, installedComponentId)+import Distribution.Package (Package (..))+import Distribution.Types.AnnotatedId (AnnotatedId (..))+import Distribution.Types.ComponentId (ComponentId)+import Distribution.Types.ComponentName (ComponentName)+import Distribution.Types.PackageId (PackageId)++-------------------------------------------------------------------------------+-- InstalledPackageId+-------------------------------------------------------------------------------++-- | Within Cabal the library we no longer have a @InstalledPackageId@ type.+-- That's because it deals with the compilers' notion of a registered library,+-- and those really are libraries not packages. Those are now named units.+--+-- The package management layer does however deal with installed packages, as+-- whole packages not just as libraries. So we do still need a type for+-- installed package ids. At the moment however we track instaled packages via+-- their primary library, which is a unit id. In future this may change+-- slightly and we may distinguish these two types and have an explicit+-- conversion when we register units with the compiler.+--+type InstalledPackageId = ComponentId++-------------------------------------------------------------------------------+-- ConfiguredId+-------------------------------------------------------------------------------++-- | A ConfiguredId is a package ID for a configured package.+--+-- Once we configure a source package we know its UnitId. It is still+-- however useful in lots of places to also know the source ID for the package.+-- We therefore bundle the two.+--+-- An already installed package of course is also "configured" (all its+-- configuration parameters and dependencies have been specified).+data ConfiguredId = ConfiguredId {+ confSrcId :: PackageId+ , confCompName :: Maybe ComponentName+ , confInstId :: ComponentId+ }+ deriving (Eq, Ord, Generic)++annotatedIdToConfiguredId :: AnnotatedId ComponentId -> ConfiguredId+annotatedIdToConfiguredId aid = ConfiguredId {+ confSrcId = ann_pid aid,+ confCompName = Just (ann_cname aid),+ confInstId = ann_id aid+ }++instance Binary ConfiguredId+instance Structured ConfiguredId++instance Show ConfiguredId where+ show cid = show (confInstId cid)++instance Package ConfiguredId where+ packageId = confSrcId++-------------------------------------------------------------------------------+-- HasConfiguredId class+-------------------------------------------------------------------------------++class HasConfiguredId a where+ configuredId :: a -> ConfiguredId++-- NB: This instance is slightly dangerous, in that you'll lose+-- information about the specific UnitId you depended on.+instance HasConfiguredId InstalledPackageInfo where+ configuredId ipkg = ConfiguredId (packageId ipkg)+ (Just (sourceComponentName ipkg))+ (installedComponentId ipkg)
+ cabal/cabal-install/Distribution/Client/Types/ConfiguredPackage.hs view
@@ -0,0 +1,86 @@+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE TypeFamilies #-}+module Distribution.Client.Types.ConfiguredPackage (+ ConfiguredPackage (..),+) where++import Distribution.Client.Compat.Prelude+import Prelude ()++import Distribution.Compat.Graph (IsNode (..))+import Distribution.Package (newSimpleUnitId, HasMungedPackageId (..), HasUnitId (..), Package (..), PackageInstalled (..), UnitId)+import Distribution.Types.Flag (FlagAssignment)+import Distribution.Types.ComponentName+import Distribution.Types.LibraryName (LibraryName (..))+import Distribution.Types.MungedPackageId (computeCompatPackageId)+import Distribution.Simple.Utils (ordNub)++import Distribution.Client.Types.ConfiguredId+import Distribution.Solver.Types.OptionalStanza (OptionalStanza)+import Distribution.Solver.Types.PackageFixedDeps+import Distribution.Solver.Types.SourcePackage (SourcePackage)++import qualified Distribution.Solver.Types.ComponentDeps as CD++-- | A 'ConfiguredPackage' is a not-yet-installed package along with the+-- total configuration information. The configuration information is total in+-- the sense that it provides all the configuration information and so the+-- final configure process will be independent of the environment.+--+-- 'ConfiguredPackage' is assumed to not support Backpack. Only the+-- @v2-build@ codepath supports Backpack.+--+data ConfiguredPackage loc = ConfiguredPackage+ { confPkgId :: InstalledPackageId+ , confPkgSource :: SourcePackage loc -- ^ package info, including repo+ , confPkgFlags :: FlagAssignment -- ^ complete flag assignment for the package+ , confPkgStanzas :: [OptionalStanza] -- ^ list of enabled optional stanzas for the package+ , confPkgDeps :: CD.ComponentDeps [ConfiguredId]+ -- ^ set of exact dependencies (installed or source).+ --+ -- These must be consistent with the 'buildDepends'+ -- in the 'PackageDescription' that you'd get by+ -- applying the flag assignment and optional stanzas.+ }+ deriving (Eq, Show, Generic)++-- | 'HasConfiguredId' indicates data types which have a 'ConfiguredId'.+-- This type class is mostly used to conveniently finesse between+-- 'ElaboratedPackage' and 'ElaboratedComponent'.+--+instance HasConfiguredId (ConfiguredPackage loc) where+ configuredId pkg = ConfiguredId (packageId pkg) (Just (CLibName LMainLibName)) (confPkgId pkg)++-- 'ConfiguredPackage' is the legacy codepath, we are guaranteed+-- to never have a nontrivial 'UnitId'+instance PackageFixedDeps (ConfiguredPackage loc) where+ depends = fmap (map (newSimpleUnitId . confInstId)) . confPkgDeps++instance IsNode (ConfiguredPackage loc) where+ type Key (ConfiguredPackage loc) = UnitId+ nodeKey = newSimpleUnitId . confPkgId+ -- TODO: if we update ConfiguredPackage to support order-only+ -- dependencies, need to include those here.+ -- NB: have to deduplicate, otherwise the planner gets confused+ nodeNeighbors = ordNub . CD.flatDeps . depends++instance (Binary loc) => Binary (ConfiguredPackage loc)+++++instance Package (ConfiguredPackage loc) where+ packageId cpkg = packageId (confPkgSource cpkg)++instance HasMungedPackageId (ConfiguredPackage loc) where+ mungedId cpkg = computeCompatPackageId (packageId cpkg) LMainLibName++-- Never has nontrivial UnitId+instance HasUnitId (ConfiguredPackage loc) where+ installedUnitId = newSimpleUnitId . confPkgId++instance PackageInstalled (ConfiguredPackage loc) where+ installedDepends = CD.flatDeps . depends+++
+ cabal/cabal-install/Distribution/Client/Types/Credentials.hs view
@@ -0,0 +1,9 @@+module Distribution.Client.Types.Credentials (+ Username (..),+ Password (..),+) where++import Prelude (String)++newtype Username = Username { unUsername :: String }+newtype Password = Password { unPassword :: String }
+ cabal/cabal-install/Distribution/Client/Types/InstallMethod.hs view
@@ -0,0 +1,32 @@+{-# LANGUAGE DeriveGeneric #-}+module Distribution.Client.Types.InstallMethod where++import Distribution.Client.Compat.Prelude+import Prelude ()++import qualified Distribution.Compat.CharParsing as P+import qualified Text.PrettyPrint as PP++data InstallMethod+ = InstallMethodCopy+ | InstallMethodSymlink+ deriving (Eq, Show, Generic, Bounded, Enum)++instance Binary InstallMethod+instance Structured InstallMethod++-- | Last+instance Semigroup InstallMethod where+ _ <> x = x++instance Parsec InstallMethod where+ parsec = do+ name <- P.munch1 isAlpha+ case name of+ "copy" -> pure InstallMethodCopy+ "symlink" -> pure InstallMethodSymlink+ _ -> P.unexpected $ "InstallMethod: " ++ name++instance Pretty InstallMethod where+ pretty InstallMethodCopy = PP.text "copy"+ pretty InstallMethodSymlink = PP.text "symlink"
+ cabal/cabal-install/Distribution/Client/Types/OverwritePolicy.hs view
@@ -0,0 +1,28 @@+{-# LANGUAGE DeriveGeneric #-}+module Distribution.Client.Types.OverwritePolicy where++import Distribution.Client.Compat.Prelude+import Prelude ()++import qualified Distribution.Compat.CharParsing as P+import qualified Text.PrettyPrint as PP++data OverwritePolicy+ = NeverOverwrite+ | AlwaysOverwrite+ deriving (Show, Eq, Generic, Bounded, Enum)++instance Binary OverwritePolicy+instance Structured OverwritePolicy++instance Parsec OverwritePolicy where+ parsec = do+ name <- P.munch1 isAlpha+ case name of+ "always" -> pure AlwaysOverwrite+ "never" -> pure NeverOverwrite+ _ -> P.unexpected $ "OverwritePolicy: " ++ name++instance Pretty OverwritePolicy where+ pretty NeverOverwrite = PP.text "never"+ pretty AlwaysOverwrite = PP.text "always"
+ cabal/cabal-install/Distribution/Client/Types/PackageLocation.hs view
@@ -0,0 +1,50 @@+{-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE DeriveGeneric #-}+module Distribution.Client.Types.PackageLocation (+ PackageLocation (..),+ UnresolvedPkgLoc,+ ResolvedPkgLoc,+ UnresolvedSourcePackage,+) where++import Distribution.Client.Compat.Prelude+import Prelude ()++import Network.URI (URI)++import Distribution.Types.PackageId (PackageId)++import Distribution.Client.Types.Repo+import Distribution.Client.Types.SourceRepo (SourceRepoMaybe)+import Distribution.Solver.Types.SourcePackage (SourcePackage)++type UnresolvedPkgLoc = PackageLocation (Maybe FilePath)++type ResolvedPkgLoc = PackageLocation FilePath++data PackageLocation local =++ -- | An unpacked package in the given dir, or current dir+ LocalUnpackedPackage FilePath++ -- | A package as a tarball that's available as a local tarball+ | LocalTarballPackage FilePath++ -- | A package as a tarball from a remote URI+ | RemoteTarballPackage URI local++ -- | A package available as a tarball from a repository.+ --+ -- It may be from a local repository or from a remote repository, with a+ -- locally cached copy. ie a package available from hackage+ | RepoTarballPackage Repo PackageId local++ -- | A package available from a version control system source repository+ | RemoteSourceRepoPackage SourceRepoMaybe local+ deriving (Show, Functor, Eq, Ord, Generic, Typeable)++instance Binary local => Binary (PackageLocation local)+instance Structured local => Structured (PackageLocation local)++-- | Convenience alias for 'SourcePackage UnresolvedPkgLoc'.+type UnresolvedSourcePackage = SourcePackage UnresolvedPkgLoc
+ cabal/cabal-install/Distribution/Client/Types/PackageSpecifier.hs view
@@ -0,0 +1,55 @@+{-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE DeriveGeneric #-}+module Distribution.Client.Types.PackageSpecifier (+ PackageSpecifier (..),+ pkgSpecifierTarget,+ pkgSpecifierConstraints,+) where++import Distribution.Client.Compat.Prelude+import Prelude ()++import Distribution.Package (Package (..), packageName, packageVersion)+import Distribution.Types.PackageName (PackageName)+import Distribution.Version (thisVersion)++import Distribution.Solver.Types.ConstraintSource+import Distribution.Solver.Types.LabeledPackageConstraint+import Distribution.Solver.Types.PackageConstraint++-- | A fully or partially resolved reference to a package.+--+data PackageSpecifier pkg =++ -- | A partially specified reference to a package (either source or+ -- installed). It is specified by package name and optionally some+ -- required properties. Use a dependency resolver to pick a specific+ -- package satisfying these properties.+ --+ NamedPackage PackageName [PackageProperty]++ -- | A fully specified source package.+ --+ | SpecificSourcePackage pkg+ deriving (Eq, Show, Functor, Generic)++instance Binary pkg => Binary (PackageSpecifier pkg)+instance Structured pkg => Structured (PackageSpecifier pkg)++pkgSpecifierTarget :: Package pkg => PackageSpecifier pkg -> PackageName+pkgSpecifierTarget (NamedPackage name _) = name+pkgSpecifierTarget (SpecificSourcePackage pkg) = packageName pkg++pkgSpecifierConstraints :: Package pkg+ => PackageSpecifier pkg -> [LabeledPackageConstraint]+pkgSpecifierConstraints (NamedPackage name props) = map toLpc props+ where+ toLpc prop = LabeledPackageConstraint+ (PackageConstraint (scopeToplevel name) prop)+ ConstraintSourceUserTarget+pkgSpecifierConstraints (SpecificSourcePackage pkg) =+ [LabeledPackageConstraint pc ConstraintSourceUserTarget]+ where+ pc = PackageConstraint+ (ScopeTarget $ packageName pkg)+ (PackagePropertyVersion $ thisVersion (packageVersion pkg))
+ cabal/cabal-install/Distribution/Client/Types/ReadyPackage.hs view
@@ -0,0 +1,31 @@+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+module Distribution.Client.Types.ReadyPackage (+ GenericReadyPackage (..),+ ReadyPackage,+) where++import Distribution.Client.Compat.Prelude+import Prelude ()++import Distribution.Compat.Graph (IsNode (..))+import Distribution.Package (HasMungedPackageId, HasUnitId, Package, PackageInstalled)++import Distribution.Client.Types.ConfiguredPackage (ConfiguredPackage)+import Distribution.Client.Types.PackageLocation (UnresolvedPkgLoc)+import Distribution.Solver.Types.PackageFixedDeps++-- | Like 'ConfiguredPackage', but with all dependencies guaranteed to be+-- installed already, hence itself ready to be installed.+newtype GenericReadyPackage srcpkg = ReadyPackage srcpkg -- see 'ConfiguredPackage'.+ deriving (Eq, Show, Generic, Package, PackageFixedDeps,+ HasMungedPackageId, HasUnitId, PackageInstalled, Binary)++-- Can't newtype derive this+instance IsNode srcpkg => IsNode (GenericReadyPackage srcpkg) where+ type Key (GenericReadyPackage srcpkg) = Key srcpkg+ nodeKey (ReadyPackage spkg) = nodeKey spkg+ nodeNeighbors (ReadyPackage spkg) = nodeNeighbors spkg++type ReadyPackage = GenericReadyPackage (ConfiguredPackage UnresolvedPkgLoc)
+ cabal/cabal-install/Distribution/Client/Types/Repo.hs view
@@ -0,0 +1,184 @@+{-# LANGUAGE DeriveGeneric #-}+module Distribution.Client.Types.Repo (+ -- * Remote repository+ RemoteRepo (..),+ emptyRemoteRepo,+ -- * Local repository (no-index)+ LocalRepo (..),+ emptyLocalRepo,+ localRepoCacheKey,+ -- * Repository+ Repo (..),+ isRepoRemote,+ maybeRepoRemote,+) where++import Distribution.Client.Compat.Prelude+import Prelude ()++import Network.URI (URI (..), nullURI, parseAbsoluteURI, uriToString)++import Distribution.Simple.Utils (toUTF8BS)++import Distribution.Client.HashValue (hashValue, showHashValue, truncateHash)++import qualified Data.ByteString.Lazy.Char8 as LBS+import qualified Distribution.Compat.CharParsing as P+import qualified Text.PrettyPrint as Disp++import Distribution.Client.Types.RepoName++-------------------------------------------------------------------------------+-- Remote repository+-------------------------------------------------------------------------------++data RemoteRepo =+ RemoteRepo {+ remoteRepoName :: RepoName,+ remoteRepoURI :: URI,++ -- | Enable secure access?+ --+ -- 'Nothing' here represents "whatever the default is"; this is important+ -- to allow for a smooth transition from opt-in to opt-out security+ -- (once we switch to opt-out, all access to the central Hackage+ -- repository should be secure by default)+ remoteRepoSecure :: Maybe Bool,++ -- | Root key IDs (for bootstrapping)+ remoteRepoRootKeys :: [String],++ -- | Threshold for verification during bootstrapping+ remoteRepoKeyThreshold :: Int,++ -- | Normally a repo just specifies an HTTP or HTTPS URI, but as a+ -- special case we may know a repo supports both and want to try HTTPS+ -- if we can, but still allow falling back to HTTP.+ --+ -- This field is not currently stored in the config file, but is filled+ -- in automagically for known repos.+ remoteRepoShouldTryHttps :: Bool+ }++ deriving (Show, Eq, Ord, Generic)++instance Binary RemoteRepo+instance Structured RemoteRepo++instance Pretty RemoteRepo where+ pretty r =+ pretty (remoteRepoName r) <<>> Disp.colon <<>>+ Disp.text (uriToString id (remoteRepoURI r) [])++-- | Note: serialised format represends 'RemoteRepo' only partially.+instance Parsec RemoteRepo where+ parsec = do+ name <- parsec+ _ <- P.char ':'+ uriStr <- P.munch1 (\c -> isAlphaNum c || c `elem` ("+-=._/*()@'$:;&!?~" :: String))+ uri <- maybe (fail $ "Cannot parse URI:" ++ uriStr) return (parseAbsoluteURI uriStr)+ return RemoteRepo+ { remoteRepoName = name+ , remoteRepoURI = uri+ , remoteRepoSecure = Nothing+ , remoteRepoRootKeys = []+ , remoteRepoKeyThreshold = 0+ , remoteRepoShouldTryHttps = False+ }++-- | Construct a partial 'RemoteRepo' value to fold the field parser list over.+emptyRemoteRepo :: RepoName -> RemoteRepo+emptyRemoteRepo name = RemoteRepo name nullURI Nothing [] 0 False++-------------------------------------------------------------------------------+-- Local repository+-------------------------------------------------------------------------------++-- | /no-index/ style local repositories.+--+-- https://github.com/haskell/cabal/issues/6359+data LocalRepo = LocalRepo+ { localRepoName :: RepoName+ , localRepoPath :: FilePath+ , localRepoSharedCache :: Bool+ }+ deriving (Show, Eq, Ord, Generic)++instance Binary LocalRepo+instance Structured LocalRepo++-- | Note: doesn't parse 'localRepoSharedCache' field.+instance Parsec LocalRepo where+ parsec = do+ n <- parsec+ _ <- P.char ':'+ p <- P.munch1 (const True) -- restrict what can be a path?+ return (LocalRepo n p False)++instance Pretty LocalRepo where+ pretty (LocalRepo n p _) = pretty n <<>> Disp.colon <<>> Disp.text p++-- | Construct a partial 'LocalRepo' value to fold the field parser list over.+emptyLocalRepo :: RepoName -> LocalRepo+emptyLocalRepo name = LocalRepo name "" False++-- | Calculate a cache key for local-repo.+--+-- For remote repositories we just use name, but local repositories may+-- all be named "local", so we add a bit of `localRepoPath` into the+-- mix.+localRepoCacheKey :: LocalRepo -> String+localRepoCacheKey local = unRepoName (localRepoName local) ++ "-" ++ hashPart where+ hashPart+ = showHashValue $ truncateHash 8 $ hashValue+ $ LBS.fromStrict $ toUTF8BS $ localRepoPath local++-------------------------------------------------------------------------------+-- Any repository+-------------------------------------------------------------------------------++-- | Different kinds of repositories+--+-- NOTE: It is important that this type remains serializable.+data Repo+ -- | Local repository, without index.+ --+ -- https://github.com/haskell/cabal/issues/6359+ = RepoLocalNoIndex+ { repoLocal :: LocalRepo+ , repoLocalDir :: FilePath+ }++ -- | Standard (unsecured) remote repositores+ | RepoRemote {+ repoRemote :: RemoteRepo+ , repoLocalDir :: FilePath+ }++ -- | Secure repositories+ --+ -- Although this contains the same fields as 'RepoRemote', we use a separate+ -- constructor to avoid confusing the two.+ --+ -- Not all access to a secure repo goes through the hackage-security+ -- library currently; code paths that do not still make use of the+ -- 'repoRemote' and 'repoLocalDir' fields directly.+ | RepoSecure {+ repoRemote :: RemoteRepo+ , repoLocalDir :: FilePath+ }+ deriving (Show, Eq, Ord, Generic)++instance Binary Repo+instance Structured Repo++-- | Check if this is a remote repo+isRepoRemote :: Repo -> Bool+isRepoRemote RepoLocalNoIndex{} = False+isRepoRemote _ = True++-- | Extract @RemoteRepo@ from @Repo@ if remote.+maybeRepoRemote :: Repo -> Maybe RemoteRepo+maybeRepoRemote (RepoLocalNoIndex _ _localDir) = Nothing+maybeRepoRemote (RepoRemote r _localDir) = Just r+maybeRepoRemote (RepoSecure r _localDir) = Just r
+ cabal/cabal-install/Distribution/Client/Types/RepoName.hs view
@@ -0,0 +1,45 @@+{-# LANGUAGE DeriveGeneric #-}+module Distribution.Client.Types.RepoName (+ RepoName (..),+ unRepoName,+) where++import Distribution.Client.Compat.Prelude+import Prelude ()++import qualified Distribution.Compat.CharParsing as P+import qualified Text.PrettyPrint as Disp++-- $setup+-- >>> import Distribution.Parsec++-- | Repository name.+--+-- May be used as path segment.+--+newtype RepoName = RepoName String+ deriving (Show, Eq, Ord, Generic)++unRepoName :: RepoName -> String+unRepoName (RepoName n) = n++instance Binary RepoName+instance Structured RepoName+instance NFData RepoName++instance Pretty RepoName where+ pretty = Disp.text . unRepoName++-- |+--+-- >>> simpleParsec "hackage.haskell.org" :: Maybe RepoName+-- Just (RepoName "hackage.haskell.org")+--+-- >>> simpleParsec "0123" :: Maybe RepoName+-- Nothing+--+instance Parsec RepoName where+ parsec = RepoName <$> parser where+ parser = (:) <$> lead <*> rest+ lead = P.satisfy (\c -> isAlpha c || c == '_' || c == '-' || c == '.')+ rest = P.munch (\c -> isAlphaNum c || c == '_' || c == '-' || c == '.')
+ cabal/cabal-install/Distribution/Client/Types/SourcePackageDb.hs view
@@ -0,0 +1,23 @@+{-# LANGUAGE DeriveGeneric #-}+module Distribution.Client.Types.SourcePackageDb (+ SourcePackageDb (..),+) where++import Distribution.Client.Compat.Prelude+import Prelude ()++import Distribution.Types.PackageName (PackageName)+import Distribution.Types.VersionRange (VersionRange)++import Distribution.Client.Types.PackageLocation (UnresolvedSourcePackage)+import Distribution.Solver.Types.PackageIndex (PackageIndex)++-- | This is the information we get from a @00-index.tar.gz@ hackage index.+--+data SourcePackageDb = SourcePackageDb+ { packageIndex :: PackageIndex UnresolvedSourcePackage+ , packagePreferences :: Map PackageName VersionRange+ }+ deriving (Eq, Generic)++instance Binary SourcePackageDb
+ cabal/cabal-install/Distribution/Client/Types/SourceRepo.hs view
@@ -0,0 +1,108 @@+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE UndecidableInstances #-}+module Distribution.Client.Types.SourceRepo (+ SourceRepositoryPackage (..),+ SourceRepoList,+ SourceRepoMaybe,+ SourceRepoProxy,+ srpHoist,+ srpToProxy,+ srpFanOut,+ sourceRepositoryPackageGrammar,+) where++import Distribution.Client.Compat.Prelude+import Distribution.Compat.Lens (Lens, Lens')+import Prelude ()++import Distribution.FieldGrammar+import Distribution.Types.SourceRepo (RepoType (..))++-- | @source-repository-package@ definition+--+data SourceRepositoryPackage f = SourceRepositoryPackage+ { srpType :: !RepoType+ , srpLocation :: !String+ , srpTag :: !(Maybe String)+ , srpBranch :: !(Maybe String)+ , srpSubdir :: !(f FilePath)+ }+ deriving (Generic)++deriving instance (Eq (f FilePath)) => Eq (SourceRepositoryPackage f)+deriving instance (Ord (f FilePath)) => Ord (SourceRepositoryPackage f)+deriving instance (Show (f FilePath)) => Show (SourceRepositoryPackage f)+deriving instance (Binary (f FilePath)) => Binary (SourceRepositoryPackage f)+deriving instance (Typeable f, Structured (f FilePath)) => Structured (SourceRepositoryPackage f)++-- | Read from @cabal.project@+type SourceRepoList = SourceRepositoryPackage []++-- | Distilled from 'Distribution.Types.SourceRepo.SourceRepo'+type SourceRepoMaybe = SourceRepositoryPackage Maybe++-- | 'SourceRepositoryPackage' without subdir. Used in clone errors. Cloning doesn't care about subdirectory.+type SourceRepoProxy = SourceRepositoryPackage Proxy++srpHoist :: (forall x. f x -> g x) -> SourceRepositoryPackage f -> SourceRepositoryPackage g+srpHoist nt s = s { srpSubdir = nt (srpSubdir s) }++srpToProxy :: SourceRepositoryPackage f -> SourceRepositoryPackage Proxy+srpToProxy s = s { srpSubdir = Proxy }++-- | Split single @source-repository-package@ declaration with multiple subdirs,+-- into multiple ones with at most single subdir.+srpFanOut :: SourceRepositoryPackage [] -> NonEmpty (SourceRepositoryPackage Maybe)+srpFanOut s@SourceRepositoryPackage { srpSubdir = [] } =+ s { srpSubdir = Nothing } :| []+srpFanOut s@SourceRepositoryPackage { srpSubdir = d:ds } = f d :| map f ds where+ f subdir = s { srpSubdir = Just subdir }++-------------------------------------------------------------------------------+-- Lens+-------------------------------------------------------------------------------++srpTypeLens :: Lens' (SourceRepositoryPackage f) RepoType+srpTypeLens f s = fmap (\x -> s { srpType = x }) (f (srpType s))+{-# INLINE srpTypeLens #-}++srpLocationLens :: Lens' (SourceRepositoryPackage f) String+srpLocationLens f s = fmap (\x -> s { srpLocation = x }) (f (srpLocation s))+{-# INLINE srpLocationLens #-}++srpTagLens :: Lens' (SourceRepositoryPackage f) (Maybe String)+srpTagLens f s = fmap (\x -> s { srpTag = x }) (f (srpTag s))+{-# INLINE srpTagLens #-}++srpBranchLens :: Lens' (SourceRepositoryPackage f) (Maybe String)+srpBranchLens f s = fmap (\x -> s { srpBranch = x }) (f (srpBranch s))+{-# INLINE srpBranchLens #-}++srpSubdirLens :: Lens (SourceRepositoryPackage f) (SourceRepositoryPackage g) (f FilePath) (g FilePath)+srpSubdirLens f s = fmap (\x -> s { srpSubdir = x }) (f (srpSubdir s))+{-# INLINE srpSubdirLens #-}++-------------------------------------------------------------------------------+-- Parser & PPrinter+-------------------------------------------------------------------------------++sourceRepositoryPackageGrammar+ :: ( FieldGrammar c g, Applicative (g SourceRepoList)+ , c (Identity RepoType)+ , c (List NoCommaFSep FilePathNT String)+ )+ => g SourceRepoList SourceRepoList+sourceRepositoryPackageGrammar = SourceRepositoryPackage+ <$> uniqueField "type" srpTypeLens+ <*> uniqueFieldAla "location" Token srpLocationLens+ <*> optionalFieldAla "tag" Token srpTagLens+ <*> optionalFieldAla "branch" Token srpBranchLens+ <*> monoidalFieldAla "subdir" (alaList' NoCommaFSep FilePathNT) srpSubdirLens -- note: NoCommaFSep is somewhat important for roundtrip, as "." is there...+{-# SPECIALIZE sourceRepositoryPackageGrammar :: ParsecFieldGrammar' SourceRepoList #-}+{-# SPECIALIZE sourceRepositoryPackageGrammar :: PrettyFieldGrammar' SourceRepoList #-}
+ cabal/cabal-install/Distribution/Client/Types/WriteGhcEnvironmentFilesPolicy.hs view
@@ -0,0 +1,20 @@+{-# LANGUAGE DeriveGeneric #-}+module Distribution.Client.Types.WriteGhcEnvironmentFilesPolicy (+ WriteGhcEnvironmentFilesPolicy (..),+) where++import Prelude ()+import Distribution.Client.Compat.Prelude++-- | Whether 'v2-build' should write a .ghc.environment file after+-- success. Possible values: 'always', 'never' (the default), 'ghc8.4.4+'+-- (8.4.4 is the earliest version that supports+-- '-package-env -').+data WriteGhcEnvironmentFilesPolicy+ = AlwaysWriteGhcEnvironmentFiles+ | NeverWriteGhcEnvironmentFiles+ | WriteGhcEnvironmentFilesOnlyForGhc844AndNewer+ deriving (Eq, Enum, Bounded, Generic, Show)++instance Binary WriteGhcEnvironmentFilesPolicy+instance Structured WriteGhcEnvironmentFilesPolicy
cabal/cabal-install/Distribution/Client/Update.hs view
@@ -15,17 +15,21 @@ ( update ) where +import Distribution.Client.Compat.Prelude+import Prelude ()+ import Distribution.Simple.Setup ( fromFlag ) import Distribution.Client.Compat.Directory ( setModificationTime ) import Distribution.Client.Types- ( Repo(..), RemoteRepo(..), maybeRepoRemote )+ ( Repo(..), RepoName (..), RemoteRepo(..), maybeRepoRemote, unRepoName ) import Distribution.Client.HttpUtils ( DownloadResult(..) ) import Distribution.Client.FetchUtils ( downloadIndex ) import Distribution.Client.IndexUtils.Timestamp+import Distribution.Client.IndexUtils.IndexState import Distribution.Client.IndexUtils ( updateRepoIndexCache, Index(..), writeIndexTimestamp , currentIndexTimestamp, indexBaseName )@@ -33,9 +37,7 @@ ( newParallelJobControl, spawnJob, collectJob ) import Distribution.Client.Setup ( RepoContext(..), UpdateFlags(..) )-import Distribution.Deprecated.Text- ( display )-import Distribution.Verbosity+import Distribution.Verbosity (lessVerbose) import Distribution.Simple.Utils ( writeFileAtomic, warn, notice, noticeNoWrap )@@ -43,9 +45,7 @@ import qualified Data.ByteString.Lazy as BS import Distribution.Client.GZipUtils (maybeDecompress) import System.FilePath ((<.>), dropExtension)-import Data.Maybe (mapMaybe) import Data.Time (getCurrentTime)-import Control.Monad import qualified Hackage.Security.Client as Sec @@ -61,19 +61,19 @@ [] -> return () [remoteRepo] -> notice verbosity $ "Downloading the latest package list from "- ++ remoteRepoName remoteRepo+ ++ unRepoName (remoteRepoName remoteRepo) _ -> notice verbosity . unlines $ "Downloading the latest package lists from: "- : map (("- " ++) . remoteRepoName) remoteRepos+ : map (("- " ++) . unRepoName . remoteRepoName) remoteRepos jobCtrl <- newParallelJobControl (length repos)- mapM_ (spawnJob jobCtrl . updateRepo verbosity updateFlags repoCtxt) repos- mapM_ (\_ -> collectJob jobCtrl) repos+ traverse_ (spawnJob jobCtrl . updateRepo verbosity updateFlags repoCtxt) repos+ traverse_ (\_ -> collectJob jobCtrl) repos updateRepo :: Verbosity -> UpdateFlags -> RepoContext -> Repo -> IO () updateRepo verbosity updateFlags repoCtxt repo = do transport <- repoContextGetTransport repoCtxt case repo of- RepoLocal{..} -> return ()+ RepoLocalNoIndex{} -> return () RepoRemote{..} -> do downloadResult <- downloadIndex transport verbosity repoRemote repoLocalDir case downloadResult of@@ -83,13 +83,20 @@ writeFileAtomic (dropExtension indexPath) . maybeDecompress =<< BS.readFile indexPath updateRepoIndexCache verbosity (RepoIndex repoCtxt repo)- RepoSecure{} -> repoContextWithSecureRepo repoCtxt repo $ \repoSecure -> do+ RepoSecure remote _ -> repoContextWithSecureRepo repoCtxt repo $ \repoSecure -> do let index = RepoIndex repoCtxt repo -- NB: This may be a nullTimestamp if we've never updated before current_ts <- currentIndexTimestamp (lessVerbose verbosity) repoCtxt repo+ -- NB: always update the timestamp, even if we didn't actually -- download anything- writeIndexTimestamp index (fromFlag (updateIndexState updateFlags))+ let rname :: RepoName+ rname = remoteRepoName remote++ let repoIndexState :: RepoIndexState+ repoIndexState = lookupIndexState rname (fromFlag (updateIndexState updateFlags))+ writeIndexTimestamp index repoIndexState+ ce <- if repoContextIgnoreExpiry repoCtxt then Just `fmap` getCurrentTime else return Nothing@@ -107,4 +114,4 @@ when (current_ts /= nullTimestamp) $ noticeNoWrap verbosity $ "To revert to previous state run:\n" ++- " cabal update --index-state='" ++ display current_ts ++ "'\n"+ " cabal update --index-state='" ++ prettyShow current_ts ++ "'\n"
cabal/cabal-install/Distribution/Client/Upload.hs view
@@ -1,18 +1,21 @@ module Distribution.Client.Upload (upload, uploadDoc, report) where -import Distribution.Client.Types ( Username(..), Password(..)- , RemoteRepo(..), maybeRepoRemote )+import Distribution.Client.Compat.Prelude+import qualified Prelude as Unsafe (tail, head, read)++import Distribution.Client.Types.Credentials ( Username(..), Password(..) )+import Distribution.Client.Types.Repo (RemoteRepo(..), maybeRepoRemote)+import Distribution.Client.Types.RepoName (unRepoName) import Distribution.Client.HttpUtils ( HttpTransport(..), remoteRepoTryUpgradeToHttps ) import Distribution.Client.Setup ( IsCandidate(..), RepoContext(..) ) -import Distribution.Simple.Utils (notice, warn, info, die')-import Distribution.Verbosity (Verbosity)-import Distribution.Deprecated.Text (display)+import Distribution.Simple.Utils (notice, warn, info, die', toUTF8BS) import Distribution.Client.Config import qualified Distribution.Client.BuildReports.Anonymous as BuildReport+import Distribution.Client.BuildReports.Anonymous (parseBuildReport) import qualified Distribution.Client.BuildReports.Upload as BuildReport import Network.URI (URI(uriPath, uriAuthority), URIAuth(uriRegName))@@ -20,13 +23,9 @@ import System.IO (hFlush, stdout) import System.IO.Echo (withoutInputEcho)-import System.Exit (exitFailure) import System.FilePath ((</>), takeExtension, takeFileName, dropExtension) import qualified System.FilePath.Posix as FilePath.Posix ((</>)) import System.Directory-import Control.Monad (forM_, when, foldM)-import Data.Maybe (mapMaybe)-import Data.Char (isSpace) type Auth = Maybe (String, String) @@ -50,7 +49,7 @@ targetRepo <- case [ remoteRepo | Just remoteRepo <- map maybeRepoRemote repos ] of [] -> die' verbosity "Cannot upload. No remote repositories are configured."- rs -> remoteRepoTryUpgradeToHttps verbosity transport (last rs)+ (r:rs) -> remoteRepoTryUpgradeToHttps verbosity transport (last (r:|rs)) let targetRepoURI = remoteRepoURI targetRepo domain = maybe "Hackage" uriRegName $ uriAuthority targetRepoURI rootIfEmpty x = if null x then "/" else x@@ -72,7 +71,7 @@ Username username <- maybe (promptUsername domain) return mUsername Password password <- maybe (promptPassword domain) return mPassword let auth = Just (username,password)- forM_ paths $ \path -> do+ for_ paths $ \path -> do notice verbosity $ "Uploading " ++ path ++ "... " case fmap takeFileName (stripExtensions ["tar", "gz"] path) of Just pkgid -> handlePackage transport verbosity uploadURI@@ -90,7 +89,7 @@ targetRepo <- case [ remoteRepo | Just remoteRepo <- map maybeRepoRemote repos ] of [] -> die' verbosity $ "Cannot upload. No remote repositories are configured."- rs -> remoteRepoTryUpgradeToHttps verbosity transport (last rs)+ (r:rs) -> remoteRepoTryUpgradeToHttps verbosity transport (last (r:|rs)) let targetRepoURI = remoteRepoURI targetRepo domain = maybe "Hackage" uriRegName $ uriAuthority targetRepoURI rootIfEmpty x = if null x then "/" else x@@ -115,9 +114,9 @@ } (reverseSuffix, reversePkgid) = break (== '-') (reverse (takeFileName path))- pkgid = reverse $ tail reversePkgid+ pkgid = reverse $ Unsafe.tail reversePkgid when (reverse reverseSuffix /= "docs.tar.gz"- || null reversePkgid || head reversePkgid /= '-') $+ || null reversePkgid || Unsafe.head reversePkgid /= '-') $ die' verbosity "Expected a file name matching the pattern <pkgid>-docs.tar.gz" Username username <- maybe (promptUsername domain) return mUsername Password password <- maybe (promptPassword domain) return mPassword@@ -170,27 +169,27 @@ report verbosity repoCtxt mUsername mPassword = do let repos = repoContextRepos repoCtxt remoteRepos = mapMaybe maybeRepoRemote repos- forM_ remoteRepos $ \remoteRepo -> do+ for_ remoteRepos $ \remoteRepo -> do let domain = maybe "Hackage" uriRegName $ uriAuthority (remoteRepoURI remoteRepo) Username username <- maybe (promptUsername domain) return mUsername Password password <- maybe (promptPassword domain) return mPassword let auth = (username, password) dotCabal <- getCabalDir- let srcDir = dotCabal </> "reports" </> remoteRepoName remoteRepo+ let srcDir = dotCabal </> "reports" </> unRepoName (remoteRepoName remoteRepo) -- We don't want to bomb out just because we haven't built any packages -- from this repo yet. srcExists <- doesDirectoryExist srcDir when srcExists $ do contents <- getDirectoryContents srcDir- forM_ (filter (\c -> takeExtension c ==".log") contents) $ \logFile ->+ for_ (filter (\c -> takeExtension c ==".log") contents) $ \logFile -> do inp <- readFile (srcDir </> logFile)- let (reportStr, buildLog) = read inp :: (String,String) -- TODO: eradicateNoParse- case BuildReport.parse reportStr of+ let (reportStr, buildLog) = Unsafe.read inp :: (String,String) -- TODO: eradicateNoParse+ case parseBuildReport (toUTF8BS reportStr) of Left errs -> warn verbosity $ "Errors: " ++ errs -- FIXME Right report' -> do info verbosity $ "Uploading report for "- ++ display (BuildReport.package report')+ ++ prettyShow (BuildReport.package report') BuildReport.uploadReports verbosity repoCtxt auth (remoteRepoURI remoteRepo) [(report', Just buildLog)] return ()
cabal/cabal-install/Distribution/Client/Utils.hs view
@@ -19,24 +19,24 @@ , tryFindPackageDesc , relaxEncodingErrors , ProgressPhase (..)- , progressMessage)+ , progressMessage+ , cabalInstallVersion) where import Prelude () import Distribution.Client.Compat.Prelude import Distribution.Compat.Environment-import Distribution.Compat.Exception ( catchIO )-import Distribution.Compat.Time ( getModTime )+import Distribution.Compat.Time ( getModTime ) import Distribution.Simple.Setup ( Flag(..) )-import Distribution.Verbosity+import Distribution.Version import Distribution.Simple.Utils ( die', findPackageDesc, noticeNoWrap ) import qualified Data.ByteString.Lazy as BS import Data.Bits ( (.|.), shiftL, shiftR ) import System.FilePath import Control.Monad- ( mapM, mapM_, zipWithM_ )+ ( zipWithM_ ) import Data.List ( groupBy ) import Foreign.C.Types ( CInt(..) )@@ -61,6 +61,10 @@ import qualified System.IO.Error as IOError #endif +#ifndef __DOCTEST__+import qualified Paths_cabal_install (version)+#endif+ -- | Generic merging utility. For sorted input lists this is a full outer join. -- mergeBy :: (a -> b -> Ordering) -> [a] -> [b] -> [MergeResult a b]@@ -143,8 +147,8 @@ -- environment is a process-global concept. withEnvOverrides :: [(String, Maybe FilePath)] -> IO a -> IO a withEnvOverrides overrides m = do- mb_olds <- mapM lookupEnv envVars- mapM_ (uncurry update) overrides+ mb_olds <- traverse lookupEnv envVars+ traverse_ (uncurry update) overrides m `Exception.finally` zipWithM_ update envVars mb_olds where envVars :: [String]@@ -356,3 +360,10 @@ ProgressHaddock -> "Haddock " ProgressInstalling -> "Installing " ProgressCompleted -> "Completed "++cabalInstallVersion :: Version+#ifdef __DOCTEST__+cabalInstallVersion = mkVersion [3,3]+#else+cabalInstallVersion = mkVersion' Paths_cabal_install.version+#endif
cabal/cabal-install/Distribution/Client/Utils/Assertion.hs view
@@ -1,9 +1,13 @@ {-# LANGUAGE CPP #-} module Distribution.Client.Utils.Assertion (expensiveAssert) where + #ifdef DEBUG_EXPENSIVE_ASSERTIONS+import Prelude (Bool) import Control.Exception (assert) import Distribution.Compat.Stack+#else+import Prelude (Bool, id) #endif -- | Like 'assert', but only enabled with -fdebug-expensive-assertions. This
cabal/cabal-install/Distribution/Client/Utils/Json.hs view
@@ -15,13 +15,10 @@ ) where -import Data.Char-import Data.Int-import Data.String-import Data.Word-import Data.List-import Data.Monoid+import Distribution.Client.Compat.Prelude +import Data.Char (intToDigit)+ import Data.ByteString.Builder (Builder) import qualified Data.ByteString.Builder as BB @@ -135,13 +132,13 @@ encodeArrayBB [] = "[]" encodeArrayBB jvs = BB.char8 '[' <> go jvs <> BB.char8 ']' where- go = Data.Monoid.mconcat . intersperse (BB.char8 ',') . map encodeValueBB+ go = mconcat . intersperse (BB.char8 ',') . map encodeValueBB encodeObjectBB :: Object -> Builder encodeObjectBB [] = "{}" encodeObjectBB jvs = BB.char8 '{' <> go jvs <> BB.char8 '}' where- go = Data.Monoid.mconcat . intersperse (BB.char8 ',') . map encPair+ go = mconcat . intersperse (BB.char8 ',') . map encPair encPair (l,x) = encodeStringBB l <> BB.char8 ':' <> encodeValueBB x encodeStringBB :: String -> Builder
cabal/cabal-install/Distribution/Client/VCS.hs view
@@ -28,18 +28,19 @@ vcsGit, vcsHg, vcsSvn,+ vcsPijul, ) where import Prelude () import Distribution.Client.Compat.Prelude import Distribution.Types.SourceRepo- ( RepoType(..) )-import Distribution.Client.SourceRepo (SourceRepoMaybe, SourceRepositoryPackage (..), srpToProxy)+ ( RepoType(..), KnownRepoType (..) )+import Distribution.Client.Types.SourceRepo (SourceRepoMaybe, SourceRepositoryPackage (..), srpToProxy) import Distribution.Client.RebuildMonad ( Rebuild, monitorFiles, MonitorFilePath, monitorDirectoryExistence ) import Distribution.Verbosity as Verbosity- ( Verbosity, normal )+ ( normal ) import Distribution.Simple.Program ( Program(programFindVersion) , ConfiguredProgram(programVersion)@@ -50,14 +51,10 @@ ( mkVersion ) import qualified Distribution.PackageDescription as PD -import Control.Monad- ( mapM_ ) import Control.Monad.Trans ( liftIO ) import qualified Data.Char as Char import qualified Data.Map as Map-import Data.Either- ( partitionEithers ) import System.FilePath ( takeDirectory ) import System.Directory@@ -186,7 +183,7 @@ -> IO () cloneSourceRepo verbosity vcs repo@SourceRepositoryPackage{ srpLocation = srcuri } destdir =- mapM_ (runProgramInvocation verbosity) invocations+ traverse_ (runProgramInvocation verbosity) invocations where invocations = vcsCloneRepo vcs verbosity (vcsProgram vcs) repo@@ -234,7 +231,7 @@ vcsBzr :: VCS Program vcsBzr = VCS {- vcsRepoType = Bazaar,+ vcsRepoType = KnownRepoType Bazaar, vcsProgram = bzrProgram, vcsCloneRepo, vcsSyncRepos@@ -280,7 +277,7 @@ vcsDarcs :: VCS Program vcsDarcs = VCS {- vcsRepoType = Darcs,+ vcsRepoType = KnownRepoType Darcs, vcsProgram = darcsProgram, vcsCloneRepo, vcsSyncRepos@@ -325,7 +322,7 @@ vcsGit :: VCS Program vcsGit = VCS {- vcsRepoType = Git,+ vcsRepoType = KnownRepoType Git, vcsProgram = gitProgram, vcsCloneRepo, vcsSyncRepos@@ -418,7 +415,7 @@ vcsHg :: VCS Program vcsHg = VCS {- vcsRepoType = Mercurial,+ vcsRepoType = KnownRepoType Mercurial, vcsProgram = hgProgram, vcsCloneRepo, vcsSyncRepos@@ -464,7 +461,7 @@ vcsSvn :: VCS Program vcsSvn = VCS {- vcsRepoType = SVN,+ vcsRepoType = KnownRepoType SVN, vcsProgram = svnProgram, vcsCloneRepo, vcsSyncRepos@@ -498,3 +495,147 @@ _ -> "" } ++-- | VCS driver for Pijul.+-- Documentation for Pijul can be found at <https://pijul.org/manual/introduction.html>+--+-- 2020-04-09 Oleg:+--+-- As far as I understand pijul, there are branches and "tags" in pijul,+-- but there aren't a "commit hash" identifying an arbitrary state.+--+-- One can create `a pijul tag`, which will make a patch hash,+-- which depends on everything currently in the repository.+-- I guess if you try to apply that patch, you'll be forced to apply+-- all the dependencies too. In other words, there are no named tags.+--+-- It's not clear to me whether there is an option to+-- "apply this patch *and* all of its dependencies".+-- And relatedly, whether how to make sure that there are no other+-- patches applied.+--+-- With branches it's easier, as you can `pull` and `checkout` them,+-- and they seem to be similar enough. Yet, pijul documentations says+--+-- > Note that the purpose of branches in Pijul is quite different from Git,+-- since Git's "feature branches" can usually be implemented by just+-- patches.+--+-- I guess it means that indeed instead of creating a branch and making PR+-- in "GitHub" workflow, you'd just create a patch and offer it.+-- You can do that with `git` too. Push (a branch with) commit to remote+-- and ask other to cherry-pick that commit. Yet, in git identity of commit+-- changes when it applied to other trees, where patches in pijul have+-- will continue to have the same hash.+--+-- Unfortunately pijul doesn't talk about conflict resolution.+-- It seems that you get something like:+--+-- % pijul status+-- On branch merge+--+-- Unresolved conflicts:+-- (fix conflicts and record the resolution with "pijul record ...")+--+-- foo+--+-- % cat foo+-- first line+-- >> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>+-- branch BBB+-- ================================+-- branch AAA+-- <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+-- last line+--+-- And then the `pijul dependencies` would draw you a graph like+--+--+-- -----> foo on branch B ----->+-- resolve confict Initial patch+-- -----> foo on branch A ----->+--+-- Which is seems reasonable.+--+-- So currently, pijul support is very experimental, and most likely+-- won't work, even the basics are in place. Tests are also written+-- but disabled, as the branching model differs from `git` one,+-- for which tests are written.+--+vcsPijul :: VCS Program+vcsPijul =+ VCS {+ vcsRepoType = KnownRepoType Pijul,+ vcsProgram = pijulProgram,+ vcsCloneRepo,+ vcsSyncRepos+ }+ where+ vcsCloneRepo :: Verbosity -- ^ it seems that pijul does not have verbose flag+ -> ConfiguredProgram+ -> SourceRepositoryPackage f+ -> FilePath+ -> FilePath+ -> [ProgramInvocation]+ vcsCloneRepo _verbosity prog repo srcuri destdir =+ [ programInvocation prog cloneArgs ]+ -- And if there's a tag, we have to do that in a second step:+ ++ [ (programInvocation prog (checkoutArgs tag)) {+ progInvokeCwd = Just destdir+ }+ | tag <- maybeToList (srpTag repo) ]+ where+ cloneArgs = ["clone", srcuri, destdir]+ ++ branchArgs+ branchArgs = case srpBranch repo of+ Just b -> ["--from-branch", b]+ Nothing -> []+ checkoutArgs tag = "checkout" : [tag] -- TODO: this probably doesn't work either++ vcsSyncRepos :: Verbosity+ -> ConfiguredProgram+ -> [(SourceRepositoryPackage f, FilePath)]+ -> IO [MonitorFilePath]+ vcsSyncRepos _ _ [] = return []+ vcsSyncRepos verbosity pijulProg+ ((primaryRepo, primaryLocalDir) : secondaryRepos) = do++ vcsSyncRepo verbosity pijulProg primaryRepo primaryLocalDir Nothing+ sequence_+ [ vcsSyncRepo verbosity pijulProg repo localDir (Just primaryLocalDir)+ | (repo, localDir) <- secondaryRepos ]+ return [ monitorDirectoryExistence dir+ | dir <- (primaryLocalDir : map snd secondaryRepos) ]++ vcsSyncRepo verbosity pijulProg SourceRepositoryPackage{..} localDir peer = do+ exists <- doesDirectoryExist localDir+ if exists+ then pijul localDir ["pull"] -- TODO: this probably doesn't work.+ else pijul (takeDirectory localDir) cloneArgs+ pijul localDir checkoutArgs+ where+ pijul :: FilePath -> [String] -> IO ()+ pijul cwd args = runProgramInvocation verbosity $+ (programInvocation pijulProg args) {+ progInvokeCwd = Just cwd+ }++ cloneArgs = ["clone", loc, localDir]+ ++ case peer of+ Nothing -> []+ Just peerLocalDir -> [peerLocalDir]+ where loc = srpLocation+ checkoutArgs = "checkout" : ["--force", checkoutTarget, "--" ]+ checkoutTarget = fromMaybe "HEAD" (srpBranch `mplus` srpTag) -- TODO: this is definitely wrong.++pijulProgram :: Program+pijulProgram = (simpleProgram "pijul") {+ programFindVersion = findProgramVersion "--version" $ \str ->+ case words str of+ -- "pijul 0.12.2+ (_:ver:_) | all isTypical ver -> ver+ _ -> ""+ }+ where+ isNum c = c >= '0' && c <= '9'+ isTypical c = isNum c || c == '.'
cabal/cabal-install/Distribution/Client/Win32SelfUpgrade.hs view
@@ -42,6 +42,9 @@ deleteOldExeFile, ) where +import Distribution.Client.Compat.Prelude hiding (log)+import Prelude ()+ #ifdef mingw32_HOST_OS import qualified System.Win32 as Win32@@ -51,10 +54,9 @@ import System.Directory (canonicalizePath) import System.FilePath (takeBaseName, replaceBaseName, equalFilePath) -import Distribution.Verbosity as Verbosity (Verbosity, showForCabal)+import Distribution.Verbosity as Verbosity (showForCabal) import Distribution.Simple.Utils (debug, info) -import Prelude hiding (log) -- | If one of the given files is our own exe file then we arrange things such -- that the nested action can replace our own exe file.@@ -68,7 +70,7 @@ possibleSelfUpgrade verbosity newPaths action = do dstPath <- canonicalizePath =<< Win32.getModuleFileName Win32.nullHANDLE - newPaths' <- mapM canonicalizePath newPaths+ newPaths' <- traverse canonicalizePath newPaths let doingSelfUpgrade = any (equalFilePath dstPath) newPaths' if not doingSelfUpgrade@@ -211,7 +213,6 @@ #else -import Distribution.Verbosity (Verbosity) import Distribution.Simple.Utils (die') possibleSelfUpgrade :: Verbosity
cabal/cabal-install/Distribution/Client/World.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE DeriveGeneric #-} ----------------------------------------------------------------------------- -- | -- Module : Distribution.Client.World@@ -33,22 +34,14 @@ import Distribution.Client.Compat.Prelude hiding (getContents) import Distribution.Types.Dependency-import Distribution.PackageDescription- ( FlagAssignment, mkFlagAssignment, unFlagAssignment- , mkFlagName, unFlagName )-import Distribution.Verbosity- ( Verbosity )+import Distribution.Types.Flag+ ( FlagAssignment, unFlagAssignment+ , unFlagName, parsecFlagAssignmentNonEmpty ) import Distribution.Simple.Utils ( die', info, chattyTry, writeFileAtomic )-import Distribution.Deprecated.Text- ( Text(..), display, simpleParse )-import qualified Distribution.Deprecated.ReadP as Parse-import Distribution.Compat.Exception ( catchIO )+import qualified Distribution.Compat.CharParsing as P import qualified Text.PrettyPrint as Disp --import Data.Char as Char- import Data.List ( unionBy, deleteFirstsBy ) import System.IO.Error@@ -57,7 +50,7 @@ data WorldPkgInfo = WorldPkgInfo Dependency FlagAssignment- deriving (Show,Eq)+ deriving (Show,Eq, Generic) -- | Adds packages to the world file; creates the file if it doesn't -- exist yet. Version constraints and flag assignments for a package are@@ -102,7 +95,7 @@ then do info verbosity "Updating world file..." writeFileAtomic world . B.pack $ unlines- [ (display pkg) | pkg <- pkgsNewWorld]+ [ (prettyShow pkg) | pkg <- pkgsNewWorld] else info verbosity "World file is already up to date." @@ -111,7 +104,7 @@ getContents :: Verbosity -> FilePath -> IO [WorldPkgInfo] getContents verbosity world = do content <- safelyReadFile world- let result = map simpleParse (lines $ B.unpack content)+ let result = map simpleParsec (lines $ B.unpack content) case sequence result of Nothing -> die' verbosity "Could not parse world file." Just xs -> return xs@@ -123,51 +116,29 @@ | otherwise = ioError e -instance Text WorldPkgInfo where- disp (WorldPkgInfo dep flags) = disp dep Disp.<+> dispFlags (unFlagAssignment flags)+instance Pretty WorldPkgInfo where+ pretty (WorldPkgInfo dep flags) = pretty dep Disp.<+> dispFlags (unFlagAssignment flags) where dispFlags [] = Disp.empty dispFlags fs = Disp.text "--flags=" <<>> Disp.doubleQuotes (flagAssToDoc fs) flagAssToDoc = foldr (\(fname,val) flagAssDoc -> (if not val then Disp.char '-'- else Disp.empty)+ else Disp.char '+') <<>> Disp.text (unFlagName fname) Disp.<+> flagAssDoc) Disp.empty- parse = do- dep <- parse- Parse.skipSpaces- flagAss <- Parse.option mempty parseFlagAssignment++instance Parsec WorldPkgInfo where+ parsec = do+ dep <- parsec+ P.spaces+ flagAss <- P.option mempty parseFlagAssignment return $ WorldPkgInfo dep flagAss where- parseFlagAssignment :: Parse.ReadP r FlagAssignment+ parseFlagAssignment :: CabalParsing m => m FlagAssignment parseFlagAssignment = do- _ <- Parse.string "--flags"- Parse.skipSpaces- _ <- Parse.char '='- Parse.skipSpaces- mkFlagAssignment <$> (inDoubleQuotes $ Parse.many1 flag)+ _ <- P.string "--flags="+ inDoubleQuotes parsecFlagAssignmentNonEmpty where- inDoubleQuotes :: Parse.ReadP r a -> Parse.ReadP r a- inDoubleQuotes = Parse.between (Parse.char '"') (Parse.char '"')-- flag = do- Parse.skipSpaces- val <- negative Parse.+++ positive- name <- ident- Parse.skipSpaces- return (mkFlagName name,val)- negative = do- _ <- Parse.char '-'- return False- positive = return True-- ident :: Parse.ReadP r String- ident = do- -- First character must be a letter/digit to avoid flags- -- like "+-debug":- c <- Parse.satisfy Char.isAlphaNum- cs <- Parse.munch (\ch -> Char.isAlphaNum ch || ch == '_'- || ch == '-')- return (c:cs)+ inDoubleQuotes = P.between (P.char '"') (P.char '"')
cabal/cabal-install/Distribution/Deprecated/ParseUtils.hs view
@@ -23,50 +23,41 @@ {-# LANGUAGE Rank2Types #-} module Distribution.Deprecated.ParseUtils ( LineNo, PError(..), PWarning(..), locatedErrorMsg, syntaxError, warning,- runP, runE, ParseResult(..), catchParseError, parseFail, showPWarning,- Field(..), fName, lineNo,- FieldDescr(..), ppField, ppFields, readFields, readFieldsFlat,- showFields, showSingleNamedField, showSimpleSingleNamedField,- parseFields, parseFieldsFlat,- parseHaskellString, parseFilePathQ, parseTokenQ, parseTokenQ',- parseModuleNameQ,- parseFlagAssignment,- parseOptVersion, parsePackageName,- parseSepList, parseCommaList, parseOptCommaList,- showFilePath, showToken, showTestedWith, showFreeText, parseFreeText,+ runP, runE, ParseResult(..), parseFail, showPWarning,+ Field(..), lineNo,+ FieldDescr(..), readFields, readFieldsFlat,+ parseHaskellString, parseFilePathQ, parseTokenQ,+ parseOptCommaList,+ showFilePath, showToken, showFreeText, field, simpleField, listField, listFieldWithSep, spaceListField,- commaListField, commaListFieldWithSep, commaNewLineListField, newLineListField,- optsField, liftField, boolField, parseQuoted, parseMaybeQuoted,+ newLineListField,+ liftField, readPToMaybe, - UnrecFieldParser, warnUnrec, ignoreUnrec,+ fieldParsec, simpleFieldParsec,+ listFieldParsec,+ commaListFieldParsec,+ commaNewLineListFieldParsec,++ UnrecFieldParser, ) where import Distribution.Client.Compat.Prelude hiding (get) import Prelude () import Distribution.Deprecated.ReadP as ReadP hiding (get)-import Distribution.Deprecated.Text -import Distribution.Compat.Newtype-import Distribution.Compiler-import Distribution.ModuleName-import Distribution.Parsec.Newtypes (TestedWith (..)) import Distribution.Pretty import Distribution.ReadE import Distribution.Utils.Generic-import Distribution.Version-import Distribution.PackageDescription (FlagAssignment, mkFlagAssignment) import Data.Tree as Tree (Tree (..), flatten) import System.FilePath (normalise)-import Text.PrettyPrint- (Doc, Mode (..), colon, comma, fsep, hsep, isEmpty, mode, nest, punctuate, render,- renderStyle, sep, style, text, vcat, ($+$), (<+>))+import Text.PrettyPrint (Doc, punctuate, comma, fsep, sep) import qualified Text.Read as Read-import qualified Data.Map as Map import qualified Control.Monad.Fail as Fail+import Distribution.Parsec (ParsecParser, parsecLeadingCommaList, parsecLeadingOptCommaList) -- ----------------------------------------------------------------------------- @@ -120,12 +111,6 @@ parseResultFail :: String -> ParseResult a parseResultFail s = parseFail (FromString s Nothing) --catchParseError :: ParseResult a -> (PError -> ParseResult a)- -> ParseResult a-p@(ParseOk _ _) `catchParseError` _ = p-ParseFailed e `catchParseError` k = k e- parseFail :: PError -> ParseResult a parseFail = ParseFailed @@ -188,6 +173,12 @@ field name showF readF = FieldDescr name showF (\line val _st -> runP line name readF val) +fieldParsec :: String -> (a -> Doc) -> ParsecParser a -> FieldDescr a+fieldParsec name showF readF =+ FieldDescr name showF $ \line val _st -> case explicitEitherParsec readF val of+ Left err -> ParseFailed (FromString err (Just line))+ Right x -> ParseOk [] x+ -- Lift a field descriptor storing into an 'a' to a field descriptor storing -- into a 'b'. liftField :: (b -> a) -> (a -> b -> b) -> FieldDescr a -> FieldDescr b@@ -205,22 +196,28 @@ simpleField name showF readF get set = liftField get set $ field name showF readF -commaListFieldWithSep :: Separator -> String -> (a -> Doc) -> ReadP [a] a+simpleFieldParsec :: String -> (a -> Doc) -> ParsecParser a+ -> (b -> a) -> (a -> b -> b) -> FieldDescr b+simpleFieldParsec name showF readF get set+ = liftField get set $ fieldParsec name showF readF++commaListFieldWithSepParsec :: Separator -> String -> (a -> Doc) -> ParsecParser a -> (b -> [a]) -> ([a] -> b -> b) -> FieldDescr b-commaListFieldWithSep separator name showF readF get set =+commaListFieldWithSepParsec separator name showF readF get set = liftField get set' $- field name showF' (parseCommaList readF)+ fieldParsec name showF' (parsecLeadingCommaList readF) where set' xs b = set (get b ++ xs) b showF' = separator . punctuate comma . map showF -commaListField :: String -> (a -> Doc) -> ReadP [a] a+commaListFieldParsec :: String -> (a -> Doc) -> ParsecParser a -> (b -> [a]) -> ([a] -> b -> b) -> FieldDescr b-commaListField = commaListFieldWithSep fsep+commaListFieldParsec = commaListFieldWithSepParsec fsep -commaNewLineListField :: String -> (a -> Doc) -> ReadP [a] a- -> (b -> [a]) -> ([a] -> b -> b) -> FieldDescr b-commaNewLineListField = commaListFieldWithSep sep+commaNewLineListFieldParsec+ :: String -> (a -> Doc) -> ParsecParser a+ -> (b -> [a]) -> ([a] -> b -> b) -> FieldDescr b+commaNewLineListFieldParsec = commaListFieldWithSepParsec sep spaceListField :: String -> (a -> Doc) -> ReadP [a] a -> (b -> [a]) -> ([a] -> b -> b) -> FieldDescr b@@ -246,83 +243,23 @@ set' xs b = set (get b ++ xs) b showF' = separator . map showF +listFieldWithSepParsec :: Separator -> String -> (a -> Doc) -> ParsecParser a+ -> (b -> [a]) -> ([a] -> b -> b) -> FieldDescr b+listFieldWithSepParsec separator name showF readF get set =+ liftField get set' $+ fieldParsec name showF' (parsecLeadingOptCommaList readF)+ where+ set' xs b = set (get b ++ xs) b+ showF' = separator . map showF+ listField :: String -> (a -> Doc) -> ReadP [a] a -> (b -> [a]) -> ([a] -> b -> b) -> FieldDescr b listField = listFieldWithSep fsep -optsField :: String -> CompilerFlavor -> (b -> [(CompilerFlavor,[String])])- -> ([(CompilerFlavor,[String])] -> b -> b) -> FieldDescr b-optsField name flavor get set =- liftField (fromMaybe [] . lookup flavor . get)- (\opts b -> set (reorder (update flavor opts (get b))) b) $- field name showF (sepBy parseTokenQ' (munch1 isSpace))- where- update _ opts l | all null opts = l --empty opts as if no opts- update f opts [] = [(f,opts)]- update f opts ((f',opts'):rest)- | f == f' = (f, opts' ++ opts) : rest- | otherwise = (f',opts') : update f opts rest- reorder = sortBy (comparing fst)- showF = hsep . map text---- TODO: this is a bit smelly hack. It's because we want to parse bool fields--- liberally but not accept new parses. We cannot do that with ReadP--- because it does not support warnings. We need a new parser framework!-boolField :: String -> (b -> Bool) -> (Bool -> b -> b) -> FieldDescr b-boolField name get set = liftField get set (FieldDescr name showF readF)- where- showF = text . show- readF line str _- | str == "True" = ParseOk [] True- | str == "False" = ParseOk [] False- | lstr == "true" = ParseOk [caseWarning] True- | lstr == "false" = ParseOk [caseWarning] False- | otherwise = ParseFailed (NoParse name line)- where- lstr = lowercase str- caseWarning = PWarning $- "The '" ++ name ++ "' field is case sensitive, use 'True' or 'False'."--ppFields :: [FieldDescr a] -> a -> Doc-ppFields fields x =- vcat [ ppField name (getter x) | FieldDescr name getter _ <- fields ]-showFields :: [FieldDescr a] -> a -> String-showFields fields = render . ($+$ text "") . ppFields fields--showSingleNamedField :: [FieldDescr a] -> String -> Maybe (a -> String)-showSingleNamedField fields f =- case [ get | (FieldDescr f' get _) <- fields, f' == f ] of- [] -> Nothing- (get:_) -> Just (render . ppField f . get)--showSimpleSingleNamedField :: [FieldDescr a] -> String -> Maybe (a -> String)-showSimpleSingleNamedField fields f =- case [ get | (FieldDescr f' get _) <- fields, f' == f ] of- [] -> Nothing- (get:_) -> Just (renderStyle myStyle . get)- where myStyle = style { mode = LeftMode }--parseFields :: [FieldDescr a] -> a -> String -> ParseResult a-parseFields fields initial str =- readFields str >>= accumFields fields initial--parseFieldsFlat :: [FieldDescr a] -> a -> String -> ParseResult a-parseFieldsFlat fields initial str =- readFieldsFlat str >>= accumFields fields initial--accumFields :: [FieldDescr a] -> a -> [Field] -> ParseResult a-accumFields fields = foldM setField- where- fieldMap = Map.fromList- [ (name, f) | f@(FieldDescr name _ _) <- fields ]- setField accum (F line name value) = case Map.lookup name fieldMap of- Just (FieldDescr _ _ set) -> set line value accum- Nothing -> do- warning ("Unrecognized field " ++ name ++ " on line " ++ show line)- return accum- setField accum f = do- warning ("Unrecognized stanza on line " ++ show (lineNo f))- return accum+listFieldParsec+ :: String -> (a -> Doc) -> ParsecParser a+ -> (b -> [a]) -> ([a] -> b -> b) -> FieldDescr b+listFieldParsec = listFieldWithSepParsec fsep -- | The type of a function which, given a name-value pair of an -- unrecognized field, and the current structure being built,@@ -331,17 +268,6 @@ -- of the structure being built), or not (by returning Nothing). type UnrecFieldParser a = (String,String) -> a -> Maybe a --- | A default unrecognized field parser which simply returns Nothing,--- i.e. ignores all unrecognized fields, so warnings will be generated.-warnUnrec :: UnrecFieldParser a-warnUnrec _ _ = Nothing---- | A default unrecognized field parser which silently (i.e. no--- warnings will be generated) ignores unrecognized fields, by--- returning the structure being built unmodified.-ignoreUnrec :: UnrecFieldParser a-ignoreUnrec _ = Just- ------------------------------------------------------------------------------ -- The data type for our three syntactic categories@@ -375,11 +301,6 @@ lineNo (Section n _ _ _) = n lineNo (IfBlock n _ _ _) = n -fName :: Field -> String-fName (F _ n _) = n-fName (Section _ n _ _) = n-fName _ = error "fname: not a field or section"- readFields :: String -> ParseResult [Field] readFields input = ifelse =<< traverse (mkField 0)@@ -603,26 +524,11 @@ ------------------------------------------------------------------------------ --- |parse a module name-parseModuleNameQ :: ReadP r ModuleName-parseModuleNameQ = parseMaybeQuoted parse- parseFilePathQ :: ReadP r FilePath parseFilePathQ = parseTokenQ -- removed until normalise is no longer broken, was: -- liftM normalise parseTokenQ -betweenSpaces :: ReadP r a -> ReadP r a-betweenSpaces act = do skipSpaces- res <- act- skipSpaces- return res--parseOptVersion :: ReadP r Version-parseOptVersion = parseMaybeQuoted ver- where ver :: ReadP r Version- ver = parse <++ return nullVersion- -- urgh, we can't define optQuotes :: ReadP r a -> ReadP r a -- because the "compat" version of ReadP isn't quite powerful enough. In -- particular, the type of <++ is ReadP r r -> ReadP r a -> ReadP r a@@ -639,23 +545,10 @@ parseTokenQ :: ReadP r String parseTokenQ = parseHaskellString <++ munch1 (\x -> not (isSpace x) && x /= ',') -parseTokenQ' :: ReadP r String-parseTokenQ' = parseHaskellString <++ munch1 (not . isSpace)--parseSepList :: ReadP r b- -> ReadP r a -- ^The parser for the stuff between commas- -> ReadP r [a]-parseSepList sepr p = sepBy p separator- where separator = betweenSpaces sepr- parseSpaceList :: ReadP r a -- ^The parser for the stuff between commas -> ReadP r [a] parseSpaceList p = sepBy p skipSpaces -parseCommaList :: ReadP r a -- ^The parser for the stuff between commas- -> ReadP r [a]-parseCommaList = parseSepList (ReadP.char ',')- -- This version avoid parse ambiguity for list element parsers -- that have multiple valid parses of prefixes. parseOptCommaList :: ReadP r a -> ReadP r [a]@@ -665,60 +558,6 @@ localSep = (skipSpaces >> char ',' >> skipSpaces) +++ (satisfy isSpace >> skipSpaces) -parseQuoted :: ReadP r a -> ReadP r a-parseQuoted = between (ReadP.char '"') (ReadP.char '"')--parseMaybeQuoted :: (forall r. ReadP r a) -> ReadP r' a-parseMaybeQuoted p = parseQuoted p <++ p--parseFreeText :: ReadP.ReadP s String-parseFreeText = ReadP.munch (const True)- readPToMaybe :: ReadP a a -> String -> Maybe a readPToMaybe p str = listToMaybe [ r | (r,s) <- readP_to_S p str , all isSpace s ]--ppField :: String -> Doc -> Doc-ppField name fielddoc- | isEmpty fielddoc = mempty- | name `elem` nestedFields = text name <<>> colon $+$ nest indentWith fielddoc- | otherwise = text name <<>> colon <+> fielddoc- where- indentWith = 4- nestedFields =- [ "description"- , "build-depends"- , "data-files"- , "extra-source-files"- , "extra-tmp-files"- , "exposed-modules"- , "asm-sources"- , "cmm-sources"- , "c-sources"- , "js-sources"- , "extra-libraries"- , "includes"- , "install-includes"- , "other-modules"- , "autogen-modules"- , "depends"- ]--parseFlagAssignment :: ReadP r FlagAssignment-parseFlagAssignment = mkFlagAssignment <$>- sepBy parseFlagValue skipSpaces1- where- parseFlagValue =- (do optional (char '+')- f <- parse- return (f, True))- +++ (do _ <- char '-'- f <- parse- return (f, False))------------------------------------------------------------------------------------ Internal----------------------------------------------------------------------------------showTestedWith :: (CompilerFlavor, VersionRange) -> Doc-showTestedWith = pretty . pack' TestedWith
− cabal/cabal-install/Distribution/Deprecated/Text.hs
@@ -1,409 +0,0 @@-{-# LANGUAGE DefaultSignatures #-}--------------------------------------------------------------------------------- |--- Module : Distribution.Deprecated.Text--- Copyright : Duncan Coutts 2007------ Maintainer : cabal-devel@haskell.org--- Portability : portable------ classes. The difference is that it uses a modern pretty printer and parser--- system and the format is not expected to be Haskell concrete syntax but--- rather the external human readable representation used by Cabal.----module Distribution.Deprecated.Text (- Text(..),- defaultStyle,- display,- flatStyle,- simpleParse,- stdParse,- -- parse utils- parsePackageName,- ) where--import Distribution.Client.Compat.Prelude-import Prelude (read)--import Distribution.Deprecated.ReadP ((<++))-import qualified Distribution.Deprecated.ReadP as Parse--import Distribution.Parsec-import Distribution.Pretty-import qualified Text.PrettyPrint as Disp--import qualified Data.Set as Set--import Data.Version (Version (Version))--import qualified Distribution.Compiler as D-import qualified Distribution.License as D-import qualified Distribution.ModuleName as D-import qualified Distribution.Package as D-import qualified Distribution.PackageDescription as D-import qualified Distribution.Simple.Setup as D-import qualified Distribution.System as D-import qualified Distribution.Types.PackageVersionConstraint as D-import qualified Distribution.Types.SourceRepo as D-import qualified Distribution.Types.UnqualComponentName as D-import qualified Distribution.Version as D-import qualified Distribution.Types.VersionRange.Internal as D-import qualified Language.Haskell.Extension as E---- | /Note:/ this class will soon be deprecated.--- It's not yet, so that we are @-Wall@ clean.-class Text a where- disp :: a -> Disp.Doc- default disp :: Pretty a => a -> Disp.Doc- disp = pretty-- parse :: Parse.ReadP r a- default parse :: Parsec a => Parse.ReadP r a- parse = parsec---- | Pretty-prints with the default style.-display :: Text a => a -> String-display = Disp.renderStyle defaultStyle . disp--simpleParse :: Text a => String -> Maybe a-simpleParse str = case [ p | (p, s) <- Parse.readP_to_S parse str- , all isSpace s ] of- [] -> Nothing- (p:_) -> Just p--stdParse :: Text ver => (ver -> String -> res) -> Parse.ReadP r res-stdParse f = do- cs <- Parse.sepBy1 component (Parse.char '-')- _ <- Parse.char '-'- ver <- parse- let name = intercalate "-" cs- return $! f ver (lowercase name)- where- component = do- cs <- Parse.munch1 isAlphaNum- if all isDigit cs then Parse.pfail else return cs- -- each component must contain an alphabetic character, to avoid- -- ambiguity in identifiers like foo-1 (the 1 is the version number).--lowercase :: String -> String-lowercase = map toLower---- -------------------------------------------------------------------------------- Instances for types from the base package--instance Text Bool where- parse = Parse.choice [ (Parse.string "True" Parse.+++- Parse.string "true") >> return True- , (Parse.string "False" Parse.+++- Parse.string "false") >> return False ]--instance Text Int where- parse = fmap negate (Parse.char '-' >> parseNat) Parse.+++ parseNat--instance Text a => Text (Identity a) where- disp = disp . runIdentity- parse = fmap Identity parse---- | Parser for non-negative integers.-parseNat :: Parse.ReadP r Int-parseNat = read `fmap` Parse.munch1 isDigit -- TODO: eradicateNoParse---instance Text Version where- disp (Version branch _tags) -- Death to version tags!!- = Disp.hcat (Disp.punctuate (Disp.char '.') (map Disp.int branch))-- parse = do- branch <- Parse.sepBy1 parseNat (Parse.char '.')- -- allow but ignore tags:- _tags <- Parse.many (Parse.char '-' >> Parse.munch1 isAlphaNum)- return (Version branch [])------------------------------------------------------------------------------------ Instances----------------------------------------------------------------------------------instance Text D.Arch where- parse = fmap (D.classifyArch D.Strict) ident--instance Text D.BuildType where- parse = do- name <- Parse.munch1 isAlphaNum- case name of- "Simple" -> return D.Simple- "Configure" -> return D.Configure- "Custom" -> return D.Custom- "Make" -> return D.Make- "Default" -> return D.Custom- _ -> fail ("unknown build-type: '" ++ name ++ "'")--instance Text D.CompilerFlavor where- parse = do- comp <- Parse.munch1 isAlphaNum- when (all isDigit comp) Parse.pfail- return (D.classifyCompilerFlavor comp)--instance Text D.CompilerId where- parse = do- flavour <- parse- version <- (Parse.char '-' >> parse) Parse.<++ return D.nullVersion- return (D.CompilerId flavour version)--instance Text D.ComponentId where- parse = D.mkComponentId `fmap` Parse.munch1 abi_char- where abi_char c = isAlphaNum c || c `elem` "-_."--instance Text D.DefUnitId where- parse = D.unsafeMkDefUnitId `fmap` parse--instance Text D.UnitId where- parse = D.mkUnitId <$> Parse.munch1 (\c -> isAlphaNum c || c `elem` "-_.+")--instance Text D.Dependency where- parse = do name <- parse- Parse.skipSpaces- libs <- Parse.option [D.LMainLibName]- $ (Parse.char ':' *>)- $ pure <$> parseLib name <|> parseMultipleLibs name- Parse.skipSpaces- ver <- parse Parse.<++ return D.anyVersion- Parse.skipSpaces- return $ D.Dependency name ver $ Set.fromList libs- where makeLib pn ln | D.unPackageName pn == ln = D.LMainLibName- | otherwise = D.LSubLibName $ D.mkUnqualComponentName ln- parseLib pn = makeLib pn <$> parsecUnqualComponentName- parseMultipleLibs pn = Parse.between (Parse.char '{' *> Parse.skipSpaces)- (Parse.skipSpaces <* Parse.char '}')- $ parsecCommaList $ parseLib pn---instance Text E.Extension where- parse = do- extension <- Parse.munch1 isAlphaNum- return (E.classifyExtension extension)--instance Text D.FlagName where- -- Note: we don't check that FlagName doesn't have leading dash,- -- cabal check will do that.- parse = D.mkFlagName . lowercase <$> parse'- where- parse' = (:) <$> lead <*> rest- lead = Parse.satisfy (\c -> isAlphaNum c || c == '_')- rest = Parse.munch (\c -> isAlphaNum c || c == '_' || c == '-')--instance Text D.HaddockTarget where- parse = Parse.choice [ Parse.string "for-hackage" >> return D.ForHackage- , Parse.string "for-development" >> return D.ForDevelopment]--instance Text E.Language where- parse = do- lang <- Parse.munch1 isAlphaNum- return (E.classifyLanguage lang)--instance Text D.License where- parse = do- name <- Parse.munch1 (\c -> isAlphaNum c && c /= '-')- version <- Parse.option Nothing (Parse.char '-' >> fmap Just parse)- return $! case (name, version :: Maybe D.Version) of- ("GPL", _ ) -> D.GPL version- ("LGPL", _ ) -> D.LGPL version- ("AGPL", _ ) -> D.AGPL version- ("BSD2", Nothing) -> D.BSD2- ("BSD3", Nothing) -> D.BSD3- ("BSD4", Nothing) -> D.BSD4- ("ISC", Nothing) -> D.ISC- ("MIT", Nothing) -> D.MIT- ("MPL", Just version') -> D.MPL version'- ("Apache", _ ) -> D.Apache version- ("PublicDomain", Nothing) -> D.PublicDomain- ("AllRightsReserved", Nothing) -> D.AllRightsReserved- ("OtherLicense", Nothing) -> D.OtherLicense- _ -> D.UnknownLicense $ name ++- maybe "" (('-':) . display) version--instance Text D.Module where- parse = do- uid <- parse- _ <- Parse.char ':'- mod_name <- parse- return (D.Module uid mod_name)--instance Text D.ModuleName where- parse = do- ms <- Parse.sepBy1 component (Parse.char '.')- return (D.fromComponents ms)-- where- component = do- c <- Parse.satisfy isUpper- cs <- Parse.munch validModuleChar- return (c:cs)--instance Text D.OS where- parse = fmap (D.classifyOS D.Compat) ident--instance Text D.PackageVersionConstraint where- parse = do name <- parse- Parse.skipSpaces- ver <- parse Parse.<++ return D.anyVersion- Parse.skipSpaces- return (D.PackageVersionConstraint name ver)--instance Text D.PkgconfigName where- parse = D.mkPkgconfigName- <$> Parse.munch1 (\c -> isAlphaNum c || c `elem` "+-._")--instance Text D.Platform where- -- TODO: there are ambigious platforms like: `arch-word-os`- -- which could be parsed as- -- * Platform "arch-word" "os"- -- * Platform "arch" "word-os"- -- We could support that preferring variants 'OtherOS' or 'OtherArch'- --- -- For now we split into arch and os parts on the first dash.- parse = do- arch <- parseDashlessArch- _ <- Parse.char '-'- os <- parse- return (D.Platform arch os)- where- parseDashlessArch :: Parse.ReadP r D.Arch- parseDashlessArch = fmap (D.classifyArch D.Strict) dashlessIdent-- dashlessIdent :: Parse.ReadP r String- dashlessIdent = liftM2 (:) firstChar rest- where firstChar = Parse.satisfy isAlpha- rest = Parse.munch (\c -> isAlphaNum c || c == '_')--instance Text D.RepoKind where- parse = fmap D.classifyRepoKind ident--instance Text D.RepoType where- parse = fmap D.classifyRepoType ident--instance Text D.UnqualComponentName where- parse = D.mkUnqualComponentName <$> parsePackageName--instance Text D.PackageIdentifier where- parse = do- n <- parse- v <- (Parse.char '-' >> parse) <++ return D.nullVersion- return (D.PackageIdentifier n v)--instance Text D.PackageName where- parse = D.mkPackageName <$> parsePackageName--instance Text D.Version where- parse = do- branch <- Parse.sepBy1 parseNat (Parse.char '.')- -- allow but ignore tags:- _tags <- Parse.many (Parse.char '-' >> Parse.munch1 isAlphaNum)- return (D.mkVersion branch)--instance Text D.VersionRange where- parse = expr- where- expr = do Parse.skipSpaces- t <- term- Parse.skipSpaces- (do _ <- Parse.string "||"- Parse.skipSpaces- e <- expr- return (D.unionVersionRanges t e)- Parse.+++- return t)- term = do f <- factor- Parse.skipSpaces- (do _ <- Parse.string "&&"- Parse.skipSpaces- t <- term- return (D.intersectVersionRanges f t)- Parse.+++- return f)- factor = Parse.choice $ parens expr- : parseAnyVersion- : parseNoVersion- : parseWildcardRange- : map parseRangeOp rangeOps- parseAnyVersion = Parse.string "-any" >> return D.anyVersion- parseNoVersion = Parse.string "-none" >> return D.noVersion-- parseWildcardRange = do- _ <- Parse.string "=="- Parse.skipSpaces- branch <- Parse.sepBy1 digits (Parse.char '.')- _ <- Parse.char '.'- _ <- Parse.char '*'- return (D.withinVersion (D.mkVersion branch))-- parens p = Parse.between (Parse.char '(' >> Parse.skipSpaces)- (Parse.char ')' >> Parse.skipSpaces)- (do a <- p- Parse.skipSpaces- return (D.VersionRangeParens a))- digits = do- firstDigit <- Parse.satisfy isDigit- if firstDigit == '0'- then return 0- else do rest <- Parse.munch isDigit- return (read (firstDigit : rest)) -- TODO: eradicateNoParse-- parseRangeOp (s,f) = Parse.string s >> Parse.skipSpaces >> fmap f parse- rangeOps = [ ("<", D.earlierVersion),- ("<=", D.orEarlierVersion),- (">", D.laterVersion),- (">=", D.orLaterVersion),- ("^>=", D.majorBoundVersion),- ("==", D.thisVersion) ]------------------------------------------------------------------------------------ ParseUtils----------------------------------------------------------------------------------parsePackageName :: Parse.ReadP r String-parsePackageName = do- ns <- Parse.sepBy1 component (Parse.char '-')- return $ intercalate "-" ns- where- component = do- cs <- Parse.munch1 isAlphaNum- if all isDigit cs then Parse.pfail else return cs- -- each component must contain an alphabetic character, to avoid- -- ambiguity in identifiers like foo-1 (the 1 is the version number).---ident :: Parse.ReadP r String-ident = liftM2 (:) firstChar rest- where firstChar = Parse.satisfy isAlpha- rest = Parse.munch (\c -> isAlphaNum c || c == '_' || c == '-')--validModuleChar :: Char -> Bool-validModuleChar c = isAlphaNum c || c == '_' || c == '\''------------------------------------------------------------------------------------ Rest of instances, we don't seem to need------------------------------------------------------------------------------------ instance Text D.AbiDependency--- instance Text D.AbiHash--- instance Text D.AbiTa--- instance Text D.BenchmarkType--- instance Text D.ExecutableScope--- instance Text D.ExeDependency--- instance Text D.ExposedModule--- instance Text D.ForeignLibOption--- instance Text D.ForeignLibType--- instance Text D.IncludeRenaming--- instance Text D.KnownExtension--- instance Text D.LegacyExeDependency--- instance Text D.LibVersionInfo--- instance Text D.License--- instance Text D.Mixin--- instance Text D.ModuleReexport--- instance Text D.ModuleRenaming--- instance Text D.MungedPackageName--- instance Text D.OpenModule--- instance Text D.OpenUnitId--- instance Text D.PackageVersionConstraint--- instance Text D.PkgconfigDependency--- instance Text D.TestType
cabal/cabal-install/Distribution/Deprecated/ViewAsFieldDescr.hs view
@@ -6,8 +6,6 @@ import Prelude () import qualified Data.List.NonEmpty as NE-import Distribution.Parsec (parsec)-import Distribution.Pretty import Distribution.ReadE (parsecToReadE) import Distribution.Simple.Command import Text.PrettyPrint (cat, comma, punctuate, text)
cabal/cabal-install/Distribution/Solver/Modular.hs view
@@ -17,7 +17,6 @@ import qualified Data.Map as M import Data.Set (isSubsetOf)-import Data.Ord import Distribution.Compat.Graph ( IsNode(..) ) import Distribution.Compiler
cabal/cabal-install/Distribution/Solver/Modular/Assignment.hs view
@@ -9,11 +9,12 @@ import Prelude () import Distribution.Solver.Compat.Prelude hiding (pi) -import Data.Array as A-import Data.List as L-import Data.Map as M-import Data.Maybe+import qualified Data.Array as A+import qualified Data.List as L+import qualified Data.Map as M +import Data.Maybe (fromJust)+ import Distribution.PackageDescription (FlagAssignment, mkFlagAssignment) -- from Cabal import Distribution.Solver.Types.ComponentDeps (ComponentDeps, Component)@@ -79,7 +80,7 @@ -- Dependencies per package. depp :: QPN -> [(Component, PI QPN)] depp qpn = let v :: Vertex- v = fromJust (cvm qpn)+ v = fromJust (cvm qpn) -- TODO: why this is safe? dvs :: [(Component, Vertex)] dvs = tg A.! v in L.map (\ (comp, dv) -> case vm dv of (_, x, _) -> (comp, PI x (pa M.! x))) dvs
cabal/cabal-install/Distribution/Solver/Modular/Builder.hs view
@@ -19,10 +19,10 @@ -- flag-guarded dependencies, we cannot introduce them immediately. Instead, we -- store the entire dependency. -import Data.List as L-import Data.Map as M-import Data.Set as S-import Prelude hiding (sequence, mapM)+import qualified Data.List as L+import qualified Data.Map as M+import qualified Data.Set as S+import Prelude import qualified Distribution.Solver.Modular.ConflictSet as CS import Distribution.Solver.Modular.Dependency@@ -55,7 +55,7 @@ } -- | Map of available linking targets.-type LinkingState = Map (PN, I) [PackagePath]+type LinkingState = M.Map (PN, I) [PackagePath] -- | Extend the set of open goals with the new goals listed. --@@ -145,7 +145,9 @@ -- and then handle each instance in turn. addChildren bs@(BS { rdeps = rdm, index = idx, next = OneGoal (PkgGoal qpn@(Q _ pn) gr) }) = case M.lookup pn idx of- Nothing -> FailF (varToConflictSet (P qpn) `CS.union` goalReasonToCS gr) UnknownPackage+ Nothing -> FailF+ (varToConflictSet (P qpn) `CS.union` goalReasonToConflictSetWithConflict qpn gr)+ UnknownPackage Just pis -> PChoiceF qpn rdm gr (W.fromList (L.map (\ (i, info) -> ([], POption i Nothing, bs { next = Instance qpn info })) (M.toList pis)))
cabal/cabal-install/Distribution/Solver/Modular/ConfiguredConversion.hs view
@@ -45,7 +45,7 @@ solverPkgExeDeps = fmap snd ds' } where- Just srcpkg = CI.lookupPackageId sidx pi+ srcpkg = fromMaybe (error "convCP: lookupPackageId failed") $ CI.lookupPackageId sidx pi where ds' :: ComponentDeps ([SolverId] {- lib -}, [SolverId] {- exe -}) ds' = fmap (partitionEithers . map convConfId) ds
cabal/cabal-install/Distribution/Solver/Modular/ConflictSet.hs view
@@ -10,7 +10,9 @@ -- > import qualified Distribution.Solver.Modular.ConflictSet as CS module Distribution.Solver.Modular.ConflictSet ( ConflictSet -- opaque+ , Conflict(..) , ConflictMap+ , OrderedVersionRange(..) #ifdef DEBUG_CONFLICT_SETS , conflictSetOrigin #endif@@ -26,19 +28,21 @@ , delete , empty , singleton+ , singletonWithConflict , size , member+ , lookup , filter , fromList ) where -import Prelude hiding (filter)+import Prelude hiding (lookup) import Data.List (intercalate, sortBy) import Data.Map (Map) import Data.Set (Set) import Data.Function (on)+import qualified Data.Map.Strict as M import qualified Data.Set as S-import qualified Data.Map as M #ifdef DEBUG_CONFLICT_SETS import Data.Tree@@ -46,15 +50,14 @@ #endif import Distribution.Solver.Modular.Var+import Distribution.Solver.Modular.Version import Distribution.Solver.Types.PackagePath --- | The set of variables involved in a solver conflict------ Since these variables should be preprocessed in some way, this type is--- kept abstract.+-- | The set of variables involved in a solver conflict, each paired with+-- details about the conflict. data ConflictSet = CS {- -- | The set of variables involved on the conflict- conflictSetToSet :: !(Set (Var QPN))+ -- | The set of variables involved in the conflict+ conflictSetToMap :: !(Map (Var QPN) (Set Conflict)) #ifdef DEBUG_CONFLICT_SETS -- | The origin of the conflict set@@ -72,11 +75,48 @@ } deriving (Show) +-- | More detailed information about how a conflict set variable caused a+-- conflict. This information can be used to determine whether a second value+-- for that variable would lead to the same conflict.+--+-- TODO: Handle dependencies under flags or stanzas.+data Conflict =++ -- | The conflict set variable represents a package which depends on the+ -- specified problematic package. For example, the conflict set entry+ -- '(P x, GoalConflict y)' means that package x introduced package y, and y+ -- led to a conflict.+ GoalConflict QPN++ -- | The conflict set variable represents a package with a constraint that+ -- excluded the specified package and version. For example, the conflict set+ -- entry '(P x, VersionConstraintConflict y (mkVersion [2, 0]))' means that+ -- package x's constraint on y excluded y-2.0.+ | VersionConstraintConflict QPN Ver++ -- | The conflict set variable represents a package that was excluded by a+ -- constraint from the specified package. For example, the conflict set+ -- entry '(P x, VersionConflict y (orLaterVersion (mkVersion [2, 0])))'+ -- means that package y's constraint 'x >= 2.0' excluded some version of x.+ | VersionConflict QPN OrderedVersionRange++ -- | Any other conflict.+ | OtherConflict+ deriving (Eq, Ord, Show)++-- | Version range with an 'Ord' instance.+newtype OrderedVersionRange = OrderedVersionRange VR+ deriving (Eq, Show)++-- TODO: Avoid converting the version ranges to strings.+instance Ord OrderedVersionRange where+ compare = compare `on` show+ instance Eq ConflictSet where- (==) = (==) `on` conflictSetToSet+ (==) = (==) `on` conflictSetToMap instance Ord ConflictSet where- compare = compare `on` conflictSetToSet+ compare = compare `on` conflictSetToMap showConflictSet :: ConflictSet -> String showConflictSet = intercalate ", " . map showVar . toList@@ -102,10 +142,10 @@ -------------------------------------------------------------------------------} toSet :: ConflictSet -> Set (Var QPN)-toSet = conflictSetToSet+toSet = M.keysSet . conflictSetToMap toList :: ConflictSet -> [Var QPN]-toList = S.toList . conflictSetToSet+toList = M.keys . conflictSetToMap union :: #ifdef DEBUG_CONFLICT_SETS@@ -113,7 +153,7 @@ #endif ConflictSet -> ConflictSet -> ConflictSet union cs cs' = CS {- conflictSetToSet = S.union (conflictSetToSet cs) (conflictSetToSet cs')+ conflictSetToMap = M.unionWith S.union (conflictSetToMap cs) (conflictSetToMap cs') #ifdef DEBUG_CONFLICT_SETS , conflictSetOrigin = Node ?loc (map conflictSetOrigin [cs, cs']) #endif@@ -125,7 +165,7 @@ #endif [ConflictSet] -> ConflictSet unions css = CS {- conflictSetToSet = S.unions (map conflictSetToSet css)+ conflictSetToMap = M.unionsWith S.union (map conflictSetToMap css) #ifdef DEBUG_CONFLICT_SETS , conflictSetOrigin = Node ?loc (map conflictSetOrigin css) #endif@@ -137,7 +177,7 @@ #endif Var QPN -> ConflictSet -> ConflictSet insert var cs = CS {- conflictSetToSet = S.insert var (conflictSetToSet cs)+ conflictSetToMap = M.insert var (S.singleton OtherConflict) (conflictSetToMap cs) #ifdef DEBUG_CONFLICT_SETS , conflictSetOrigin = Node ?loc [conflictSetOrigin cs] #endif@@ -145,7 +185,7 @@ delete :: Var QPN -> ConflictSet -> ConflictSet delete var cs = CS {- conflictSetToSet = S.delete var (conflictSetToSet cs)+ conflictSetToMap = M.delete var (conflictSetToMap cs) } empty ::@@ -154,7 +194,7 @@ #endif ConflictSet empty = CS {- conflictSetToSet = S.empty+ conflictSetToMap = M.empty #ifdef DEBUG_CONFLICT_SETS , conflictSetOrigin = Node ?loc [] #endif@@ -165,30 +205,28 @@ (?loc :: CallStack) => #endif Var QPN -> ConflictSet-singleton var = CS {- conflictSetToSet = S.singleton var+singleton var = singletonWithConflict var OtherConflict++singletonWithConflict :: #ifdef DEBUG_CONFLICT_SETS+ (?loc :: CallStack) =>+#endif+ Var QPN -> Conflict -> ConflictSet+singletonWithConflict var conflict = CS {+ conflictSetToMap = M.singleton var (S.singleton conflict)+#ifdef DEBUG_CONFLICT_SETS , conflictSetOrigin = Node ?loc [] #endif } size :: ConflictSet -> Int-size = S.size . conflictSetToSet+size = M.size . conflictSetToMap member :: Var QPN -> ConflictSet -> Bool-member var = S.member var . conflictSetToSet+member var = M.member var . conflictSetToMap -filter ::-#ifdef DEBUG_CONFLICT_SETS- (?loc :: CallStack) =>-#endif- (Var QPN -> Bool) -> ConflictSet -> ConflictSet-filter p cs = CS {- conflictSetToSet = S.filter p (conflictSetToSet cs)-#ifdef DEBUG_CONFLICT_SETS- , conflictSetOrigin = Node ?loc [conflictSetOrigin cs]-#endif- }+lookup :: Var QPN -> ConflictSet -> Maybe (Set Conflict)+lookup var = M.lookup var . conflictSetToMap fromList :: #ifdef DEBUG_CONFLICT_SETS@@ -196,7 +234,7 @@ #endif [Var QPN] -> ConflictSet fromList vars = CS {- conflictSetToSet = S.fromList vars+ conflictSetToMap = M.fromList [(var, S.singleton OtherConflict) | var <- vars] #ifdef DEBUG_CONFLICT_SETS , conflictSetOrigin = Node ?loc [] #endif
cabal/cabal-install/Distribution/Solver/Modular/Dependency.hs view
@@ -32,8 +32,11 @@ , QGoalReason , goalToVar , varToConflictSet- , goalReasonToCS- , dependencyReasonToCS+ , goalReasonToConflictSet+ , goalReasonToConflictSetWithConflict+ , dependencyReasonToConflictSet+ , dependencyReasonToConflictSetWithVersionConstraintConflict+ , dependencyReasonToConflictSetWithVersionConflict ) where import Prelude ()@@ -52,6 +55,7 @@ import Distribution.Solver.Types.ComponentDeps (Component(..)) import Distribution.Solver.Types.PackagePath+import Distribution.Types.LibraryName import Distribution.Types.PkgconfigVersionRange import Distribution.Types.UnqualComponentName @@ -128,7 +132,9 @@ -- | A component that can be depended upon by another package, i.e., a library -- or an executable.-data ExposedComponent = ExposedLib | ExposedExe UnqualComponentName+data ExposedComponent =+ ExposedLib LibraryName+ | ExposedExe UnqualComponentName deriving (Eq, Ord, Show) -- | The reason that a dependency is active. It identifies the package and any@@ -182,7 +188,7 @@ -- Suppose package B has a setup dependency on package A. -- This will be recorded as something like --- -- > LDep (DependencyReason "B") (Dep (PkgComponent "A" ExposedLib) (Constrained AnyVersion))+ -- > LDep (DependencyReason "B") (Dep (PkgComponent "A" (ExposedLib LMainLibName)) (Constrained AnyVersion)) -- -- Observe that when we qualify this dependency, we need to turn that -- @"A"@ into @"B-setup.A"@, but we should not apply that same qualifier@@ -196,7 +202,7 @@ goD (Pkg pkn vr) _ = Pkg pkn vr goD (Dep dep@(PkgComponent qpn (ExposedExe _)) ci) _ = Dep (Q (PackagePath ns (QualExe pn qpn)) <$> dep) ci- goD (Dep dep@(PkgComponent qpn ExposedLib) ci) comp+ goD (Dep dep@(PkgComponent qpn (ExposedLib _)) ci) comp | qBase qpn = Dep (Q (PackagePath ns (QualBase pn)) <$> dep) ci | qSetup comp = Dep (Q (PackagePath ns (QualSetup pn)) <$> dep) ci | otherwise = Dep (Q (PackagePath ns inheritedQ ) <$> dep) ci@@ -279,14 +285,30 @@ varToConflictSet :: Var QPN -> ConflictSet varToConflictSet = CS.singleton -goalReasonToCS :: GoalReason QPN -> ConflictSet-goalReasonToCS UserGoal = CS.empty-goalReasonToCS (DependencyGoal dr) = dependencyReasonToCS dr+-- | Convert a 'GoalReason' to a 'ConflictSet' that can be used when the goal+-- leads to a conflict.+goalReasonToConflictSet :: GoalReason QPN -> ConflictSet+goalReasonToConflictSet UserGoal = CS.empty+goalReasonToConflictSet (DependencyGoal dr) = dependencyReasonToConflictSet dr +-- | Convert a 'GoalReason' to a 'ConflictSet' containing the reason that the+-- conflict occurred, namely the conflict set variables caused a conflict by+-- introducing the given package goal. See the documentation for 'GoalConflict'.+--+-- This function currently only specifies the reason for the conflict in the+-- simple case where the 'GoalReason' does not involve any flags or stanzas.+-- Otherwise, it falls back to calling 'goalReasonToConflictSet'.+goalReasonToConflictSetWithConflict :: QPN -> GoalReason QPN -> ConflictSet+goalReasonToConflictSetWithConflict goal (DependencyGoal (DependencyReason qpn flags stanzas))+ | M.null flags && S.null stanzas =+ CS.singletonWithConflict (P qpn) $ CS.GoalConflict goal+goalReasonToConflictSetWithConflict _ gr = goalReasonToConflictSet gr+ -- | This function returns the solver variables responsible for the dependency.--- It drops the flag and stanza values, which are only needed for log messages.-dependencyReasonToCS :: DependencyReason QPN -> ConflictSet-dependencyReasonToCS (DependencyReason qpn flags stanzas) =+-- It drops the values chosen for flag and stanza variables, which are only+-- needed for log messages.+dependencyReasonToConflictSet :: DependencyReason QPN -> ConflictSet+dependencyReasonToConflictSet (DependencyReason qpn flags stanzas) = CS.fromList $ P qpn : flagVars ++ map stanzaToVar (S.toList stanzas) where -- Filter out any flags that introduced the dependency with both values.@@ -297,3 +319,40 @@ stanzaToVar :: Stanza -> Var QPN stanzaToVar = S . SN qpn++-- | Convert a 'DependencyReason' to a 'ConflictSet' specifying that the+-- conflict occurred because the conflict set variables introduced a problematic+-- version constraint. See the documentation for 'VersionConstraintConflict'.+--+-- This function currently only specifies the reason for the conflict in the+-- simple case where the 'DependencyReason' does not involve any flags or+-- stanzas. Otherwise, it falls back to calling 'dependencyReasonToConflictSet'.+dependencyReasonToConflictSetWithVersionConstraintConflict :: QPN+ -> Ver+ -> DependencyReason QPN+ -> ConflictSet+dependencyReasonToConflictSetWithVersionConstraintConflict+ dependency excludedVersion dr@(DependencyReason qpn flags stanzas)+ | M.null flags && S.null stanzas =+ CS.singletonWithConflict (P qpn) $+ CS.VersionConstraintConflict dependency excludedVersion+ | otherwise = dependencyReasonToConflictSet dr++-- | Convert a 'DependencyReason' to a 'ConflictSet' specifying that the+-- conflict occurred because the conflict set variables introduced a version of+-- a package that was excluded by a version constraint. See the documentation+-- for 'VersionConflict'.+--+-- This function currently only specifies the reason for the conflict in the+-- simple case where the 'DependencyReason' does not involve any flags or+-- stanzas. Otherwise, it falls back to calling 'dependencyReasonToConflictSet'.+dependencyReasonToConflictSetWithVersionConflict :: QPN+ -> CS.OrderedVersionRange+ -> DependencyReason QPN+ -> ConflictSet+dependencyReasonToConflictSetWithVersionConflict+ pkgWithVersionConstraint constraint dr@(DependencyReason qpn flags stanzas)+ | M.null flags && S.null stanzas =+ CS.singletonWithConflict (P qpn) $+ CS.VersionConflict pkgWithVersionConstraint constraint+ | otherwise = dependencyReasonToConflictSet dr
cabal/cabal-install/Distribution/Solver/Modular/Explore.hs view
@@ -3,23 +3,33 @@ {-# LANGUAGE ScopedTypeVariables #-} module Distribution.Solver.Modular.Explore (backjumpAndExplore) where +import Distribution.Solver.Compat.Prelude+import Prelude ()+ import qualified Distribution.Solver.Types.Progress as P -import Data.Foldable as F-import Data.List as L (foldl')-import Data.Map.Strict as M+import qualified Data.List as L (foldl')+import qualified Data.Map.Strict as M+import qualified Data.Set as S +import Distribution.Simple.Setup (asBool)+ import Distribution.Solver.Modular.Assignment import Distribution.Solver.Modular.Dependency+import Distribution.Solver.Modular.Index import Distribution.Solver.Modular.Log import Distribution.Solver.Modular.Message+import Distribution.Solver.Modular.Package import qualified Distribution.Solver.Modular.PSQ as P import qualified Distribution.Solver.Modular.ConflictSet as CS import Distribution.Solver.Modular.RetryLog import Distribution.Solver.Modular.Tree+import Distribution.Solver.Modular.Version import qualified Distribution.Solver.Modular.WeightedPSQ as W import Distribution.Solver.Types.PackagePath-import Distribution.Solver.Types.Settings (EnableBackjumping(..), CountConflicts(..))+import Distribution.Solver.Types.Settings+ (CountConflicts(..), EnableBackjumping(..), FineGrainedConflicts(..))+import Distribution.Types.VersionRange (anyVersion) -- | This function takes the variable we're currently considering, a -- last conflict set and a list of children's logs. Each log yields@@ -43,25 +53,70 @@ -- with the (virtual) option not to choose anything for the current -- variable. See also the comments for 'avoidSet'. ---backjump :: Maybe Int -> EnableBackjumping -> Var QPN- -> ConflictSet -> W.WeightedPSQ w k (ExploreState -> ConflictSetLog a)+-- We can also skip a child if it does not resolve any of the conflicts paired+-- with the current variable in the previous child's conflict set. 'backjump'+-- takes a function to determine whether a child can be skipped. If the child+-- can be skipped, the function returns a new conflict set to be merged with the+-- previous conflict set.+--+backjump :: forall w k a . Maybe Int+ -> EnableBackjumping+ -> FineGrainedConflicts++ -> (k -> S.Set CS.Conflict -> Maybe ConflictSet)+ -- ^ Function that determines whether the given choice could resolve+ -- the given conflict. It indicates false by returning 'Just',+ -- with the new conflicts to be added to the conflict set.++ -> (k -> ConflictSet -> ExploreState -> ConflictSetLog a)+ -- ^ Function that logs the given choice that was skipped.++ -> Var QPN -- ^ The current variable.++ -> ConflictSet -- ^ Conflict set representing the reason that the goal+ -- was introduced.++ -> W.WeightedPSQ w k (ExploreState -> ConflictSetLog a)+ -- ^ List of children's logs.+ -> ExploreState -> ConflictSetLog a-backjump mbj (EnableBackjumping enableBj) var lastCS xs =- F.foldr combine avoidGoal xs CS.empty+backjump mbj enableBj fineGrainedConflicts couldResolveConflicts+ logSkippedChoice var lastCS xs =+ foldr combine avoidGoal [(k, v) | (_, k, v) <- W.toList xs] CS.empty Nothing where- combine :: forall a . (ExploreState -> ConflictSetLog a)- -> (ConflictSet -> ExploreState -> ConflictSetLog a)- -> ConflictSet -> ExploreState -> ConflictSetLog a- combine x f csAcc es = retryNoSolution (x es) next+ combine :: (k, ExploreState -> ConflictSetLog a)+ -> (ConflictSet -> Maybe ConflictSet -> ExploreState -> ConflictSetLog a)+ -> ConflictSet -> Maybe ConflictSet -> ExploreState -> ConflictSetLog a+ combine (k, x) f csAcc mPreviousCS es =+ case (asBool fineGrainedConflicts, mPreviousCS) of+ (True, Just previousCS) ->+ case CS.lookup var previousCS of+ Just conflicts ->+ case couldResolveConflicts k conflicts of+ Nothing -> retryNoSolution (x es) next+ Just newConflicts -> skipChoice (previousCS `CS.union` newConflicts)+ _ -> skipChoice previousCS+ _ -> retryNoSolution (x es) next where next :: ConflictSet -> ExploreState -> ConflictSetLog a- next !cs es' = if enableBj && not (var `CS.member` cs)+ next !cs es' = if asBool enableBj && not (var `CS.member` cs) then skipLoggingBackjump cs es'- else f (csAcc `CS.union` cs) es'+ else f (csAcc `CS.union` cs) (Just cs) es' + -- This function is for skipping the choice when it cannot resolve any+ -- of the previous conflicts.+ skipChoice :: ConflictSet -> ConflictSetLog a+ skipChoice newCS =+ retryNoSolution (logSkippedChoice k newCS es) $ \cs' es' ->+ f (csAcc `CS.union` cs') (Just cs') $++ -- Update the conflict map with the conflict set, to make up for+ -- skipping the whole subtree.+ es' { esConflictMap = updateCM cs' (esConflictMap es') }+ -- This function represents the option to not choose a value for this goal.- avoidGoal :: ConflictSet -> ExploreState -> ConflictSetLog a- avoidGoal cs !es =+ avoidGoal :: ConflictSet -> Maybe ConflictSet -> ExploreState -> ConflictSetLog a+ avoidGoal cs _mPreviousCS !es = logBackjump mbj (cs `CS.union` lastCS) $ -- Use 'lastCS' below instead of 'cs' since we do not want to@@ -86,7 +141,7 @@ where reachedBjLimit = case mbj of Nothing -> const False- Just limit -> (== limit)+ Just limit -> (>= limit) -- | Like 'retry', except that it only applies the input function when the -- backjump limit has not been reached.@@ -144,15 +199,20 @@ -- | A tree traversal that simultaneously propagates conflict sets up -- the tree from the leaves and creates a log.-exploreLog :: Maybe Int -> EnableBackjumping -> CountConflicts+exploreLog :: Maybe Int+ -> EnableBackjumping+ -> FineGrainedConflicts+ -> CountConflicts+ -> Index -> Tree Assignment QGoalReason -> ConflictSetLog (Assignment, RevDepMap)-exploreLog mbj enableBj (CountConflicts countConflicts) t = para go t initES+exploreLog mbj enableBj fineGrainedConflicts (CountConflicts countConflicts) idx t =+ para go t initES where getBestGoal' :: P.PSQ (Goal QPN) a -> ConflictMap -> (Goal QPN, a) getBestGoal'- | countConflicts = \ ts cm -> getBestGoal cm ts- | otherwise = \ ts _ -> getFirstGoal ts+ | asBool countConflicts = \ ts cm -> getBestGoal cm ts+ | otherwise = \ ts _ -> getFirstGoal ts go :: TreeF Assignment QGoalReason (ExploreState -> ConflictSetLog (Assignment, RevDepMap), Tree Assignment QGoalReason)@@ -162,20 +222,29 @@ in failWith (Failure c fr) (NoSolution c es') go (DoneF rdm a) = \ _ -> succeedWith Success (a, rdm) go (PChoiceF qpn _ gr ts) =- backjump mbj enableBj (P qpn) (avoidSet (P qpn) gr) $ -- try children in order,- W.mapWithKey -- when descending ...- (\ k r es -> tryWith (TryP qpn k) (r es))- (fmap fst ts)+ backjump mbj enableBj fineGrainedConflicts+ (couldResolveConflicts qpn)+ (logSkippedPackage qpn)+ (P qpn) (avoidSet (P qpn) gr) $ -- try children in order,+ W.mapWithKey -- when descending ...+ (\ k r es -> tryWith (TryP qpn k) (r es))+ (fmap fst ts) go (FChoiceF qfn _ gr _ _ _ ts) =- backjump mbj enableBj (F qfn) (avoidSet (F qfn) gr) $ -- try children in order,- W.mapWithKey -- when descending ...- (\ k r es -> tryWith (TryF qfn k) (r es))- (fmap fst ts)+ backjump mbj enableBj fineGrainedConflicts+ (\_ _ -> Nothing)+ (const logSkippedChoiceSimple)+ (F qfn) (avoidSet (F qfn) gr) $ -- try children in order,+ W.mapWithKey -- when descending ...+ (\ k r es -> tryWith (TryF qfn k) (r es))+ (fmap fst ts) go (SChoiceF qsn _ gr _ ts) =- backjump mbj enableBj (S qsn) (avoidSet (S qsn) gr) $ -- try children in order,- W.mapWithKey -- when descending ...- (\ k r es -> tryWith (TryS qsn k) (r es))- (fmap fst ts)+ backjump mbj enableBj fineGrainedConflicts+ (\_ _ -> Nothing)+ (const logSkippedChoiceSimple)+ (S qsn) (avoidSet (S qsn) gr) $ -- try children in order,+ W.mapWithKey -- when descending ...+ (\ k r es -> tryWith (TryS qsn k) (r es))+ (fmap fst ts) go (GoalChoiceF _ ts) = \ es -> let (k, (v, tree)) = getBestGoal' ts (esConflictMap es) in continueWith (Next k) $@@ -194,6 +263,59 @@ , esBackjumps = 0 } + -- Is it possible for this package instance (QPN and POption) to resolve any+ -- of the conflicts that were caused by the previous instance? The default+ -- is true, because it is always safe to explore a package instance.+ -- Skipping it is an optimization. If false, it returns a new conflict set+ -- to be merged with the previous one.+ couldResolveConflicts :: QPN -> POption -> S.Set CS.Conflict -> Maybe ConflictSet+ couldResolveConflicts currentQPN@(Q _ pn) (POption i@(I v _) _) conflicts =+ let (PInfo deps _ _ _) = idx M.! pn M.! i+ qdeps = qualifyDeps (defaultQualifyOptions idx) currentQPN deps++ couldBeResolved :: CS.Conflict -> Maybe ConflictSet+ couldBeResolved CS.OtherConflict = Nothing+ couldBeResolved (CS.GoalConflict conflictingDep) =+ -- Check whether this package instance also has 'conflictingDep'+ -- as a dependency (ignoring flag and stanza choices).+ if null [() | Simple (LDep _ (Dep (PkgComponent qpn _) _)) _ <- qdeps, qpn == conflictingDep]+ then Nothing+ else Just CS.empty+ couldBeResolved (CS.VersionConstraintConflict dep excludedVersion) =+ -- Check whether this package instance also excludes version+ -- 'excludedVersion' of 'dep' (ignoring flag and stanza choices).+ let vrs = [vr | Simple (LDep _ (Dep (PkgComponent qpn _) (Constrained vr))) _ <- qdeps, qpn == dep ]+ vrIntersection = L.foldl' (.&&.) anyVersion vrs+ in if checkVR vrIntersection excludedVersion+ then Nothing+ else -- If we skip this package instance, we need to update the+ -- conflict set to say that 'dep' was also excluded by+ -- this package instance's constraint.+ Just $ CS.singletonWithConflict (P dep) $+ CS.VersionConflict currentQPN (CS.OrderedVersionRange vrIntersection)+ couldBeResolved (CS.VersionConflict reverseDep (CS.OrderedVersionRange excludingVR)) =+ -- Check whether this package instance's version is also excluded+ -- by 'excludingVR'.+ if checkVR excludingVR v+ then Nothing+ else -- If we skip this version, we need to update the conflict+ -- set to say that the reverse dependency also excluded this+ -- version.+ Just $ CS.singletonWithConflict (P reverseDep) (CS.VersionConstraintConflict currentQPN v)+ in fmap CS.unions $ traverse couldBeResolved (S.toList conflicts)++ logSkippedPackage :: QPN -> POption -> ConflictSet -> ExploreState -> ConflictSetLog a+ logSkippedPackage qpn pOption cs es =+ tryWith (TryP qpn pOption) $+ failWith (Skip (fromMaybe S.empty $ CS.lookup (P qpn) cs)) $+ NoSolution cs es++ -- This function is used for flag and stanza choices, but it should not be+ -- called, because there is currently no way to skip a value for a flag or+ -- stanza.+ logSkippedChoiceSimple :: ConflictSet -> ExploreState -> ConflictSetLog a+ logSkippedChoiceSimple cs es = fromProgress $ P.Fail $ NoSolution cs es+ -- | Build a conflict set corresponding to the (virtual) option not to -- choose a solution for a goal at all. --@@ -219,8 +341,10 @@ -- conflict set. -- avoidSet :: Var QPN -> QGoalReason -> ConflictSet-avoidSet var gr =- CS.union (CS.singleton var) (goalReasonToCS gr)+avoidSet var@(P qpn) gr =+ CS.union (CS.singleton var) (goalReasonToConflictSetWithConflict qpn gr)+avoidSet var gr =+ CS.union (CS.singleton var) (goalReasonToConflictSet gr) -- | Interface. --@@ -229,11 +353,15 @@ -- backtracking is completely disabled. backjumpAndExplore :: Maybe Int -> EnableBackjumping+ -> FineGrainedConflicts -> CountConflicts+ -> Index -> Tree d QGoalReason -> RetryLog Message SolverFailure (Assignment, RevDepMap)-backjumpAndExplore mbj enableBj countConflicts =- mapFailure convertFailure . exploreLog mbj enableBj countConflicts . assign+backjumpAndExplore mbj enableBj fineGrainedConflicts countConflicts idx =+ mapFailure convertFailure+ . exploreLog mbj enableBj fineGrainedConflicts countConflicts idx+ . assign where convertFailure (NoSolution cs es) = ExhaustiveSearch cs (esConflictMap es) convertFailure BackjumpLimit = BackjumpLimitReached
cabal/cabal-install/Distribution/Solver/Modular/Index.hs view
@@ -1,15 +1,19 @@ module Distribution.Solver.Modular.Index ( Index , PInfo(..)+ , ComponentInfo(..)+ , IsVisible(..) , IsBuildable(..) , defaultQualifyOptions , mkIndex ) where -import Data.List as L-import Data.Map as M import Prelude hiding (pi) +import Data.Map (Map)+import qualified Data.List as L+import qualified Data.Map as M+ import Distribution.Solver.Modular.Dependency import Distribution.Solver.Modular.Flag import Distribution.Solver.Modular.Package@@ -28,10 +32,24 @@ -- globally, for reasons external to the solver. We currently use this -- for shadowing which essentially is a GHC limitation, and for -- installed packages that are broken.-data PInfo = PInfo (FlaggedDeps PN) (Map ExposedComponent IsBuildable) FlagInfo (Maybe FailReason)+data PInfo = PInfo (FlaggedDeps PN)+ (Map ExposedComponent ComponentInfo)+ FlagInfo+ (Maybe FailReason) +-- | Info associated with each library and executable in a package instance.+data ComponentInfo = ComponentInfo {+ compIsVisible :: IsVisible+ , compIsBuildable :: IsBuildable+ }++-- | Whether a component is visible in the current environment.+newtype IsVisible = IsVisible Bool+ deriving Eq+ -- | Whether a component is made unbuildable by a "buildable: False" field. newtype IsBuildable = IsBuildable Bool+ deriving Eq mkIndex :: [(PN, I, PInfo)] -> Index mkIndex xs = M.map M.fromList (groupMap (L.map (\ (pn, i, pi) -> (pn, (i, pi))) xs))
cabal/cabal-install/Distribution/Solver/Modular/IndexConversion.hs view
@@ -2,30 +2,28 @@ ( convPIs ) where -import Data.List as L-import Data.Map.Strict (Map)+import Distribution.Solver.Compat.Prelude+import Prelude ()++import qualified Data.List as L import qualified Data.Map.Strict as M-import Data.Maybe-import Data.Monoid as Mon-import Data.Set as S+import qualified Distribution.Compat.NonEmptySet as NonEmptySet+import qualified Data.Set as S +import qualified Distribution.InstalledPackageInfo as IPI import Distribution.Compiler-import Distribution.InstalledPackageInfo as IPI import Distribution.Package -- from Cabal import Distribution.Simple.BuildToolDepends -- from Cabal-import Distribution.Simple.Utils (cabalVersion) -- from Cabal import Distribution.Types.ExeDependency -- from Cabal import Distribution.Types.PkgconfigDependency -- from Cabal import Distribution.Types.ComponentName -- from Cabal-import Distribution.Types.UnqualComponentName -- from Cabal import Distribution.Types.CondTree -- from Cabal import Distribution.Types.MungedPackageId -- from Cabal import Distribution.Types.MungedPackageName -- from Cabal-import Distribution.PackageDescription as PD -- from Cabal-import Distribution.PackageDescription.Configuration as PDC+import Distribution.PackageDescription -- from Cabal+import Distribution.PackageDescription.Configuration import qualified Distribution.Simple.PackageIndex as SI import Distribution.System-import Distribution.Types.ForeignLib import Distribution.Solver.Types.ComponentDeps ( Component(..), componentNameToComponent )@@ -81,26 +79,33 @@ | sip = (pn, i, PInfo fdeps comps fds (Just Shadowed)) shadow x = x --- | Extract/recover the the package ID from an installed package info, and convert it to a solver's I.-convId :: InstalledPackageInfo -> (PN, I)+-- | Extract/recover the package ID from an installed package info, and convert it to a solver's I.+convId :: IPI.InstalledPackageInfo -> (PN, I) convId ipi = (pn, I ver $ Inst $ IPI.installedUnitId ipi) where MungedPackageId mpn ver = mungedId ipi -- HACK. See Note [Index conversion with internal libraries] pn = encodeCompatPackageName mpn -- | Convert a single installed package into the solver-specific format.-convIP :: SI.InstalledPackageIndex -> InstalledPackageInfo -> (PN, I, PInfo)+convIP :: SI.InstalledPackageIndex -> IPI.InstalledPackageInfo -> (PN, I, PInfo) convIP idx ipi =- case mapM (convIPId (DependencyReason pn M.empty S.empty) comp idx) (IPI.depends ipi) of+ case traverse (convIPId (DependencyReason pn M.empty S.empty) comp idx) (IPI.depends ipi) of Nothing -> (pn, i, PInfo [] M.empty M.empty (Just Broken))- Just fds -> ( pn- , i- , PInfo fds (M.singleton ExposedLib (IsBuildable True)) M.empty Nothing)+ Just fds -> ( pn, i, PInfo fds components M.empty Nothing) where+ -- TODO: Handle sub-libraries and visibility.+ components =+ M.singleton (ExposedLib LMainLibName)+ ComponentInfo {+ compIsVisible = IsVisible True+ , compIsBuildable = IsBuildable True+ }+ (pn, i) = convId ipi+ -- 'sourceLibName' is unreliable, but for now we only really use this for -- primary libs anyways- comp = componentNameToComponent $ CLibName $ sourceLibName ipi+ comp = componentNameToComponent $ CLibName $ IPI.sourceLibName ipi -- TODO: Installed packages should also store their encapsulations! -- Note [Index conversion with internal libraries]@@ -141,7 +146,8 @@ case SI.lookupUnitId idx ipid of Nothing -> Nothing Just ipi -> let (pn, i) = convId ipi- in Just (D.Simple (LDep dr (Dep (PkgComponent pn ExposedLib) (Fixed i))) comp)+ name = ExposedLib LMainLibName -- TODO: Handle sub-libraries.+ in Just (D.Simple (LDep dr (Dep (PkgComponent pn name) (Fixed i))) comp) -- NB: something we pick up from the -- InstalledPackageIndex is NEVER an executable @@ -170,24 +176,16 @@ -> StrongFlags -> SolveExecutables -> PN -> GenericPackageDescription -> PInfo convGPD os arch cinfo constraints strfl solveExes pn- (GenericPackageDescription pkg flags mlib sub_libs flibs exes tests benchs) =+ (GenericPackageDescription pkg scannedVersion flags mlib sub_libs flibs exes tests benchs) = let fds = flagInfo strfl flags - -- | We have to be careful to filter out dependencies on- -- internal libraries, since they don't refer to real packages- -- and thus cannot actually be solved over. We'll do this- -- by creating a set of package names which are "internal"- -- and dropping them as we convert. - ipns = S.fromList $ [ unqualComponentNameToPackageName nm- | (nm, _) <- sub_libs ]-- conv :: Mon.Monoid a => Component -> (a -> BuildInfo) -> DependencyReason PN ->+ conv :: Monoid a => Component -> (a -> BuildInfo) -> DependencyReason PN -> CondTree ConfVar [Dependency] a -> FlaggedDeps PN conv comp getInfo dr =- convCondTree M.empty dr pkg os arch cinfo pn fds comp getInfo ipns solveExes .- PDC.addBuildableCondition getInfo+ convCondTree M.empty dr pkg os arch cinfo pn fds comp getInfo solveExes .+ addBuildableCondition getInfo initDR = DependencyReason pn M.empty S.empty @@ -207,63 +205,59 @@ addStanza :: Stanza -> DependencyReason pn -> DependencyReason pn addStanza s (DependencyReason pn' fs ss) = DependencyReason pn' fs (S.insert s ss) - -- | We infer the maximally supported spec-version from @lib:Cabal@'s version- --- -- As we cannot predict the future, we can only properly support- -- spec-versions predating (and including) the @lib:Cabal@ version- -- used by @cabal-install@.- --- -- This relies on 'cabalVersion' having always at least 3 components to avoid- -- comparisons like @2.0.0 > 2.0@ which would result in confusing results.- --- -- NOTE: Before we can switch to a /normalised/ spec-version- -- comparison (e.g. by truncating to 3 components, and removing- -- trailing zeroes) we'd have to make sure all other places where- -- the spec-version is compared against a bound do it- -- consistently.- maxSpecVer = cabalVersion-- -- | Required/declared spec-version of the package- --- -- We don't truncate patch-levels, as specifying a patch-level- -- spec-version is discouraged and not supported anymore starting- -- with spec-version 2.2.- reqSpecVer = specVersion pkg- -- | A too-new specVersion is turned into a global 'FailReason' -- which prevents the solver from selecting this release (and if -- forced to, emit a meaningful solver error message).- fr | reqSpecVer > maxSpecVer = Just (UnsupportedSpecVer reqSpecVer)- | otherwise = Nothing+ fr = case scannedVersion of+ Just ver -> Just (UnsupportedSpecVer ver)+ Nothing -> Nothing - components :: Map ExposedComponent IsBuildable- components = M.fromList $ libComps ++ exeComps+ components :: Map ExposedComponent ComponentInfo+ components = M.fromList $ libComps ++ subLibComps ++ exeComps where- libComps = [ (ExposedLib, IsBuildable $ isBuildable libBuildInfo lib)+ libComps = [ (ExposedLib LMainLibName, libToComponentInfo lib) | lib <- maybeToList mlib ]- exeComps = [ (ExposedExe name, IsBuildable $ isBuildable buildInfo exe)+ subLibComps = [ (ExposedLib (LSubLibName name), libToComponentInfo lib)+ | (name, lib) <- sub_libs ]+ exeComps = [ ( ExposedExe name+ , ComponentInfo {+ compIsVisible = IsVisible True+ , compIsBuildable = IsBuildable $ testCondition (buildable . buildInfo) exe /= Just False+ }+ ) | (name, exe) <- exes ]- isBuildable = isBuildableComponent os arch cinfo constraints + libToComponentInfo lib =+ ComponentInfo {+ compIsVisible = IsVisible $ testCondition (isPrivate . libVisibility) lib /= Just True+ , compIsBuildable = IsBuildable $ testCondition (buildable . libBuildInfo) lib /= Just False+ }++ testCondition = testConditionForComponent os arch cinfo constraints++ isPrivate LibraryVisibilityPrivate = True+ isPrivate LibraryVisibilityPublic = False+ in PInfo flagged_deps components fds fr --- | Returns true if the component is buildable in the given environment.--- This function can give false-positives. For example, it only considers flags--- that are set by unqualified flag constraints, and it doesn't check whether--- the intra-package dependencies of a component are buildable. It is also--- possible for the solver to later assign a value to an automatic flag that--- makes the component unbuildable.-isBuildableComponent :: OS- -> Arch- -> CompilerInfo- -> [LabeledPackageConstraint]- -> (a -> BuildInfo)- -> CondTree ConfVar [Dependency] a- -> Bool-isBuildableComponent os arch cinfo constraints getInfo tree =- case simplifyCondition $ extractCondition (buildable . getInfo) tree of- Lit False -> False- _ -> True+-- | Applies the given predicate (for example, testing buildability or+-- visibility) to the given component and environment. Values are combined with+-- AND. This function returns 'Nothing' when the result cannot be determined+-- before dependency solving. Additionally, this function only considers flags+-- that are set by unqualified flag constraints, and it doesn't check the+-- intra-package dependencies of a component.+testConditionForComponent :: OS+ -> Arch+ -> CompilerInfo+ -> [LabeledPackageConstraint]+ -> (a -> Bool)+ -> CondTree ConfVar [Dependency] a+ -> Maybe Bool+testConditionForComponent os arch cinfo constraints p tree =+ case go $ extractCondition p tree of+ Lit True -> Just True+ Lit False -> Just False+ _ -> Nothing where flagAssignment :: [(FlagName, Bool)] flagAssignment =@@ -274,10 +268,10 @@ -- Simplify the condition, using the current environment. Most of this -- function was copied from convBranch and -- Distribution.Types.Condition.simplifyCondition.- simplifyCondition :: Condition ConfVar -> Condition ConfVar- simplifyCondition (Var (OS os')) = Lit (os == os')- simplifyCondition (Var (Arch arch')) = Lit (arch == arch')- simplifyCondition (Var (Impl cf cvr))+ go :: Condition ConfVar -> Condition ConfVar+ go (Var (OS os')) = Lit (os == os')+ go (Var (Arch arch')) = Lit (arch == arch')+ go (Var (Impl cf cvr)) | matchImpl (compilerInfoId cinfo) || -- fixme: Nothing should be treated as unknown, rather than empty -- list. This code should eventually be changed to either@@ -287,24 +281,24 @@ | otherwise = Lit False where matchImpl (CompilerId cf' cv) = cf == cf' && checkVR cvr cv- simplifyCondition (Var (Flag f))+ go (Var (PackageFlag f)) | Just b <- L.lookup f flagAssignment = Lit b- simplifyCondition (Var v) = Var v- simplifyCondition (Lit b) = Lit b- simplifyCondition (CNot c) =- case simplifyCondition c of+ go (Var v) = Var v+ go (Lit b) = Lit b+ go (CNot c) =+ case go c of Lit True -> Lit False Lit False -> Lit True c' -> CNot c'- simplifyCondition (COr c d) =- case (simplifyCondition c, simplifyCondition d) of+ go (COr c d) =+ case (go c, go d) of (Lit False, d') -> d' (Lit True, _) -> Lit True (c', Lit False) -> c' (_, Lit True) -> Lit True (c', d') -> COr c' d'- simplifyCondition (CAnd c d) =- case (simplifyCondition c, simplifyCondition d) of+ go (CAnd c d) =+ case (go c, go d) of (Lit False, _) -> Lit False (Lit True, d') -> d' (_, Lit False) -> Lit False@@ -321,46 +315,36 @@ -- | Convert flag information. Automatic flags are now considered weak -- unless strong flags have been selected explicitly.-flagInfo :: StrongFlags -> [PD.Flag] -> FlagInfo+flagInfo :: StrongFlags -> [PackageFlag] -> FlagInfo flagInfo (StrongFlags strfl) =- M.fromList . L.map (\ (MkFlag fn _ b m) -> (fn, FInfo b (flagType m) (weak m)))+ M.fromList . L.map (\ (MkPackageFlag fn _ b m) -> (fn, FInfo b (flagType m) (weak m))) where weak m = WeakOrTrivial $ not (strfl || m) flagType m = if m then Manual else Automatic --- | Internal package names, which should not be interpreted as true--- dependencies.-type IPNs = Set PN---- | Convenience function to delete a 'Dependency' if it's--- for a 'PN' that isn't actually real.-filterIPNs :: IPNs -> Dependency -> Maybe Dependency-filterIPNs ipns d@(Dependency pn _ _)- | S.notMember pn ipns = Just d- | otherwise = Nothing- -- | Convert condition trees to flagged dependencies. Mutually -- recursive with 'convBranch'. See 'convBranch' for an explanation -- of all arguments preceding the input 'CondTree'. convCondTree :: Map FlagName Bool -> DependencyReason PN -> PackageDescription -> OS -> Arch -> CompilerInfo -> PN -> FlagInfo -> Component -> (a -> BuildInfo) ->- IPNs -> SolveExecutables -> CondTree ConfVar [Dependency] a -> FlaggedDeps PN-convCondTree flags dr pkg os arch cinfo pn fds comp getInfo ipns solveExes@(SolveExecutables solveExes') (CondNode info ds branches) =+convCondTree flags dr pkg os arch cinfo pn fds comp getInfo solveExes@(SolveExecutables solveExes') (CondNode info ds branches) = -- Merge all library and build-tool dependencies at every level in -- the tree of flagged dependencies. Otherwise 'extractCommon' -- could create duplicate dependencies, and the number of -- duplicates could grow exponentially from the leaves to the root -- of the tree. mergeSimpleDeps $- L.map (\d -> D.Simple (convLibDep dr d) comp)- (mapMaybe (filterIPNs ipns) ds) -- unconditional package dependencies- ++ L.map (\e -> D.Simple (LDep dr (Ext e)) comp) (PD.allExtensions bi) -- unconditional extension dependencies- ++ L.map (\l -> D.Simple (LDep dr (Lang l)) comp) (PD.allLanguages bi) -- unconditional language dependencies- ++ L.map (\(PkgconfigDependency pkn vr) -> D.Simple (LDep dr (Pkg pkn vr)) comp) (PD.pkgconfigDepends bi) -- unconditional pkg-config dependencies- ++ concatMap (convBranch flags dr pkg os arch cinfo pn fds comp getInfo ipns solveExes) branches+ [ D.Simple singleDep comp+ | dep <- ds+ , singleDep <- convLibDeps dr dep ] -- unconditional package dependencies++ ++ L.map (\e -> D.Simple (LDep dr (Ext e)) comp) (allExtensions bi) -- unconditional extension dependencies+ ++ L.map (\l -> D.Simple (LDep dr (Lang l)) comp) (allLanguages bi) -- unconditional language dependencies+ ++ L.map (\(PkgconfigDependency pkn vr) -> D.Simple (LDep dr (Pkg pkn vr)) comp) (pkgconfigDepends bi) -- unconditional pkg-config dependencies+ ++ concatMap (convBranch flags dr pkg os arch cinfo pn fds comp getInfo solveExes) branches -- build-tools dependencies -- NB: Only include these dependencies if SolveExecutables -- is True. It might be false in the legacy solver@@ -476,14 +460,13 @@ -> FlagInfo -> Component -> (a -> BuildInfo)- -> IPNs -> SolveExecutables -> CondBranch ConfVar [Dependency] a -> FlaggedDeps PN-convBranch flags dr pkg os arch cinfo pn fds comp getInfo ipns solveExes (CondBranch c' t' mf') =+convBranch flags dr pkg os arch cinfo pn fds comp getInfo solveExes (CondBranch c' t' mf') = go c'- (\flags' dr' -> convCondTree flags' dr' pkg os arch cinfo pn fds comp getInfo ipns solveExes t')- (\flags' dr' -> maybe [] (convCondTree flags' dr' pkg os arch cinfo pn fds comp getInfo ipns solveExes) mf')+ (\flags' dr' -> convCondTree flags' dr' pkg os arch cinfo pn fds comp getInfo solveExes t')+ (\flags' dr' -> maybe [] (convCondTree flags' dr' pkg os arch cinfo pn fds comp getInfo solveExes) mf') flags dr where go :: Condition ConfVar@@ -495,7 +478,7 @@ go (CNot c) t f = go c f t go (CAnd c d) t f = go c (go d t f) f go (COr c d) t f = go c t (go d t f)- go (Var (Flag fn)) t f = \flags' ->+ go (Var (PackageFlag fn)) t f = \flags' -> case M.lookup fn flags' of Just True -> t flags' Just False -> f flags'@@ -560,9 +543,12 @@ unionDRs (DependencyReason pn' fs1 ss1) (DependencyReason _ fs2 ss2) = DependencyReason pn' (M.union fs1 fs2) (S.union ss1 ss2) --- | Convert a Cabal dependency on a library to a solver-specific dependency.-convLibDep :: DependencyReason PN -> Dependency -> LDep PN-convLibDep dr (Dependency pn vr _) = LDep dr $ Dep (PkgComponent pn ExposedLib) (Constrained vr)+-- | Convert a Cabal dependency on a set of library components (from a single+-- package) to solver-specific dependencies.+convLibDeps :: DependencyReason PN -> Dependency -> [LDep PN]+convLibDeps dr (Dependency pn vr libs) =+ [ LDep dr $ Dep (PkgComponent pn (ExposedLib lib)) (Constrained vr)+ | lib <- NonEmptySet.toList libs ] -- | Convert a Cabal dependency on an executable (build-tools) to a solver-specific dependency. convExeDep :: DependencyReason PN -> ExeDependency -> LDep PN@@ -571,5 +557,6 @@ -- | Convert setup dependencies convSetupBuildInfo :: PN -> SetupBuildInfo -> FlaggedDeps PN convSetupBuildInfo pn nfo =- L.map (\d -> D.Simple (convLibDep (DependencyReason pn M.empty S.empty) d) ComponentSetup)- (PD.setupDepends nfo)+ [ D.Simple singleDep ComponentSetup+ | dep <- setupDepends nfo+ , singleDep <- convLibDeps (DependencyReason pn M.empty S.empty) dep ]
cabal/cabal-install/Distribution/Solver/Modular/LabeledGraph.hs view
@@ -17,10 +17,11 @@ , topSort ) where +import Distribution.Solver.Compat.Prelude+import Prelude ()+ import Data.Array import Data.Graph (Vertex, Bounds)-import Data.List (sortBy)-import Data.Maybe (mapMaybe) import qualified Data.Graph as G {-------------------------------------------------------------------------------
cabal/cabal-install/Distribution/Solver/Modular/Linking.hs view
@@ -1,5 +1,8 @@ {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE MultiParamTypeClasses #-}++-- TODO: remove this+{-# OPTIONS -fno-warn-incomplete-uni-patterns #-} module Distribution.Solver.Modular.Linking ( validateLinking ) where@@ -10,7 +13,6 @@ import Control.Exception (assert) import Control.Monad.Reader import Control.Monad.State-import Data.Function (on) import Data.Map ((!)) import qualified Data.Map as M import qualified Data.Set as S@@ -248,7 +250,7 @@ vs <- get let lg = M.findWithDefault (lgSingleton qpn Nothing) qpn $ vsLinks vs lg' = M.findWithDefault (lgSingleton qpn' Nothing) qpn' $ vsLinks vs- lg'' <- lift' $ lgMerge ((CS.union `on` dependencyReasonToCS) dr1 dr2) lg lg'+ lg'' <- lift' $ lgMerge ((CS.union `on` dependencyReasonToConflictSet) dr1 dr2) lg lg' updateLinkGroup lg'' (Flagged fn _ t f, ~(Flagged _ _ t' f')) -> do vs <- get@@ -264,7 +266,7 @@ Just False -> return () -- stanza not enabled; no new deps -- For extensions and language dependencies, there is nothing to do. -- No choice is involved, just checking, so there is nothing to link.- -- The same goes for for pkg-config constraints.+ -- The same goes for pkg-config constraints. (Simple (LDep _ (Ext _)) _, _) -> return () (Simple (LDep _ (Lang _)) _, _) -> return () (Simple (LDep _ (Pkg _ _)) _, _) -> return ()
cabal/cabal-install/Distribution/Solver/Modular/Message.hs view
@@ -6,10 +6,16 @@ ) where import qualified Data.List as L+import Data.Map (Map)+import qualified Data.Map as M+import Data.Set (Set)+import qualified Data.Set as S+import Data.Maybe (catMaybes, mapMaybe) import Prelude hiding (pi) import Distribution.Pretty (prettyShow) -- from Cabal +import qualified Distribution.Solver.Modular.ConflictSet as CS import Distribution.Solver.Modular.Dependency import Distribution.Solver.Modular.Flag import Distribution.Solver.Modular.Package@@ -19,6 +25,7 @@ import Distribution.Solver.Types.ConstraintSource import Distribution.Solver.Types.PackagePath import Distribution.Solver.Types.Progress+import Distribution.Types.LibraryName import Distribution.Types.UnqualComponentName data Message =@@ -28,6 +35,7 @@ | TryF QFN Bool | TryS QSN Bool | Next (Goal QPN)+ | Skip (Set CS.Conflict) | Success | Failure ConflictSet FailReason @@ -47,6 +55,8 @@ -- complex patterns go !l (Step (TryP qpn i) (Step Enter (Step (Failure c fr) (Step Leave ms)))) = goPReject l qpn [i] c fr ms+ go !l (Step (TryP qpn i) (Step Enter (Step (Skip conflicts) (Step Leave ms)))) =+ goPSkip l qpn [i] conflicts ms go !l (Step (TryF qfn b) (Step Enter (Step (Failure c fr) (Step Leave ms)))) = (atLevel l $ "rejecting: " ++ showQFNBool qfn b ++ showFR c fr) (go l ms) go !l (Step (TryS qsn b) (Step Enter (Step (Failure c fr) (Step Leave ms)))) =@@ -63,6 +73,9 @@ go !l (Step (TryS qsn b) ms) = (atLevel l $ "trying: " ++ showQSNBool qsn b) (go l ms) go !l (Step (Next (Goal (P qpn) gr)) ms) = (atLevel l $ showPackageGoal qpn gr) (go l ms) go !l (Step (Next _) ms) = go l ms -- ignore flag goals in the log+ go !l (Step (Skip conflicts) ms) =+ -- 'Skip' should always be handled by 'goPSkip' in the case above.+ (atLevel l $ "skipping: " ++ showConflicts conflicts) (go l ms) go !l (Step (Success) ms) = (atLevel l $ "done") (go l ms) go !l (Step (Failure c fr) ms) = (atLevel l $ showFailure c fr) (go l ms) @@ -85,12 +98,112 @@ goPReject l qpn is c fr ms = (atLevel l $ "rejecting: " ++ L.intercalate ", " (map (showQPNPOpt qpn) (reverse is)) ++ showFR c fr) (go l ms) + -- Handle many subsequent skipped package instances.+ goPSkip :: Int+ -> QPN+ -> [POption]+ -> Set CS.Conflict+ -> Progress Message a b+ -> Progress String a b+ goPSkip l qpn is conflicts (Step (TryP qpn' i) (Step Enter (Step (Skip conflicts') (Step Leave ms))))+ | qpn == qpn' && conflicts == conflicts' = goPSkip l qpn (i : is) conflicts ms+ goPSkip l qpn is conflicts ms =+ let msg = "skipping: "+ ++ L.intercalate ", " (map (showQPNPOpt qpn) (reverse is))+ ++ showConflicts conflicts+ in atLevel l msg (go l ms)+ -- write a message with the current level number atLevel :: Int -> String -> Progress String a b -> Progress String a b atLevel l x xs = let s = show l in Step ("[" ++ replicate (3 - length s) '_' ++ s ++ "] " ++ x) xs +-- | Display the set of 'Conflicts' for a skipped package version.+showConflicts :: Set CS.Conflict -> String+showConflicts conflicts =+ " (has the same characteristics that caused the previous version to fail: "+ ++ conflictMsg ++ ")"+ where+ conflictMsg :: String+ conflictMsg =+ if S.member CS.OtherConflict conflicts+ then+ -- This case shouldn't happen, because an unknown conflict should not+ -- cause a version to be skipped.+ "unknown conflict"+ else let mergedConflicts =+ [ showConflict qpn conflict+ | (qpn, conflict) <- M.toList (mergeConflicts conflicts) ]+ in if L.null mergedConflicts+ then+ -- This case shouldn't happen unless backjumping is turned off.+ "none"+ else L.intercalate "; " mergedConflicts++ -- Merge conflicts to simplify the log message.+ mergeConflicts :: Set CS.Conflict -> Map QPN MergedPackageConflict+ mergeConflicts = M.fromListWith mergeConflict . mapMaybe toMergedConflict . S.toList+ where+ mergeConflict :: MergedPackageConflict+ -> MergedPackageConflict+ -> MergedPackageConflict+ mergeConflict mergedConflict1 mergedConflict2 = MergedPackageConflict {+ isGoalConflict =+ isGoalConflict mergedConflict1 || isGoalConflict mergedConflict2+ , versionConstraintConflict =+ L.nub $ versionConstraintConflict mergedConflict1+ ++ versionConstraintConflict mergedConflict2+ , versionConflict =+ mergeVersionConflicts (versionConflict mergedConflict1)+ (versionConflict mergedConflict2)+ }+ where+ mergeVersionConflicts (Just vr1) (Just vr2) = Just (vr1 .||. vr2)+ mergeVersionConflicts (Just vr1) Nothing = Just vr1+ mergeVersionConflicts Nothing (Just vr2) = Just vr2+ mergeVersionConflicts Nothing Nothing = Nothing++ toMergedConflict :: CS.Conflict -> Maybe (QPN, MergedPackageConflict)+ toMergedConflict (CS.GoalConflict qpn) =+ Just (qpn, MergedPackageConflict True [] Nothing)+ toMergedConflict (CS.VersionConstraintConflict qpn v) =+ Just (qpn, MergedPackageConflict False [v] Nothing)+ toMergedConflict (CS.VersionConflict qpn (CS.OrderedVersionRange vr)) =+ Just (qpn, MergedPackageConflict False [] (Just vr))+ toMergedConflict CS.OtherConflict = Nothing++ showConflict :: QPN -> MergedPackageConflict -> String+ showConflict qpn mergedConflict = L.intercalate "; " conflictStrings+ where+ conflictStrings = catMaybes [+ case () of+ () | isGoalConflict mergedConflict -> Just $+ "depends on '" ++ showQPN qpn ++ "'" +++ (if null (versionConstraintConflict mergedConflict)+ then ""+ else " but excludes "+ ++ showVersions (versionConstraintConflict mergedConflict))+ | not $ L.null (versionConstraintConflict mergedConflict) -> Just $+ "excludes '" ++ showQPN qpn+ ++ "' " ++ showVersions (versionConstraintConflict mergedConflict)+ | otherwise -> Nothing+ , (\vr -> "excluded by constraint '" ++ showVR vr ++ "' from '" ++ showQPN qpn ++ "'")+ <$> versionConflict mergedConflict+ ]++ showVersions [] = "no versions"+ showVersions [v] = "version " ++ showVer v+ showVersions vs = "versions " ++ L.intercalate ", " (map showVer vs)++-- | All conflicts related to one package, used for simplifying the display of+-- a 'Set CS.Conflict'.+data MergedPackageConflict = MergedPackageConflict {+ isGoalConflict :: Bool+ , versionConstraintConflict :: [Ver]+ , versionConflict :: Maybe VR+ }+ showQPNPOpt :: QPN -> POption -> String showQPNPOpt qpn@(Q _pp pn) (POption i linkedTo) = case linkedTo of@@ -108,8 +221,10 @@ showFR _ (NewPackageDoesNotMatchExistingConstraint d) = " (conflict: " ++ showConflictingDep d ++ ")" showFR _ (ConflictingConstraints d1 d2) = " (conflict: " ++ L.intercalate ", " (L.map showConflictingDep [d1, d2]) ++ ")" showFR _ (NewPackageIsMissingRequiredComponent comp dr) = " (does not contain " ++ showExposedComponent comp ++ ", which is required by " ++ showDependencyReason dr ++ ")"+showFR _ (NewPackageHasPrivateRequiredComponent comp dr) = " (" ++ showExposedComponent comp ++ " is private, but it is required by " ++ showDependencyReason dr ++ ")" showFR _ (NewPackageHasUnbuildableRequiredComponent comp dr) = " (" ++ showExposedComponent comp ++ " is not buildable in the current environment, but it is required by " ++ showDependencyReason dr ++ ")" showFR _ (PackageRequiresMissingComponent qpn comp) = " (requires " ++ showExposedComponent comp ++ " from " ++ showQPN qpn ++ ", but the component does not exist)"+showFR _ (PackageRequiresPrivateComponent qpn comp) = " (requires " ++ showExposedComponent comp ++ " from " ++ showQPN qpn ++ ", but the component is private)" showFR _ (PackageRequiresUnbuildableComponent qpn comp) = " (requires " ++ showExposedComponent comp ++ " from " ++ showQPN qpn ++ ", but the component is not buildable in the current environment)" showFR _ CannotInstall = " (only already installed instances can be used)" showFR _ CannotReinstall = " (avoiding to reinstall a package with same version but new dependencies)"@@ -135,8 +250,9 @@ showFR _ EmptyGoalChoice = " (INTERNAL ERROR: EMPTY GOAL CHOICE)" showExposedComponent :: ExposedComponent -> String-showExposedComponent ExposedLib = "library"-showExposedComponent (ExposedExe name) = "executable '" ++ unUnqualComponentName name ++ "'"+showExposedComponent (ExposedLib LMainLibName) = "library"+showExposedComponent (ExposedLib (LSubLibName name)) = "library '" ++ unUnqualComponentName name ++ "'"+showExposedComponent (ExposedExe name) = "executable '" ++ unUnqualComponentName name ++ "'" constraintSource :: ConstraintSource -> String constraintSource src = "constraint from " ++ showConstraintSource src@@ -145,8 +261,9 @@ showConflictingDep (ConflictingDep dr (PkgComponent qpn comp) ci) = let DependencyReason qpn' _ _ = dr componentStr = case comp of- ExposedExe exe -> " (exe " ++ unUnqualComponentName exe ++ ")"- ExposedLib -> ""+ ExposedExe exe -> " (exe " ++ unUnqualComponentName exe ++ ")"+ ExposedLib LMainLibName -> ""+ ExposedLib (LSubLibName lib) -> " (lib " ++ unUnqualComponentName lib ++ ")" in case ci of Fixed i -> (if qpn /= qpn' then showDependencyReason dr ++ " => " else "") ++ showQPN qpn ++ componentStr ++ "==" ++ showI i
cabal/cabal-install/Distribution/Solver/Modular/Package.hs view
@@ -18,10 +18,11 @@ , unPN ) where -import Data.List as L+import Prelude ()+import Distribution.Solver.Compat.Prelude import Distribution.Package -- from Cabal-import Distribution.Deprecated.Text (display)+import Distribution.Pretty (prettyShow) import Distribution.Solver.Modular.Version import Distribution.Solver.Types.PackagePath@@ -57,14 +58,12 @@ -- | String representation of an instance. showI :: I -> String showI (I v InRepo) = showVer v-showI (I v (Inst uid)) = showVer v ++ "/installed" ++ shortId uid+showI (I v (Inst uid)) = showVer v ++ "/installed" ++ extractPackageAbiHash uid where- -- A hack to extract the beginning of the package ABI hash- shortId = snip (splitAt 4) (++ "...")- . snip ((\ (x, y) -> (reverse x, y)) . break (=='-') . reverse) ('-':)- . display- snip p f xs = case p xs of- (ys, zs) -> (if L.null zs then id else f) ys+ extractPackageAbiHash xs =+ case first reverse $ break (=='-') $ reverse (prettyShow xs) of+ (ys, []) -> ys+ (ys, _) -> '-' : ys -- | Package instance. A package name and an instance. data PI qpn = PI qpn I
cabal/cabal-install/Distribution/Solver/Modular/Preference.hs view
@@ -21,11 +21,9 @@ import Prelude () import Distribution.Solver.Compat.Prelude -import Data.Function (on) import qualified Data.List as L import qualified Data.Map as M-import Control.Monad.Reader hiding (sequence)-import Data.Traversable (sequence)+import Control.Monad.Trans.Reader (Reader, runReader, ask, local) import Distribution.PackageDescription (lookupFlagAssignment, unFlagAssignment) -- from Cabal @@ -343,7 +341,9 @@ onlyConstrained p = trav go where go (PChoiceF v@(Q _ pn) _ gr _) | not (p pn)- = FailF (varToConflictSet (P v) `CS.union` goalReasonToCS gr) NotExplicit+ = FailF+ (varToConflictSet (P v) `CS.union` goalReasonToConflictSetWithConflict v gr)+ NotExplicit go x = x @@ -460,7 +460,7 @@ -- We just verify package choices. go (PChoiceF qpn rdm gr cs) =- PChoice qpn rdm gr <$> sequence (W.mapWithKey (goP qpn) cs)+ PChoice qpn rdm gr <$> sequenceA (W.mapWithKey (goP qpn) cs) go _otherwise = innM _otherwise
cabal/cabal-install/Distribution/Solver/Modular/RetryLog.hs view
@@ -11,6 +11,9 @@ , tryWith ) where +import Distribution.Solver.Compat.Prelude+import Prelude ()+ import Distribution.Solver.Modular.Message import Distribution.Solver.Types.Progress
cabal/cabal-install/Distribution/Solver/Modular/Solver.hs view
@@ -9,9 +9,12 @@ , PruneAfterFirstSuccess(..) ) where -import Data.Map as M-import Data.List as L-import Data.Set as S+import Distribution.Solver.Compat.Prelude+import Prelude ()++import qualified Data.Map as M+import qualified Data.List as L+import qualified Data.Set as S import Distribution.Verbosity import Distribution.Compiler (CompilerInfo)@@ -57,6 +60,7 @@ data SolverConfig = SolverConfig { reorderGoals :: ReorderGoals, countConflicts :: CountConflicts,+ fineGrainedConflicts :: FineGrainedConflicts, minimizeConflictSet :: MinimizeConflictSet, independentGoals :: IndependentGoals, avoidReinstalls :: AvoidReinstalls,@@ -90,8 +94,8 @@ -> Index -- ^ all available packages as an index -> PkgConfigDb -- ^ available pkg-config pkgs -> (PN -> PackagePreferences) -- ^ preferences- -> Map PN [LabeledPackageConstraint] -- ^ global constraints- -> Set PN -- ^ global goals+ -> M.Map PN [LabeledPackageConstraint] -- ^ global constraints+ -> S.Set PN -- ^ global goals -> RetryLog Message SolverFailure (Assignment, RevDepMap) solve sc cinfo idx pkgConfigDB userPrefs userConstraints userGoals = explorePhase $@@ -104,7 +108,9 @@ where explorePhase = backjumpAndExplore (maxBackjumps sc) (enableBackjumping sc)+ (fineGrainedConflicts sc) (countConflicts sc)+ idx detectCycles = traceTree "cycles.json" id . detectCyclesPhase heuristicsPhase = let heuristicsTree = traceTree "heuristics.json" id
cabal/cabal-install/Distribution/Solver/Modular/Tree.hs view
@@ -102,8 +102,10 @@ | NewPackageDoesNotMatchExistingConstraint ConflictingDep | ConflictingConstraints ConflictingDep ConflictingDep | NewPackageIsMissingRequiredComponent ExposedComponent (DependencyReason QPN)+ | NewPackageHasPrivateRequiredComponent ExposedComponent (DependencyReason QPN) | NewPackageHasUnbuildableRequiredComponent ExposedComponent (DependencyReason QPN) | PackageRequiresMissingComponent QPN ExposedComponent+ | PackageRequiresPrivateComponent QPN ExposedComponent | PackageRequiresUnbuildableComponent QPN ExposedComponent | CannotInstall | CannotReinstall
cabal/cabal-install/Distribution/Solver/Modular/Validate.hs view
@@ -14,12 +14,14 @@ import Control.Applicative import Control.Monad.Reader hiding (sequence)+import Data.Either (lefts) import Data.Function (on)-import Data.List as L-import Data.Set as S import Data.Traversable import Prelude hiding (sequence) +import qualified Data.List as L+import qualified Data.Set as S+ import Language.Haskell.Extension (Extension, Language) import Data.Map.Strict as M@@ -37,6 +39,7 @@ import Distribution.Solver.Types.PackagePath import Distribution.Solver.Types.PkgConfigDb (PkgConfigDb, pkgConfigPkgIsPresent)+import Distribution.Types.LibraryName import Distribution.Types.PkgconfigVersionRange #ifdef DEBUG_CONFLICT_SETS@@ -59,7 +62,7 @@ -- active constraints, we must check that they are consistent with -- the current state. ----- We can actually merge (1) and (2) by saying the the current choice is+-- We can actually merge (1) and (2) by saying the current choice is -- a new active constraint, fixing the choice. -- -- If a test fails, we have detected an inconsistent state. We can@@ -109,8 +112,9 @@ pa :: PreAssignment, -- Map from package name to the components that are provided by the chosen- -- instance of that package, and whether those components are buildable.- availableComponents :: Map QPN (Map ExposedComponent IsBuildable),+ -- instance of that package, and whether those components are visible and+ -- buildable.+ availableComponents :: Map QPN (Map ExposedComponent ComponentInfo), -- Map from package name to the components that are required from that -- package.@@ -300,30 +304,36 @@ local (\ s -> s { pa = PA nppa pfa npsa, requiredComponents = rComps' }) r -- | Check that a newly chosen package instance contains all components that--- are required from that package so far. The components must also be buildable.+-- are required from that package so far. The components must also be visible+-- and buildable. checkComponentsInNewPackage :: ComponentDependencyReasons -> QPN- -> Map ExposedComponent IsBuildable+ -> Map ExposedComponent ComponentInfo -> Either Conflict () checkComponentsInNewPackage required qpn providedComps = case M.toList $ deleteKeys (M.keys providedComps) required of (missingComp, dr) : _ -> Left $ mkConflict missingComp dr NewPackageIsMissingRequiredComponent [] ->- case M.toList $ deleteKeys buildableProvidedComps required of- (unbuildableComp, dr) : _ ->- Left $ mkConflict unbuildableComp dr NewPackageHasUnbuildableRequiredComponent- [] -> Right ()+ let failures = lefts+ [ case () of+ _ | compIsVisible compInfo == IsVisible False ->+ Left $ mkConflict comp dr NewPackageHasPrivateRequiredComponent+ | compIsBuildable compInfo == IsBuildable False ->+ Left $ mkConflict comp dr NewPackageHasUnbuildableRequiredComponent+ | otherwise -> Right ()+ | let merged = M.intersectionWith (,) required providedComps+ , (comp, (dr, compInfo)) <- M.toList merged ]+ in case failures of+ failure : _ -> Left failure+ [] -> Right () where mkConflict :: ExposedComponent -> DependencyReason QPN -> (ExposedComponent -> DependencyReason QPN -> FailReason) -> Conflict mkConflict comp dr mkFailure =- (CS.insert (P qpn) (dependencyReasonToCS dr), mkFailure comp dr)-- buildableProvidedComps :: [ExposedComponent]- buildableProvidedComps = [comp | (comp, IsBuildable True) <- M.toList providedComps]+ (CS.insert (P qpn) (dependencyReasonToConflictSet dr), mkFailure comp dr) deleteKeys :: Ord k => [k] -> Map k v -> Map k v deleteKeys ks m = L.foldr M.delete m ks@@ -393,13 +403,13 @@ extendSingle :: PPreAssignment -> LDep QPN -> Either Conflict PPreAssignment extendSingle a (LDep dr (Ext ext )) = if extSupported ext then Right a- else Left (dependencyReasonToCS dr, UnsupportedExtension ext)+ else Left (dependencyReasonToConflictSet dr, UnsupportedExtension ext) extendSingle a (LDep dr (Lang lang)) = if langSupported lang then Right a- else Left (dependencyReasonToCS dr, UnsupportedLanguage lang)+ else Left (dependencyReasonToConflictSet dr, UnsupportedLanguage lang) extendSingle a (LDep dr (Pkg pn vr)) = if pkgPresent pn vr then Right a- else Left (dependencyReasonToCS dr, MissingPkgconfigPackage pn vr)+ else Left (dependencyReasonToConflictSet dr, MissingPkgconfigPackage pn vr) extendSingle a (LDep dr (Dep dep@(PkgComponent qpn _) ci)) = let mergedDep = M.findWithDefault (MergedDepConstrained []) qpn a in case (\ x -> M.insert qpn x a) <$> merge mergedDep (PkgDep dr dep ci) of@@ -410,13 +420,15 @@ -- the solver chooses foo-2.0, it tries to add the constraint foo==2.0. -- -- TODO: The new constraint is implemented as a dependency from foo to foo's--- library. That isn't correct, because foo might only be needed as a build+-- main library. That isn't correct, because foo might only be needed as a build -- tool dependency. The implemention may need to change when we support -- component-based dependency solving. extendWithPackageChoice :: PI QPN -> PPreAssignment -> Either Conflict PPreAssignment extendWithPackageChoice (PI qpn i) ppa = let mergedDep = M.findWithDefault (MergedDepConstrained []) qpn ppa- newChoice = PkgDep (DependencyReason qpn M.empty S.empty) (PkgComponent qpn ExposedLib) (Fixed i)+ newChoice = PkgDep (DependencyReason qpn M.empty S.empty)+ (PkgComponent qpn (ExposedLib LMainLibName))+ (Fixed i) in case (\ x -> M.insert qpn x ppa) <$> merge mergedDep newChoice of Left (c, (d, _d')) -> -- Don't include the package choice in the -- FailReason, because it is redundant.@@ -448,14 +460,14 @@ merge (MergedDepFixed comp1 vs1 i1) (PkgDep vs2 (PkgComponent p comp2) ci@(Fixed i2)) | i1 == i2 = Right $ MergedDepFixed comp1 vs1 i1 | otherwise =- Left ( (CS.union `on` dependencyReasonToCS) vs1 vs2+ Left ( (CS.union `on` dependencyReasonToConflictSet) vs1 vs2 , ( ConflictingDep vs1 (PkgComponent p comp1) (Fixed i1) , ConflictingDep vs2 (PkgComponent p comp2) ci ) ) merge (MergedDepFixed comp1 vs1 i@(I v _)) (PkgDep vs2 (PkgComponent p comp2) ci@(Constrained vr)) | checkVR vr v = Right $ MergedDepFixed comp1 vs1 i | otherwise =- Left ( (CS.union `on` dependencyReasonToCS) vs1 vs2+ Left ( createConflictSetForVersionConflict p v vs1 vr vs2 , ( ConflictingDep vs1 (PkgComponent p comp1) (Fixed i) , ConflictingDep vs2 (PkgComponent p comp2) ci ) ) @@ -467,7 +479,7 @@ go ((vr, comp1, vs1) : vros) | checkVR vr v = go vros | otherwise =- Left ( (CS.union `on` dependencyReasonToCS) vs1 vs2+ Left ( createConflictSetForVersionConflict p v vs2 vr vs1 , ( ConflictingDep vs1 (PkgComponent p comp1) (Constrained vr) , ConflictingDep vs2 (PkgComponent p comp2) ci ) ) @@ -479,11 +491,50 @@ -- no negative performance impact. vrOrigins ++ [(vr, comp2, vs2)]) +-- | Creates a conflict set representing a conflict between a version constraint+-- and the fixed version chosen for a package.+createConflictSetForVersionConflict :: QPN+ -> Ver+ -> DependencyReason QPN+ -> VR+ -> DependencyReason QPN+ -> ConflictSet+createConflictSetForVersionConflict pkg+ conflictingVersion+ versionDR@(DependencyReason p1 _ _)+ conflictingVersionRange+ versionRangeDR@(DependencyReason p2 _ _) =+ let hasFlagsOrStanzas (DependencyReason _ fs ss) = not (M.null fs) || not (S.null ss)+ in+ -- The solver currently only optimizes the case where there is a conflict+ -- between the version chosen for a package and a version constraint that+ -- is not under any flags or stanzas. Here is how we check for this case:+ --+ -- (1) Choosing a specific version for a package foo is implemented as+ -- adding a dependency from foo to that version of foo (See+ -- extendWithPackageChoice), so we check that the DependencyReason+ -- contains the current package and no flag or stanza choices.+ --+ -- (2) We check that the DependencyReason for the version constraint also+ -- contains no flag or stanza choices.+ --+ -- When these criteria are not met, we fall back to calling+ -- dependencyReasonToConflictSet.+ if p1 == pkg && not (hasFlagsOrStanzas versionDR) && not (hasFlagsOrStanzas versionRangeDR)+ then let cs1 = dependencyReasonToConflictSetWithVersionConflict+ p2+ (CS.OrderedVersionRange conflictingVersionRange)+ versionDR+ cs2 = dependencyReasonToConflictSetWithVersionConstraintConflict+ pkg conflictingVersion versionRangeDR+ in cs1 `CS.union` cs2+ else dependencyReasonToConflictSet versionRangeDR `CS.union` dependencyReasonToConflictSet versionDR+ -- | Takes a list of new dependencies and uses it to try to update the map of -- known component dependencies. It returns a failure when a new dependency--- requires a component that is missing or unbuildable in a previously chosen--- packages.-extendRequiredComponents :: Map QPN (Map ExposedComponent IsBuildable)+-- requires a component that is missing, private, or unbuildable in a previously+-- chosen package.+extendRequiredComponents :: Map QPN (Map ExposedComponent ComponentInfo) -> Map QPN ComponentDependencyReasons -> [LDep QPN] -> Either Conflict (Map QPN ComponentDependencyReasons)@@ -494,16 +545,21 @@ -> Either Conflict (Map QPN ComponentDependencyReasons) extendSingle required (LDep dr (Dep (PkgComponent qpn comp) _)) = let compDeps = M.findWithDefault M.empty qpn required+ success = Right $ M.insertWith M.union qpn (M.insert comp dr compDeps) required in -- Only check for the existence of the component if its package has -- already been chosen. case M.lookup qpn available of- Just comps- | M.notMember comp comps ->- Left $ mkConflict qpn comp dr PackageRequiresMissingComponent- | L.notElem comp (buildableComps comps) ->- Left $ mkConflict qpn comp dr PackageRequiresUnbuildableComponent- _ ->- Right $ M.insertWith M.union qpn (M.insert comp dr compDeps) required+ Just comps ->+ case M.lookup comp comps of+ Nothing ->+ Left $ mkConflict qpn comp dr PackageRequiresMissingComponent+ Just compInfo+ | compIsVisible compInfo == IsVisible False ->+ Left $ mkConflict qpn comp dr PackageRequiresPrivateComponent+ | compIsBuildable compInfo == IsBuildable False ->+ Left $ mkConflict qpn comp dr PackageRequiresUnbuildableComponent+ | otherwise -> success+ Nothing -> success extendSingle required _ = Right required mkConflict :: QPN@@ -512,10 +568,7 @@ -> (QPN -> ExposedComponent -> FailReason) -> Conflict mkConflict qpn comp dr mkFailure =- (CS.insert (P qpn) (dependencyReasonToCS dr), mkFailure qpn comp)-- buildableComps :: Map comp IsBuildable -> [comp]- buildableComps comps = [comp | (comp, IsBuildable True) <- M.toList comps]+ (CS.insert (P qpn) (dependencyReasonToConflictSet dr), mkFailure qpn comp) -- | Interface.
cabal/cabal-install/Distribution/Solver/Modular/Version.hs view
@@ -11,22 +11,25 @@ , (.||.) ) where +import Distribution.Solver.Compat.Prelude+import Prelude ()+ import qualified Distribution.Version as CV -- from Cabal-import Distribution.Deprecated.Text -- from Cabal+import Distribution.Pretty (prettyShow) -- | Preliminary type for versions. type Ver = CV.Version -- | String representation of a version. showVer :: Ver -> String-showVer = display+showVer = prettyShow -- | Version range. Consists of a lower and upper bound. type VR = CV.VersionRange -- | String representation of a version range. showVR :: VR -> String-showVR = display+showVR = prettyShow -- | Unconstrained version range. anyVR :: VR
cabal/cabal-install/Distribution/Solver/Types/ComponentDeps.hs view
@@ -34,6 +34,7 @@ , libraryDeps , setupDeps , select+ , components ) where import Prelude ()@@ -43,9 +44,12 @@ import qualified Data.Map as Map import Data.Foldable (fold) +import Distribution.Pretty (Pretty (..)) import qualified Distribution.Types.ComponentName as CN import qualified Distribution.Types.LibraryName as LN+import qualified Text.PrettyPrint as PP + {------------------------------------------------------------------------------- Types -------------------------------------------------------------------------------}@@ -62,7 +66,17 @@ deriving (Show, Eq, Ord, Generic) instance Binary Component+instance Structured Component +instance Pretty Component where+ pretty ComponentLib = PP.text "lib"+ pretty (ComponentSubLib n) = PP.text "lib:" <<>> pretty n+ pretty (ComponentFLib n) = PP.text "flib:" <<>> pretty n+ pretty (ComponentExe n) = PP.text "exe:" <<>> pretty n+ pretty (ComponentTest n) = PP.text "test:" <<>> pretty n+ pretty (ComponentBench n) = PP.text "bench:" <<>> pretty n+ pretty ComponentSetup = PP.text "setup"+ -- | Dependency for a single component. type ComponentDep a = (Component, a) @@ -89,6 +103,7 @@ traverse f = fmap ComponentDeps . traverse f . unComponentDeps instance Binary a => Binary (ComponentDeps a)+instance Structured a => Structured (ComponentDeps a) componentNameToComponent :: CN.ComponentName -> Component componentNameToComponent (CN.CLibName LN.LMainLibName) = ComponentLib@@ -176,6 +191,10 @@ libraryDeps = select (\c -> case c of ComponentSubLib _ -> True ComponentLib -> True _ -> False)++-- | List components+components :: ComponentDeps a -> Set Component+components = Map.keysSet . unComponentDeps -- | Setup dependencies. setupDeps :: Monoid a => ComponentDeps a -> a
cabal/cabal-install/Distribution/Solver/Types/ConstraintSource.hs view
@@ -4,8 +4,8 @@ , showConstraintSource ) where -import GHC.Generics (Generic)-import Distribution.Compat.Binary (Binary(..))+import Distribution.Solver.Compat.Prelude+import Prelude () -- | Source of a 'PackageConstraint'. data ConstraintSource =@@ -56,6 +56,7 @@ deriving (Eq, Show, Generic) instance Binary ConstraintSource+instance Structured ConstraintSource -- | Description of a 'ConstraintSource'. showConstraintSource :: ConstraintSource -> String
cabal/cabal-install/Distribution/Solver/Types/DependencyResolver.hs view
@@ -2,7 +2,8 @@ ( DependencyResolver ) where -import Data.Set (Set)+import Distribution.Solver.Compat.Prelude+import Prelude () import Distribution.Solver.Types.LabeledPackageConstraint import Distribution.Solver.Types.PkgConfigDb ( PkgConfigDb )
cabal/cabal-install/Distribution/Solver/Types/Flag.hs view
@@ -2,5 +2,7 @@ ( FlagType(..) ) where +import Prelude (Eq, Show)+ data FlagType = Manual | Automatic deriving (Eq, Show)
cabal/cabal-install/Distribution/Solver/Types/InstSolverPackage.hs view
@@ -1,9 +1,11 @@ {-# LANGUAGE DeriveGeneric #-}-module Distribution.Solver.Types.InstSolverPackage +module Distribution.Solver.Types.InstSolverPackage ( InstSolverPackage(..) ) where -import Distribution.Compat.Binary (Binary(..))+import Distribution.Solver.Compat.Prelude+import Prelude ()+ import Distribution.Package ( Package(..), HasMungedPackageId(..), HasUnitId(..) ) import Distribution.Solver.Types.ComponentDeps ( ComponentDeps ) import Distribution.Solver.Types.SolverId@@ -11,9 +13,8 @@ import Distribution.Types.PackageId import Distribution.Types.MungedPackageName import Distribution.InstalledPackageInfo (InstalledPackageInfo)-import GHC.Generics (Generic) --- | An 'InstSolverPackage' is a pre-existing installed pacakge+-- | An 'InstSolverPackage' is a pre-existing installed package -- specified by the dependency solver. data InstSolverPackage = InstSolverPackage { instSolverPkgIPI :: InstalledPackageInfo,@@ -23,6 +24,7 @@ deriving (Eq, Show, Generic) instance Binary InstSolverPackage+instance Structured InstSolverPackage instance Package InstSolverPackage where packageId i =
cabal/cabal-install/Distribution/Solver/Types/InstalledPreference.hs view
@@ -2,6 +2,8 @@ ( InstalledPreference(..), ) where +import Prelude (Show)+ -- | Whether we prefer an installed version of a package or simply the latest -- version. --
cabal/cabal-install/Distribution/Solver/Types/OptionalStanza.hs view
@@ -6,12 +6,10 @@ , enableStanzas ) where -import GHC.Generics (Generic)-import Data.Typeable-import Distribution.Compat.Binary (Binary(..))+import Distribution.Solver.Compat.Prelude+import Prelude () import Distribution.Types.ComponentRequestedSpec (ComponentRequestedSpec(..), defaultComponentRequestedSpec)-import Data.List (foldl') data OptionalStanza = TestStanzas@@ -32,3 +30,4 @@ addStanza enabled BenchStanzas = enabled { benchmarksRequested = True } instance Binary OptionalStanza+instance Structured OptionalStanza
cabal/cabal-install/Distribution/Solver/Types/PackageConstraint.hs view
@@ -18,22 +18,19 @@ packageConstraintToDependency ) where -import Distribution.Compat.Binary (Binary(..))-import Distribution.Package (PackageName)-import Distribution.PackageDescription (FlagAssignment, dispFlagAssignment)-import Distribution.Types.Dependency (Dependency(..))-import Distribution.Types.LibraryName (LibraryName(..))-import Distribution.Version (VersionRange, simplifyVersionRange)+import Distribution.Solver.Compat.Prelude+import Prelude () -import Distribution.Solver.Compat.Prelude ((<<>>))+import Distribution.Package (PackageName)+import Distribution.PackageDescription (FlagAssignment, dispFlagAssignment)+import Distribution.Pretty (flatStyle, pretty)+import Distribution.Types.PackageVersionConstraint (PackageVersionConstraint (..))+import Distribution.Version (VersionRange, simplifyVersionRange)+ import Distribution.Solver.Types.OptionalStanza import Distribution.Solver.Types.PackagePath -import Distribution.Deprecated.Text (disp, flatStyle)-import GHC.Generics (Generic)-import Text.PrettyPrint ((<+>)) import qualified Text.PrettyPrint as Disp-import qualified Data.Set as Set -- | Determines to what packages and in what contexts a@@ -87,10 +84,10 @@ -- | Pretty-prints a constraint scope. dispConstraintScope :: ConstraintScope -> Disp.Doc-dispConstraintScope (ScopeTarget pn) = disp pn <<>> Disp.text "." <<>> disp pn-dispConstraintScope (ScopeQualified q pn) = dispQualifier q <<>> disp pn-dispConstraintScope (ScopeAnySetupQualifier pn) = Disp.text "setup." <<>> disp pn-dispConstraintScope (ScopeAnyQualifier pn) = Disp.text "any." <<>> disp pn+dispConstraintScope (ScopeTarget pn) = pretty pn <<>> Disp.text "." <<>> pretty pn+dispConstraintScope (ScopeQualified q pn) = dispQualifier q <<>> pretty pn+dispConstraintScope (ScopeAnySetupQualifier pn) = Disp.text "setup." <<>> pretty pn+dispConstraintScope (ScopeAnyQualifier pn) = Disp.text "any." <<>> pretty pn -- | A package property is a logical predicate on packages. data PackageProperty@@ -102,10 +99,11 @@ deriving (Eq, Show, Generic) instance Binary PackageProperty+instance Structured PackageProperty -- | Pretty-prints a package property. dispPackageProperty :: PackageProperty -> Disp.Doc-dispPackageProperty (PackagePropertyVersion verrange) = disp verrange+dispPackageProperty (PackagePropertyVersion verrange) = pretty verrange dispPackageProperty PackagePropertyInstalled = Disp.text "installed" dispPackageProperty PackagePropertySource = Disp.text "source" dispPackageProperty (PackagePropertyFlags flags) = dispFlagAssignment flags@@ -140,11 +138,10 @@ _ -> id -- | Lossily convert a 'PackageConstraint' to a 'Dependency'.-packageConstraintToDependency :: PackageConstraint -> Maybe Dependency+packageConstraintToDependency :: PackageConstraint -> Maybe PackageVersionConstraint packageConstraintToDependency (PackageConstraint scope prop) = toDep prop where- toDep (PackagePropertyVersion vr) = - Just $ Dependency (scopeToPackageName scope) vr (Set.singleton LMainLibName)+ toDep (PackagePropertyVersion vr) = Just $ PackageVersionConstraint (scopeToPackageName scope) vr toDep (PackagePropertyInstalled) = Nothing toDep (PackagePropertySource) = Nothing toDep (PackagePropertyFlags _) = Nothing
cabal/cabal-install/Distribution/Solver/Types/PackageIndex.hs view
@@ -21,6 +21,7 @@ -- * Updates merge,+ override, insert, deletePackageName, deletePackageId,@@ -39,6 +40,7 @@ searchByName, SearchResult(..), searchByNameSubstring,+ searchWithPredicate, -- ** Bulk queries allPackages,@@ -59,7 +61,7 @@ import Distribution.Version ( VersionRange, withinRange ) import Distribution.Simple.Utils- ( lowercase, comparing )+ ( lowercase ) import qualified Prelude (foldr1) @@ -158,6 +160,7 @@ assert (invariant i1 && invariant i2) $ mkPackageIndex (Map.unionWith mergeBuckets m1 m2) + -- | Elements in the second list mask those in the first. mergeBuckets :: Package pkg => [pkg] -> [pkg] -> [pkg] mergeBuckets [] ys = ys@@ -168,6 +171,16 @@ EQ -> y : mergeBuckets xs' ys' LT -> x : mergeBuckets xs' ys +-- | Override-merge oftwo indexes.+--+-- Packages from the second mask packages of the same exact name+-- (case-sensitively) from the first.+--+override :: Package pkg => PackageIndex pkg -> PackageIndex pkg -> PackageIndex pkg+override i1@(PackageIndex m1) i2@(PackageIndex m2) =+ assert (invariant i1 && invariant i2) $+ mkPackageIndex (Map.unionWith (\_l r -> r) m1 m2)+ -- | Inserts a single package into the index. -- -- This is equivalent to (but slightly quicker than) using 'mappend' or@@ -312,9 +325,14 @@ -- searchByNameSubstring :: PackageIndex pkg -> String -> [(PackageName, [pkg])]-searchByNameSubstring (PackageIndex m) searchterm =+searchByNameSubstring index searchterm =+ searchWithPredicate index (\n -> lsearchterm `isInfixOf` lowercase n)+ where lsearchterm = lowercase searchterm++searchWithPredicate :: PackageIndex pkg+ -> (String -> Bool) -> [(PackageName, [pkg])]+searchWithPredicate (PackageIndex m) predicate = [ pkgs | pkgs@(pname, _) <- Map.toList m- , lsearchterm `isInfixOf` lowercase (unPackageName pname) ]- where- lsearchterm = lowercase searchterm+ , predicate (unPackageName pname)+ ]
cabal/cabal-install/Distribution/Solver/Types/PackagePath.hs view
@@ -9,10 +9,11 @@ , showQPN ) where -import Distribution.Package-import Distribution.Deprecated.Text+import Distribution.Solver.Compat.Prelude+import Prelude ()+import Distribution.Package (PackageName)+import Distribution.Pretty (pretty, flatStyle) import qualified Text.PrettyPrint as Disp-import Distribution.Solver.Compat.Prelude ((<<>>)) -- | A package path consists of a namespace and a package path inside that -- namespace.@@ -35,7 +36,7 @@ -- ends in a period, so it can be prepended onto a qualifier. dispNamespace :: Namespace -> Disp.Doc dispNamespace DefaultNamespace = Disp.empty-dispNamespace (Independent i) = disp i <<>> Disp.text "."+dispNamespace (Independent i) = pretty i <<>> Disp.text "." -- | Qualifier of a package within a namespace (see 'PackagePath') data Qualifier =@@ -79,10 +80,10 @@ -- 'Base' qualifier, will always be @base@). dispQualifier :: Qualifier -> Disp.Doc dispQualifier QualToplevel = Disp.empty-dispQualifier (QualSetup pn) = disp pn <<>> Disp.text ":setup."-dispQualifier (QualExe pn pn2) = disp pn <<>> Disp.text ":" <<>>- disp pn2 <<>> Disp.text ":exe."-dispQualifier (QualBase pn) = disp pn <<>> Disp.text "."+dispQualifier (QualSetup pn) = pretty pn <<>> Disp.text ":setup."+dispQualifier (QualExe pn pn2) = pretty pn <<>> Disp.text ":" <<>>+ pretty pn2 <<>> Disp.text ":exe."+dispQualifier (QualBase pn) = pretty pn <<>> Disp.text "." -- | A qualified entity. Pairs a package path with the entity. data Qualified a = Q PackagePath a@@ -94,7 +95,7 @@ -- | Pretty-prints a qualified package name. dispQPN :: QPN -> Disp.Doc dispQPN (Q (PackagePath ns qual) pn) =- dispNamespace ns <<>> dispQualifier qual <<>> disp pn+ dispNamespace ns <<>> dispQualifier qual <<>> pretty pn -- | String representation of a qualified package name. showQPN :: QPN -> String
cabal/cabal-install/Distribution/Solver/Types/PkgConfigDb.hs view
@@ -23,7 +23,7 @@ import Distribution.Solver.Compat.Prelude import Prelude () -import Control.Exception (IOException, handle)+import Control.Exception (handle) import qualified Data.Map as M import System.FilePath (splitSearchPath) @@ -50,6 +50,7 @@ deriving (Show, Generic, Typeable) instance Binary PkgConfigDb+instance Structured PkgConfigDb -- | Query pkg-config for the list of installed packages, together -- with their versions. Return a `PkgConfigDb` encapsulating this
cabal/cabal-install/Distribution/Solver/Types/Progress.hs view
@@ -15,7 +15,7 @@ | Done done -- This Functor instance works around a bug in GHC 7.6.3.--- See https://ghc.haskell.org/trac/ghc/ticket/7436#comment:6.+-- See https://gitlab.haskell.org/ghc/ghc/-/issues/7436#note_66637. -- The derived functor instance caused a space leak in the solver. instance Functor (Progress step fail) where fmap f (Step s p) = Step s (fmap f p)
cabal/cabal-install/Distribution/Solver/Types/ResolverPackage.hs view
@@ -6,16 +6,17 @@ , resolverPackageExeDeps ) where +import Distribution.Solver.Compat.Prelude+import Prelude ()+ import Distribution.Solver.Types.InstSolverPackage import Distribution.Solver.Types.SolverId import Distribution.Solver.Types.SolverPackage import qualified Distribution.Solver.Types.ComponentDeps as CD -import Distribution.Compat.Binary (Binary(..)) import Distribution.Compat.Graph (IsNode(..)) import Distribution.Package (Package(..), HasUnitId(..)) import Distribution.Simple.Utils (ordNub)-import GHC.Generics (Generic) -- | The dependency resolver picks either pre-existing installed packages -- or it picks source packages along with package configuration.@@ -27,6 +28,7 @@ deriving (Eq, Show, Generic) instance Binary loc => Binary (ResolverPackage loc)+instance Structured loc => Structured (ResolverPackage loc) instance Package (ResolverPackage loc) where packageId (PreExisting ipkg) = packageId ipkg
cabal/cabal-install/Distribution/Solver/Types/Settings.hs view
@@ -11,16 +11,18 @@ , OnlyConstrained(..) , EnableBackjumping(..) , CountConflicts(..)+ , FineGrainedConflicts(..) , SolveExecutables(..) ) where +import Distribution.Solver.Compat.Prelude+import Prelude ()+ import Distribution.Simple.Setup ( BooleanFlag(..) )-import Distribution.Compat.Binary (Binary(..)) import Distribution.Pretty ( Pretty(pretty) )-import Distribution.Deprecated.Text ( Text(parse) )-import GHC.Generics (Generic)+import Distribution.Parsec ( Parsec(parsec) ) -import qualified Distribution.Deprecated.ReadP as Parse+import qualified Distribution.Compat.CharParsing as P import qualified Text.PrettyPrint as PP newtype ReorderGoals = ReorderGoals Bool@@ -29,6 +31,9 @@ newtype CountConflicts = CountConflicts Bool deriving (BooleanFlag, Eq, Generic, Show) +newtype FineGrainedConflicts = FineGrainedConflicts Bool+ deriving (BooleanFlag, Eq, Generic, Show)+ newtype MinimizeConflictSet = MinimizeConflictSet Bool deriving (BooleanFlag, Eq, Generic, Show) @@ -62,6 +67,7 @@ instance Binary ReorderGoals instance Binary CountConflicts+instance Binary FineGrainedConflicts instance Binary IndependentGoals instance Binary MinimizeConflictSet instance Binary AvoidReinstalls@@ -71,13 +77,25 @@ instance Binary OnlyConstrained instance Binary SolveExecutables +instance Structured ReorderGoals+instance Structured CountConflicts+instance Structured FineGrainedConflicts+instance Structured IndependentGoals+instance Structured MinimizeConflictSet+instance Structured AvoidReinstalls+instance Structured ShadowPkgs+instance Structured StrongFlags+instance Structured AllowBootLibInstalls+instance Structured OnlyConstrained+instance Structured SolveExecutables+ instance Pretty OnlyConstrained where- pretty OnlyConstrainedAll = PP.text "all"+ pretty OnlyConstrainedAll = PP.text "all" pretty OnlyConstrainedNone = PP.text "none" -instance Text OnlyConstrained where- parse = Parse.choice- [ Parse.string "all" >> return OnlyConstrainedAll- , Parse.string "none" >> return OnlyConstrainedNone+instance Parsec OnlyConstrained where+ parsec = P.choice+ [ P.string "all" >> return OnlyConstrainedAll+ , P.string "none" >> return OnlyConstrainedNone ]
cabal/cabal-install/Distribution/Solver/Types/SolverId.hs view
@@ -5,9 +5,10 @@ where -import Distribution.Compat.Binary (Binary(..))+import Distribution.Solver.Compat.Prelude+import Prelude ()+ import Distribution.Package (PackageId, Package(..), UnitId)-import GHC.Generics (Generic) -- | The solver can produce references to existing packages or -- packages we plan to install. Unlike 'ConfiguredId' we don't@@ -19,6 +20,7 @@ deriving (Eq, Ord, Generic) instance Binary SolverId+instance Structured SolverId instance Show SolverId where show = show . solverSrcId
cabal/cabal-install/Distribution/Solver/Types/SolverPackage.hs view
@@ -3,14 +3,15 @@ ( SolverPackage(..) ) where -import Distribution.Compat.Binary (Binary(..))+import Distribution.Solver.Compat.Prelude+import Prelude ()+ import Distribution.Package ( Package(..) ) import Distribution.PackageDescription ( FlagAssignment ) import Distribution.Solver.Types.ComponentDeps ( ComponentDeps ) import Distribution.Solver.Types.OptionalStanza import Distribution.Solver.Types.SolverId import Distribution.Solver.Types.SourcePackage-import GHC.Generics (Generic) -- | A 'SolverPackage' is a package specified by the dependency solver. -- It will get elaborated into a 'ConfiguredPackage' or even an@@ -29,6 +30,7 @@ deriving (Eq, Show, Generic) instance Binary loc => Binary (SolverPackage loc)+instance Structured loc => Structured (SolverPackage loc) instance Package (SolverPackage loc) where packageId = packageId . solverPkgSource
cabal/cabal-install/Distribution/Solver/Types/SourcePackage.hs view
@@ -5,29 +5,32 @@ , SourcePackage(..) ) where +import Distribution.Solver.Compat.Prelude+import Prelude ()+ import Distribution.Package ( PackageId, Package(..) ) import Distribution.PackageDescription ( GenericPackageDescription(..) ) import Data.ByteString.Lazy (ByteString)-import GHC.Generics (Generic)-import Distribution.Compat.Binary (Binary(..))-import Data.Typeable -- | A package description along with the location of the package sources. ---data SourcePackage loc = SourcePackage {- packageInfoId :: PackageId,- packageDescription :: GenericPackageDescription,- packageSource :: loc,- packageDescrOverride :: PackageDescriptionOverride+data SourcePackage loc = SourcePackage+ { srcpkgPackageId :: PackageId+ , srcpkgDescription :: GenericPackageDescription+ -- ^ Note, this field is lazy, e.g. when reading in hackage index+ -- we parse only what we need, not whole index.+ , srcpkgSource :: loc+ , srcpkgDescrOverride :: PackageDescriptionOverride } deriving (Eq, Show, Generic, Typeable) -instance (Binary loc) => Binary (SourcePackage loc)+instance Binary loc => Binary (SourcePackage loc)+instance Structured loc => Structured (SourcePackage loc) -instance Package (SourcePackage a) where packageId = packageInfoId+instance Package (SourcePackage a) where packageId = srcpkgPackageId -- | We sometimes need to override the .cabal file in the tarball with -- the newer one from the package index.
cabal/cabal-install/Distribution/Solver/Types/Variable.hs view
@@ -1,5 +1,7 @@ module Distribution.Solver.Types.Variable where +import Prelude (Eq, Show)+ import Distribution.Solver.Types.OptionalStanza import Distribution.PackageDescription (FlagName)
cabal/cabal-install/LICENSE view
@@ -1,5 +1,8 @@-Copyright (c) 2003-2017, Cabal Development Team.+Copyright (c) 2003-2020, Cabal Development Team. See the AUTHORS file for the full list of copyright holders.++See */LICENSE for the copyright holders of the subcomponents.+ All rights reserved. Redistribution and use in source and binary forms, with or without
cabal/cabal-install/Setup.hs view
@@ -1,63 +1,3 @@-import Distribution.PackageDescription ( PackageDescription )-import Distribution.Simple ( defaultMainWithHooks- , simpleUserHooks- , postBuild- , postCopy- , postInst- )-import Distribution.Simple.InstallDirs ( mandir- , CopyDest (NoCopyDest)- )-import Distribution.Simple.LocalBuildInfo ( LocalBuildInfo(..)- , absoluteInstallDirs- )-import Distribution.Simple.Utils ( installOrdinaryFiles- , notice )-import Distribution.Simple.Setup ( buildVerbosity- , copyDest- , copyVerbosity- , fromFlag- , installVerbosity- )-import Distribution.Verbosity ( Verbosity )--import System.IO ( openFile- , IOMode (WriteMode)- )-import System.Process ( runProcess )-import System.FilePath ( (</>) )---- WARNING to editors of this file:--- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~--- At this moment (Cabal 1.23), whatever you write here must be--- compatible with ALL Cabal libraries which we support bootstrapping--- with. This is because pre-setup-depends versions of cabal-install will--- build Setup.hs against the version of Cabal which MATCHES the library--- that cabal-install was built against. There is no way of overriding--- this behavior without bumping the required 'cabal-version' in our--- Cabal file. Travis will let you know if we fail to install from--- tarball!-+import Distribution.Simple main :: IO ()-main = defaultMainWithHooks $ simpleUserHooks- { postBuild = \ _ flags _ lbi ->- buildManpage lbi (fromFlag $ buildVerbosity flags)- , postCopy = \ _ flags pkg lbi ->- installManpage pkg lbi (fromFlag $ copyVerbosity flags) (fromFlag $ copyDest flags)- , postInst = \ _ flags pkg lbi ->- installManpage pkg lbi (fromFlag $ installVerbosity flags) NoCopyDest- }--buildManpage :: LocalBuildInfo -> Verbosity -> IO ()-buildManpage lbi verbosity = do- let cabal = buildDir lbi </> "cabal/cabal"- manpage = buildDir lbi </> "cabal/cabal.1"- manpageHandle <- openFile manpage WriteMode- notice verbosity ("Generating manual page " ++ manpage ++ " ...")- _ <- runProcess cabal ["manpage"] Nothing Nothing Nothing (Just manpageHandle) Nothing- return ()--installManpage :: PackageDescription -> LocalBuildInfo -> Verbosity -> CopyDest -> IO ()-installManpage pkg lbi verbosity copy = do- let destDir = mandir (absoluteInstallDirs pkg lbi copy) </> "man1"- installOrdinaryFiles verbosity destDir [(buildDir lbi </> "cabal", "cabal.1")]+main = defaultMain
cabal/cabal-install/bootstrap.sh view
@@ -11,6 +11,9 @@ # you don't want profiling and dynamic versions of libraries to be installed in # addition to vanilla, run 'EXTRA_CONFIGURE_OPTS="" ./bootstrap.sh' +echo "DON'T USE THIS SCRIPT IF YOU HAVE other recent cabal-install INSTALLED"+echo "THIS SCRIPT IS MADE FOR BOOTSTRAPPING cabal-install ON NEW ARCHITECTURES"+ #VERBOSE DEFAULT_CONFIGURE_OPTS="--enable-library-profiling --enable-shared" EXTRA_CONFIGURE_OPTS=${EXTRA_CONFIGURE_OPTS-$DEFAULT_CONFIGURE_OPTS}@@ -224,25 +227,25 @@ # >= 2.6.0.2 && < 2.7 NETWORK_VER="2.7.0.0"; NETWORK_VER_REGEXP="2\.[0-7]\." # >= 2.0 && < 2.7-CABAL_VER="3.1.0.0"; CABAL_VER_REGEXP="3\.1\.[0-9]"- # >= 2.5 && < 2.6+CABAL_VER="3.3.0.0"; CABAL_VER_REGEXP="3\.3\.[0-9]"+ # >= 3.3 && < 3.4 TRANS_VER="0.5.5.0"; TRANS_VER_REGEXP="0\.[45]\." # >= 0.2.* && < 0.6 MTL_VER="2.2.2"; MTL_VER_REGEXP="[2]\." # >= 2.0 && < 3-HTTP_VER="4000.3.12"; HTTP_VER_REGEXP="4000\.(2\.([5-9]|1[0-9]|2[0-9])|3\.?)"+HTTP_VER="4000.3.14"; HTTP_VER_REGEXP="4000\.(2\.([5-9]|1[0-9]|2[0-9])|3\.?)" # >= 4000.2.5 < 4000.4-ZLIB_VER="0.6.2"; ZLIB_VER_REGEXP="(0\.5\.([3-9]|1[0-9])|0\.6)"+ZLIB_VER="0.6.2.1"; ZLIB_VER_REGEXP="(0\.5\.([3-9]|1[0-9])|0\.6)" # >= 0.5.3 && <= 0.7-TIME_VER="1.9.1" TIME_VER_REGEXP="1\.[1-9]\.?"+TIME_VER="1.9.3" TIME_VER_REGEXP="1\.[1-9]\.?" # >= 1.1 && < 1.10 RANDOM_VER="1.1" RANDOM_VER_REGEXP="1\.[01]\.?" # >= 1 && < 1.2 STM_VER="2.4.5.0"; STM_VER_REGEXP="2\." # == 2.*-HASHABLE_VER="1.2.7.0"; HASHABLE_VER_REGEXP="1\."+HASHABLE_VER="1.3.0.0"; HASHABLE_VER_REGEXP="1\." # 1.*-ASYNC_VER="2.2.1"; ASYNC_VER_REGEXP="2\."+ASYNC_VER="2.2.2"; ASYNC_VER_REGEXP="2\." # 2.* BASE16_BYTESTRING_VER="0.1.1.6"; BASE16_BYTESTRING_VER_REGEXP="0\.1" # 0.1.*@@ -250,8 +253,8 @@ # >=1.0 CRYPTOHASH_SHA256_VER="0.11.101.0"; CRYPTOHASH_SHA256_VER_REGEXP="0\.11\.?" # 0.11.*-RESOLV_VER="0.1.1.1"; RESOLV_VER_REGEXP="0\.1\.[1-9]"- # >= 0.1.1 && < 0.2+RESOLV_VER="0.1.2.0"; RESOLV_VER_REGEXP="0\.1\.[2-9]"+ # >= 0.1.2 && < 0.2 MINTTY_VER="0.1.2"; MINTTY_VER_REGEXP="0\.1\.?" # 0.1.* ECHO_VER="0.1.3"; ECHO_VER_REGEXP="0\.1\.[3-9]"@@ -260,14 +263,16 @@ # 0.2.2.* ED25519_VER="0.0.5.0"; ED25519_VER_REGEXP="0\.0\.?" # 0.0.*-HACKAGE_SECURITY_VER="0.6.0.0"; HACKAGE_SECURITY_VER_REGEXP="0\.6\."- # >= 0.7.0.0 && < 0.7-TAR_VER="0.5.1.0"; TAR_VER_REGEXP="0\.5\.([1-9]|1[0-9]|0\.[3-9]|0\.1[0-9])\.?"+HACKAGE_SECURITY_VER="0.6.0.1"; HACKAGE_SECURITY_VER_REGEXP="0\.6\."+ # >= 0.6.0.0 && < 0.7+TAR_VER="0.5.1.1"; TAR_VER_REGEXP="0\.5\.([1-9]|1[0-9]|0\.[3-9]|0\.1[0-9])\.?" # >= 0.5.0.3 && < 0.6 DIGEST_VER="0.0.1.2"; DIGEST_REGEXP="0\.0\.(1\.[2-9]|[2-9]\.?)" # >= 0.0.1.2 && < 0.1 LUKKO_VER="0.1.1"; LUKKO_VER_REGEXP="0\.1\.[1-9]" # >= 0.1.1 && <0.2+REGEX_POSIX_VER="0.96.0.0"; REGEX_POSIX_REGEXP="0\.96\.[0-9]"+REGEX_BASE_VER="0.94.0.0"; REGEX_BASE_REGEXP="0\.94\.[0-9]" HACKAGE_URL="https://hackage.haskell.org/package" @@ -472,6 +477,8 @@ info_pkg "tar" ${TAR_VER} ${TAR_VER_REGEXP} info_pkg "digest" ${DIGEST_VER} ${DIGEST_REGEXP} info_pkg "lukko" ${LUKKO_VER} ${LUKKO_REGEXP}+info_pkg "regex-base" ${REGEX_BASE_VER} ${REGEX_BASE_REGEXP}+info_pkg "regex-posix" ${REGEX_POSIX_VER} ${REGEX_POSIX_REGEXP} info_pkg "hackage-security" ${HACKAGE_SECURITY_VER} \ ${HACKAGE_SECURITY_VER_REGEXP} @@ -510,6 +517,8 @@ do_pkg "tar" ${TAR_VER} ${TAR_VER_REGEXP} do_pkg "digest" ${DIGEST_VER} ${DIGEST_REGEXP} do_pkg "lukko" ${LUKKO_VER} ${LUKKO_REGEXP}+do_pkg "regex-base" ${REGEX_BASE_VER} ${REGEX_BASE_REGEXP}+do_pkg "regex-posix" ${REGEX_POSIX_VER} ${REGEX_POSIX_REGEXP} do_pkg "hackage-security" ${HACKAGE_SECURITY_VER} \ ${HACKAGE_SECURITY_VER_REGEXP}
cabal/cabal-install/cabal-install.cabal view
@@ -4,7 +4,7 @@ -- To update this file, edit 'cabal-install.cabal.pp' and run -- 'make cabal-install-prod' in the project's root folder. Name: cabal-install-Version: 3.1.0.0+Version: 3.3.0.0 Synopsis: The command-line interface for Cabal and Hackage. Description: The \'cabal\' command-line program simplifies the process of managing@@ -16,9 +16,9 @@ License-File: LICENSE Author: Cabal Development Team (see AUTHORS file) Maintainer: Cabal Development Team <cabal-devel@haskell.org>-Copyright: 2003-2019, Cabal Development Team+Copyright: 2003-2020, Cabal Development Team Category: Distribution-Build-type: Custom+Build-type: Simple Extra-Source-Files: README.md bash-completion/cabal bootstrap.sh changelog @@ -80,8 +80,10 @@ tests/IntegrationTests2/targets/multiple-tests/cabal.project tests/IntegrationTests2/targets/multiple-tests/p.cabal tests/IntegrationTests2/targets/simple/P.hs+ tests/IntegrationTests2/targets/simple/app/Main.hs tests/IntegrationTests2/targets/simple/cabal.project tests/IntegrationTests2/targets/simple/p.cabal+ tests/IntegrationTests2/targets/simple/q/Q.hs tests/IntegrationTests2/targets/simple/q/QQ.hs tests/IntegrationTests2/targets/simple/q/q.cabal tests/IntegrationTests2/targets/test-only/p.cabal@@ -126,23 +128,18 @@ default: True manual: True -custom-setup- setup-depends:- Cabal >= 2.2,- base,- process >= 1.1.0.1 && < 1.7,- filepath >= 1.3 && < 1.5- executable cabal main-is: Main.hs hs-source-dirs: main default-language: Haskell2010- ghc-options: -Wall -fwarn-tabs+ ghc-options: -Wall -fwarn-tabs -fwarn-incomplete-uni-patterns if impl(ghc >= 8.0) ghc-options: -Wcompat -Wnoncanonical-monad-instances- -Wnoncanonical-monadfail-instances+ if impl(ghc < 8.8)+ ghc-options: -Wnoncanonical-monadfail-instances + ghc-options: -rtsopts -threaded -- On AIX, some legacy BSD operations such as flock(2) are provided by libbsd.a@@ -154,10 +151,10 @@ -- they are needed for as long until cabal-install moves to parsec parser Distribution.Deprecated.ParseUtils Distribution.Deprecated.ReadP- Distribution.Deprecated.Text Distribution.Deprecated.ViewAsFieldDescr Distribution.Client.BuildReports.Anonymous+ Distribution.Client.BuildReports.Lens Distribution.Client.BuildReports.Storage Distribution.Client.BuildReports.Types Distribution.Client.BuildReports.Upload@@ -166,21 +163,24 @@ Distribution.Client.CmdBuild Distribution.Client.CmdClean Distribution.Client.CmdConfigure- Distribution.Client.CmdUpdate Distribution.Client.CmdErrorMessages Distribution.Client.CmdExec Distribution.Client.CmdFreeze Distribution.Client.CmdHaddock Distribution.Client.CmdInstall Distribution.Client.CmdInstall.ClientInstallFlags+ Distribution.Client.CmdInstall.ClientInstallTargetSelector+ Distribution.Client.CmdLegacy+ Distribution.Client.CmdListBin Distribution.Client.CmdRepl Distribution.Client.CmdRun- Distribution.Client.CmdTest- Distribution.Client.CmdLegacy Distribution.Client.CmdSdist+ Distribution.Client.CmdTest+ Distribution.Client.CmdUpdate Distribution.Client.Compat.Directory Distribution.Client.Compat.ExecutablePath Distribution.Client.Compat.FilePerms+ Distribution.Client.Compat.Orphans Distribution.Client.Compat.Prelude Distribution.Client.Compat.Process Distribution.Client.Compat.Semaphore@@ -200,29 +200,39 @@ Distribution.Client.Glob Distribution.Client.GlobalFlags Distribution.Client.Haddock+ Distribution.Client.HashValue Distribution.Client.HttpUtils Distribution.Client.IndexUtils+ Distribution.Client.IndexUtils.ActiveRepos+ Distribution.Client.IndexUtils.IndexState Distribution.Client.IndexUtils.Timestamp Distribution.Client.Init+ Distribution.Client.Init.Command+ Distribution.Client.Init.Defaults+ Distribution.Client.Init.FileCreators Distribution.Client.Init.Heuristics Distribution.Client.Init.Licenses+ Distribution.Client.Init.Prompt Distribution.Client.Init.Types+ Distribution.Client.Init.Utils Distribution.Client.Install Distribution.Client.InstallPlan Distribution.Client.InstallSymlink Distribution.Client.JobControl Distribution.Client.List Distribution.Client.Manpage+ Distribution.Client.ManpageFlags Distribution.Client.Nix+ Distribution.Client.NixStyleOptions Distribution.Client.Outdated Distribution.Client.PackageHash- Distribution.Client.PackageUtils Distribution.Client.ParseUtils Distribution.Client.ProjectBuilding Distribution.Client.ProjectBuilding.Types Distribution.Client.ProjectConfig Distribution.Client.ProjectConfig.Legacy Distribution.Client.ProjectConfig.Types+ Distribution.Client.ProjectFlags Distribution.Client.ProjectOrchestration Distribution.Client.ProjectPlanOutput Distribution.Client.ProjectPlanning@@ -231,10 +241,7 @@ Distribution.Client.Reconfigure Distribution.Client.Run Distribution.Client.Sandbox- Distribution.Client.Sandbox.Index Distribution.Client.Sandbox.PackageEnvironment- Distribution.Client.Sandbox.Timestamp- Distribution.Client.Sandbox.Types Distribution.Client.SavedFlags Distribution.Client.Security.DNS Distribution.Client.Security.HTTP@@ -242,13 +249,28 @@ Distribution.Client.SetupWrapper Distribution.Client.SolverInstallPlan Distribution.Client.SourceFiles- Distribution.Client.SourceRepo Distribution.Client.SrcDist Distribution.Client.Store Distribution.Client.Tar+ Distribution.Client.TargetProblem Distribution.Client.TargetSelector Distribution.Client.Targets Distribution.Client.Types+ Distribution.Client.Types.AllowNewer+ Distribution.Client.Types.BuildResults+ Distribution.Client.Types.ConfiguredId+ Distribution.Client.Types.ConfiguredPackage+ Distribution.Client.Types.Credentials+ Distribution.Client.Types.InstallMethod+ Distribution.Client.Types.OverwritePolicy+ Distribution.Client.Types.PackageLocation+ Distribution.Client.Types.PackageSpecifier+ Distribution.Client.Types.ReadyPackage+ Distribution.Client.Types.Repo+ Distribution.Client.Types.RepoName+ Distribution.Client.Types.SourcePackageDb+ Distribution.Client.Types.SourceRepo+ Distribution.Client.Types.WriteGhcEnvironmentFilesPolicy Distribution.Client.Update Distribution.Client.Upload Distribution.Client.Utils@@ -311,11 +333,11 @@ build-depends: async >= 2.0 && < 2.3, array >= 0.4 && < 0.6,- base >= 4.8 && < 4.14,+ base >= 4.8 && < 4.15, base16-bytestring >= 0.1.1 && < 0.2, binary >= 0.7.3 && < 0.9, bytestring >= 0.10.6.0 && < 0.11,- Cabal == 3.1.*,+ Cabal == 3.3.*, containers >= 0.5.6.2 && < 0.7, cryptohash-sha256 >= 0.11 && < 0.12, deepseq >= 1.4.1.1 && < 1.5,@@ -333,12 +355,14 @@ random >= 1 && < 1.2, stm >= 2.0 && < 2.6, tar >= 0.5.0.3 && < 0.6,- time >= 1.5.0.1 && < 1.10,+ time >= 1.5.0.1 && < 1.11, transformers >= 0.4.2.0 && < 0.6, zlib >= 0.5.3 && < 0.7,- hackage-security >= 0.6.0.0 && < 0.7,+ hackage-security >= 0.6.0.1 && < 0.7, text >= 1.2.3 && < 1.3,- parsec >= 3.1.13.0 && < 3.2+ parsec >= 3.1.13.0 && < 3.2,+ regex-base >= 0.94.0.0 && <0.95,+ regex-posix >= 0.96.0.0 && <0.97 if !impl(ghc >= 8.0) build-depends: fail == 4.9.*@@ -351,7 +375,8 @@ build-depends: resolv >= 0.1.1 && < 0.2 if os(windows)- build-depends: Win32 >= 2 && < 3+ -- newer directory for symlinks+ build-depends: Win32 >= 2 && < 3, directory >=1.3.1.0 else build-depends: unix >= 2.5 && < 2.9
+ cabal/cabal-install/cabal-install.cabal.dev view
@@ -0,0 +1,587 @@+Cabal-Version: 2.0+-- NOTE: This file is autogenerated from 'cabal-install.cabal.pp'.+-- DO NOT EDIT MANUALLY.+-- To update this file, edit 'cabal-install.cabal.pp' and run+-- 'make cabal-install-prod' in the project's root folder.+Name: cabal-install+Version: 3.3.0.0+Synopsis: The command-line interface for Cabal and Hackage.+Description:+ The \'cabal\' command-line program simplifies the process of managing+ Haskell software by automating the fetching, configuration, compilation+ and installation of Haskell libraries and programs.+homepage: http://www.haskell.org/cabal/+bug-reports: https://github.com/haskell/cabal/issues+License: BSD3+License-File: LICENSE+Author: Cabal Development Team (see AUTHORS file)+Maintainer: Cabal Development Team <cabal-devel@haskell.org>+Copyright: 2003-2020, Cabal Development Team+Category: Distribution+Build-type: Simple+Extra-Source-Files:+ README.md bash-completion/cabal bootstrap.sh changelog++ -- Generated with 'make gen-extra-source-files'+ -- Do NOT edit this section manually; instead, run the script.+ -- BEGIN gen-extra-source-files+ tests/IntegrationTests2/build/keep-going/cabal.project+ tests/IntegrationTests2/build/keep-going/p/P.hs+ tests/IntegrationTests2/build/keep-going/p/p.cabal+ tests/IntegrationTests2/build/keep-going/q/Q.hs+ tests/IntegrationTests2/build/keep-going/q/q.cabal+ tests/IntegrationTests2/build/local-tarball/cabal.project+ tests/IntegrationTests2/build/local-tarball/q/Q.hs+ tests/IntegrationTests2/build/local-tarball/q/q.cabal+ tests/IntegrationTests2/build/setup-custom1/A.hs+ tests/IntegrationTests2/build/setup-custom1/Setup.hs+ tests/IntegrationTests2/build/setup-custom1/a.cabal+ tests/IntegrationTests2/build/setup-custom2/A.hs+ tests/IntegrationTests2/build/setup-custom2/Setup.hs+ tests/IntegrationTests2/build/setup-custom2/a.cabal+ tests/IntegrationTests2/build/setup-simple/A.hs+ tests/IntegrationTests2/build/setup-simple/Setup.hs+ tests/IntegrationTests2/build/setup-simple/a.cabal+ tests/IntegrationTests2/exception/bad-config/cabal.project+ tests/IntegrationTests2/exception/build/Main.hs+ tests/IntegrationTests2/exception/build/a.cabal+ tests/IntegrationTests2/exception/configure/a.cabal+ tests/IntegrationTests2/exception/no-pkg/empty.in+ tests/IntegrationTests2/exception/no-pkg2/cabal.project+ tests/IntegrationTests2/regression/3324/cabal.project+ tests/IntegrationTests2/regression/3324/p/P.hs+ tests/IntegrationTests2/regression/3324/p/p.cabal+ tests/IntegrationTests2/regression/3324/q/Q.hs+ tests/IntegrationTests2/regression/3324/q/q.cabal+ tests/IntegrationTests2/targets/all-disabled/cabal.project+ tests/IntegrationTests2/targets/all-disabled/p.cabal+ tests/IntegrationTests2/targets/benchmarks-disabled/cabal.project+ tests/IntegrationTests2/targets/benchmarks-disabled/p.cabal+ tests/IntegrationTests2/targets/benchmarks-disabled/q/q.cabal+ tests/IntegrationTests2/targets/complex/cabal.project+ tests/IntegrationTests2/targets/complex/q/Q.hs+ tests/IntegrationTests2/targets/complex/q/q.cabal+ tests/IntegrationTests2/targets/empty-pkg/cabal.project+ tests/IntegrationTests2/targets/empty-pkg/p.cabal+ tests/IntegrationTests2/targets/empty/cabal.project+ tests/IntegrationTests2/targets/empty/foo.hs+ tests/IntegrationTests2/targets/exes-disabled/cabal.project+ tests/IntegrationTests2/targets/exes-disabled/p/p.cabal+ tests/IntegrationTests2/targets/exes-disabled/q/q.cabal+ tests/IntegrationTests2/targets/lib-only/p.cabal+ tests/IntegrationTests2/targets/libs-disabled/cabal.project+ tests/IntegrationTests2/targets/libs-disabled/p/p.cabal+ tests/IntegrationTests2/targets/libs-disabled/q/q.cabal+ tests/IntegrationTests2/targets/multiple-exes/cabal.project+ tests/IntegrationTests2/targets/multiple-exes/p.cabal+ tests/IntegrationTests2/targets/multiple-libs/cabal.project+ tests/IntegrationTests2/targets/multiple-libs/p/p.cabal+ tests/IntegrationTests2/targets/multiple-libs/q/q.cabal+ tests/IntegrationTests2/targets/multiple-tests/cabal.project+ tests/IntegrationTests2/targets/multiple-tests/p.cabal+ tests/IntegrationTests2/targets/simple/P.hs+ tests/IntegrationTests2/targets/simple/app/Main.hs+ tests/IntegrationTests2/targets/simple/cabal.project+ tests/IntegrationTests2/targets/simple/p.cabal+ tests/IntegrationTests2/targets/simple/q/Q.hs+ tests/IntegrationTests2/targets/simple/q/QQ.hs+ tests/IntegrationTests2/targets/simple/q/q.cabal+ tests/IntegrationTests2/targets/test-only/p.cabal+ tests/IntegrationTests2/targets/tests-disabled/cabal.project+ tests/IntegrationTests2/targets/tests-disabled/p.cabal+ tests/IntegrationTests2/targets/tests-disabled/q/q.cabal+ tests/IntegrationTests2/targets/variety/cabal.project+ tests/IntegrationTests2/targets/variety/p.cabal+ -- END gen-extra-source-files++ -- Additional manual extra-source-files:+ tests/IntegrationTests2/build/local-tarball/p-0.1.tar.gz+++source-repository head+ type: git+ location: https://github.com/haskell/cabal/+ subdir: cabal-install++Flag native-dns+ description: Enable use of the [resolv](https://hackage.haskell.org/package/resolv) & [windns](https://hackage.haskell.org/package/windns) packages for performing DNS lookups+ default: True+ manual: True++Flag debug-expensive-assertions+ description: Enable expensive assertions for testing or debugging+ default: False+ manual: True++Flag debug-conflict-sets+ description: Add additional information to ConflictSets+ default: False+ manual: True++Flag debug-tracetree+ description: Compile in support for tracetree (used to debug the solver)+ default: False+ manual: True++Flag lukko+ description: Use @lukko@ for file-locking+ default: True+ manual: True++library cabal-lib-client+ default-language: Haskell2010+ ghc-options: -Wall -fwarn-tabs -fwarn-incomplete-uni-patterns+ if impl(ghc >= 8.0)+ ghc-options: -Wcompat+ -Wnoncanonical-monad-instances+ if impl(ghc < 8.8)+ ghc-options: -Wnoncanonical-monadfail-instances++ hs-source-dirs: .+ exposed-modules:+ -- this modules are moved from Cabal+ -- they are needed for as long until cabal-install moves to parsec parser+ Distribution.Deprecated.ParseUtils+ Distribution.Deprecated.ReadP+ Distribution.Deprecated.ViewAsFieldDescr++ Distribution.Client.BuildReports.Anonymous+ Distribution.Client.BuildReports.Lens+ Distribution.Client.BuildReports.Storage+ Distribution.Client.BuildReports.Types+ Distribution.Client.BuildReports.Upload+ Distribution.Client.Check+ Distribution.Client.CmdBench+ Distribution.Client.CmdBuild+ Distribution.Client.CmdClean+ Distribution.Client.CmdConfigure+ Distribution.Client.CmdErrorMessages+ Distribution.Client.CmdExec+ Distribution.Client.CmdFreeze+ Distribution.Client.CmdHaddock+ Distribution.Client.CmdInstall+ Distribution.Client.CmdInstall.ClientInstallFlags+ Distribution.Client.CmdInstall.ClientInstallTargetSelector+ Distribution.Client.CmdLegacy+ Distribution.Client.CmdListBin+ Distribution.Client.CmdRepl+ Distribution.Client.CmdRun+ Distribution.Client.CmdSdist+ Distribution.Client.CmdTest+ Distribution.Client.CmdUpdate+ Distribution.Client.Compat.Directory+ Distribution.Client.Compat.ExecutablePath+ Distribution.Client.Compat.FilePerms+ Distribution.Client.Compat.Orphans+ Distribution.Client.Compat.Prelude+ Distribution.Client.Compat.Process+ Distribution.Client.Compat.Semaphore+ Distribution.Client.Config+ Distribution.Client.Configure+ Distribution.Client.Dependency+ Distribution.Client.Dependency.Types+ Distribution.Client.DistDirLayout+ Distribution.Client.Exec+ Distribution.Client.Fetch+ Distribution.Client.FetchUtils+ Distribution.Client.FileMonitor+ Distribution.Client.Freeze+ Distribution.Client.GZipUtils+ Distribution.Client.GenBounds+ Distribution.Client.Get+ Distribution.Client.Glob+ Distribution.Client.GlobalFlags+ Distribution.Client.Haddock+ Distribution.Client.HashValue+ Distribution.Client.HttpUtils+ Distribution.Client.IndexUtils+ Distribution.Client.IndexUtils.ActiveRepos+ Distribution.Client.IndexUtils.IndexState+ Distribution.Client.IndexUtils.Timestamp+ Distribution.Client.Init+ Distribution.Client.Init.Command+ Distribution.Client.Init.Defaults+ Distribution.Client.Init.FileCreators+ Distribution.Client.Init.Heuristics+ Distribution.Client.Init.Licenses+ Distribution.Client.Init.Prompt+ Distribution.Client.Init.Types+ Distribution.Client.Init.Utils+ Distribution.Client.Install+ Distribution.Client.InstallPlan+ Distribution.Client.InstallSymlink+ Distribution.Client.JobControl+ Distribution.Client.List+ Distribution.Client.Manpage+ Distribution.Client.ManpageFlags+ Distribution.Client.Nix+ Distribution.Client.NixStyleOptions+ Distribution.Client.Outdated+ Distribution.Client.PackageHash+ Distribution.Client.ParseUtils+ Distribution.Client.ProjectBuilding+ Distribution.Client.ProjectBuilding.Types+ Distribution.Client.ProjectConfig+ Distribution.Client.ProjectConfig.Legacy+ Distribution.Client.ProjectConfig.Types+ Distribution.Client.ProjectFlags+ Distribution.Client.ProjectOrchestration+ Distribution.Client.ProjectPlanOutput+ Distribution.Client.ProjectPlanning+ Distribution.Client.ProjectPlanning.Types+ Distribution.Client.RebuildMonad+ Distribution.Client.Reconfigure+ Distribution.Client.Run+ Distribution.Client.Sandbox+ Distribution.Client.Sandbox.PackageEnvironment+ Distribution.Client.SavedFlags+ Distribution.Client.Security.DNS+ Distribution.Client.Security.HTTP+ Distribution.Client.Setup+ Distribution.Client.SetupWrapper+ Distribution.Client.SolverInstallPlan+ Distribution.Client.SourceFiles+ Distribution.Client.SrcDist+ Distribution.Client.Store+ Distribution.Client.Tar+ Distribution.Client.TargetProblem+ Distribution.Client.TargetSelector+ Distribution.Client.Targets+ Distribution.Client.Types+ Distribution.Client.Types.AllowNewer+ Distribution.Client.Types.BuildResults+ Distribution.Client.Types.ConfiguredId+ Distribution.Client.Types.ConfiguredPackage+ Distribution.Client.Types.Credentials+ Distribution.Client.Types.InstallMethod+ Distribution.Client.Types.OverwritePolicy+ Distribution.Client.Types.PackageLocation+ Distribution.Client.Types.PackageSpecifier+ Distribution.Client.Types.ReadyPackage+ Distribution.Client.Types.Repo+ Distribution.Client.Types.RepoName+ Distribution.Client.Types.SourcePackageDb+ Distribution.Client.Types.SourceRepo+ Distribution.Client.Types.WriteGhcEnvironmentFilesPolicy+ Distribution.Client.Update+ Distribution.Client.Upload+ Distribution.Client.Utils+ Distribution.Client.Utils.Assertion+ Distribution.Client.Utils.Json+ Distribution.Client.Utils.Parsec+ Distribution.Client.VCS+ Distribution.Client.Win32SelfUpgrade+ Distribution.Client.World+ Distribution.Solver.Compat.Prelude+ Distribution.Solver.Modular+ Distribution.Solver.Modular.Assignment+ Distribution.Solver.Modular.Builder+ Distribution.Solver.Modular.Configured+ Distribution.Solver.Modular.ConfiguredConversion+ Distribution.Solver.Modular.ConflictSet+ Distribution.Solver.Modular.Cycles+ Distribution.Solver.Modular.Dependency+ Distribution.Solver.Modular.Explore+ Distribution.Solver.Modular.Flag+ Distribution.Solver.Modular.Index+ Distribution.Solver.Modular.IndexConversion+ Distribution.Solver.Modular.LabeledGraph+ Distribution.Solver.Modular.Linking+ Distribution.Solver.Modular.Log+ Distribution.Solver.Modular.Message+ Distribution.Solver.Modular.PSQ+ Distribution.Solver.Modular.Package+ Distribution.Solver.Modular.Preference+ Distribution.Solver.Modular.RetryLog+ Distribution.Solver.Modular.Solver+ Distribution.Solver.Modular.Tree+ Distribution.Solver.Modular.Validate+ Distribution.Solver.Modular.Var+ Distribution.Solver.Modular.Version+ Distribution.Solver.Modular.WeightedPSQ+ Distribution.Solver.Types.ComponentDeps+ Distribution.Solver.Types.ConstraintSource+ Distribution.Solver.Types.DependencyResolver+ Distribution.Solver.Types.Flag+ Distribution.Solver.Types.InstSolverPackage+ Distribution.Solver.Types.InstalledPreference+ Distribution.Solver.Types.LabeledPackageConstraint+ Distribution.Solver.Types.OptionalStanza+ Distribution.Solver.Types.PackageConstraint+ Distribution.Solver.Types.PackageFixedDeps+ Distribution.Solver.Types.PackageIndex+ Distribution.Solver.Types.PackagePath+ Distribution.Solver.Types.PackagePreferences+ Distribution.Solver.Types.PkgConfigDb+ Distribution.Solver.Types.Progress+ Distribution.Solver.Types.ResolverPackage+ Distribution.Solver.Types.Settings+ Distribution.Solver.Types.SolverId+ Distribution.Solver.Types.SolverPackage+ Distribution.Solver.Types.SourcePackage+ Distribution.Solver.Types.Variable+ Paths_cabal_install++ autogen-modules:+ Paths_cabal_install+ build-depends:+ async >= 2.0 && < 2.3,+ array >= 0.4 && < 0.6,+ base >= 4.8 && < 4.15,+ base16-bytestring >= 0.1.1 && < 0.2,+ binary >= 0.7.3 && < 0.9,+ bytestring >= 0.10.6.0 && < 0.11,+ Cabal == 3.3.*,+ containers >= 0.5.6.2 && < 0.7,+ cryptohash-sha256 >= 0.11 && < 0.12,+ deepseq >= 1.4.1.1 && < 1.5,+ directory >= 1.2.2.0 && < 1.4,+ echo >= 0.1.3 && < 0.2,+ edit-distance >= 0.2.2 && < 0.3,+ filepath >= 1.4.0.0 && < 1.5,+ hashable >= 1.0 && < 1.4,+ HTTP >= 4000.1.5 && < 4000.4,+ mtl >= 2.0 && < 2.3,+ network-uri >= 2.6.0.2 && < 2.7,+ network >= 2.6 && < 3.2,+ pretty >= 1.1 && < 1.2,+ process >= 1.2.3.0 && < 1.7,+ random >= 1 && < 1.2,+ stm >= 2.0 && < 2.6,+ tar >= 0.5.0.3 && < 0.6,+ time >= 1.5.0.1 && < 1.11,+ transformers >= 0.4.2.0 && < 0.6,+ zlib >= 0.5.3 && < 0.7,+ hackage-security >= 0.6.0.1 && < 0.7,+ text >= 1.2.3 && < 1.3,+ parsec >= 3.1.13.0 && < 3.2,+ regex-base >= 0.94.0.0 && <0.95,+ regex-posix >= 0.96.0.0 && <0.97++ if !impl(ghc >= 8.0)+ build-depends: fail == 4.9.*+ build-depends: semigroups >= 0.18.3 && <0.20++ if flag(native-dns)+ if os(windows)+ build-depends: windns >= 0.1.0 && < 0.2+ else+ build-depends: resolv >= 0.1.1 && < 0.2++ if os(windows)+ -- newer directory for symlinks+ build-depends: Win32 >= 2 && < 3, directory >=1.3.1.0+ else+ build-depends: unix >= 2.5 && < 2.9++ if flag(lukko)+ build-depends: lukko >= 0.1 && <0.2+ else+ build-depends: base >= 4.10++ if flag(debug-expensive-assertions)+ cpp-options: -DDEBUG_EXPENSIVE_ASSERTIONS++ if flag(debug-conflict-sets)+ cpp-options: -DDEBUG_CONFLICT_SETS+ build-depends: base >= 4.8++ if flag(debug-tracetree)+ cpp-options: -DDEBUG_TRACETREE+ build-depends: tracetree >= 0.1 && < 0.2++library cabal-install-solver-dsl+ default-language: Haskell2010+ ghc-options: -Wall -fwarn-tabs -fwarn-incomplete-uni-patterns+ if impl(ghc >= 8.0)+ ghc-options: -Wcompat+ -Wnoncanonical-monad-instances+ if impl(ghc < 8.8)+ ghc-options: -Wnoncanonical-monadfail-instances++ hs-source-dirs: solver-dsl+ exposed-modules:+ UnitTests.Distribution.Solver.Modular.DSL+ build-depends:+ base,+ Cabal,+ containers,+ -- TODO: depend on cabal-install-solver only+ cabal-lib-client+executable cabal+ main-is: Main.hs+ hs-source-dirs: main+ default-language: Haskell2010+ ghc-options: -Wall -fwarn-tabs -fwarn-incomplete-uni-patterns+ if impl(ghc >= 8.0)+ ghc-options: -Wcompat+ -Wnoncanonical-monad-instances+ if impl(ghc < 8.8)+ ghc-options: -Wnoncanonical-monadfail-instances+++ ghc-options: -rtsopts -threaded++ -- On AIX, some legacy BSD operations such as flock(2) are provided by libbsd.a+ if os(aix)+ extra-libraries: bsd+ build-depends:+ cabal-lib-client,+ Cabal,+ base,+ directory,+ filepath++ other-modules: Paths_cabal_install+-- Small, fast running tests.+--+Test-Suite unit-tests+ type: exitcode-stdio-1.0+ main-is: UnitTests.hs+ hs-source-dirs: tests+ ghc-options: -Wall -fwarn-tabs -fwarn-incomplete-uni-patterns -main-is UnitTests+ other-modules:+ UnitTests.Distribution.Client.ArbitraryInstances+ UnitTests.Distribution.Client.BuildReport+ UnitTests.Distribution.Client.Described+ UnitTests.Distribution.Client.DescribedInstances+ UnitTests.Distribution.Client.Targets+ UnitTests.Distribution.Client.FileMonitor+ UnitTests.Distribution.Client.Get+ UnitTests.Distribution.Client.Glob+ UnitTests.Distribution.Client.GZipUtils+ UnitTests.Distribution.Client.Init.FileCreators+ UnitTests.Distribution.Client.Store+ UnitTests.Distribution.Client.Tar+ UnitTests.Distribution.Client.TreeDiffInstances+ UnitTests.Distribution.Client.UserConfig+ UnitTests.Distribution.Client.ProjectConfig+ UnitTests.Distribution.Client.JobControl+ UnitTests.Distribution.Client.IndexUtils.Timestamp+ UnitTests.Distribution.Client.InstallPlan+ UnitTests.Distribution.Client.VCS+ UnitTests.Distribution.Solver.Modular.Builder+ UnitTests.Distribution.Solver.Modular.RetryLog+ UnitTests.Distribution.Solver.Modular.Solver+ UnitTests.Distribution.Solver.Modular.DSL.TestCaseUtils+ UnitTests.Distribution.Solver.Modular.WeightedPSQ+ UnitTests.Options+ UnitTests.TempTestDir+ build-depends:+ array,+ base,+ async,+ bytestring,+ cabal-lib-client,+ cabal-install-solver-dsl,+ Cabal,+ Cabal-described,+ Cabal-tree-diff,+ Cabal-QuickCheck,+ containers,+ deepseq,+ mtl,+ random,+ directory,+ filepath,+ tar,+ time,+ zlib,+ network-uri >= 2.6.2.0 && <2.6.4.0,+ network,+ tasty >= 1.2.3 && <1.4,+ tasty-golden >=2.3.1.1 && <2.4,+ tasty-hunit >= 0.10,+ tasty-quickcheck,+ tagged,+ tree-diff,+ QuickCheck >= 2.14 && <2.15++ ghc-options: -threaded++ default-language: Haskell2010++-- Tests to run with a limited stack and heap size+--+Test-Suite memory-usage-tests+ type: exitcode-stdio-1.0+ main-is: MemoryUsageTests.hs+ hs-source-dirs: tests+ ghc-options: -Wall -fwarn-tabs -fwarn-incomplete-uni-patterns "-with-rtsopts=-M4M -K1K" -main-is MemoryUsageTests+ other-modules:+ UnitTests.Distribution.Solver.Modular.DSL.TestCaseUtils+ UnitTests.Distribution.Solver.Modular.MemoryUsage+ UnitTests.Options+ build-depends:+ base,+ async,+ Cabal,+ cabal-lib-client,+ cabal-install-solver-dsl,+ containers,+ deepseq,+ tagged,+ tasty >= 1.2.3 && <1.4,+ tasty-hunit >= 0.10++ ghc-options: -threaded++ default-language: Haskell2010++-- Slow solver tests+--+Test-Suite solver-quickcheck+ type: exitcode-stdio-1.0+ main-is: SolverQuickCheck.hs+ hs-source-dirs: tests+ ghc-options: -Wall -fwarn-tabs -fwarn-incomplete-uni-patterns -main-is SolverQuickCheck+ other-modules:+ UnitTests.Distribution.Solver.Modular.QuickCheck+ UnitTests.Distribution.Solver.Modular.QuickCheck.Utils+ build-depends:+ base,+ async,+ Cabal,+ Cabal-QuickCheck,+ cabal-lib-client,+ cabal-install-solver-dsl,+ containers,+ deepseq >= 1.2,+ hashable,+ random,+ tagged,+ tasty >= 1.2.3 && <1.4,+ tasty-quickcheck,+ QuickCheck >= 2.14 && <2.15,+ pretty-show >= 1.6.15++ ghc-options: -threaded++ default-language: Haskell2010+++-- Integration tests that use the cabal-install code directly+-- but still build whole projects+test-suite integration-tests2+ type: exitcode-stdio-1.0+ main-is: IntegrationTests2.hs+ hs-source-dirs: tests+ ghc-options: -Wall -fwarn-tabs -fwarn-incomplete-uni-patterns -main-is IntegrationTests2+ other-modules:+ build-depends:+ base,+ bytestring,+ Cabal,+ cabal-lib-client,+ containers,+ deepseq,+ directory,+ edit-distance,+ filepath,+ tasty >= 1.2.3 && <1.4,+ tasty-hunit >= 0.10,+ tagged++ ghc-options: -threaded+ default-language: Haskell2010+
− cabal/cabal-install/cabal-install.cabal.pp
@@ -1,669 +0,0 @@-# lib enabled means that we have internal library: cabal-lib-client-%if CABAL_FLAG_LIB-Cabal-Version: 2.0-%else-Cabal-Version: >= 1.10-%endif- $variable--- NOTE: This file is autogenerated from 'cabal-install.cabal.pp'.--- DO NOT EDIT MANUALLY.--- To update this file, edit 'cabal-install.cabal.pp' and run--- 'make cabal-install-prod' in the project's root folder.-Name: cabal-install-Version: 3.1.0.0-#-# NOTE: when updating build-depends, don't forget to update version regexps in bootstrap.sh.-#-%def CABAL_BUILDDEPENDS- build-depends:- async >= 2.0 && < 2.3,- array >= 0.4 && < 0.6,- base >= 4.8 && < 4.14,- base16-bytestring >= 0.1.1 && < 0.2,- binary >= 0.7.3 && < 0.9,- bytestring >= 0.10.6.0 && < 0.11,- Cabal == 3.1.*,- containers >= 0.5.6.2 && < 0.7,- cryptohash-sha256 >= 0.11 && < 0.12,- deepseq >= 1.4.1.1 && < 1.5,- directory >= 1.2.2.0 && < 1.4,- echo >= 0.1.3 && < 0.2,- edit-distance >= 0.2.2 && < 0.3,- filepath >= 1.4.0.0 && < 1.5,- hashable >= 1.0 && < 1.4,- HTTP >= 4000.1.5 && < 4000.4,- mtl >= 2.0 && < 2.3,- network-uri >= 2.6.0.2 && < 2.7,- network >= 2.6 && < 3.2,- pretty >= 1.1 && < 1.2,- process >= 1.2.3.0 && < 1.7,- random >= 1 && < 1.2,- stm >= 2.0 && < 2.6,- tar >= 0.5.0.3 && < 0.6,- time >= 1.5.0.1 && < 1.10,- transformers >= 0.4.2.0 && < 0.6,- zlib >= 0.5.3 && < 0.7,- hackage-security >= 0.6.0.0 && < 0.7,- text >= 1.2.3 && < 1.3,- parsec >= 3.1.13.0 && < 3.2-- if !impl(ghc >= 8.0)- build-depends: fail == 4.9.*- build-depends: semigroups >= 0.18.3 && <0.20-- if flag(native-dns)- if os(windows)- build-depends: windns >= 0.1.0 && < 0.2- else- build-depends: resolv >= 0.1.1 && < 0.2-- if os(windows)- build-depends: Win32 >= 2 && < 3- else- build-depends: unix >= 2.5 && < 2.9-- if flag(lukko)- build-depends: lukko >= 0.1 && <0.2- else- build-depends: base >= 4.10-%enddef-%def CABAL_COMPONENTCOMMON- default-language: Haskell2010- ghc-options: -Wall -fwarn-tabs- if impl(ghc >= 8.0)- ghc-options: -Wcompat- -Wnoncanonical-monad-instances- -Wnoncanonical-monadfail-instances-%enddef-%def CABAL_BUILDINFO-%if CABAL_FLAG_LIB- exposed-modules:-%else- other-modules:-%endif- -- this modules are moved from Cabal- -- they are needed for as long until cabal-install moves to parsec parser- Distribution.Deprecated.ParseUtils- Distribution.Deprecated.ReadP- Distribution.Deprecated.Text- Distribution.Deprecated.ViewAsFieldDescr-- Distribution.Client.BuildReports.Anonymous- Distribution.Client.BuildReports.Storage- Distribution.Client.BuildReports.Types- Distribution.Client.BuildReports.Upload- Distribution.Client.Check- Distribution.Client.CmdBench- Distribution.Client.CmdBuild- Distribution.Client.CmdClean- Distribution.Client.CmdConfigure- Distribution.Client.CmdUpdate- Distribution.Client.CmdErrorMessages- Distribution.Client.CmdExec- Distribution.Client.CmdFreeze- Distribution.Client.CmdHaddock- Distribution.Client.CmdInstall- Distribution.Client.CmdInstall.ClientInstallFlags- Distribution.Client.CmdRepl- Distribution.Client.CmdRun- Distribution.Client.CmdTest- Distribution.Client.CmdLegacy- Distribution.Client.CmdSdist- Distribution.Client.Compat.Directory- Distribution.Client.Compat.ExecutablePath- Distribution.Client.Compat.FilePerms- Distribution.Client.Compat.Prelude- Distribution.Client.Compat.Process- Distribution.Client.Compat.Semaphore- Distribution.Client.Config- Distribution.Client.Configure- Distribution.Client.Dependency- Distribution.Client.Dependency.Types- Distribution.Client.DistDirLayout- Distribution.Client.Exec- Distribution.Client.Fetch- Distribution.Client.FetchUtils- Distribution.Client.FileMonitor- Distribution.Client.Freeze- Distribution.Client.GZipUtils- Distribution.Client.GenBounds- Distribution.Client.Get- Distribution.Client.Glob- Distribution.Client.GlobalFlags- Distribution.Client.Haddock- Distribution.Client.HttpUtils- Distribution.Client.IndexUtils- Distribution.Client.IndexUtils.Timestamp- Distribution.Client.Init- Distribution.Client.Init.Heuristics- Distribution.Client.Init.Licenses- Distribution.Client.Init.Types- Distribution.Client.Install- Distribution.Client.InstallPlan- Distribution.Client.InstallSymlink- Distribution.Client.JobControl- Distribution.Client.List- Distribution.Client.Manpage- Distribution.Client.Nix- Distribution.Client.Outdated- Distribution.Client.PackageHash- Distribution.Client.PackageUtils- Distribution.Client.ParseUtils- Distribution.Client.ProjectBuilding- Distribution.Client.ProjectBuilding.Types- Distribution.Client.ProjectConfig- Distribution.Client.ProjectConfig.Legacy- Distribution.Client.ProjectConfig.Types- Distribution.Client.ProjectOrchestration- Distribution.Client.ProjectPlanOutput- Distribution.Client.ProjectPlanning- Distribution.Client.ProjectPlanning.Types- Distribution.Client.RebuildMonad- Distribution.Client.Reconfigure- Distribution.Client.Run- Distribution.Client.Sandbox- Distribution.Client.Sandbox.Index- Distribution.Client.Sandbox.PackageEnvironment- Distribution.Client.Sandbox.Timestamp- Distribution.Client.Sandbox.Types- Distribution.Client.SavedFlags- Distribution.Client.Security.DNS- Distribution.Client.Security.HTTP- Distribution.Client.Setup- Distribution.Client.SetupWrapper- Distribution.Client.SolverInstallPlan- Distribution.Client.SourceFiles- Distribution.Client.SourceRepo- Distribution.Client.SrcDist- Distribution.Client.Store- Distribution.Client.Tar- Distribution.Client.TargetSelector- Distribution.Client.Targets- Distribution.Client.Types- Distribution.Client.Update- Distribution.Client.Upload- Distribution.Client.Utils- Distribution.Client.Utils.Assertion- Distribution.Client.Utils.Json- Distribution.Client.Utils.Parsec- Distribution.Client.VCS- Distribution.Client.Win32SelfUpgrade- Distribution.Client.World- Distribution.Solver.Compat.Prelude- Distribution.Solver.Modular- Distribution.Solver.Modular.Assignment- Distribution.Solver.Modular.Builder- Distribution.Solver.Modular.Configured- Distribution.Solver.Modular.ConfiguredConversion- Distribution.Solver.Modular.ConflictSet- Distribution.Solver.Modular.Cycles- Distribution.Solver.Modular.Dependency- Distribution.Solver.Modular.Explore- Distribution.Solver.Modular.Flag- Distribution.Solver.Modular.Index- Distribution.Solver.Modular.IndexConversion- Distribution.Solver.Modular.LabeledGraph- Distribution.Solver.Modular.Linking- Distribution.Solver.Modular.Log- Distribution.Solver.Modular.Message- Distribution.Solver.Modular.PSQ- Distribution.Solver.Modular.Package- Distribution.Solver.Modular.Preference- Distribution.Solver.Modular.RetryLog- Distribution.Solver.Modular.Solver- Distribution.Solver.Modular.Tree- Distribution.Solver.Modular.Validate- Distribution.Solver.Modular.Var- Distribution.Solver.Modular.Version- Distribution.Solver.Modular.WeightedPSQ- Distribution.Solver.Types.ComponentDeps- Distribution.Solver.Types.ConstraintSource- Distribution.Solver.Types.DependencyResolver- Distribution.Solver.Types.Flag- Distribution.Solver.Types.InstSolverPackage- Distribution.Solver.Types.InstalledPreference- Distribution.Solver.Types.LabeledPackageConstraint- Distribution.Solver.Types.OptionalStanza- Distribution.Solver.Types.PackageConstraint- Distribution.Solver.Types.PackageFixedDeps- Distribution.Solver.Types.PackageIndex- Distribution.Solver.Types.PackagePath- Distribution.Solver.Types.PackagePreferences- Distribution.Solver.Types.PkgConfigDb- Distribution.Solver.Types.Progress- Distribution.Solver.Types.ResolverPackage- Distribution.Solver.Types.Settings- Distribution.Solver.Types.SolverId- Distribution.Solver.Types.SolverPackage- Distribution.Solver.Types.SourcePackage- Distribution.Solver.Types.Variable- Paths_cabal_install--%if CABAL_FLAG_LIB- autogen-modules:- Paths_cabal_install-%endif- $CABAL_BUILDDEPENDS-- if flag(debug-expensive-assertions)- cpp-options: -DDEBUG_EXPENSIVE_ASSERTIONS-- if flag(debug-conflict-sets)- cpp-options: -DDEBUG_CONFLICT_SETS- build-depends: base >= 4.8-- if flag(debug-tracetree)- cpp-options: -DDEBUG_TRACETREE- build-depends: tracetree >= 0.1 && < 0.2-%enddef-#-# Package Description-#-Synopsis: The command-line interface for Cabal and Hackage.-Description:- The \'cabal\' command-line program simplifies the process of managing- Haskell software by automating the fetching, configuration, compilation- and installation of Haskell libraries and programs.-homepage: http://www.haskell.org/cabal/-bug-reports: https://github.com/haskell/cabal/issues-License: BSD3-License-File: LICENSE-Author: Cabal Development Team (see AUTHORS file)-Maintainer: Cabal Development Team <cabal-devel@haskell.org>-Copyright: 2003-2019, Cabal Development Team-Category: Distribution-%if CABAL_FLAG_LIB-Build-type: Simple-%else-Build-type: Custom-%endif-Extra-Source-Files:- README.md bash-completion/cabal bootstrap.sh changelog-- -- Generated with 'make gen-extra-source-files'- -- Do NOT edit this section manually; instead, run the script.- -- BEGIN gen-extra-source-files- tests/IntegrationTests2/build/keep-going/cabal.project- tests/IntegrationTests2/build/keep-going/p/P.hs- tests/IntegrationTests2/build/keep-going/p/p.cabal- tests/IntegrationTests2/build/keep-going/q/Q.hs- tests/IntegrationTests2/build/keep-going/q/q.cabal- tests/IntegrationTests2/build/local-tarball/cabal.project- tests/IntegrationTests2/build/local-tarball/q/Q.hs- tests/IntegrationTests2/build/local-tarball/q/q.cabal- tests/IntegrationTests2/build/setup-custom1/A.hs- tests/IntegrationTests2/build/setup-custom1/Setup.hs- tests/IntegrationTests2/build/setup-custom1/a.cabal- tests/IntegrationTests2/build/setup-custom2/A.hs- tests/IntegrationTests2/build/setup-custom2/Setup.hs- tests/IntegrationTests2/build/setup-custom2/a.cabal- tests/IntegrationTests2/build/setup-simple/A.hs- tests/IntegrationTests2/build/setup-simple/Setup.hs- tests/IntegrationTests2/build/setup-simple/a.cabal- tests/IntegrationTests2/exception/bad-config/cabal.project- tests/IntegrationTests2/exception/build/Main.hs- tests/IntegrationTests2/exception/build/a.cabal- tests/IntegrationTests2/exception/configure/a.cabal- tests/IntegrationTests2/exception/no-pkg/empty.in- tests/IntegrationTests2/exception/no-pkg2/cabal.project- tests/IntegrationTests2/regression/3324/cabal.project- tests/IntegrationTests2/regression/3324/p/P.hs- tests/IntegrationTests2/regression/3324/p/p.cabal- tests/IntegrationTests2/regression/3324/q/Q.hs- tests/IntegrationTests2/regression/3324/q/q.cabal- tests/IntegrationTests2/targets/all-disabled/cabal.project- tests/IntegrationTests2/targets/all-disabled/p.cabal- tests/IntegrationTests2/targets/benchmarks-disabled/cabal.project- tests/IntegrationTests2/targets/benchmarks-disabled/p.cabal- tests/IntegrationTests2/targets/benchmarks-disabled/q/q.cabal- tests/IntegrationTests2/targets/complex/cabal.project- tests/IntegrationTests2/targets/complex/q/Q.hs- tests/IntegrationTests2/targets/complex/q/q.cabal- tests/IntegrationTests2/targets/empty-pkg/cabal.project- tests/IntegrationTests2/targets/empty-pkg/p.cabal- tests/IntegrationTests2/targets/empty/cabal.project- tests/IntegrationTests2/targets/empty/foo.hs- tests/IntegrationTests2/targets/exes-disabled/cabal.project- tests/IntegrationTests2/targets/exes-disabled/p/p.cabal- tests/IntegrationTests2/targets/exes-disabled/q/q.cabal- tests/IntegrationTests2/targets/lib-only/p.cabal- tests/IntegrationTests2/targets/libs-disabled/cabal.project- tests/IntegrationTests2/targets/libs-disabled/p/p.cabal- tests/IntegrationTests2/targets/libs-disabled/q/q.cabal- tests/IntegrationTests2/targets/multiple-exes/cabal.project- tests/IntegrationTests2/targets/multiple-exes/p.cabal- tests/IntegrationTests2/targets/multiple-libs/cabal.project- tests/IntegrationTests2/targets/multiple-libs/p/p.cabal- tests/IntegrationTests2/targets/multiple-libs/q/q.cabal- tests/IntegrationTests2/targets/multiple-tests/cabal.project- tests/IntegrationTests2/targets/multiple-tests/p.cabal- tests/IntegrationTests2/targets/simple/P.hs- tests/IntegrationTests2/targets/simple/cabal.project- tests/IntegrationTests2/targets/simple/p.cabal- tests/IntegrationTests2/targets/simple/q/QQ.hs- tests/IntegrationTests2/targets/simple/q/q.cabal- tests/IntegrationTests2/targets/test-only/p.cabal- tests/IntegrationTests2/targets/tests-disabled/cabal.project- tests/IntegrationTests2/targets/tests-disabled/p.cabal- tests/IntegrationTests2/targets/tests-disabled/q/q.cabal- tests/IntegrationTests2/targets/variety/cabal.project- tests/IntegrationTests2/targets/variety/p.cabal- -- END gen-extra-source-files-- -- Additional manual extra-source-files:- tests/IntegrationTests2/build/local-tarball/p-0.1.tar.gz---source-repository head- type: git- location: https://github.com/haskell/cabal/- subdir: cabal-install--Flag native-dns- description: Enable use of the [resolv](https://hackage.haskell.org/package/resolv) & [windns](https://hackage.haskell.org/package/windns) packages for performing DNS lookups- default: True- manual: True--Flag debug-expensive-assertions- description: Enable expensive assertions for testing or debugging- default: False- manual: True--Flag debug-conflict-sets- description: Add additional information to ConflictSets- default: False- manual: True--Flag debug-tracetree- description: Compile in support for tracetree (used to debug the solver)- default: False- manual: True--Flag lukko- description: Use @lukko@ for file-locking- default: True- manual: True--%if CABAL_FLAG_LIB-%else-custom-setup- setup-depends:- Cabal >= 2.2,- base,- process >= 1.1.0.1 && < 1.7,- filepath >= 1.3 && < 1.5--%endif-#-# Libraries, if CABAL_FLAG_LIB-#-%if CABAL_FLAG_LIB-library cabal-lib-client- $CABAL_COMPONENTCOMMON- hs-source-dirs: .- $CABAL_BUILDINFO--library cabal-install-solver-dsl- $CABAL_COMPONENTCOMMON- hs-source-dirs: solver-dsl- exposed-modules:- UnitTests.Distribution.Solver.Modular.DSL- build-depends:- base,- Cabal,- containers,- -- TODO: depend on cabal-install-solver only- cabal-lib-client-%endif-#-# Executable-#-executable cabal- main-is: Main.hs- hs-source-dirs: main- $CABAL_COMPONENTCOMMON-- ghc-options: -rtsopts -threaded-- -- On AIX, some legacy BSD operations such as flock(2) are provided by libbsd.a- if os(aix)- extra-libraries: bsd-%if CABAL_FLAG_LIB- build-depends:- cabal-lib-client,- Cabal,- base,- directory,- filepath-- other-modules: Paths_cabal_install-%else- hs-source-dirs: .- $CABAL_BUILDINFO-%endif-#-# MONOLITHIC exe additions-#-%if CABAL_FLAG_LIB-%if CABAL_FLAG_MONOLITHIC- -- Monolithic: tests fused into executable- hs-source-dirs: tests- other-modules:- UnitTests- MemoryUsageTests- SolverQuickCheck- IntegrationTests2-- UnitTests.Distribution.Client.ArbitraryInstances- UnitTests.Distribution.Client.FileMonitor- UnitTests.Distribution.Client.Get- UnitTests.Distribution.Client.GenericInstances- UnitTests.Distribution.Client.GZipUtils- UnitTests.Distribution.Client.Glob- UnitTests.Distribution.Client.IndexUtils.Timestamp- UnitTests.Distribution.Client.InstallPlan- UnitTests.Distribution.Client.JobControl- UnitTests.Distribution.Client.ProjectConfig- UnitTests.Distribution.Client.Sandbox- UnitTests.Distribution.Client.Sandbox.Timestamp- UnitTests.Distribution.Client.Store- UnitTests.Distribution.Client.Tar- UnitTests.Distribution.Client.Targets- UnitTests.Distribution.Client.TreeDiffInstances- UnitTests.Distribution.Client.UserConfig- UnitTests.Distribution.Client.VCS- UnitTests.Distribution.Solver.Modular.Builder- UnitTests.Distribution.Solver.Modular.DSL.TestCaseUtils- UnitTests.Distribution.Solver.Modular.MemoryUsage- UnitTests.Distribution.Solver.Modular.QuickCheck- UnitTests.Distribution.Solver.Modular.QuickCheck.Utils- UnitTests.Distribution.Solver.Modular.RetryLog- UnitTests.Distribution.Solver.Modular.Solver- UnitTests.Distribution.Solver.Modular.WeightedPSQ- UnitTests.Options- UnitTests.TempTestDir-- cpp-options: -DMONOLITHIC- build-depends:- Cabal == 3.1.*,- cabal-install-solver-dsl,- QuickCheck >= 2.8.2,- array,- async,- bytestring,- containers,- deepseq,- directory,- edit-distance,- filepath,- hashable,- mtl,- network,- network-uri,- pretty-show >= 1.6.15,- random,- tagged,- tar,- tasty >= 1.2.3 && < 1.3,- tasty-hunit >= 0.10,- tasty-quickcheck,- tree-diff,- time,- zlib-%endif-%endif-#-# Test-suites-# disable if we don't configure with an (internal) libs-#-%if CABAL_FLAG_LIB-#-# Small, fast running tests.-#-Test-Suite unit-tests- type: exitcode-stdio-1.0- main-is: UnitTests.hs- hs-source-dirs: tests- ghc-options: -Wall -fwarn-tabs -main-is UnitTests- other-modules:- UnitTests.Distribution.Client.ArbitraryInstances- UnitTests.Distribution.Client.Targets- UnitTests.Distribution.Client.FileMonitor- UnitTests.Distribution.Client.Get- UnitTests.Distribution.Client.GenericInstances- UnitTests.Distribution.Client.Glob- UnitTests.Distribution.Client.GZipUtils- UnitTests.Distribution.Client.Sandbox- UnitTests.Distribution.Client.Sandbox.Timestamp- UnitTests.Distribution.Client.Store- UnitTests.Distribution.Client.Tar- UnitTests.Distribution.Client.TreeDiffInstances- UnitTests.Distribution.Client.UserConfig- UnitTests.Distribution.Client.ProjectConfig- UnitTests.Distribution.Client.JobControl- UnitTests.Distribution.Client.IndexUtils.Timestamp- UnitTests.Distribution.Client.InstallPlan- UnitTests.Distribution.Client.VCS- UnitTests.Distribution.Solver.Modular.Builder- UnitTests.Distribution.Solver.Modular.RetryLog- UnitTests.Distribution.Solver.Modular.Solver- UnitTests.Distribution.Solver.Modular.DSL.TestCaseUtils- UnitTests.Distribution.Solver.Modular.WeightedPSQ- UnitTests.Options- UnitTests.TempTestDir- build-depends:- array,- base,- async,- bytestring,- cabal-lib-client,- cabal-install-solver-dsl,- Cabal,- containers,- deepseq,- mtl,- random,- directory,- filepath,- tar,- time,- zlib,- network-uri < 2.6.2.0,- network,- tasty >= 1.2.3 && <1.3,- tasty-hunit >= 0.10,- tasty-quickcheck,- tagged,- tree-diff,- QuickCheck >= 2.8.2-- ghc-options: -threaded-- default-language: Haskell2010--#-# Tests to run with a limited stack and heap size-#-Test-Suite memory-usage-tests- type: exitcode-stdio-1.0- main-is: MemoryUsageTests.hs- hs-source-dirs: tests- ghc-options: -Wall -fwarn-tabs "-with-rtsopts=-M4M -K1K" -main-is MemoryUsageTests- other-modules:- UnitTests.Distribution.Solver.Modular.DSL.TestCaseUtils- UnitTests.Distribution.Solver.Modular.MemoryUsage- UnitTests.Options- build-depends:- base,- async,- Cabal,- cabal-lib-client,- cabal-install-solver-dsl,- containers,- deepseq,- tagged,- tasty >= 1.2.3 && <1.3,- tasty-hunit >= 0.10-- ghc-options: -threaded-- default-language: Haskell2010--#-# Slow solver tests-#-Test-Suite solver-quickcheck- type: exitcode-stdio-1.0- main-is: SolverQuickCheck.hs- hs-source-dirs: tests- ghc-options: -Wall -fwarn-tabs -main-is SolverQuickCheck- other-modules:- UnitTests.Distribution.Solver.Modular.QuickCheck- UnitTests.Distribution.Solver.Modular.QuickCheck.Utils- build-depends:- base,- async,- Cabal,- cabal-lib-client,- cabal-install-solver-dsl,- containers,- deepseq >= 1.2,- hashable,- random,- tagged,- tasty >= 1.2.3 && <1.3,- tasty-quickcheck,- QuickCheck >= 2.8.2,- pretty-show >= 1.6.15-- ghc-options: -threaded-- default-language: Haskell2010--#-# Integration tests that use the cabal-install code directly-# but still build whole projects-#-test-suite integration-tests2- type: exitcode-stdio-1.0- main-is: IntegrationTests2.hs- hs-source-dirs: tests- ghc-options: -Wall -fwarn-tabs -main-is IntegrationTests2- other-modules:- build-depends:- base,- Cabal,- cabal-lib-client,- containers,- deepseq,- directory,- edit-distance,- filepath,- tasty >= 1.2.3 && <1.3,- tasty-hunit >= 0.10,- tagged-- ghc-options: -threaded- default-language: Haskell2010--%endif
+ cabal/cabal-install/cabal-install.cabal.prod view
@@ -0,0 +1,397 @@+Cabal-Version: >= 1.10+-- NOTE: This file is autogenerated from 'cabal-install.cabal.pp'.+-- DO NOT EDIT MANUALLY.+-- To update this file, edit 'cabal-install.cabal.pp' and run+-- 'make cabal-install-prod' in the project's root folder.+Name: cabal-install+Version: 3.3.0.0+Synopsis: The command-line interface for Cabal and Hackage.+Description:+ The \'cabal\' command-line program simplifies the process of managing+ Haskell software by automating the fetching, configuration, compilation+ and installation of Haskell libraries and programs.+homepage: http://www.haskell.org/cabal/+bug-reports: https://github.com/haskell/cabal/issues+License: BSD3+License-File: LICENSE+Author: Cabal Development Team (see AUTHORS file)+Maintainer: Cabal Development Team <cabal-devel@haskell.org>+Copyright: 2003-2020, Cabal Development Team+Category: Distribution+Build-type: Simple+Extra-Source-Files:+ README.md bash-completion/cabal bootstrap.sh changelog++ -- Generated with 'make gen-extra-source-files'+ -- Do NOT edit this section manually; instead, run the script.+ -- BEGIN gen-extra-source-files+ tests/IntegrationTests2/build/keep-going/cabal.project+ tests/IntegrationTests2/build/keep-going/p/P.hs+ tests/IntegrationTests2/build/keep-going/p/p.cabal+ tests/IntegrationTests2/build/keep-going/q/Q.hs+ tests/IntegrationTests2/build/keep-going/q/q.cabal+ tests/IntegrationTests2/build/local-tarball/cabal.project+ tests/IntegrationTests2/build/local-tarball/q/Q.hs+ tests/IntegrationTests2/build/local-tarball/q/q.cabal+ tests/IntegrationTests2/build/setup-custom1/A.hs+ tests/IntegrationTests2/build/setup-custom1/Setup.hs+ tests/IntegrationTests2/build/setup-custom1/a.cabal+ tests/IntegrationTests2/build/setup-custom2/A.hs+ tests/IntegrationTests2/build/setup-custom2/Setup.hs+ tests/IntegrationTests2/build/setup-custom2/a.cabal+ tests/IntegrationTests2/build/setup-simple/A.hs+ tests/IntegrationTests2/build/setup-simple/Setup.hs+ tests/IntegrationTests2/build/setup-simple/a.cabal+ tests/IntegrationTests2/exception/bad-config/cabal.project+ tests/IntegrationTests2/exception/build/Main.hs+ tests/IntegrationTests2/exception/build/a.cabal+ tests/IntegrationTests2/exception/configure/a.cabal+ tests/IntegrationTests2/exception/no-pkg/empty.in+ tests/IntegrationTests2/exception/no-pkg2/cabal.project+ tests/IntegrationTests2/regression/3324/cabal.project+ tests/IntegrationTests2/regression/3324/p/P.hs+ tests/IntegrationTests2/regression/3324/p/p.cabal+ tests/IntegrationTests2/regression/3324/q/Q.hs+ tests/IntegrationTests2/regression/3324/q/q.cabal+ tests/IntegrationTests2/targets/all-disabled/cabal.project+ tests/IntegrationTests2/targets/all-disabled/p.cabal+ tests/IntegrationTests2/targets/benchmarks-disabled/cabal.project+ tests/IntegrationTests2/targets/benchmarks-disabled/p.cabal+ tests/IntegrationTests2/targets/benchmarks-disabled/q/q.cabal+ tests/IntegrationTests2/targets/complex/cabal.project+ tests/IntegrationTests2/targets/complex/q/Q.hs+ tests/IntegrationTests2/targets/complex/q/q.cabal+ tests/IntegrationTests2/targets/empty-pkg/cabal.project+ tests/IntegrationTests2/targets/empty-pkg/p.cabal+ tests/IntegrationTests2/targets/empty/cabal.project+ tests/IntegrationTests2/targets/empty/foo.hs+ tests/IntegrationTests2/targets/exes-disabled/cabal.project+ tests/IntegrationTests2/targets/exes-disabled/p/p.cabal+ tests/IntegrationTests2/targets/exes-disabled/q/q.cabal+ tests/IntegrationTests2/targets/lib-only/p.cabal+ tests/IntegrationTests2/targets/libs-disabled/cabal.project+ tests/IntegrationTests2/targets/libs-disabled/p/p.cabal+ tests/IntegrationTests2/targets/libs-disabled/q/q.cabal+ tests/IntegrationTests2/targets/multiple-exes/cabal.project+ tests/IntegrationTests2/targets/multiple-exes/p.cabal+ tests/IntegrationTests2/targets/multiple-libs/cabal.project+ tests/IntegrationTests2/targets/multiple-libs/p/p.cabal+ tests/IntegrationTests2/targets/multiple-libs/q/q.cabal+ tests/IntegrationTests2/targets/multiple-tests/cabal.project+ tests/IntegrationTests2/targets/multiple-tests/p.cabal+ tests/IntegrationTests2/targets/simple/P.hs+ tests/IntegrationTests2/targets/simple/app/Main.hs+ tests/IntegrationTests2/targets/simple/cabal.project+ tests/IntegrationTests2/targets/simple/p.cabal+ tests/IntegrationTests2/targets/simple/q/Q.hs+ tests/IntegrationTests2/targets/simple/q/QQ.hs+ tests/IntegrationTests2/targets/simple/q/q.cabal+ tests/IntegrationTests2/targets/test-only/p.cabal+ tests/IntegrationTests2/targets/tests-disabled/cabal.project+ tests/IntegrationTests2/targets/tests-disabled/p.cabal+ tests/IntegrationTests2/targets/tests-disabled/q/q.cabal+ tests/IntegrationTests2/targets/variety/cabal.project+ tests/IntegrationTests2/targets/variety/p.cabal+ -- END gen-extra-source-files++ -- Additional manual extra-source-files:+ tests/IntegrationTests2/build/local-tarball/p-0.1.tar.gz+++source-repository head+ type: git+ location: https://github.com/haskell/cabal/+ subdir: cabal-install++Flag native-dns+ description: Enable use of the [resolv](https://hackage.haskell.org/package/resolv) & [windns](https://hackage.haskell.org/package/windns) packages for performing DNS lookups+ default: True+ manual: True++Flag debug-expensive-assertions+ description: Enable expensive assertions for testing or debugging+ default: False+ manual: True++Flag debug-conflict-sets+ description: Add additional information to ConflictSets+ default: False+ manual: True++Flag debug-tracetree+ description: Compile in support for tracetree (used to debug the solver)+ default: False+ manual: True++Flag lukko+ description: Use @lukko@ for file-locking+ default: True+ manual: True++executable cabal+ main-is: Main.hs+ hs-source-dirs: main+ default-language: Haskell2010+ ghc-options: -Wall -fwarn-tabs -fwarn-incomplete-uni-patterns+ if impl(ghc >= 8.0)+ ghc-options: -Wcompat+ -Wnoncanonical-monad-instances+ if impl(ghc < 8.8)+ ghc-options: -Wnoncanonical-monadfail-instances+++ ghc-options: -rtsopts -threaded++ -- On AIX, some legacy BSD operations such as flock(2) are provided by libbsd.a+ if os(aix)+ extra-libraries: bsd+ hs-source-dirs: .+ other-modules:+ -- this modules are moved from Cabal+ -- they are needed for as long until cabal-install moves to parsec parser+ Distribution.Deprecated.ParseUtils+ Distribution.Deprecated.ReadP+ Distribution.Deprecated.ViewAsFieldDescr++ Distribution.Client.BuildReports.Anonymous+ Distribution.Client.BuildReports.Lens+ Distribution.Client.BuildReports.Storage+ Distribution.Client.BuildReports.Types+ Distribution.Client.BuildReports.Upload+ Distribution.Client.Check+ Distribution.Client.CmdBench+ Distribution.Client.CmdBuild+ Distribution.Client.CmdClean+ Distribution.Client.CmdConfigure+ Distribution.Client.CmdErrorMessages+ Distribution.Client.CmdExec+ Distribution.Client.CmdFreeze+ Distribution.Client.CmdHaddock+ Distribution.Client.CmdInstall+ Distribution.Client.CmdInstall.ClientInstallFlags+ Distribution.Client.CmdInstall.ClientInstallTargetSelector+ Distribution.Client.CmdLegacy+ Distribution.Client.CmdListBin+ Distribution.Client.CmdRepl+ Distribution.Client.CmdRun+ Distribution.Client.CmdSdist+ Distribution.Client.CmdTest+ Distribution.Client.CmdUpdate+ Distribution.Client.Compat.Directory+ Distribution.Client.Compat.ExecutablePath+ Distribution.Client.Compat.FilePerms+ Distribution.Client.Compat.Orphans+ Distribution.Client.Compat.Prelude+ Distribution.Client.Compat.Process+ Distribution.Client.Compat.Semaphore+ Distribution.Client.Config+ Distribution.Client.Configure+ Distribution.Client.Dependency+ Distribution.Client.Dependency.Types+ Distribution.Client.DistDirLayout+ Distribution.Client.Exec+ Distribution.Client.Fetch+ Distribution.Client.FetchUtils+ Distribution.Client.FileMonitor+ Distribution.Client.Freeze+ Distribution.Client.GZipUtils+ Distribution.Client.GenBounds+ Distribution.Client.Get+ Distribution.Client.Glob+ Distribution.Client.GlobalFlags+ Distribution.Client.Haddock+ Distribution.Client.HashValue+ Distribution.Client.HttpUtils+ Distribution.Client.IndexUtils+ Distribution.Client.IndexUtils.ActiveRepos+ Distribution.Client.IndexUtils.IndexState+ Distribution.Client.IndexUtils.Timestamp+ Distribution.Client.Init+ Distribution.Client.Init.Command+ Distribution.Client.Init.Defaults+ Distribution.Client.Init.FileCreators+ Distribution.Client.Init.Heuristics+ Distribution.Client.Init.Licenses+ Distribution.Client.Init.Prompt+ Distribution.Client.Init.Types+ Distribution.Client.Init.Utils+ Distribution.Client.Install+ Distribution.Client.InstallPlan+ Distribution.Client.InstallSymlink+ Distribution.Client.JobControl+ Distribution.Client.List+ Distribution.Client.Manpage+ Distribution.Client.ManpageFlags+ Distribution.Client.Nix+ Distribution.Client.NixStyleOptions+ Distribution.Client.Outdated+ Distribution.Client.PackageHash+ Distribution.Client.ParseUtils+ Distribution.Client.ProjectBuilding+ Distribution.Client.ProjectBuilding.Types+ Distribution.Client.ProjectConfig+ Distribution.Client.ProjectConfig.Legacy+ Distribution.Client.ProjectConfig.Types+ Distribution.Client.ProjectFlags+ Distribution.Client.ProjectOrchestration+ Distribution.Client.ProjectPlanOutput+ Distribution.Client.ProjectPlanning+ Distribution.Client.ProjectPlanning.Types+ Distribution.Client.RebuildMonad+ Distribution.Client.Reconfigure+ Distribution.Client.Run+ Distribution.Client.Sandbox+ Distribution.Client.Sandbox.PackageEnvironment+ Distribution.Client.SavedFlags+ Distribution.Client.Security.DNS+ Distribution.Client.Security.HTTP+ Distribution.Client.Setup+ Distribution.Client.SetupWrapper+ Distribution.Client.SolverInstallPlan+ Distribution.Client.SourceFiles+ Distribution.Client.SrcDist+ Distribution.Client.Store+ Distribution.Client.Tar+ Distribution.Client.TargetProblem+ Distribution.Client.TargetSelector+ Distribution.Client.Targets+ Distribution.Client.Types+ Distribution.Client.Types.AllowNewer+ Distribution.Client.Types.BuildResults+ Distribution.Client.Types.ConfiguredId+ Distribution.Client.Types.ConfiguredPackage+ Distribution.Client.Types.Credentials+ Distribution.Client.Types.InstallMethod+ Distribution.Client.Types.OverwritePolicy+ Distribution.Client.Types.PackageLocation+ Distribution.Client.Types.PackageSpecifier+ Distribution.Client.Types.ReadyPackage+ Distribution.Client.Types.Repo+ Distribution.Client.Types.RepoName+ Distribution.Client.Types.SourcePackageDb+ Distribution.Client.Types.SourceRepo+ Distribution.Client.Types.WriteGhcEnvironmentFilesPolicy+ Distribution.Client.Update+ Distribution.Client.Upload+ Distribution.Client.Utils+ Distribution.Client.Utils.Assertion+ Distribution.Client.Utils.Json+ Distribution.Client.Utils.Parsec+ Distribution.Client.VCS+ Distribution.Client.Win32SelfUpgrade+ Distribution.Client.World+ Distribution.Solver.Compat.Prelude+ Distribution.Solver.Modular+ Distribution.Solver.Modular.Assignment+ Distribution.Solver.Modular.Builder+ Distribution.Solver.Modular.Configured+ Distribution.Solver.Modular.ConfiguredConversion+ Distribution.Solver.Modular.ConflictSet+ Distribution.Solver.Modular.Cycles+ Distribution.Solver.Modular.Dependency+ Distribution.Solver.Modular.Explore+ Distribution.Solver.Modular.Flag+ Distribution.Solver.Modular.Index+ Distribution.Solver.Modular.IndexConversion+ Distribution.Solver.Modular.LabeledGraph+ Distribution.Solver.Modular.Linking+ Distribution.Solver.Modular.Log+ Distribution.Solver.Modular.Message+ Distribution.Solver.Modular.PSQ+ Distribution.Solver.Modular.Package+ Distribution.Solver.Modular.Preference+ Distribution.Solver.Modular.RetryLog+ Distribution.Solver.Modular.Solver+ Distribution.Solver.Modular.Tree+ Distribution.Solver.Modular.Validate+ Distribution.Solver.Modular.Var+ Distribution.Solver.Modular.Version+ Distribution.Solver.Modular.WeightedPSQ+ Distribution.Solver.Types.ComponentDeps+ Distribution.Solver.Types.ConstraintSource+ Distribution.Solver.Types.DependencyResolver+ Distribution.Solver.Types.Flag+ Distribution.Solver.Types.InstSolverPackage+ Distribution.Solver.Types.InstalledPreference+ Distribution.Solver.Types.LabeledPackageConstraint+ Distribution.Solver.Types.OptionalStanza+ Distribution.Solver.Types.PackageConstraint+ Distribution.Solver.Types.PackageFixedDeps+ Distribution.Solver.Types.PackageIndex+ Distribution.Solver.Types.PackagePath+ Distribution.Solver.Types.PackagePreferences+ Distribution.Solver.Types.PkgConfigDb+ Distribution.Solver.Types.Progress+ Distribution.Solver.Types.ResolverPackage+ Distribution.Solver.Types.Settings+ Distribution.Solver.Types.SolverId+ Distribution.Solver.Types.SolverPackage+ Distribution.Solver.Types.SourcePackage+ Distribution.Solver.Types.Variable+ Paths_cabal_install++ build-depends:+ async >= 2.0 && < 2.3,+ array >= 0.4 && < 0.6,+ base >= 4.8 && < 4.15,+ base16-bytestring >= 0.1.1 && < 0.2,+ binary >= 0.7.3 && < 0.9,+ bytestring >= 0.10.6.0 && < 0.11,+ Cabal == 3.3.*,+ containers >= 0.5.6.2 && < 0.7,+ cryptohash-sha256 >= 0.11 && < 0.12,+ deepseq >= 1.4.1.1 && < 1.5,+ directory >= 1.2.2.0 && < 1.4,+ echo >= 0.1.3 && < 0.2,+ edit-distance >= 0.2.2 && < 0.3,+ filepath >= 1.4.0.0 && < 1.5,+ hashable >= 1.0 && < 1.4,+ HTTP >= 4000.1.5 && < 4000.4,+ mtl >= 2.0 && < 2.3,+ network-uri >= 2.6.0.2 && < 2.7,+ network >= 2.6 && < 3.2,+ pretty >= 1.1 && < 1.2,+ process >= 1.2.3.0 && < 1.7,+ random >= 1 && < 1.2,+ stm >= 2.0 && < 2.6,+ tar >= 0.5.0.3 && < 0.6,+ time >= 1.5.0.1 && < 1.11,+ transformers >= 0.4.2.0 && < 0.6,+ zlib >= 0.5.3 && < 0.7,+ hackage-security >= 0.6.0.1 && < 0.7,+ text >= 1.2.3 && < 1.3,+ parsec >= 3.1.13.0 && < 3.2,+ regex-base >= 0.94.0.0 && <0.95,+ regex-posix >= 0.96.0.0 && <0.97++ if !impl(ghc >= 8.0)+ build-depends: fail == 4.9.*+ build-depends: semigroups >= 0.18.3 && <0.20++ if flag(native-dns)+ if os(windows)+ build-depends: windns >= 0.1.0 && < 0.2+ else+ build-depends: resolv >= 0.1.1 && < 0.2++ if os(windows)+ -- newer directory for symlinks+ build-depends: Win32 >= 2 && < 3, directory >=1.3.1.0+ else+ build-depends: unix >= 2.5 && < 2.9++ if flag(lukko)+ build-depends: lukko >= 0.1 && <0.2+ else+ build-depends: base >= 4.10++ if flag(debug-expensive-assertions)+ cpp-options: -DDEBUG_EXPENSIVE_ASSERTIONS++ if flag(debug-conflict-sets)+ cpp-options: -DDEBUG_CONFLICT_SETS+ build-depends: base >= 4.8++ if flag(debug-tracetree)+ cpp-options: -DDEBUG_TRACETREE+ build-depends: tracetree >= 0.1 && < 0.2
+ cabal/cabal-install/cabal-install.cabal.zinza view
@@ -0,0 +1,616 @@+{# lib enabled means that we have internal library: cabal-lib-client #}+{% if dev %}+Cabal-Version: 2.0+{% else %}+Cabal-Version: >= 1.10+{% endif %}+-- NOTE: This file is autogenerated from 'cabal-install.cabal.pp'.+-- DO NOT EDIT MANUALLY.+-- To update this file, edit 'cabal-install.cabal.pp' and run+-- 'make cabal-install-prod' in the project's root folder.+Name: cabal-install+Version: 3.3.0.0+{# NOTE: when updating build-depends, don't forget to update version regexps in bootstrap.sh. #}+{% defblock buildDepends %}+ build-depends:+ async >= 2.0 && < 2.3,+ array >= 0.4 && < 0.6,+ base >= 4.8 && < 4.15,+ base16-bytestring >= 0.1.1 && < 0.2,+ binary >= 0.7.3 && < 0.9,+ bytestring >= 0.10.6.0 && < 0.11,+ Cabal == 3.3.*,+ containers >= 0.5.6.2 && < 0.7,+ cryptohash-sha256 >= 0.11 && < 0.12,+ deepseq >= 1.4.1.1 && < 1.5,+ directory >= 1.2.2.0 && < 1.4,+ echo >= 0.1.3 && < 0.2,+ edit-distance >= 0.2.2 && < 0.3,+ filepath >= 1.4.0.0 && < 1.5,+ hashable >= 1.0 && < 1.4,+ HTTP >= 4000.1.5 && < 4000.4,+ mtl >= 2.0 && < 2.3,+ network-uri >= 2.6.0.2 && < 2.7,+ network >= 2.6 && < 3.2,+ pretty >= 1.1 && < 1.2,+ process >= 1.2.3.0 && < 1.7,+ random >= 1 && < 1.2,+ stm >= 2.0 && < 2.6,+ tar >= 0.5.0.3 && < 0.6,+ time >= 1.5.0.1 && < 1.11,+ transformers >= 0.4.2.0 && < 0.6,+ zlib >= 0.5.3 && < 0.7,+ hackage-security >= 0.6.0.1 && < 0.7,+ text >= 1.2.3 && < 1.3,+ parsec >= 3.1.13.0 && < 3.2,+ regex-base >= 0.94.0.0 && <0.95,+ regex-posix >= 0.96.0.0 && <0.97++ if !impl(ghc >= 8.0)+ build-depends: fail == 4.9.*+ build-depends: semigroups >= 0.18.3 && <0.20++ if flag(native-dns)+ if os(windows)+ build-depends: windns >= 0.1.0 && < 0.2+ else+ build-depends: resolv >= 0.1.1 && < 0.2++ if os(windows)+ -- newer directory for symlinks+ build-depends: Win32 >= 2 && < 3, directory >=1.3.1.0+ else+ build-depends: unix >= 2.5 && < 2.9++ if flag(lukko)+ build-depends: lukko >= 0.1 && <0.2+ else+ build-depends: base >= 4.10+{% endblock %}+{% defblock componentCommon %}+ default-language: Haskell2010+ ghc-options: -Wall -fwarn-tabs -fwarn-incomplete-uni-patterns+ if impl(ghc >= 8.0)+ ghc-options: -Wcompat+ -Wnoncanonical-monad-instances+ if impl(ghc < 8.8)+ ghc-options: -Wnoncanonical-monadfail-instances++{% endblock %}+{% defblock buildInfo %}+{% if dev %}+ exposed-modules:+{% else %}+ other-modules:+{% endif %}+ -- this modules are moved from Cabal+ -- they are needed for as long until cabal-install moves to parsec parser+ Distribution.Deprecated.ParseUtils+ Distribution.Deprecated.ReadP+ Distribution.Deprecated.ViewAsFieldDescr++ Distribution.Client.BuildReports.Anonymous+ Distribution.Client.BuildReports.Lens+ Distribution.Client.BuildReports.Storage+ Distribution.Client.BuildReports.Types+ Distribution.Client.BuildReports.Upload+ Distribution.Client.Check+ Distribution.Client.CmdBench+ Distribution.Client.CmdBuild+ Distribution.Client.CmdClean+ Distribution.Client.CmdConfigure+ Distribution.Client.CmdErrorMessages+ Distribution.Client.CmdExec+ Distribution.Client.CmdFreeze+ Distribution.Client.CmdHaddock+ Distribution.Client.CmdInstall+ Distribution.Client.CmdInstall.ClientInstallFlags+ Distribution.Client.CmdInstall.ClientInstallTargetSelector+ Distribution.Client.CmdLegacy+ Distribution.Client.CmdListBin+ Distribution.Client.CmdRepl+ Distribution.Client.CmdRun+ Distribution.Client.CmdSdist+ Distribution.Client.CmdTest+ Distribution.Client.CmdUpdate+ Distribution.Client.Compat.Directory+ Distribution.Client.Compat.ExecutablePath+ Distribution.Client.Compat.FilePerms+ Distribution.Client.Compat.Orphans+ Distribution.Client.Compat.Prelude+ Distribution.Client.Compat.Process+ Distribution.Client.Compat.Semaphore+ Distribution.Client.Config+ Distribution.Client.Configure+ Distribution.Client.Dependency+ Distribution.Client.Dependency.Types+ Distribution.Client.DistDirLayout+ Distribution.Client.Exec+ Distribution.Client.Fetch+ Distribution.Client.FetchUtils+ Distribution.Client.FileMonitor+ Distribution.Client.Freeze+ Distribution.Client.GZipUtils+ Distribution.Client.GenBounds+ Distribution.Client.Get+ Distribution.Client.Glob+ Distribution.Client.GlobalFlags+ Distribution.Client.Haddock+ Distribution.Client.HashValue+ Distribution.Client.HttpUtils+ Distribution.Client.IndexUtils+ Distribution.Client.IndexUtils.ActiveRepos+ Distribution.Client.IndexUtils.IndexState+ Distribution.Client.IndexUtils.Timestamp+ Distribution.Client.Init+ Distribution.Client.Init.Command+ Distribution.Client.Init.Defaults+ Distribution.Client.Init.FileCreators+ Distribution.Client.Init.Heuristics+ Distribution.Client.Init.Licenses+ Distribution.Client.Init.Prompt+ Distribution.Client.Init.Types+ Distribution.Client.Init.Utils+ Distribution.Client.Install+ Distribution.Client.InstallPlan+ Distribution.Client.InstallSymlink+ Distribution.Client.JobControl+ Distribution.Client.List+ Distribution.Client.Manpage+ Distribution.Client.ManpageFlags+ Distribution.Client.Nix+ Distribution.Client.NixStyleOptions+ Distribution.Client.Outdated+ Distribution.Client.PackageHash+ Distribution.Client.ParseUtils+ Distribution.Client.ProjectBuilding+ Distribution.Client.ProjectBuilding.Types+ Distribution.Client.ProjectConfig+ Distribution.Client.ProjectConfig.Legacy+ Distribution.Client.ProjectConfig.Types+ Distribution.Client.ProjectFlags+ Distribution.Client.ProjectOrchestration+ Distribution.Client.ProjectPlanOutput+ Distribution.Client.ProjectPlanning+ Distribution.Client.ProjectPlanning.Types+ Distribution.Client.RebuildMonad+ Distribution.Client.Reconfigure+ Distribution.Client.Run+ Distribution.Client.Sandbox+ Distribution.Client.Sandbox.PackageEnvironment+ Distribution.Client.SavedFlags+ Distribution.Client.Security.DNS+ Distribution.Client.Security.HTTP+ Distribution.Client.Setup+ Distribution.Client.SetupWrapper+ Distribution.Client.SolverInstallPlan+ Distribution.Client.SourceFiles+ Distribution.Client.SrcDist+ Distribution.Client.Store+ Distribution.Client.Tar+ Distribution.Client.TargetProblem+ Distribution.Client.TargetSelector+ Distribution.Client.Targets+ Distribution.Client.Types+ Distribution.Client.Types.AllowNewer+ Distribution.Client.Types.BuildResults+ Distribution.Client.Types.ConfiguredId+ Distribution.Client.Types.ConfiguredPackage+ Distribution.Client.Types.Credentials+ Distribution.Client.Types.InstallMethod+ Distribution.Client.Types.OverwritePolicy+ Distribution.Client.Types.PackageLocation+ Distribution.Client.Types.PackageSpecifier+ Distribution.Client.Types.ReadyPackage+ Distribution.Client.Types.Repo+ Distribution.Client.Types.RepoName+ Distribution.Client.Types.SourcePackageDb+ Distribution.Client.Types.SourceRepo+ Distribution.Client.Types.WriteGhcEnvironmentFilesPolicy+ Distribution.Client.Update+ Distribution.Client.Upload+ Distribution.Client.Utils+ Distribution.Client.Utils.Assertion+ Distribution.Client.Utils.Json+ Distribution.Client.Utils.Parsec+ Distribution.Client.VCS+ Distribution.Client.Win32SelfUpgrade+ Distribution.Client.World+ Distribution.Solver.Compat.Prelude+ Distribution.Solver.Modular+ Distribution.Solver.Modular.Assignment+ Distribution.Solver.Modular.Builder+ Distribution.Solver.Modular.Configured+ Distribution.Solver.Modular.ConfiguredConversion+ Distribution.Solver.Modular.ConflictSet+ Distribution.Solver.Modular.Cycles+ Distribution.Solver.Modular.Dependency+ Distribution.Solver.Modular.Explore+ Distribution.Solver.Modular.Flag+ Distribution.Solver.Modular.Index+ Distribution.Solver.Modular.IndexConversion+ Distribution.Solver.Modular.LabeledGraph+ Distribution.Solver.Modular.Linking+ Distribution.Solver.Modular.Log+ Distribution.Solver.Modular.Message+ Distribution.Solver.Modular.PSQ+ Distribution.Solver.Modular.Package+ Distribution.Solver.Modular.Preference+ Distribution.Solver.Modular.RetryLog+ Distribution.Solver.Modular.Solver+ Distribution.Solver.Modular.Tree+ Distribution.Solver.Modular.Validate+ Distribution.Solver.Modular.Var+ Distribution.Solver.Modular.Version+ Distribution.Solver.Modular.WeightedPSQ+ Distribution.Solver.Types.ComponentDeps+ Distribution.Solver.Types.ConstraintSource+ Distribution.Solver.Types.DependencyResolver+ Distribution.Solver.Types.Flag+ Distribution.Solver.Types.InstSolverPackage+ Distribution.Solver.Types.InstalledPreference+ Distribution.Solver.Types.LabeledPackageConstraint+ Distribution.Solver.Types.OptionalStanza+ Distribution.Solver.Types.PackageConstraint+ Distribution.Solver.Types.PackageFixedDeps+ Distribution.Solver.Types.PackageIndex+ Distribution.Solver.Types.PackagePath+ Distribution.Solver.Types.PackagePreferences+ Distribution.Solver.Types.PkgConfigDb+ Distribution.Solver.Types.Progress+ Distribution.Solver.Types.ResolverPackage+ Distribution.Solver.Types.Settings+ Distribution.Solver.Types.SolverId+ Distribution.Solver.Types.SolverPackage+ Distribution.Solver.Types.SourcePackage+ Distribution.Solver.Types.Variable+ Paths_cabal_install++{% if dev %}+ autogen-modules:+ Paths_cabal_install+{% endif %}+{% useblock buildDepends %}++ if flag(debug-expensive-assertions)+ cpp-options: -DDEBUG_EXPENSIVE_ASSERTIONS++ if flag(debug-conflict-sets)+ cpp-options: -DDEBUG_CONFLICT_SETS+ build-depends: base >= 4.8++ if flag(debug-tracetree)+ cpp-options: -DDEBUG_TRACETREE+ build-depends: tracetree >= 0.1 && < 0.2+{% endblock %}+{############################################################################}+{# Package Description #}+{############################################################################}+Synopsis: The command-line interface for Cabal and Hackage.+Description:+ The \'cabal\' command-line program simplifies the process of managing+ Haskell software by automating the fetching, configuration, compilation+ and installation of Haskell libraries and programs.+homepage: http://www.haskell.org/cabal/+bug-reports: https://github.com/haskell/cabal/issues+License: BSD3+License-File: LICENSE+Author: Cabal Development Team (see AUTHORS file)+Maintainer: Cabal Development Team <cabal-devel@haskell.org>+Copyright: 2003-2020, Cabal Development Team+Category: Distribution+Build-type: Simple+Extra-Source-Files:+ README.md bash-completion/cabal bootstrap.sh changelog++ -- Generated with 'make gen-extra-source-files'+ -- Do NOT edit this section manually; instead, run the script.+ -- BEGIN gen-extra-source-files+ tests/IntegrationTests2/build/keep-going/cabal.project+ tests/IntegrationTests2/build/keep-going/p/P.hs+ tests/IntegrationTests2/build/keep-going/p/p.cabal+ tests/IntegrationTests2/build/keep-going/q/Q.hs+ tests/IntegrationTests2/build/keep-going/q/q.cabal+ tests/IntegrationTests2/build/local-tarball/cabal.project+ tests/IntegrationTests2/build/local-tarball/q/Q.hs+ tests/IntegrationTests2/build/local-tarball/q/q.cabal+ tests/IntegrationTests2/build/setup-custom1/A.hs+ tests/IntegrationTests2/build/setup-custom1/Setup.hs+ tests/IntegrationTests2/build/setup-custom1/a.cabal+ tests/IntegrationTests2/build/setup-custom2/A.hs+ tests/IntegrationTests2/build/setup-custom2/Setup.hs+ tests/IntegrationTests2/build/setup-custom2/a.cabal+ tests/IntegrationTests2/build/setup-simple/A.hs+ tests/IntegrationTests2/build/setup-simple/Setup.hs+ tests/IntegrationTests2/build/setup-simple/a.cabal+ tests/IntegrationTests2/exception/bad-config/cabal.project+ tests/IntegrationTests2/exception/build/Main.hs+ tests/IntegrationTests2/exception/build/a.cabal+ tests/IntegrationTests2/exception/configure/a.cabal+ tests/IntegrationTests2/exception/no-pkg/empty.in+ tests/IntegrationTests2/exception/no-pkg2/cabal.project+ tests/IntegrationTests2/regression/3324/cabal.project+ tests/IntegrationTests2/regression/3324/p/P.hs+ tests/IntegrationTests2/regression/3324/p/p.cabal+ tests/IntegrationTests2/regression/3324/q/Q.hs+ tests/IntegrationTests2/regression/3324/q/q.cabal+ tests/IntegrationTests2/targets/all-disabled/cabal.project+ tests/IntegrationTests2/targets/all-disabled/p.cabal+ tests/IntegrationTests2/targets/benchmarks-disabled/cabal.project+ tests/IntegrationTests2/targets/benchmarks-disabled/p.cabal+ tests/IntegrationTests2/targets/benchmarks-disabled/q/q.cabal+ tests/IntegrationTests2/targets/complex/cabal.project+ tests/IntegrationTests2/targets/complex/q/Q.hs+ tests/IntegrationTests2/targets/complex/q/q.cabal+ tests/IntegrationTests2/targets/empty-pkg/cabal.project+ tests/IntegrationTests2/targets/empty-pkg/p.cabal+ tests/IntegrationTests2/targets/empty/cabal.project+ tests/IntegrationTests2/targets/empty/foo.hs+ tests/IntegrationTests2/targets/exes-disabled/cabal.project+ tests/IntegrationTests2/targets/exes-disabled/p/p.cabal+ tests/IntegrationTests2/targets/exes-disabled/q/q.cabal+ tests/IntegrationTests2/targets/lib-only/p.cabal+ tests/IntegrationTests2/targets/libs-disabled/cabal.project+ tests/IntegrationTests2/targets/libs-disabled/p/p.cabal+ tests/IntegrationTests2/targets/libs-disabled/q/q.cabal+ tests/IntegrationTests2/targets/multiple-exes/cabal.project+ tests/IntegrationTests2/targets/multiple-exes/p.cabal+ tests/IntegrationTests2/targets/multiple-libs/cabal.project+ tests/IntegrationTests2/targets/multiple-libs/p/p.cabal+ tests/IntegrationTests2/targets/multiple-libs/q/q.cabal+ tests/IntegrationTests2/targets/multiple-tests/cabal.project+ tests/IntegrationTests2/targets/multiple-tests/p.cabal+ tests/IntegrationTests2/targets/simple/P.hs+ tests/IntegrationTests2/targets/simple/app/Main.hs+ tests/IntegrationTests2/targets/simple/cabal.project+ tests/IntegrationTests2/targets/simple/p.cabal+ tests/IntegrationTests2/targets/simple/q/Q.hs+ tests/IntegrationTests2/targets/simple/q/QQ.hs+ tests/IntegrationTests2/targets/simple/q/q.cabal+ tests/IntegrationTests2/targets/test-only/p.cabal+ tests/IntegrationTests2/targets/tests-disabled/cabal.project+ tests/IntegrationTests2/targets/tests-disabled/p.cabal+ tests/IntegrationTests2/targets/tests-disabled/q/q.cabal+ tests/IntegrationTests2/targets/variety/cabal.project+ tests/IntegrationTests2/targets/variety/p.cabal+ -- END gen-extra-source-files++ -- Additional manual extra-source-files:+ tests/IntegrationTests2/build/local-tarball/p-0.1.tar.gz+++source-repository head+ type: git+ location: https://github.com/haskell/cabal/+ subdir: cabal-install++Flag native-dns+ description: Enable use of the [resolv](https://hackage.haskell.org/package/resolv) & [windns](https://hackage.haskell.org/package/windns) packages for performing DNS lookups+ default: True+ manual: True++Flag debug-expensive-assertions+ description: Enable expensive assertions for testing or debugging+ default: False+ manual: True++Flag debug-conflict-sets+ description: Add additional information to ConflictSets+ default: False+ manual: True++Flag debug-tracetree+ description: Compile in support for tracetree (used to debug the solver)+ default: False+ manual: True++Flag lukko+ description: Use @lukko@ for file-locking+ default: True+ manual: True++{############################################################################}+{# Libraries, if dev #}+{############################################################################}+{% if dev %}+library cabal-lib-client+{% useblock componentCommon %}+ hs-source-dirs: .+{% useblock buildInfo %}++library cabal-install-solver-dsl+{% useblock componentCommon %}+ hs-source-dirs: solver-dsl+ exposed-modules:+ UnitTests.Distribution.Solver.Modular.DSL+ build-depends:+ base,+ Cabal,+ containers,+ -- TODO: depend on cabal-install-solver only+ cabal-lib-client+{% endif %}+{############################################################################}+{# Executable #}+{############################################################################}+executable cabal+ main-is: Main.hs+ hs-source-dirs: main+{% useblock componentCommon %}++ ghc-options: -rtsopts -threaded++ -- On AIX, some legacy BSD operations such as flock(2) are provided by libbsd.a+ if os(aix)+ extra-libraries: bsd+{% if dev %}+ build-depends:+ cabal-lib-client,+ Cabal,+ base,+ directory,+ filepath++ other-modules: Paths_cabal_install+{% else %}+ hs-source-dirs: .+{% useblock buildInfo %}+{% endif %}+{############################################################################}+{# Test-suites #}+{# disable if we don't configure with an (internal) libs #}+{############################################################################}+{% if dev %}+-- Small, fast running tests.+--+Test-Suite unit-tests+ type: exitcode-stdio-1.0+ main-is: UnitTests.hs+ hs-source-dirs: tests+ ghc-options: -Wall -fwarn-tabs -fwarn-incomplete-uni-patterns -main-is UnitTests+ other-modules:+ UnitTests.Distribution.Client.ArbitraryInstances+ UnitTests.Distribution.Client.BuildReport+ UnitTests.Distribution.Client.Described+ UnitTests.Distribution.Client.DescribedInstances+ UnitTests.Distribution.Client.Targets+ UnitTests.Distribution.Client.FileMonitor+ UnitTests.Distribution.Client.Get+ UnitTests.Distribution.Client.Glob+ UnitTests.Distribution.Client.GZipUtils+ UnitTests.Distribution.Client.Init.FileCreators+ UnitTests.Distribution.Client.Store+ UnitTests.Distribution.Client.Tar+ UnitTests.Distribution.Client.TreeDiffInstances+ UnitTests.Distribution.Client.UserConfig+ UnitTests.Distribution.Client.ProjectConfig+ UnitTests.Distribution.Client.JobControl+ UnitTests.Distribution.Client.IndexUtils.Timestamp+ UnitTests.Distribution.Client.InstallPlan+ UnitTests.Distribution.Client.VCS+ UnitTests.Distribution.Solver.Modular.Builder+ UnitTests.Distribution.Solver.Modular.RetryLog+ UnitTests.Distribution.Solver.Modular.Solver+ UnitTests.Distribution.Solver.Modular.DSL.TestCaseUtils+ UnitTests.Distribution.Solver.Modular.WeightedPSQ+ UnitTests.Options+ UnitTests.TempTestDir+ build-depends:+ array,+ base,+ async,+ bytestring,+ cabal-lib-client,+ cabal-install-solver-dsl,+ Cabal,+ Cabal-described,+ Cabal-tree-diff,+ Cabal-QuickCheck,+ containers,+ deepseq,+ mtl,+ random,+ directory,+ filepath,+ tar,+ time,+ zlib,+ network-uri >= 2.6.2.0 && <2.6.4.0,+ network,+ tasty >= 1.2.3 && <1.4,+ tasty-golden >=2.3.1.1 && <2.4,+ tasty-hunit >= 0.10,+ tasty-quickcheck,+ tagged,+ tree-diff,+ QuickCheck >= 2.14 && <2.15++ ghc-options: -threaded++ default-language: Haskell2010++-- Tests to run with a limited stack and heap size+--+Test-Suite memory-usage-tests+ type: exitcode-stdio-1.0+ main-is: MemoryUsageTests.hs+ hs-source-dirs: tests+ ghc-options: -Wall -fwarn-tabs -fwarn-incomplete-uni-patterns "-with-rtsopts=-M4M -K1K" -main-is MemoryUsageTests+ other-modules:+ UnitTests.Distribution.Solver.Modular.DSL.TestCaseUtils+ UnitTests.Distribution.Solver.Modular.MemoryUsage+ UnitTests.Options+ build-depends:+ base,+ async,+ Cabal,+ cabal-lib-client,+ cabal-install-solver-dsl,+ containers,+ deepseq,+ tagged,+ tasty >= 1.2.3 && <1.4,+ tasty-hunit >= 0.10++ ghc-options: -threaded++ default-language: Haskell2010++-- Slow solver tests+--+Test-Suite solver-quickcheck+ type: exitcode-stdio-1.0+ main-is: SolverQuickCheck.hs+ hs-source-dirs: tests+ ghc-options: -Wall -fwarn-tabs -fwarn-incomplete-uni-patterns -main-is SolverQuickCheck+ other-modules:+ UnitTests.Distribution.Solver.Modular.QuickCheck+ UnitTests.Distribution.Solver.Modular.QuickCheck.Utils+ build-depends:+ base,+ async,+ Cabal,+ Cabal-QuickCheck,+ cabal-lib-client,+ cabal-install-solver-dsl,+ containers,+ deepseq >= 1.2,+ hashable,+ random,+ tagged,+ tasty >= 1.2.3 && <1.4,+ tasty-quickcheck,+ QuickCheck >= 2.14 && <2.15,+ pretty-show >= 1.6.15++ ghc-options: -threaded++ default-language: Haskell2010+++-- Integration tests that use the cabal-install code directly+-- but still build whole projects+test-suite integration-tests2+ type: exitcode-stdio-1.0+ main-is: IntegrationTests2.hs+ hs-source-dirs: tests+ ghc-options: -Wall -fwarn-tabs -fwarn-incomplete-uni-patterns -main-is IntegrationTests2+ other-modules:+ build-depends:+ base,+ bytestring,+ Cabal,+ cabal-lib-client,+ containers,+ deepseq,+ directory,+ edit-distance,+ filepath,+ tasty >= 1.2.3 && <1.4,+ tasty-hunit >= 0.10,+ tagged++ ghc-options: -threaded+ default-language: Haskell2010++{% endif %}
cabal/cabal-install/changelog view
@@ -1,15 +1,45 @@ -*-change-log-*- -3.1.0.0 (current development version)+3.2.0.0 Herbert Valerio Riedel <hvr@gnu.org> April 2020 * `v2-build` (and other `v2-`prefixed commands) now accept the `--benchmark-option(s)` flags, which pass options to benchmark executables (analogous to how `--test-option(s)` works). (#6209)+ * Add solver optimization to skip a version of a package if it does not resolve+ any conflicts encountered in the last version, controlled by flag+ '--fine-grained-conflicts'. (#5918)+ * `cabal v2-exec` doesn't fail in clean package (#6479)+ * Show full ABI hash for installed packages in solver log (#5892)+ * Create incoming directory even for empty packages (#4130)+ * Start GHCi with `main-is` module in scope (#6311)+ * Implement `--benchmark-options` for `v2-bench` (#6224)+ * Fix store-dir in ghc env files generated by `cabal install --lib+ --package-env` (#6298)+ * `cabal v2-run` works with `.lhs` files (#6134)+ * `subdir` in source-repository-package accepts multiple entries (#5472) +3.0.1.0 Herbert Valerio Riedel <hvr@gnu.org> April 2020+ * Create store incoming directory+ ([#4130](https://github.com/haskell/cabal/issues/4130))+ * `fetchRepoTarball` output is not marked+ ([#6385](https://github.com/haskell/cabal/pull/6385))+ * Update `setupMinCabalVersionConstraint` for GHC-8.8+ ([#6217](https://github.com/haskell/cabal/pull/6217))+ * Implement `cabal install --ignore-project`+ ([#5919](https://github.com/haskell/cabal/issues/5919))+ * `cabal install executable` solver isn't affected by default+ environment contents+ ([#6410](https://github.com/haskell/cabal/issues/6410))+ * Use `lukko` for file locking+ ([#6345](https://github.com/haskell/cabal/pull/6345))+ * Use `hackage-security-0.6`+ ([#6388](https://github.com/haskell/cabal/pull/6388))+ * Other dependency upgrades+ 3.0.0.0 Mikhail Glushenkov <mikhail.glushenkov@gmail.com> August 2019- * Parse comma-separated lists for extra-prog-path, extra-lib-dirs, extra-framework-dirs,- and extra-include-dirs as actual lists. (#5420) * `v2-haddock` fails on `haddock` failures (#5977) * `v2-run` works when given `File.lhs` literate file. (#6134)+ * Parse comma-separated lists for extra-prog-path, extra-lib-dirs, extra-framework-dirs,+ and extra-include-dirs as actual lists. (#5420) * `v2-repl` no longer changes directory to a randomized temporary folder when used outside of a project. (#5544) * `install-method` and `overwrite-policy` in `.cabal/config` now actually work. (#5942)
cabal/cabal-install/main/Main.hs view
@@ -21,10 +21,10 @@ , ConfigExFlags(..), defaultConfigExFlags, configureExCommand , reconfigureCommand , configCompilerAux', configPackageDB'- , BuildFlags(..), BuildExFlags(..), SkipAddSourceDepsCheck(..)+ , BuildFlags(..) , buildCommand, replCommand, testCommand, benchmarkCommand , InstallFlags(..), defaultInstallFlags- , installCommand, upgradeCommand, uninstallCommand+ , installCommand , FetchFlags(..), fetchCommand , FreezeFlags(..), freezeCommand , genBoundsCommand@@ -33,16 +33,13 @@ , checkCommand , formatCommand , UpdateFlags(..), updateCommand- , ListFlags(..), listCommand+ , ListFlags(..), listCommand, listNeedsCompiler , InfoFlags(..), infoCommand , UploadFlags(..), uploadCommand , ReportFlags(..), reportCommand , runCommand , InitFlags(initVerbosity, initHcPath), initCommand- , SDistFlags(..), sdistCommand- , Win32SelfUpgradeFlags(..), win32SelfUpgradeCommand , ActAsSetupFlags(..), actAsSetupCommand- , SandboxFlags(..), sandboxCommand , ExecFlags(..), execCommand , UserConfigFlags(..), userConfigCommand , reportCommand@@ -93,6 +90,7 @@ import qualified Distribution.Client.CmdExec as CmdExec import qualified Distribution.Client.CmdClean as CmdClean import qualified Distribution.Client.CmdSdist as CmdSdist+import qualified Distribution.Client.CmdListBin as CmdListBin import Distribution.Client.CmdLegacy import Distribution.Client.Install (install)@@ -107,39 +105,20 @@ --import Distribution.Client.Clean (clean) import qualified Distribution.Client.Upload as Upload import Distribution.Client.Run (run, splitRunArgs)-import Distribution.Client.SrcDist (sdist) import Distribution.Client.Get (get) import Distribution.Client.Reconfigure (Check(..), reconfigure) import Distribution.Client.Nix (nixInstantiate ,nixShell- ,nixShellIfSandboxed)-import Distribution.Client.Sandbox (sandboxInit- ,sandboxAddSource- ,sandboxDelete- ,sandboxDeleteSource- ,sandboxListSources- ,sandboxHcPkg- ,dumpPackageEnvironment-- ,loadConfigOrSandboxConfig+ )+import Distribution.Client.Sandbox (loadConfigOrSandboxConfig ,findSavedDistPref- ,initPackageDBIfNeeded- ,maybeWithSandboxDirOnSearchPath- ,maybeWithSandboxPackageInfo- ,tryGetIndexFilePath- ,sandboxBuildDir- ,updateSandboxConfigFileFlag ,updateInstallDirs- ,getPersistOrConfigCompiler)-import Distribution.Client.Sandbox.PackageEnvironment (setPackageDB)-import Distribution.Client.Sandbox.Timestamp (maybeAddCompilerTimestampRecord)-import Distribution.Client.Sandbox.Types (UseSandbox(..), whenUsingSandbox) import Distribution.Client.Tar (createTarGzFile)-import Distribution.Client.Types (Password (..))+import Distribution.Client.Types.Credentials (Password (..)) import Distribution.Client.Init (initCabal)-import Distribution.Client.Manpage (manpage)-import qualified Distribution.Client.Win32SelfUpgrade as Win32SelfUpgrade+import Distribution.Client.Manpage (manpageCmd)+import Distribution.Client.ManpageFlags (ManpageFlags (..)) import Distribution.Client.Utils (determineNumJobs ,relaxEncodingErrors )@@ -160,7 +139,7 @@ ( CommandParse(..), CommandUI(..), Command, CommandSpec(..) , CommandType(..), commandsRun, commandAddAction, hiddenCommand , commandFromSpec, commandShowOptions )-import Distribution.Simple.Compiler (Compiler(..), PackageDBStack)+import Distribution.Simple.Compiler (PackageDBStack) import Distribution.Simple.Configure ( configCompilerAuxEx, ConfigStateFileError(..) , getPersistBuildConfig, interpretPackageDbFlags@@ -185,44 +164,19 @@ import Distribution.Compat.ResponseFile import System.Environment (getArgs, getProgName)-import System.Exit (exitFailure, exitSuccess) import System.FilePath ( dropExtension, splitExtension , takeExtension, (</>), (<.>) ) import System.IO ( BufferMode(LineBuffering), hSetBuffering , stderr, stdout ) import System.Directory (doesFileExist, getCurrentDirectory) import Data.Monoid (Any(..))-import Control.Exception (SomeException(..), try)-import Control.Monad (mapM_)+import Control.Exception (try) import Data.Version (showVersion) -#ifdef MONOLITHIC-import qualified UnitTests-import qualified MemoryUsageTests-import qualified SolverQuickCheck-import qualified IntegrationTests2-import qualified System.Environment as Monolithic-#endif- -- | Entry point -- main :: IO ()-#ifdef MONOLITHIC main = do- mb_exec <- Monolithic.lookupEnv "CABAL_INSTALL_MONOLITHIC_MODE"- case mb_exec of- Just "UnitTests" -> UnitTests.main- Just "MemoryUsageTests" -> MemoryUsageTests.main- Just "SolverQuickCheck" -> SolverQuickCheck.main- Just "IntegrationTests2" -> IntegrationTests2.main- Just s -> error $ "Unrecognized mode '" ++ show s ++ "' in CABAL_INSTALL_MONOLITHIC_MODE"- Nothing -> main'-#else-main = main'-#endif--main' :: IO ()-main' = do -- Enable line buffering so that we can get fast feedback even when piped. -- This is especially important for CI and build systems. hSetBuffering stdout LineBuffering@@ -255,9 +209,7 @@ CommandList opts -> printOptionsList opts CommandErrors errs -> maybe (printErrors errs) go maybeScriptAndArgs where go (script:|scriptArgs) = CmdRun.handleShebang script scriptArgs- CommandReadyToGo action -> do- globalFlags' <- updateSandboxConfigFileFlag globalFlags- action globalFlags'+ CommandReadyToGo action -> action globalFlags where printCommandHelp help = do@@ -297,12 +249,10 @@ , regularCmd genBoundsCommand genBoundsAction , regularCmd outdatedCommand outdatedAction , wrapperCmd hscolourCommand hscolourVerbosity hscolourDistPref- , hiddenCmd uninstallCommand uninstallAction , hiddenCmd formatCommand formatAction- , hiddenCmd upgradeCommand upgradeAction- , hiddenCmd win32SelfUpgradeCommand win32SelfUpgradeAction , hiddenCmd actAsSetupCommand actAsSetupAction , hiddenCmd manpageCommand (manpageAction commandSpecs)+ , regularCmd CmdListBin.listbinCommand CmdListBin.listbinAction ] ++ concat [ newCmd CmdConfigure.configureCommand CmdConfigure.configureAction@@ -331,12 +281,10 @@ , legacyCmd benchmarkCommand benchmarkAction , legacyCmd execCommand execAction , legacyCmd cleanCommand cleanAction- , legacyCmd sdistCommand sdistAction , legacyCmd doctestCommand doctestAction , legacyWrapperCmd copyCommand copyVerbosity copyDistPref , legacyWrapperCmd registerCommand regVerbosity regDistPref , legacyCmd reconfigureCommand reconfigureAction- , legacyCmd sandboxCommand sandboxAction ] type Action = GlobalFlags -> IO ()@@ -369,7 +317,7 @@ { commandDefaultFlags = mempty } $ \flags extraArgs globalFlags -> do let verbosity = fromFlagOrDefault normal (verbosityFlag flags) load <- try (loadConfigOrSandboxConfig verbosity globalFlags)- let config = either (\(SomeException _) -> mempty) snd load+ let config = either (\(SomeException _) -> mempty) id load distPref <- findSavedDistPref config (distPrefFlag flags) let setupScriptOptions = defaultSetupScriptOptions { useDistPref = distPref } setupWrapper verbosity setupScriptOptions Nothing@@ -379,7 +327,7 @@ -> [String] -> Action configureAction (configFlags, configExFlags) extraArgs globalFlags = do let verbosity = fromFlagOrDefault normal (configVerbosity configFlags)- (useSandbox, config) <- updateInstallDirs (configUserInstall configFlags)+ config <- updateInstallDirs (configUserInstall configFlags) <$> loadConfigOrSandboxConfig verbosity globalFlags distPref <- findSavedDistPref config (configDistPref configFlags) nixInstantiate verbosity distPref True globalFlags config@@ -389,43 +337,24 @@ globalFlags' = savedGlobalFlags config `mappend` globalFlags (comp, platform, progdb) <- configCompilerAuxEx configFlags' - -- If we're working inside a sandbox and the user has set the -w option, we- -- may need to create a sandbox-local package DB for this compiler and add a- -- timestamp record for this compiler to the timestamp file.- let configFlags'' = case useSandbox of- NoSandbox -> configFlags'- (UseSandbox sandboxDir) -> setPackageDB sandboxDir- comp platform configFlags'-- writeConfigFlags verbosity distPref (configFlags'', configExFlags')+ writeConfigFlags verbosity distPref (configFlags', configExFlags') -- What package database(s) to use let packageDBs :: PackageDBStack packageDBs = interpretPackageDbFlags- (fromFlag (configUserInstall configFlags''))- (configPackageDBs configFlags'')-- whenUsingSandbox useSandbox $ \sandboxDir -> do- initPackageDBIfNeeded verbosity configFlags'' comp progdb- -- NOTE: We do not write the new sandbox package DB location to- -- 'cabal.sandbox.config' here because 'configure -w' must not affect- -- subsequent 'install' (for UI compatibility with non-sandboxed mode).-- indexFile <- tryGetIndexFilePath verbosity config- maybeAddCompilerTimestampRecord verbosity sandboxDir indexFile- (compilerId comp) platform+ (fromFlag (configUserInstall configFlags'))+ (configPackageDBs configFlags') - maybeWithSandboxDirOnSearchPath useSandbox $- withRepoContext verbosity globalFlags' $ \repoContext ->+ withRepoContext verbosity globalFlags' $ \repoContext -> configure verbosity packageDBs repoContext- comp platform progdb configFlags'' configExFlags' extraArgs+ comp platform progdb configFlags' configExFlags' extraArgs reconfigureAction :: (ConfigFlags, ConfigExFlags) -> [String] -> Action reconfigureAction flags@(configFlags, _) _ globalFlags = do let verbosity = fromFlagOrDefault normal (configVerbosity configFlags)- (useSandbox, config) <- updateInstallDirs (configUserInstall configFlags)+ config <- updateInstallDirs (configUserInstall configFlags) <$> loadConfigOrSandboxConfig verbosity globalFlags distPref <- findSavedDistPref config (configDistPref configFlags) let checkFlags = Check $ \_ saved -> do@@ -442,26 +371,23 @@ nixInstantiate verbosity distPref True globalFlags config _ <- reconfigure configureAction- verbosity distPref useSandbox DontSkipAddSourceDepsCheck NoFlag+ verbosity distPref NoFlag checkFlags [] globalFlags config pure () -buildAction :: (BuildFlags, BuildExFlags) -> [String] -> Action-buildAction (buildFlags, buildExFlags) extraArgs globalFlags = do+buildAction :: BuildFlags -> [String] -> Action+buildAction buildFlags extraArgs globalFlags = do let verbosity = fromFlagOrDefault normal (buildVerbosity buildFlags)- noAddSource = fromFlagOrDefault DontSkipAddSourceDepsCheck- (buildOnly buildExFlags)- (useSandbox, config) <- loadConfigOrSandboxConfig verbosity globalFlags+ config <- loadConfigOrSandboxConfig verbosity globalFlags distPref <- findSavedDistPref config (buildDistPref buildFlags) -- Calls 'configureAction' to do the real work, so nothing special has to be -- done to support sandboxes. config' <- reconfigure configureAction- verbosity distPref useSandbox noAddSource (buildNumJobs buildFlags)+ verbosity distPref (buildNumJobs buildFlags) mempty [] globalFlags config nixShell verbosity distPref globalFlags config $ do- maybeWithSandboxDirOnSearchPath useSandbox $- build verbosity config' distPref buildFlags extraArgs+ build verbosity config' distPref buildFlags extraArgs -- | Actually do the work of building the package. This is separate from@@ -501,10 +427,10 @@ numJobsCmdLineFlag = buildNumJobs buildFlags -replAction :: (ReplFlags, BuildExFlags) -> [String] -> Action-replAction (replFlags, buildExFlags) extraArgs globalFlags = do+replAction :: ReplFlags -> [String] -> Action+replAction replFlags extraArgs globalFlags = do let verbosity = fromFlagOrDefault normal (replVerbosity replFlags)- (useSandbox, config) <- loadConfigOrSandboxConfig verbosity globalFlags+ config <- loadConfigOrSandboxConfig verbosity globalFlags distPref <- findSavedDistPref config (replDistPref replFlags) cwd <- getCurrentDirectory pkgDesc <- findPackageDesc cwd@@ -512,16 +438,11 @@ -- There is a .cabal file in the current directory: start a REPL and load -- the project's modules. onPkgDesc = do- let noAddSource = case replReload replFlags of- Flag True -> SkipAddSourceDepsCheck- _ -> fromFlagOrDefault DontSkipAddSourceDepsCheck- (buildOnly buildExFlags)- -- Calls 'configureAction' to do the real work, so nothing special has to -- be done to support sandboxes. _ <- reconfigure configureAction- verbosity distPref useSandbox noAddSource NoFlag+ verbosity distPref NoFlag mempty [] globalFlags config let progDb = defaultProgramDb setupOptions = defaultSetupScriptOptions@@ -533,10 +454,8 @@ , replDistPref = toFlag distPref } - nixShell verbosity distPref globalFlags config $ do- maybeWithSandboxDirOnSearchPath useSandbox $- setupWrapper verbosity setupOptions Nothing- (Cabal.replCommand progDb) (const replFlags') (const extraArgs)+ nixShell verbosity distPref globalFlags config $+ setupWrapper verbosity setupOptions Nothing (Cabal.replCommand progDb) (const replFlags') (const extraArgs) -- No .cabal file in the current directory: just start the REPL (possibly -- using the sandbox package DB).@@ -559,11 +478,10 @@ installAction (configFlags, _, installFlags, _, _, _) _ globalFlags | fromFlagOrDefault False (installOnly installFlags) = do let verb = fromFlagOrDefault normal (configVerbosity configFlags)- (useSandbox, config) <- loadConfigOrSandboxConfig verb globalFlags+ config <- loadConfigOrSandboxConfig verb globalFlags dist <- findSavedDistPref config (configDistPref configFlags) let setupOpts = defaultSetupScriptOptions { useDistPref = dist }- nixShellIfSandboxed verb dist globalFlags config useSandbox $- setupWrapper+ setupWrapper verb setupOpts Nothing installCommand (const (mempty, mempty, mempty, mempty, mempty, mempty)) (const [])@@ -573,29 +491,14 @@ , haddockFlags, testFlags, benchmarkFlags ) extraArgs globalFlags = do let verb = fromFlagOrDefault normal (configVerbosity configFlags)- (useSandbox, config) <- updateInstallDirs (configUserInstall configFlags)+ config <- updateInstallDirs (configUserInstall configFlags) <$> loadConfigOrSandboxConfig verb globalFlags - let sandboxDist =- case useSandbox of- NoSandbox -> NoFlag- UseSandbox sandboxDir -> Flag $ sandboxBuildDir sandboxDir- dist <- findSavedDistPref config- (configDistPref configFlags `mappend` sandboxDist)+ dist <- findSavedDistPref config (configDistPref configFlags) - nixShellIfSandboxed verb dist globalFlags config useSandbox $ do+ do targets <- readUserTargets verb extraArgs - -- TODO: It'd be nice if 'cabal install' picked up the '-w' flag passed to- -- 'configure' when run inside a sandbox. Right now, running- --- -- \$ cabal sandbox init && cabal configure -w /path/to/ghc- -- && cabal build && cabal install- --- -- performs the compilation twice unless you also pass -w to 'install'.- -- However, this is the same behaviour that 'cabal install' has in the normal- -- mode of operation, so we stick to it for consistency.- let configFlags' = maybeForceTests installFlags' $ savedConfigureFlags config `mappend` configFlags { configDistPref = toFlag dist }@@ -614,39 +517,18 @@ benchmarkFlags { benchmarkDistPref = toFlag dist } globalFlags' = savedGlobalFlags config `mappend` globalFlags (comp, platform, progdb) <- configCompilerAux' configFlags'+ -- TODO: Redesign ProgramDB API to prevent such problems as #2241 in the -- future. progdb' <- configureAllKnownPrograms verb progdb - -- If we're working inside a sandbox and the user has set the -w option, we- -- may need to create a sandbox-local package DB for this compiler and add a- -- timestamp record for this compiler to the timestamp file.- configFlags'' <- case useSandbox of- NoSandbox -> configAbsolutePaths $ configFlags'- (UseSandbox sandboxDir) -> return $ setPackageDB sandboxDir comp platform- configFlags'-- whenUsingSandbox useSandbox $ \sandboxDir -> do- initPackageDBIfNeeded verb configFlags'' comp progdb'-- indexFile <- tryGetIndexFilePath verb config- maybeAddCompilerTimestampRecord verb sandboxDir indexFile- (compilerId comp) platform+ configFlags'' <- configAbsolutePaths configFlags' - -- TODO: Passing 'SandboxPackageInfo' to install unconditionally here means- -- that 'cabal install some-package' inside a sandbox will sometimes reinstall- -- modified add-source deps, even if they are not among the dependencies of- -- 'some-package'. This can also prevent packages that depend on older- -- versions of add-source'd packages from building (see #1362).- maybeWithSandboxPackageInfo verb configFlags'' globalFlags'- comp platform progdb useSandbox $ \mSandboxPkgInfo ->- maybeWithSandboxDirOnSearchPath useSandbox $- withRepoContext verb globalFlags' $ \repoContext ->+ withRepoContext verb globalFlags' $ \repoContext -> install verb (configPackageDB' configFlags'') repoContext comp platform progdb'- useSandbox mSandboxPkgInfo globalFlags' configFlags'' configExFlags' installFlags' haddockFlags' testFlags' benchmarkFlags' targets@@ -658,15 +540,13 @@ then configFlags' { configTests = toFlag True } else configFlags' -testAction :: (TestFlags, BuildFlags, BuildExFlags) -> [String] -> GlobalFlags+testAction :: (BuildFlags, TestFlags) -> [String] -> GlobalFlags -> IO ()-testAction (testFlags, buildFlags, buildExFlags) extraArgs globalFlags = do- let verbosity = fromFlagOrDefault normal (testVerbosity testFlags)- (useSandbox, config) <- loadConfigOrSandboxConfig verbosity globalFlags+testAction (buildFlags, testFlags) extraArgs globalFlags = do+ let verbosity = fromFlagOrDefault normal (buildVerbosity buildFlags)+ config <- loadConfigOrSandboxConfig verbosity globalFlags distPref <- findSavedDistPref config (testDistPref testFlags)- let noAddSource = fromFlagOrDefault DontSkipAddSourceDepsCheck- (buildOnly buildExFlags)- buildFlags' = buildFlags+ let buildFlags' = buildFlags { buildVerbosity = testVerbosity testFlags } checkFlags = Check $ \_ flags@(configFlags, configExFlags) -> if fromFlagOrDefault False (configTests configFlags)@@ -678,11 +558,9 @@ ) pure (Any True, flags') - -- reconfigure also checks if we're in a sandbox and reinstalls add-source- -- deps if needed. _ <- reconfigure configureAction- verbosity distPref useSandbox noAddSource (buildNumJobs buildFlags')+ verbosity distPref (buildNumJobs buildFlags') checkFlags [] globalFlags config nixShell verbosity distPref globalFlags config $ do let setupOptions = defaultSetupScriptOptions { useDistPref = distPref }@@ -698,12 +576,8 @@ | LBI.CTestName name <- names' ] | otherwise = extraArgs - maybeWithSandboxDirOnSearchPath useSandbox $- build verbosity config distPref buildFlags' extraArgs'-- maybeWithSandboxDirOnSearchPath useSandbox $- setupWrapper verbosity setupOptions Nothing- Cabal.testCommand (const testFlags') (const extraArgs')+ build verbosity config distPref buildFlags' extraArgs'+ setupWrapper verbosity setupOptions Nothing Cabal.testCommand (const testFlags') (const extraArgs') data ComponentNames = ComponentNamesUnknown | ComponentNames [LBI.ComponentName]@@ -734,21 +608,19 @@ else return $! (ComponentNames names) -benchmarkAction :: (BenchmarkFlags, BuildFlags, BuildExFlags)+benchmarkAction :: (BuildFlags, BenchmarkFlags) -> [String] -> GlobalFlags -> IO () benchmarkAction- (benchmarkFlags, buildFlags, buildExFlags)+ (buildFlags, benchmarkFlags) extraArgs globalFlags = do let verbosity = fromFlagOrDefault normal- (benchmarkVerbosity benchmarkFlags)+ (buildVerbosity buildFlags) - (useSandbox, config) <- loadConfigOrSandboxConfig verbosity globalFlags+ config <- loadConfigOrSandboxConfig verbosity globalFlags distPref <- findSavedDistPref config (benchmarkDistPref benchmarkFlags) let buildFlags' = buildFlags { buildVerbosity = benchmarkVerbosity benchmarkFlags }- noAddSource = fromFlagOrDefault DontSkipAddSourceDepsCheck- (buildOnly buildExFlags) let checkFlags = Check $ \_ flags@(configFlags, configExFlags) -> if fromFlagOrDefault False (configBenchmarks configFlags)@@ -760,12 +632,9 @@ ) pure (Any True, flags') -- -- reconfigure also checks if we're in a sandbox and reinstalls add-source- -- deps if needed. config' <- reconfigure configureAction- verbosity distPref useSandbox noAddSource (buildNumJobs buildFlags')+ verbosity distPref (buildNumJobs buildFlags') checkFlags [] globalFlags config nixShell verbosity distPref globalFlags config $ do let setupOptions = defaultSetupScriptOptions { useDistPref = distPref }@@ -781,21 +650,17 @@ | LBI.CBenchName name <- names'] | otherwise = extraArgs - maybeWithSandboxDirOnSearchPath useSandbox $- build verbosity config' distPref buildFlags' extraArgs'-- maybeWithSandboxDirOnSearchPath useSandbox $- setupWrapper verbosity setupOptions Nothing- Cabal.benchmarkCommand (const benchmarkFlags') (const extraArgs')+ build verbosity config' distPref buildFlags' extraArgs'+ setupWrapper verbosity setupOptions Nothing Cabal.benchmarkCommand (const benchmarkFlags') (const extraArgs') haddockAction :: HaddockFlags -> [String] -> Action haddockAction haddockFlags extraArgs globalFlags = do let verbosity = fromFlag (haddockVerbosity haddockFlags)- (useSandbox, config) <- loadConfigOrSandboxConfig verbosity globalFlags+ config <- loadConfigOrSandboxConfig verbosity globalFlags distPref <- findSavedDistPref config (haddockDistPref haddockFlags) config' <- reconfigure configureAction- verbosity distPref useSandbox DontSkipAddSourceDepsCheck NoFlag+ verbosity distPref NoFlag mempty [] globalFlags config nixShell verbosity distPref globalFlags config $ do let haddockFlags' = defaultHaddockFlags `mappend`@@ -823,7 +688,7 @@ cleanAction :: CleanFlags -> [String] -> Action cleanAction cleanFlags extraArgs globalFlags = do load <- try (loadConfigOrSandboxConfig verbosity globalFlags)- let config = either (\(SomeException _) -> mempty) snd load+ let config = either (\(SomeException _) -> mempty) id load distPref <- findSavedDistPref config (cleanDistPref cleanFlags) let setupScriptOptions = defaultSetupScriptOptions { useDistPref = distPref@@ -838,21 +703,24 @@ listAction :: ListFlags -> [String] -> Action listAction listFlags extraArgs globalFlags = do let verbosity = fromFlag (listVerbosity listFlags)- (_useSandbox, config) <- loadConfigOrSandboxConfig verbosity- (globalFlags { globalRequireSandbox = Flag False })+ config <- loadConfigOrSandboxConfig verbosity globalFlags let configFlags' = savedConfigureFlags config- configFlags = configFlags' {- configPackageDBs = configPackageDBs configFlags'+ configFlags = configFlags'+ { configPackageDBs = configPackageDBs configFlags' `mappend` listPackageDBs listFlags+ , configHcPath = listHcPath listFlags } globalFlags' = savedGlobalFlags config `mappend` globalFlags- (comp, _, progdb) <- configCompilerAux' configFlags+ compProgdb <- if listNeedsCompiler listFlags + then do+ (comp, _, progdb) <- configCompilerAux' configFlags+ return (Just (comp, progdb))+ else return Nothing withRepoContext verbosity globalFlags' $ \repoContext -> List.list verbosity (configPackageDB' configFlags) repoContext- comp- progdb+ compProgdb listFlags extraArgs @@ -860,8 +728,7 @@ infoAction infoFlags extraArgs globalFlags = do let verbosity = fromFlag (infoVerbosity infoFlags) targets <- readUserTargets verbosity extraArgs- (_useSandbox, config) <- loadConfigOrSandboxConfig verbosity- (globalFlags { globalRequireSandbox = Flag False })+ config <- loadConfigOrSandboxConfig verbosity globalFlags let configFlags' = savedConfigureFlags config configFlags = configFlags' { configPackageDBs = configPackageDBs configFlags'@@ -884,30 +751,11 @@ let verbosity = fromFlag (updateVerbosity updateFlags) unless (null extraArgs) $ die' verbosity $ "'update' doesn't take any extra arguments: " ++ unwords extraArgs- (_useSandbox, config) <- loadConfigOrSandboxConfig verbosity- (globalFlags { globalRequireSandbox = Flag False })+ config <- loadConfigOrSandboxConfig verbosity globalFlags let globalFlags' = savedGlobalFlags config `mappend` globalFlags withRepoContext verbosity globalFlags' $ \repoContext -> update verbosity updateFlags repoContext -upgradeAction :: ( ConfigFlags, ConfigExFlags, InstallFlags- , HaddockFlags, TestFlags, BenchmarkFlags )- -> [String] -> Action-upgradeAction (configFlags, _, _, _, _, _) _ _ = die' verbosity $- "Use the 'cabal install' command instead of 'cabal upgrade'.\n"- ++ "You can install the latest version of a package using 'cabal install'. "- ++ "The 'cabal upgrade' command has been removed because people found it "- ++ "confusing and it often led to broken packages.\n"- ++ "If you want the old upgrade behaviour then use the install command "- ++ "with the --upgrade-dependencies flag (but check first with --dry-run "- ++ "to see what would happen). This will try to pick the latest versions "- ++ "of all dependencies, rather than the usual behaviour of trying to pick "- ++ "installed versions of all dependencies. If you do use "- ++ "--upgrade-dependencies, it is recommended that you do not upgrade core "- ++ "packages (e.g. by using appropriate --constraint= flags)."- where- verbosity = fromFlag (configVerbosity configFlags)- fetchAction :: FetchFlags -> [String] -> Action fetchAction fetchFlags extraArgs globalFlags = do let verbosity = fromFlag (fetchVerbosity fetchFlags)@@ -926,51 +774,41 @@ freezeAction :: FreezeFlags -> [String] -> Action freezeAction freezeFlags _extraArgs globalFlags = do let verbosity = fromFlag (freezeVerbosity freezeFlags)- (useSandbox, config) <- loadConfigOrSandboxConfig verbosity globalFlags+ config <- loadConfigOrSandboxConfig verbosity globalFlags distPref <- findSavedDistPref config NoFlag nixShell verbosity distPref globalFlags config $ do let configFlags = savedConfigureFlags config globalFlags' = savedGlobalFlags config `mappend` globalFlags (comp, platform, progdb) <- configCompilerAux' configFlags - maybeWithSandboxPackageInfo- verbosity configFlags globalFlags'- comp platform progdb useSandbox $ \mSandboxPkgInfo ->- maybeWithSandboxDirOnSearchPath useSandbox $- withRepoContext verbosity globalFlags' $ \repoContext ->- freeze verbosity+ withRepoContext verbosity globalFlags' $ \repoContext ->+ freeze verbosity (configPackageDB' configFlags) repoContext comp platform progdb- mSandboxPkgInfo globalFlags' freezeFlags genBoundsAction :: FreezeFlags -> [String] -> GlobalFlags -> IO () genBoundsAction freezeFlags _extraArgs globalFlags = do let verbosity = fromFlag (freezeVerbosity freezeFlags)- (useSandbox, config) <- loadConfigOrSandboxConfig verbosity globalFlags+ config <- loadConfigOrSandboxConfig verbosity globalFlags distPref <- findSavedDistPref config NoFlag nixShell verbosity distPref globalFlags config $ do let configFlags = savedConfigureFlags config globalFlags' = savedGlobalFlags config `mappend` globalFlags (comp, platform, progdb) <- configCompilerAux' configFlags - maybeWithSandboxPackageInfo- verbosity configFlags globalFlags'- comp platform progdb useSandbox $ \mSandboxPkgInfo ->- maybeWithSandboxDirOnSearchPath useSandbox $- withRepoContext verbosity globalFlags' $ \repoContext ->- genBounds verbosity+ withRepoContext verbosity globalFlags' $ \repoContext ->+ genBounds verbosity (configPackageDB' configFlags) repoContext comp platform progdb- mSandboxPkgInfo globalFlags' freezeFlags outdatedAction :: OutdatedFlags -> [String] -> GlobalFlags -> IO () outdatedAction outdatedFlags _extraArgs globalFlags = do let verbosity = fromFlag (outdatedVerbosity outdatedFlags)- (_useSandbox, config) <- loadConfigOrSandboxConfig verbosity globalFlags+ config <- loadConfigOrSandboxConfig verbosity globalFlags let configFlags = savedConfigureFlags config globalFlags' = savedGlobalFlags config `mappend` globalFlags (comp, platform, _progdb) <- configCompilerAux' configFlags@@ -1060,29 +898,6 @@ -- Uses 'writeFileAtomic' under the hood. writeGenericPackageDescription path pkgDesc -uninstallAction :: Flag Verbosity -> [String] -> Action-uninstallAction verbosityFlag extraArgs _globalFlags = do- let verbosity = fromFlag verbosityFlag- package = case extraArgs of- p:_ -> p- _ -> "PACKAGE_NAME"- die' verbosity $ "This version of 'cabal-install' does not support the 'uninstall' "- ++ "operation. "- ++ "It will likely be implemented at some point in the future; "- ++ "in the meantime you're advised to use either 'ghc-pkg unregister "- ++ package ++ "' or 'cabal sandbox hc-pkg -- unregister " ++ package ++ "'."---sdistAction :: SDistFlags -> [String] -> Action-sdistAction sdistFlags extraArgs globalFlags = do- let verbosity = fromFlag (sDistVerbosity sdistFlags)- unless (null extraArgs) $- die' verbosity $ "'sdist' doesn't take any extra arguments: " ++ unwords extraArgs- load <- try (loadConfigOrSandboxConfig verbosity globalFlags)- let config = either (\(SomeException _) -> mempty) snd load- distPref <- findSavedDistPref config (sDistDistPref sdistFlags)- sdist sdistFlags { sDistDistPref = toFlag distPref }- reportAction :: ReportFlags -> [String] -> Action reportAction reportFlags extraArgs globalFlags = do let verbosity = fromFlag (reportVerbosity reportFlags)@@ -1097,35 +912,27 @@ (flagToMaybe $ reportUsername reportFlags') (flagToMaybe $ reportPassword reportFlags') -runAction :: (BuildFlags, BuildExFlags) -> [String] -> Action-runAction (buildFlags, buildExFlags) extraArgs globalFlags = do+runAction :: BuildFlags -> [String] -> Action+runAction buildFlags extraArgs globalFlags = do let verbosity = fromFlagOrDefault normal (buildVerbosity buildFlags)- (useSandbox, config) <- loadConfigOrSandboxConfig verbosity globalFlags+ config <- loadConfigOrSandboxConfig verbosity globalFlags distPref <- findSavedDistPref config (buildDistPref buildFlags)- let noAddSource = fromFlagOrDefault DontSkipAddSourceDepsCheck- (buildOnly buildExFlags)- -- reconfigure also checks if we're in a sandbox and reinstalls add-source- -- deps if needed. config' <- reconfigure configureAction- verbosity distPref useSandbox noAddSource (buildNumJobs buildFlags)+ verbosity distPref (buildNumJobs buildFlags) mempty [] globalFlags config nixShell verbosity distPref globalFlags config $ do lbi <- getPersistBuildConfig distPref (exe, exeArgs) <- splitRunArgs verbosity lbi extraArgs - maybeWithSandboxDirOnSearchPath useSandbox $- build verbosity config' distPref buildFlags ["exe:" ++ display (exeName exe)]-- maybeWithSandboxDirOnSearchPath useSandbox $- run verbosity lbi exe exeArgs+ build verbosity config' distPref buildFlags ["exe:" ++ display (exeName exe)]+ run verbosity lbi exe exeArgs getAction :: GetFlags -> [String] -> Action getAction getFlags extraArgs globalFlags = do let verbosity = fromFlag (getVerbosity getFlags) targets <- readUserTargets verbosity extraArgs- (_useSandbox, config) <- loadConfigOrSandboxConfig verbosity- (globalFlags { globalRequireSandbox = Flag False })+ config <- loadConfigOrSandboxConfig verbosity globalFlags let globalFlags' = savedGlobalFlags config `mappend` globalFlags withRepoContext verbosity (savedGlobalFlags config) $ \repoContext -> get verbosity@@ -1143,8 +950,7 @@ let verbosity = fromFlag (initVerbosity initFlags) when (extraArgs /= []) $ die' verbosity $ "'init' doesn't take any extra arguments: " ++ unwords extraArgs- (_useSandbox, config) <- loadConfigOrSandboxConfig verbosity- (globalFlags { globalRequireSandbox = Flag False })+ config <- loadConfigOrSandboxConfig verbosity globalFlags let configFlags = savedConfigureFlags config `mappend` -- override with `--with-compiler` from CLI if available mempty { configHcPath = initHcPath initFlags }@@ -1159,78 +965,35 @@ progdb initFlags' -sandboxAction :: SandboxFlags -> [String] -> Action-sandboxAction sandboxFlags extraArgs globalFlags = do- let verbosity = fromFlag (sandboxVerbosity sandboxFlags)- case extraArgs of- -- Basic sandbox commands.- ["init"] -> sandboxInit verbosity sandboxFlags globalFlags- ["delete"] -> sandboxDelete verbosity sandboxFlags globalFlags- ("add-source":extra) -> do- when (noExtraArgs extra) $- die' verbosity "The 'sandbox add-source' command expects at least one argument"- sandboxAddSource verbosity extra sandboxFlags globalFlags- ("delete-source":extra) -> do- when (noExtraArgs extra) $- die' verbosity ("The 'sandbox delete-source' command expects " ++- "at least one argument")- sandboxDeleteSource verbosity extra sandboxFlags globalFlags- ["list-sources"] -> sandboxListSources verbosity sandboxFlags globalFlags-- -- More advanced commands.- ("hc-pkg":extra) -> do- when (noExtraArgs extra) $- die' verbosity $ "The 'sandbox hc-pkg' command expects at least one argument"- sandboxHcPkg verbosity sandboxFlags globalFlags extra- ["buildopts"] -> die' verbosity "Not implemented!"-- -- Hidden commands.- ["dump-pkgenv"] -> dumpPackageEnvironment verbosity sandboxFlags globalFlags-- -- Error handling.- [] -> die' verbosity $ "Please specify a subcommand (see 'help sandbox')"- _ -> die' verbosity $ "Unknown 'sandbox' subcommand: " ++ unwords extraArgs-- where- noExtraArgs = (<1) . length- execAction :: ExecFlags -> [String] -> Action execAction execFlags extraArgs globalFlags = do let verbosity = fromFlag (execVerbosity execFlags)- (useSandbox, config) <- loadConfigOrSandboxConfig verbosity globalFlags+ config <- loadConfigOrSandboxConfig verbosity globalFlags distPref <- findSavedDistPref config (execDistPref execFlags) let configFlags = savedConfigureFlags config configFlags' = configFlags { configDistPref = Flag distPref } (comp, platform, progdb) <- getPersistOrConfigCompiler configFlags'- exec verbosity useSandbox comp platform progdb extraArgs+ exec verbosity comp platform progdb extraArgs userConfigAction :: UserConfigFlags -> [String] -> Action userConfigAction ucflags extraArgs globalFlags = do let verbosity = fromFlag (userConfigVerbosity ucflags)- force = fromFlag (userConfigForce ucflags)+ frc = fromFlag (userConfigForce ucflags) extraLines = fromFlag (userConfigAppendLines ucflags) case extraArgs of ("init":_) -> do path <- configFile fileExists <- doesFileExist path- if (not fileExists || (fileExists && force))+ if (not fileExists || (fileExists && frc)) then void $ createDefaultConfigFile verbosity extraLines path else die' verbosity $ path ++ " already exists."- ("diff":_) -> mapM_ putStrLn =<< userConfigDiff verbosity globalFlags extraLines+ ("diff":_) -> traverse_ putStrLn =<< userConfigDiff verbosity globalFlags extraLines ("update":_) -> userConfigUpdate verbosity globalFlags extraLines -- Error handling. [] -> die' verbosity $ "Please specify a subcommand (see 'help user-config')" _ -> die' verbosity $ "Unknown 'user-config' subcommand: " ++ unwords extraArgs where configFile = getConfigFilePath (globalConfigFile globalFlags) --- | See 'Distribution.Client.Install.withWin32SelfUpgrade' for details.----win32SelfUpgradeAction :: Win32SelfUpgradeFlags -> [String] -> Action-win32SelfUpgradeAction selfUpgradeFlags (pid:path:_extraArgs) _globalFlags = do- let verbosity = fromFlag (win32SelfUpgradeVerbosity selfUpgradeFlags)- Win32SelfUpgrade.deleteOldExeFile verbosity (fromMaybe (error $ "panic! read pid=" ++ show pid) $ readMaybe pid) path -- TODO: eradicateNoParse-win32SelfUpgradeAction _ _ _ = return ()- -- | Used as an entry point when cabal-install needs to invoke itself -- as a setup script. This can happen e.g. when doing parallel builds. --@@ -1244,13 +1007,13 @@ Make -> Make.defaultMainArgs args Custom -> error "actAsSetupAction Custom" -manpageAction :: [CommandSpec action] -> Flag Verbosity -> [String] -> Action-manpageAction commands flagVerbosity extraArgs _ = do- let verbosity = fromFlag flagVerbosity+manpageAction :: [CommandSpec action] -> ManpageFlags -> [String] -> Action+manpageAction commands flags extraArgs _ = do+ let verbosity = fromFlag (manpageVerbosity flags) unless (null extraArgs) $ die' verbosity $ "'manpage' doesn't take any extra arguments: " ++ unwords extraArgs pname <- getProgName let cabalCmd = if takeExtension pname == ".exe" then dropExtension pname else pname- putStrLn $ manpage cabalCmd commands+ manpageCmd cabalCmd commands flags
cabal/cabal-install/solver-dsl/UnitTests/Distribution/Solver/Modular/DSL.hs view
@@ -1,10 +1,12 @@ {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE OverloadedStrings #-} -- | DSL for testing the modular solver module UnitTests.Distribution.Solver.Modular.DSL ( ExampleDependency(..) , Dependencies(..)+ , ExSubLib(..) , ExTest(..) , ExExe(..) , ExConstraint(..)@@ -20,13 +22,21 @@ , ExampleQualifier(..) , ExampleVar(..) , EnableAllTests(..)+ , dependencies+ , publicDependencies+ , unbuildableDependencies , exAv , exAvNoLibrary , exInst+ , exSubLib+ , exTest+ , exExe , exFlagged , exResolve , extractInstallPlan , declareFlags+ , withSubLibrary+ , withSubLibraries , withSetupDeps , withTest , withTests@@ -43,11 +53,11 @@ -- base import Control.Arrow (second)-import Data.Either (partitionEithers) import qualified Data.Map as Map-import qualified Data.Set as Set+import qualified Distribution.Compat.NonEmptySet as NonEmptySet -- Cabal+import qualified Distribution.CabalSpecVersion as C import qualified Distribution.Compiler as C import qualified Distribution.InstalledPackageInfo as IPI import Distribution.License (License(..))@@ -57,6 +67,7 @@ import qualified Distribution.Types.ExeDependency as C import qualified Distribution.Types.ForeignLib as C import qualified Distribution.Types.LegacyExeDependency as C+import qualified Distribution.Types.LibraryVisibility as C import qualified Distribution.Types.PkgconfigDependency as C import qualified Distribution.Types.PkgconfigVersion as C import qualified Distribution.Types.PkgconfigVersionRange as C@@ -139,13 +150,41 @@ type ExamplePkgVersion = Int type ExamplePkgHash = String -- for example "installed" packages type ExampleFlagName = String+type ExampleSubLibName = String type ExampleTestName = String type ExampleExeName = String type ExampleVersionRange = C.VersionRange -data Dependencies = NotBuildable | Buildable [ExampleDependency]- deriving Show+data Dependencies = Dependencies {+ depsVisibility :: C.LibraryVisibility+ , depsIsBuildable :: Bool+ , depsExampleDependencies :: [ExampleDependency]+ } deriving Show +instance Semigroup Dependencies where+ deps1 <> deps2 = Dependencies {+ depsVisibility = depsVisibility deps1 <> depsVisibility deps2+ , depsIsBuildable = depsIsBuildable deps1 && depsIsBuildable deps2+ , depsExampleDependencies = depsExampleDependencies deps1 ++ depsExampleDependencies deps2+ }++instance Monoid Dependencies where+ mempty = Dependencies {+ depsVisibility = mempty+ , depsIsBuildable = True+ , depsExampleDependencies = []+ }+ mappend = (<>)++dependencies :: [ExampleDependency] -> Dependencies+dependencies deps = mempty { depsExampleDependencies = deps }++publicDependencies :: Dependencies+publicDependencies = mempty { depsVisibility = C.LibraryVisibilityPublic }++unbuildableDependencies :: Dependencies+unbuildableDependencies = mempty { depsIsBuildable = False }+ data ExampleDependency = -- | Simple dependency on any version ExAny ExamplePkgName@@ -157,6 +196,12 @@ -- and an exclusive upper bound. | ExRange ExamplePkgName ExamplePkgVersion ExamplePkgVersion + -- | Sub-library dependency+ | ExSubLibAny ExamplePkgName ExampleSubLibName++ -- | Sub-library dependency on a fixed version+ | ExSubLibFix ExamplePkgName ExampleSubLibName ExamplePkgVersion+ -- | Build-tool-depends dependency | ExBuildToolAny ExamplePkgName ExampleExeName @@ -190,13 +235,24 @@ , exFlagType :: FlagType } deriving Show -data ExTest = ExTest ExampleTestName [ExampleDependency]+data ExSubLib = ExSubLib ExampleSubLibName Dependencies -data ExExe = ExExe ExampleExeName [ExampleDependency]+data ExTest = ExTest ExampleTestName Dependencies +data ExExe = ExExe ExampleExeName Dependencies++exSubLib :: ExampleSubLibName -> [ExampleDependency] -> ExSubLib+exSubLib name deps = ExSubLib name (dependencies deps)++exTest :: ExampleTestName -> [ExampleDependency] -> ExTest+exTest name deps = ExTest name (dependencies deps)++exExe :: ExampleExeName -> [ExampleDependency] -> ExExe+exExe name deps = ExExe name (dependencies deps)+ exFlagged :: ExampleFlagName -> [ExampleDependency] -> [ExampleDependency] -> ExampleDependency-exFlagged n t e = ExFlagged n (Buildable t) (Buildable e)+exFlagged n t e = ExFlagged n (dependencies t) (dependencies e) data ExConstraint = ExVersionConstraint ConstraintScope ExampleVersionRange@@ -212,7 +268,7 @@ data ExampleAvailable = ExAv { exAvName :: ExamplePkgName , exAvVersion :: ExamplePkgVersion- , exAvDeps :: ComponentDeps [ExampleDependency]+ , exAvDeps :: ComponentDeps Dependencies -- Setting flags here is only necessary to override the default values of -- the fields in C.Flag.@@ -252,7 +308,7 @@ -- exAv :: ExamplePkgName -> ExamplePkgVersion -> [ExampleDependency] -> ExampleAvailable-exAv n v ds = (exAvNoLibrary n v) { exAvDeps = CD.fromLibraryDeps ds }+exAv n v ds = (exAvNoLibrary n v) { exAvDeps = CD.fromLibraryDeps (dependencies ds) } -- | Constructs an 'ExampleAvailable' package without a default library -- component.@@ -269,9 +325,18 @@ exAvFlags = flags } +withSubLibrary :: ExampleAvailable -> ExSubLib -> ExampleAvailable+withSubLibrary ex lib = withSubLibraries ex [lib]++withSubLibraries :: ExampleAvailable -> [ExSubLib] -> ExampleAvailable+withSubLibraries ex libs =+ let subLibCDs = CD.fromList [(CD.ComponentSubLib $ C.mkUnqualComponentName name, deps)+ | ExSubLib name deps <- libs]+ in ex { exAvDeps = exAvDeps ex <> subLibCDs }+ withSetupDeps :: ExampleAvailable -> [ExampleDependency] -> ExampleAvailable withSetupDeps ex setupDeps = ex {- exAvDeps = exAvDeps ex <> CD.fromSetupDeps setupDeps+ exAvDeps = exAvDeps ex <> CD.fromSetupDeps (dependencies setupDeps) } withTest :: ExampleAvailable -> ExTest -> ExampleAvailable@@ -330,18 +395,18 @@ exAvSrcPkg ex = let pkgId = exAvPkgId ex - flags :: [C.Flag]+ flags :: [C.PackageFlag] flags =- let declaredFlags :: Map ExampleFlagName C.Flag+ let declaredFlags :: Map ExampleFlagName C.PackageFlag declaredFlags = Map.fromListWith (\f1 f2 -> error $ "duplicate flag declarations: " ++ show [f1, f2]) [(exFlagName flag, mkFlag flag) | flag <- exAvFlags ex] - usedFlags :: Map ExampleFlagName C.Flag+ usedFlags :: Map ExampleFlagName C.PackageFlag usedFlags = Map.fromList [(fn, mkDefaultFlag fn) | fn <- names] where- names = concatMap extractFlags $ CD.flatDeps (exAvDeps ex)+ names = extractFlags $ CD.flatDeps (exAvDeps ex) in -- 'declaredFlags' overrides 'usedFlags' to give flags non-default settings: Map.elems $ declaredFlags `Map.union` usedFlags @@ -350,17 +415,17 @@ testSuites = [(name, deps) | (CD.ComponentTest name, deps) <- CD.toList (exAvDeps ex)] benchmarks = [(name, deps) | (CD.ComponentBench name, deps) <- CD.toList (exAvDeps ex)] executables = [(name, deps) | (CD.ComponentExe name, deps) <- CD.toList (exAvDeps ex)]- setup = case CD.setupDeps (exAvDeps ex) of+ setup = case depsExampleDependencies $ CD.setupDeps (exAvDeps ex) of [] -> Nothing deps -> Just C.SetupBuildInfo { C.setupDepends = mkSetupDeps deps, C.defaultSetupDepends = False }- package = SourcePackage {- packageInfoId = pkgId- , packageSource = LocalTarballPackage "<<path>>"- , packageDescrOverride = Nothing- , packageDescription = C.GenericPackageDescription {+ package = SourcePackage+ { srcpkgPackageId = pkgId+ , srcpkgSource = LocalTarballPackage "<<path>>"+ , srcpkgDescrOverride = Nothing+ , srcpkgDescription = C.GenericPackageDescription { C.packageDescription = C.emptyPackageDescription { C.package = pkgId , C.setupBuildInfo = setup@@ -374,34 +439,35 @@ , C.synopsis = "synopsis" , C.licenseFiles = ["LICENSE"] -- Version 2.0 is required for internal libraries.- , C.specVersionRaw = Left $ C.mkVersion [2,0]+ , C.specVersion = C.CabalSpecV2_0 }+ , C.gpdScannedVersion = Nothing , C.genPackageFlags = flags , C.condLibrary =- let mkLib bi = mempty { C.libBuildInfo = bi }+ let mkLib v bi = mempty { C.libVisibility = v, C.libBuildInfo = bi } -- Avoid using the Monoid instance for [a] when getting -- the library dependencies, to allow for the possibility -- that the package doesn't have a library: libDeps = lookup CD.ComponentLib (CD.toList (exAvDeps ex))- in mkCondTree defaultLib mkLib . mkBuildInfoTree . Buildable <$> libDeps+ in mkTopLevelCondTree defaultLib mkLib <$> libDeps , C.condSubLibraries =- let mkTree = mkCondTree defaultLib mkLib . mkBuildInfoTree . Buildable- mkLib bi = mempty { C.libBuildInfo = bi }+ let mkTree = mkTopLevelCondTree defaultSubLib mkLib+ mkLib v bi = mempty { C.libVisibility = v, C.libBuildInfo = bi } in map (second mkTree) subLibraries , C.condForeignLibs =- let mkTree = mkCondTree mempty mkLib . mkBuildInfoTree . Buildable+ let mkTree = mkTopLevelCondTree (mkLib defaultTopLevelBuildInfo) (const mkLib) mkLib bi = mempty { C.foreignLibBuildInfo = bi } in map (second mkTree) foreignLibraries , C.condExecutables =- let mkTree = mkCondTree defaultExe mkExe . mkBuildInfoTree . Buildable+ let mkTree = mkTopLevelCondTree defaultExe (const mkExe) mkExe bi = mempty { C.buildInfo = bi } in map (second mkTree) executables , C.condTestSuites =- let mkTree = mkCondTree defaultTest mkTest . mkBuildInfoTree . Buildable+ let mkTree = mkTopLevelCondTree defaultTest (const mkTest) mkTest bi = mempty { C.testBuildInfo = bi } in map (second mkTree) testSuites , C.condBenchmarks =- let mkTree = mkCondTree defaultBenchmark mkBench . mkBuildInfoTree . Buildable+ let mkTree = mkTopLevelCondTree defaultBenchmark (const mkBench) mkBench bi = mempty { C.benchmarkBuildInfo = bi } in map (second mkTree) benchmarks }@@ -411,7 +477,7 @@ -- solver allows unknown extensions/languages when the compiler -- supports them. let ignore = ["Unknown extensions:", "Unknown languages:"]- in [ err | err <- C.checkPackage (packageDescription package) Nothing+ in [ err | err <- C.checkPackage (srcpkgDescription package) Nothing , not $ any (`isPrefixOf` C.explanation err) ignore ] in if null pkgCheckErrors then package@@ -422,19 +488,34 @@ defaultTopLevelBuildInfo = mempty { C.defaultLanguage = Just Haskell98 } defaultLib :: C.Library- defaultLib = mempty { C.exposedModules = [Module.fromString "Module"] }+ defaultLib = mempty {+ C.libBuildInfo = defaultTopLevelBuildInfo+ , C.exposedModules = [Module.fromString "Module"]+ , C.libVisibility = C.LibraryVisibilityPublic+ } + defaultSubLib :: C.Library+ defaultSubLib = mempty {+ C.libBuildInfo = defaultTopLevelBuildInfo+ , C.exposedModules = [Module.fromString "Module"]+ }+ defaultExe :: C.Executable- defaultExe = mempty { C.modulePath = "Main.hs" }+ defaultExe = mempty {+ C.buildInfo = defaultTopLevelBuildInfo+ , C.modulePath = "Main.hs"+ } defaultTest :: C.TestSuite defaultTest = mempty {- C.testInterface = C.TestSuiteExeV10 (C.mkVersion [1,0]) "Test.hs"+ C.testBuildInfo = defaultTopLevelBuildInfo+ , C.testInterface = C.TestSuiteExeV10 (C.mkVersion [1,0]) "Test.hs" } defaultBenchmark :: C.Benchmark defaultBenchmark = mempty {- C.benchmarkInterface = C.BenchmarkExeV10 (C.mkVersion [1,0]) "Benchmark.hs"+ C.benchmarkBuildInfo = defaultTopLevelBuildInfo+ , C.benchmarkInterface = C.BenchmarkExeV10 (C.mkVersion [1,0]) "Benchmark.hs" } -- Split the set of dependencies into the set of dependencies of the library,@@ -476,57 +557,43 @@ in (dep:other, exts, lang, pcpkgs, exes, legacyExes) -- Extract the total set of flags used- extractFlags :: ExampleDependency -> [ExampleFlagName]- extractFlags (ExAny _) = []- extractFlags (ExFix _ _) = []- extractFlags (ExRange _ _ _) = []- extractFlags (ExBuildToolAny _ _) = []- extractFlags (ExBuildToolFix _ _ _) = []- extractFlags (ExLegacyBuildToolAny _) = []- extractFlags (ExLegacyBuildToolFix _ _) = []- extractFlags (ExFlagged f a b) =- f : concatMap extractFlags (deps a ++ deps b)- where- deps :: Dependencies -> [ExampleDependency]- deps NotBuildable = []- deps (Buildable ds) = ds- extractFlags (ExExt _) = []- extractFlags (ExLang _) = []- extractFlags (ExPkg _) = []-- -- Convert a tree of BuildInfos into a tree of a specific component type.- -- 'defaultTopLevel' contains the default values for the component, and- -- 'mkComponent' creates a component from a 'BuildInfo'.- mkCondTree :: forall a. Semigroup a =>- a -> (C.BuildInfo -> a)- -> DependencyTree C.BuildInfo- -> DependencyTree a- mkCondTree defaultTopLevel mkComponent (C.CondNode topData topConstraints topComps) =- C.CondNode {- C.condTreeData =- defaultTopLevel <> mkComponent (defaultTopLevelBuildInfo <> topData)- , C.condTreeConstraints = topConstraints- , C.condTreeComponents = goComponents topComps- }+ extractFlags :: Dependencies -> [ExampleFlagName]+ extractFlags deps = concatMap go (depsExampleDependencies deps) where- go :: DependencyTree C.BuildInfo -> DependencyTree a- go (C.CondNode ctData constraints comps) =- C.CondNode (mkComponent ctData) constraints (goComponents comps)+ go :: ExampleDependency -> [ExampleFlagName]+ go (ExAny _) = []+ go (ExFix _ _) = []+ go (ExRange _ _ _) = []+ go (ExSubLibAny _ _) = []+ go (ExSubLibFix _ _ _) = []+ go (ExBuildToolAny _ _) = []+ go (ExBuildToolFix _ _ _) = []+ go (ExLegacyBuildToolAny _) = []+ go (ExLegacyBuildToolFix _ _) = []+ go (ExFlagged f a b) = f : extractFlags a ++ extractFlags b+ go (ExExt _) = []+ go (ExLang _) = []+ go (ExPkg _) = [] - goComponents :: [DependencyComponent C.BuildInfo]- -> [DependencyComponent a]- goComponents comps = [C.CondBranch cond (go t) (go <$> me) | C.CondBranch cond t me <- comps]+ -- Convert 'Dependencies' into a tree of a specific component type, using+ -- the given top level component and function for creating a component at+ -- any level.+ mkTopLevelCondTree :: forall a. Semigroup a =>+ a+ -> (C.LibraryVisibility -> C.BuildInfo -> a)+ -> Dependencies+ -> DependencyTree a+ mkTopLevelCondTree defaultTopLevel mkComponent deps =+ let condNode = mkCondTree mkComponent deps+ in condNode { C.condTreeData = defaultTopLevel <> C.condTreeData condNode } - mkBuildInfoTree :: Dependencies -> DependencyTree C.BuildInfo- mkBuildInfoTree NotBuildable =- C.CondNode {- C.condTreeData = mempty { C.buildable = False }- , C.condTreeConstraints = []- , C.condTreeComponents = []- }- mkBuildInfoTree (Buildable deps) =- let (libraryDeps, exts, mlang, pcpkgs, buildTools, legacyBuildTools) = splitTopLevel deps+ -- Convert 'Dependencies' into a tree of a specific component type, using+ -- the given function to generate each component.+ mkCondTree :: (C.LibraryVisibility -> C.BuildInfo -> a) -> Dependencies -> DependencyTree a+ mkCondTree mkComponent deps =+ let (libraryDeps, exts, mlang, pcpkgs, buildTools, legacyBuildTools) = splitTopLevel (depsExampleDependencies deps) (directDeps, flaggedDeps) = splitDeps libraryDeps+ component = mkComponent (depsVisibility deps) bi bi = mempty { C.otherExtensions = exts , C.defaultLanguage = mlang@@ -538,25 +605,27 @@ | (n,v) <- pcpkgs , let n' = C.mkPkgconfigName n , let v' = C.PcThisVersion (mkSimplePkgconfigVersion v) ]+ , C.buildable = depsIsBuildable deps } in C.CondNode {- C.condTreeData = bi -- Necessary for language extensions+ C.condTreeData = component -- TODO: Arguably, build-tools dependencies should also -- effect constraints on conditional tree. But no way to -- distinguish between them , C.condTreeConstraints = map mkDirect directDeps- , C.condTreeComponents = map mkFlagged flaggedDeps+ , C.condTreeComponents = map (mkFlagged mkComponent) flaggedDeps } - mkDirect :: (ExamplePkgName, C.VersionRange) -> C.Dependency- mkDirect (dep, vr) = C.Dependency (C.mkPackageName dep) vr (Set.singleton C.LMainLibName)+ mkDirect :: (ExamplePkgName, C.LibraryName, C.VersionRange) -> C.Dependency+ mkDirect (dep, name, vr) = C.Dependency (C.mkPackageName dep) vr (NonEmptySet.singleton name) - mkFlagged :: (ExampleFlagName, Dependencies, Dependencies)- -> DependencyComponent C.BuildInfo- mkFlagged (f, a, b) =- C.CondBranch (C.Var (C.Flag (C.mkFlagName f)))- (mkBuildInfoTree a)- (Just (mkBuildInfoTree b))+ mkFlagged :: (C.LibraryVisibility -> C.BuildInfo -> a)+ -> (ExampleFlagName, Dependencies, Dependencies)+ -> DependencyComponent a+ mkFlagged mkComponent (f, a, b) =+ C.CondBranch (C.Var (C.PackageFlag (C.mkFlagName f)))+ (mkCondTree mkComponent a)+ (Just (mkCondTree mkComponent b)) -- Split a set of dependencies into direct dependencies and flagged -- dependencies. A direct dependency is a tuple of the name of package and@@ -564,20 +633,26 @@ -- 'mkDirect' for example. A flagged dependency is the set of dependencies -- guarded by a flag. splitDeps :: [ExampleDependency]- -> ( [(ExamplePkgName, C.VersionRange)]+ -> ( [(ExamplePkgName, C.LibraryName, C.VersionRange)] , [(ExampleFlagName, Dependencies, Dependencies)] ) splitDeps [] = ([], []) splitDeps (ExAny p:deps) = let (directDeps, flaggedDeps) = splitDeps deps- in ((p, C.anyVersion):directDeps, flaggedDeps)+ in ((p, C.LMainLibName, C.anyVersion):directDeps, flaggedDeps) splitDeps (ExFix p v:deps) = let (directDeps, flaggedDeps) = splitDeps deps- in ((p, C.thisVersion $ mkSimpleVersion v):directDeps, flaggedDeps)+ in ((p, C.LMainLibName, C.thisVersion $ mkSimpleVersion v):directDeps, flaggedDeps) splitDeps (ExRange p v1 v2:deps) = let (directDeps, flaggedDeps) = splitDeps deps- in ((p, mkVersionRange v1 v2):directDeps, flaggedDeps)+ in ((p, C.LMainLibName, mkVersionRange v1 v2):directDeps, flaggedDeps)+ splitDeps (ExSubLibAny p lib:deps) =+ let (directDeps, flaggedDeps) = splitDeps deps+ in ((p, C.LSubLibName (C.mkUnqualComponentName lib), C.anyVersion):directDeps, flaggedDeps)+ splitDeps (ExSubLibFix p lib v:deps) =+ let (directDeps, flaggedDeps) = splitDeps deps+ in ((p, C.LSubLibName (C.mkUnqualComponentName lib), C.thisVersion $ mkSimpleVersion v):directDeps, flaggedDeps) splitDeps (ExFlagged f a b:deps) = let (directDeps, flaggedDeps) = splitDeps deps in (directDeps, (f, a, b):flaggedDeps)@@ -586,7 +661,9 @@ -- custom-setup only supports simple dependencies mkSetupDeps :: [ExampleDependency] -> [C.Dependency] mkSetupDeps deps =- let (directDeps, []) = splitDeps deps in map mkDirect directDeps+ case splitDeps deps of+ (directDeps, []) -> map mkDirect directDeps+ _ -> error "mkSetupDeps: custom setup has non-simple deps" mkSimpleVersion :: ExamplePkgVersion -> C.Version mkSimpleVersion n = C.mkVersion [n, 0, 0]@@ -599,8 +676,8 @@ C.intersectVersionRanges (C.orLaterVersion $ mkSimpleVersion v1) (C.earlierVersion $ mkSimpleVersion v2) -mkFlag :: ExFlag -> C.Flag-mkFlag flag = C.MkFlag {+mkFlag :: ExFlag -> C.PackageFlag+mkFlag flag = C.MkPackageFlag { C.flagName = C.mkFlagName $ exFlagName flag , C.flagDescription = "" , C.flagDefault = exFlagDefault flag@@ -610,8 +687,8 @@ Automatic -> False } -mkDefaultFlag :: ExampleFlagName -> C.Flag-mkDefaultFlag flag = C.MkFlag {+mkDefaultFlag :: ExampleFlagName -> C.PackageFlag+mkDefaultFlag flag = C.MkPackageFlag { C.flagName = C.mkFlagName flag , C.flagDescription = "" , C.flagDefault = True@@ -652,6 +729,7 @@ -> [ExamplePkgName] -> Maybe Int -> CountConflicts+ -> FineGrainedConflicts -> MinimizeConflictSet -> IndependentGoals -> ReorderGoals@@ -666,9 +744,9 @@ -> EnableAllTests -> Progress String String CI.SolverInstallPlan.SolverInstallPlan exResolve db exts langs pkgConfigDb targets mbj countConflicts- minimizeConflictSet indepGoals reorder allowBootLibInstalls- onlyConstrained enableBj solveExes goalOrder constraints- prefs verbosity enableAllTests+ fineGrainedConflicts minimizeConflictSet indepGoals reorder+ allowBootLibInstalls onlyConstrained enableBj solveExes goalOrder+ constraints prefs verbosity enableAllTests = resolveDependencies C.buildPlatform compiler pkgConfigDb Modular params where defaultCompiler = C.unknownCompilerInfo C.buildCompilerId C.NoAbiTag@@ -692,6 +770,7 @@ $ addConstraints (fmap toLpc enableTests) $ addPreferences (fmap toPref prefs) $ setCountConflicts countConflicts+ $ setFineGrainedConflicts fineGrainedConflicts $ setMinimizeConflictSet minimizeConflictSet $ setIndependentGoals indepGoals $ setReorderGoals reorder@@ -725,7 +804,7 @@ srcPkg :: SolverPackage UnresolvedPkgLoc -> Maybe (String, Int) srcPkg cpkg =- let C.PackageIdentifier pn ver = packageInfoId (solverPkgSource cpkg)+ let C.PackageIdentifier pn ver = C.packageId (solverPkgSource cpkg) in (\vn -> (C.unPackageName pn, vn)) <$> safeHead (C.versionNumbers ver) {-------------------------------------------------------------------------------
cabal/cabal-install/tests/IntegrationTests2.hs view
@@ -1,6 +1,8 @@ {-# LANGUAGE CPP #-}+{-# LANGUAGE BangPatterns #-} {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE OverloadedStrings #-} -- For the handy instance IsString PackageIdentifier@@ -8,6 +10,9 @@ module IntegrationTests2 where +import Distribution.Client.Compat.Prelude+import Prelude ()+ import Distribution.Client.DistDirLayout import Distribution.Client.ProjectConfig import Distribution.Client.Config (getCabalDir)@@ -17,7 +22,9 @@ import Distribution.Client.ProjectPlanning.Types import Distribution.Client.ProjectBuilding import Distribution.Client.ProjectOrchestration- ( resolveTargets, TargetProblemCommon(..), distinctTargetComponents )+ ( resolveTargets, distinctTargetComponents )+import Distribution.Client.TargetProblem+ ( TargetProblem', TargetProblem (..) ) import Distribution.Client.Types ( PackageLocation(..), UnresolvedSourcePackage , PackageSpecifier(..) )@@ -39,35 +46,30 @@ import Distribution.Package import Distribution.PackageDescription-import qualified Distribution.Types.GenericPackageDescription as GPG import Distribution.InstalledPackageInfo (InstalledPackageInfo) import Distribution.Simple.Setup (toFlag, HaddockFlags(..), defaultHaddockFlags) import Distribution.Simple.Compiler import Distribution.System import Distribution.Version import Distribution.ModuleName (ModuleName)-import Distribution.Verbosity import Distribution.Text -#if !MIN_VERSION_base(4,8,0)-import Data.Monoid (mempty, mappend)-#endif-import Data.List (sort)-import Data.String (IsString(..)) import qualified Data.Map as Map import qualified Data.Set as Set import Control.Monad+import Control.Concurrent (threadDelay) import Control.Exception hiding (assert) import System.FilePath import System.Directory+import System.IO (hPutStrLn, stderr) import Test.Tasty import Test.Tasty.HUnit import Test.Tasty.Options import Data.Tagged (Tagged(..))-import Data.Proxy (Proxy(..))-import Data.Typeable (Typeable) +import qualified Data.ByteString as BS+ #if !MIN_VERSION_directory(1,2,7) removePathForcibly :: FilePath -> IO () removePathForcibly = removeDirectoryRecursive@@ -245,9 +247,15 @@ ":pkg:p:lib:p:file:P.y" , "q/QQ.hs", "q:QQ.lhs", "lib:q:QQ.hsc", "q:q:QQ.hsc", ":pkg:q:lib:q:file:QQ.y"+ , "q/Q.hs", "q:Q.lhs", "lib:q:Q.hsc", "q:q:Q.hsc",+ ":pkg:q:lib:q:file:Q.y"+ , "app/Main.hs", "p:app/Main.hs", "exe:ppexe:app/Main.hs", "p:ppexe:app/Main.hs",+ ":pkg:p:exe:ppexe:file:app/Main.hs" ] ts @?= replicate 5 (TargetComponent "p-0.1" (CLibName LMainLibName) (FileTarget "P")) ++ replicate 5 (TargetComponent "q-0.1" (CLibName LMainLibName) (FileTarget "QQ"))+ ++ replicate 5 (TargetComponent "q-0.1" (CLibName LMainLibName) (FileTarget "Q"))+ ++ replicate 5 (TargetComponent "p-0.1" (CExeName "ppexe") (FileTarget ("app" </> "Main.hs"))) -- Note there's a bit of an inconsistency here: for the single-part -- syntax the target has to point to a file that exists, whereas for -- all the other forms we don't require that.@@ -353,6 +361,24 @@ , mkexe "other2" `withCFiles` ["Foo"] ] ] + -- File target is ambiguous, part of multiple components+ reportSubCase "ambiguous: file in multiple comps"+ assertAmbiguous "Bar.hs"+ [ mkTargetFile "foo" (CExeName "bar") "Bar"+ , mkTargetFile "foo" (CExeName "bar2") "Bar"+ ]+ [ mkpkg "foo" [ mkexe "bar" `withModules` ["Bar"]+ , mkexe "bar2" `withModules` ["Bar"] ]+ ]+ reportSubCase "ambiguous: file in multiple comps with path"+ assertAmbiguous ("src" </> "Bar.hs")+ [ mkTargetFile "foo" (CExeName "bar") ("src" </> "Bar")+ , mkTargetFile "foo" (CExeName "bar2") ("src" </> "Bar")+ ]+ [ mkpkg "foo" [ mkexe "bar" `withModules` ["Bar"] `withHsSrcDirs` ["src"]+ , mkexe "bar2" `withModules` ["Bar"] `withHsSrcDirs` ["src"] ]+ ]+ -- non-exact case packages and components are ambiguous reportSubCase "ambiguous: non-exact-case pkg names" assertAmbiguous "Foo"@@ -423,11 +449,12 @@ -> SourcePackage (PackageLocation a) mkpkgAt pkgidstr exes loc = SourcePackage {- packageInfoId = pkgid,- packageSource = LocalUnpackedPackage loc,- packageDescrOverride = Nothing,- SP.packageDescription = GenericPackageDescription {- GPG.packageDescription = emptyPackageDescription { package = pkgid },+ srcpkgPackageId = pkgid,+ srcpkgSource = LocalUnpackedPackage loc,+ srcpkgDescrOverride = Nothing,+ srcpkgDescription = GenericPackageDescription {+ packageDescription = emptyPackageDescription { package = pkgid },+ gpdScannedVersion = Nothing, genPackageFlags = [], condLibrary = Nothing, condSubLibraries = [],@@ -439,7 +466,7 @@ } } where- Just pkgid = simpleParse pkgidstr+ pkgid = fromMaybe (error $ "failed to parse " ++ pkgidstr) $ simpleParse pkgidstr mkexe :: String -> Executable mkexe name = mempty { exeName = fromString name }@@ -452,7 +479,11 @@ withCFiles exe files = exe { buildInfo = (buildInfo exe) { cSources = files } } + withHsSrcDirs :: Executable -> [FilePath] -> Executable+ withHsSrcDirs exe srcDirs =+ exe { buildInfo = (buildInfo exe) { hsSourceDirs = srcDirs }} + mkTargetPackage :: PackageId -> TargetSelector mkTargetPackage pkgid = TargetPackage TargetExplicitNamed [pkgid] Nothing@@ -474,7 +505,7 @@ instance IsString PackageIdentifier where fromString pkgidstr = pkgid- where Just pkgid = simpleParse pkgidstr+ where pkgid = fromMaybe (error $"fromString @PackageIdentifier " ++ show pkgidstr) $ simpleParse pkgidstr testTargetSelectorNoCurrentPackage :: Assertion@@ -492,7 +523,7 @@ zipWithM_ (@?=) errs [ TargetSelectorNoCurrentPackage ts | target <- targets- , let Just ts = parseTargetString target+ , let ts = fromMaybe (error $ "failed to parse target string " ++ target) $ parseTargetString target ] cleanProject testdir where@@ -531,61 +562,53 @@ [ (packageName p, packageId p) | p <- InstallPlan.toList elaboratedPlan ] - cases :: [( TargetSelector -> CmdBuild.TargetProblem+ cases :: [( TargetSelector -> TargetProblem' , TargetSelector )] cases = [ -- Cannot resolve packages outside of the project- ( \_ -> CmdBuild.TargetProblemCommon $- TargetProblemNoSuchPackage "foobar"+ ( \_ -> TargetProblemNoSuchPackage "foobar" , mkTargetPackage "foobar" ) -- We cannot currently build components like testsuites or -- benchmarks from packages that are not local to the project- , ( \_ -> CmdBuild.TargetProblemCommon $- TargetComponentNotProjectLocal+ , ( \_ -> TargetComponentNotProjectLocal (pkgIdMap Map.! "filepath") (CTestName "filepath-tests") WholeComponent , mkTargetComponent (pkgIdMap Map.! "filepath") (CTestName "filepath-tests") ) -- Components can be explicitly @buildable: False@- , ( \_ -> CmdBuild.TargetProblemCommon $- TargetComponentNotBuildable "q-0.1" (CExeName "buildable-false") WholeComponent+ , ( \_ -> TargetComponentNotBuildable "q-0.1" (CExeName "buildable-false") WholeComponent , mkTargetComponent "q-0.1" (CExeName "buildable-false") ) -- Testsuites and benchmarks can be disabled by the solver if it -- cannot satisfy deps- , ( \_ -> CmdBuild.TargetProblemCommon $- TargetOptionalStanzaDisabledBySolver "q-0.1" (CTestName "solver-disabled") WholeComponent+ , ( \_ -> TargetOptionalStanzaDisabledBySolver "q-0.1" (CTestName "solver-disabled") WholeComponent , mkTargetComponent "q-0.1" (CTestName "solver-disabled") ) -- Testsuites and benchmarks can be disabled explicitly by the -- user via config- , ( \_ -> CmdBuild.TargetProblemCommon $- TargetOptionalStanzaDisabledByUser+ , ( \_ -> TargetOptionalStanzaDisabledByUser "q-0.1" (CBenchName "user-disabled") WholeComponent , mkTargetComponent "q-0.1" (CBenchName "user-disabled") ) -- An unknown package. The target selector resolution should only -- produce known packages, so this should not happen with the -- output from 'readTargetSelectors'.- , ( \_ -> CmdBuild.TargetProblemCommon $- TargetProblemNoSuchPackage "foobar"+ , ( \_ -> TargetProblemNoSuchPackage "foobar" , mkTargetPackage "foobar" ) -- An unknown component of a known package. The target selector -- resolution should only produce known packages, so this should -- not happen with the output from 'readTargetSelectors'.- , ( \_ -> CmdBuild.TargetProblemCommon $- TargetProblemNoSuchComponent "q-0.1" (CExeName "no-such")+ , ( \_ -> TargetProblemNoSuchComponent "q-0.1" (CExeName "no-such") , mkTargetComponent "q-0.1" (CExeName "no-such") ) ] assertTargetProblems elaboratedPlan CmdBuild.selectPackageTargets CmdBuild.selectComponentTarget- CmdBuild.TargetProblemCommon cases where testdir = "targets/complex"@@ -609,8 +632,7 @@ "targets/empty-pkg" config CmdBuild.selectPackageTargets CmdBuild.selectComponentTarget- CmdBuild.TargetProblemCommon- [ ( CmdBuild.TargetProblemNoTargets, mkTargetPackage "p-0.1" )+ [ ( TargetProblemNoTargets, mkTargetPackage "p-0.1" ) ] reportSubCase "all-disabled"@@ -623,8 +645,7 @@ } CmdBuild.selectPackageTargets CmdBuild.selectComponentTarget- CmdBuild.TargetProblemCommon- [ ( flip CmdBuild.TargetProblemNoneEnabled+ [ ( flip TargetProblemNoneEnabled [ AvailableTarget "p-0.1" (CBenchName "user-disabled") TargetDisabledByUser True , AvailableTarget "p-0.1" (CTestName "solver-disabled")@@ -650,7 +671,6 @@ elaboratedPlan CmdBuild.selectPackageTargets CmdBuild.selectComponentTarget- CmdBuild.TargetProblemCommon [ mkTargetPackage "p-0.1" ] [ ("p-0.1-inplace", (CLibName LMainLibName)) , ("p-0.1-inplace-a-benchmark", CBenchName "a-benchmark")@@ -672,7 +692,6 @@ elaboratedPlan CmdBuild.selectPackageTargets CmdBuild.selectComponentTarget- CmdBuild.TargetProblemCommon [ mkTargetPackage "p-0.1" ] [ ("p-0.1-inplace", (CLibName LMainLibName)) , ("p-0.1-inplace-an-exe", CExeName "an-exe")@@ -687,7 +706,6 @@ elaboratedPlan CmdBuild.selectPackageTargets CmdBuild.selectComponentTarget- CmdBuild.TargetProblemCommon [ TargetPackage TargetExplicitNamed ["p-0.1"] (Just TestKind) , TargetPackage TargetExplicitNamed ["p-0.1"] (Just BenchKind) ]@@ -704,8 +722,7 @@ "targets/multiple-libs" config CmdRepl.selectPackageTargets CmdRepl.selectComponentTarget- CmdRepl.TargetProblemCommon- [ ( flip CmdRepl.TargetProblemMatchesMultiple+ [ ( flip CmdRepl.matchesMultipleProblem [ AvailableTarget "p-0.1" (CLibName LMainLibName) (TargetBuildable () TargetRequestedByDefault) True , AvailableTarget "q-0.1" (CLibName LMainLibName)@@ -719,8 +736,7 @@ "targets/multiple-exes" config CmdRepl.selectPackageTargets CmdRepl.selectComponentTarget- CmdRepl.TargetProblemCommon- [ ( flip CmdRepl.TargetProblemMatchesMultiple+ [ ( flip CmdRepl.matchesMultipleProblem [ AvailableTarget "p-0.1" (CExeName "p2") (TargetBuildable () TargetRequestedByDefault) True , AvailableTarget "p-0.1" (CExeName "p1")@@ -734,8 +750,7 @@ "targets/multiple-tests" config CmdRepl.selectPackageTargets CmdRepl.selectComponentTarget- CmdRepl.TargetProblemCommon- [ ( flip CmdRepl.TargetProblemMatchesMultiple+ [ ( flip CmdRepl.matchesMultipleProblem [ AvailableTarget "p-0.1" (CTestName "p2") (TargetBuildable () TargetNotRequestedByDefault) True , AvailableTarget "p-0.1" (CTestName "p1")@@ -750,7 +765,6 @@ elaboratedPlan CmdRepl.selectPackageTargets CmdRepl.selectComponentTarget- CmdRepl.TargetProblemCommon [ mkTargetComponent "p-0.1" (CExeName "p1") , mkTargetComponent "p-0.1" (CExeName "p2") ]@@ -763,8 +777,7 @@ "targets/libs-disabled" config CmdRepl.selectPackageTargets CmdRepl.selectComponentTarget- CmdRepl.TargetProblemCommon- [ ( flip CmdRepl.TargetProblemNoneEnabled+ [ ( flip TargetProblemNoneEnabled [ AvailableTarget "p-0.1" (CLibName LMainLibName) TargetNotBuildable True ] , mkTargetPackage "p-0.1" ) ]@@ -774,8 +787,7 @@ "targets/exes-disabled" config CmdRepl.selectPackageTargets CmdRepl.selectComponentTarget- CmdRepl.TargetProblemCommon- [ ( flip CmdRepl.TargetProblemNoneEnabled+ [ ( flip TargetProblemNoneEnabled [ AvailableTarget "p-0.1" (CExeName "p") TargetNotBuildable True ] , mkTargetPackage "p-0.1" )@@ -786,8 +798,7 @@ "targets/test-only" config CmdRepl.selectPackageTargets CmdRepl.selectComponentTarget- CmdRepl.TargetProblemCommon- [ ( flip CmdRepl.TargetProblemNoneEnabled+ [ ( flip TargetProblemNoneEnabled [ AvailableTarget "p-0.1" (CTestName "pexe") (TargetBuildable () TargetNotRequestedByDefault) True ]@@ -799,8 +810,7 @@ "targets/empty-pkg" config CmdRepl.selectPackageTargets CmdRepl.selectComponentTarget- CmdRepl.TargetProblemCommon- [ ( CmdRepl.TargetProblemNoTargets, mkTargetPackage "p-0.1" )+ [ ( TargetProblemNoTargets, mkTargetPackage "p-0.1" ) ] reportSubCase "requested component kinds"@@ -810,7 +820,6 @@ elaboratedPlan CmdRepl.selectPackageTargets CmdRepl.selectComponentTarget- CmdRepl.TargetProblemCommon [ TargetPackage TargetExplicitNamed ["p-0.1"] Nothing ] [ ("p-0.1-inplace", (CLibName LMainLibName)) ] -- When we select the package with an explicit filter then we get those@@ -819,14 +828,12 @@ elaboratedPlan CmdRepl.selectPackageTargets CmdRepl.selectComponentTarget- CmdRepl.TargetProblemCommon [ TargetPackage TargetExplicitNamed ["p-0.1"] (Just TestKind) ] [ ("p-0.1-inplace-a-testsuite", CTestName "a-testsuite") ] assertProjectDistinctTargets elaboratedPlan CmdRepl.selectPackageTargets CmdRepl.selectComponentTarget- CmdRepl.TargetProblemCommon [ TargetPackage TargetExplicitNamed ["p-0.1"] (Just BenchKind) ] [ ("p-0.1-inplace-a-benchmark", CBenchName "a-benchmark") ] @@ -839,8 +846,7 @@ "targets/multiple-exes" config CmdRun.selectPackageTargets CmdRun.selectComponentTarget- CmdRun.TargetProblemCommon- [ ( flip CmdRun.TargetProblemMatchesMultiple+ [ ( flip CmdRun.matchesMultipleProblem [ AvailableTarget "p-0.1" (CExeName "p2") (TargetBuildable () TargetRequestedByDefault) True , AvailableTarget "p-0.1" (CExeName "p1")@@ -855,7 +861,6 @@ elaboratedPlan CmdRun.selectPackageTargets CmdRun.selectComponentTarget- CmdRun.TargetProblemCommon [ mkTargetComponent "p-0.1" (CExeName "p1") , mkTargetComponent "p-0.1" (CExeName "p2") ]@@ -868,8 +873,7 @@ "targets/exes-disabled" config CmdRun.selectPackageTargets CmdRun.selectComponentTarget- CmdRun.TargetProblemCommon- [ ( flip CmdRun.TargetProblemNoneEnabled+ [ ( flip TargetProblemNoneEnabled [ AvailableTarget "p-0.1" (CExeName "p") TargetNotBuildable True ] , mkTargetPackage "p-0.1" )@@ -880,8 +884,7 @@ "targets/empty-pkg" config CmdRun.selectPackageTargets CmdRun.selectComponentTarget- CmdRun.TargetProblemCommon- [ ( CmdRun.TargetProblemNoTargets, mkTargetPackage "p-0.1" )+ [ ( TargetProblemNoTargets, mkTargetPackage "p-0.1" ) ] reportSubCase "lib-only"@@ -889,8 +892,7 @@ "targets/lib-only" config CmdRun.selectPackageTargets CmdRun.selectComponentTarget- CmdRun.TargetProblemCommon- [ ( CmdRun.TargetProblemNoExes, mkTargetPackage "p-0.1" )+ [ (CmdRun.noExesProblem, mkTargetPackage "p-0.1" ) ] @@ -907,8 +909,7 @@ } CmdTest.selectPackageTargets CmdTest.selectComponentTarget- CmdTest.TargetProblemCommon- [ ( flip CmdTest.TargetProblemNoneEnabled+ [ ( flip TargetProblemNoneEnabled [ AvailableTarget "p-0.1" (CTestName "user-disabled") TargetDisabledByUser True , AvailableTarget "p-0.1" (CTestName "solver-disabled")@@ -923,8 +924,7 @@ config CmdTest.selectPackageTargets CmdTest.selectComponentTarget- CmdTest.TargetProblemCommon- [ ( flip CmdTest.TargetProblemNoneEnabled+ [ ( flip TargetProblemNoneEnabled [ AvailableTarget "p-0.1" (CTestName "user-disabled") TargetDisabledBySolver True , AvailableTarget "p-0.1" (CTestName "solver-disabled")@@ -932,7 +932,7 @@ ] , mkTargetPackage "p-0.1" ) - , ( flip CmdTest.TargetProblemNoneEnabled+ , ( flip TargetProblemNoneEnabled [ AvailableTarget "q-0.1" (CTestName "buildable-false") TargetNotBuildable True ]@@ -944,8 +944,7 @@ "targets/empty-pkg" config CmdTest.selectPackageTargets CmdTest.selectComponentTarget- CmdTest.TargetProblemCommon- [ ( CmdTest.TargetProblemNoTargets, mkTargetPackage "p-0.1" )+ [ ( TargetProblemNoTargets, mkTargetPackage "p-0.1" ) ] reportSubCase "no tests"@@ -954,9 +953,8 @@ config CmdTest.selectPackageTargets CmdTest.selectComponentTarget- CmdTest.TargetProblemCommon- [ ( CmdTest.TargetProblemNoTests, mkTargetPackage "p-0.1" )- , ( CmdTest.TargetProblemNoTests, mkTargetPackage "q-0.1" )+ [ ( CmdTest.noTestsProblem, mkTargetPackage "p-0.1" )+ , ( CmdTest.noTestsProblem, mkTargetPackage "q-0.1" ) ] reportSubCase "not a test"@@ -964,25 +962,24 @@ "targets/variety" config CmdTest.selectPackageTargets- CmdTest.selectComponentTarget- CmdTest.TargetProblemCommon $- [ ( const (CmdTest.TargetProblemComponentNotTest+ CmdTest.selectComponentTarget $+ [ ( const (CmdTest.notTestProblem "p-0.1" (CLibName LMainLibName)) , mkTargetComponent "p-0.1" (CLibName LMainLibName) ) - , ( const (CmdTest.TargetProblemComponentNotTest+ , ( const (CmdTest.notTestProblem "p-0.1" (CExeName "an-exe")) , mkTargetComponent "p-0.1" (CExeName "an-exe") ) - , ( const (CmdTest.TargetProblemComponentNotTest+ , ( const (CmdTest.notTestProblem "p-0.1" (CFLibName "libp")) , mkTargetComponent "p-0.1" (CFLibName "libp") ) - , ( const (CmdTest.TargetProblemComponentNotTest+ , ( const (CmdTest.notTestProblem "p-0.1" (CBenchName "a-benchmark")) , mkTargetComponent "p-0.1" (CBenchName "a-benchmark") ) ] ++- [ ( const (CmdTest.TargetProblemIsSubComponent+ [ ( const (CmdTest.isSubComponentProblem "p-0.1" cname (ModuleTarget modname)) , mkTargetModule "p-0.1" cname modname ) | (cname, modname) <- [ (CTestName "a-testsuite", "TestModule")@@ -991,7 +988,7 @@ , ((CLibName LMainLibName), "P") ] ] ++- [ ( const (CmdTest.TargetProblemIsSubComponent+ [ ( const (CmdTest.isSubComponentProblem "p-0.1" cname (FileTarget fname)) , mkTargetFile "p-0.1" cname fname) | (cname, fname) <- [ (CTestName "a-testsuite", "Test.hs")@@ -1014,8 +1011,7 @@ } CmdBench.selectPackageTargets CmdBench.selectComponentTarget- CmdBench.TargetProblemCommon- [ ( flip CmdBench.TargetProblemNoneEnabled+ [ ( flip TargetProblemNoneEnabled [ AvailableTarget "p-0.1" (CBenchName "user-disabled") TargetDisabledByUser True , AvailableTarget "p-0.1" (CBenchName "solver-disabled")@@ -1030,8 +1026,7 @@ config CmdBench.selectPackageTargets CmdBench.selectComponentTarget- CmdBench.TargetProblemCommon- [ ( flip CmdBench.TargetProblemNoneEnabled+ [ ( flip TargetProblemNoneEnabled [ AvailableTarget "p-0.1" (CBenchName "user-disabled") TargetDisabledBySolver True , AvailableTarget "p-0.1" (CBenchName "solver-disabled")@@ -1039,7 +1034,7 @@ ] , mkTargetPackage "p-0.1" ) - , ( flip CmdBench.TargetProblemNoneEnabled+ , ( flip TargetProblemNoneEnabled [ AvailableTarget "q-0.1" (CBenchName "buildable-false") TargetNotBuildable True ]@@ -1051,8 +1046,7 @@ "targets/empty-pkg" config CmdBench.selectPackageTargets CmdBench.selectComponentTarget- CmdBench.TargetProblemCommon- [ ( CmdBench.TargetProblemNoTargets, mkTargetPackage "p-0.1" )+ [ ( TargetProblemNoTargets, mkTargetPackage "p-0.1" ) ] reportSubCase "no benchmarks"@@ -1061,9 +1055,8 @@ config CmdBench.selectPackageTargets CmdBench.selectComponentTarget- CmdBench.TargetProblemCommon- [ ( CmdBench.TargetProblemNoBenchmarks, mkTargetPackage "p-0.1" )- , ( CmdBench.TargetProblemNoBenchmarks, mkTargetPackage "q-0.1" )+ [ ( CmdBench.noBenchmarksProblem, mkTargetPackage "p-0.1" )+ , ( CmdBench.noBenchmarksProblem, mkTargetPackage "q-0.1" ) ] reportSubCase "not a benchmark"@@ -1071,25 +1064,24 @@ "targets/variety" config CmdBench.selectPackageTargets- CmdBench.selectComponentTarget- CmdBench.TargetProblemCommon $- [ ( const (CmdBench.TargetProblemComponentNotBenchmark+ CmdBench.selectComponentTarget $+ [ ( const (CmdBench.componentNotBenchmarkProblem "p-0.1" (CLibName LMainLibName)) , mkTargetComponent "p-0.1" (CLibName LMainLibName) ) - , ( const (CmdBench.TargetProblemComponentNotBenchmark+ , ( const (CmdBench.componentNotBenchmarkProblem "p-0.1" (CExeName "an-exe")) , mkTargetComponent "p-0.1" (CExeName "an-exe") ) - , ( const (CmdBench.TargetProblemComponentNotBenchmark+ , ( const (CmdBench.componentNotBenchmarkProblem "p-0.1" (CFLibName "libp")) , mkTargetComponent "p-0.1" (CFLibName "libp") ) - , ( const (CmdBench.TargetProblemComponentNotBenchmark+ , ( const (CmdBench.componentNotBenchmarkProblem "p-0.1" (CTestName "a-testsuite")) , mkTargetComponent "p-0.1" (CTestName "a-testsuite") ) ] ++- [ ( const (CmdBench.TargetProblemIsSubComponent+ [ ( const (CmdBench.isSubComponentProblem "p-0.1" cname (ModuleTarget modname)) , mkTargetModule "p-0.1" cname modname ) | (cname, modname) <- [ (CTestName "a-testsuite", "TestModule")@@ -1098,7 +1090,7 @@ , ((CLibName LMainLibName), "P") ] ] ++- [ ( const (CmdBench.TargetProblemIsSubComponent+ [ ( const (CmdBench.isSubComponentProblem "p-0.1" cname (FileTarget fname)) , mkTargetFile "p-0.1" cname fname) | (cname, fname) <- [ (CTestName "a-testsuite", "Test.hs")@@ -1118,8 +1110,7 @@ (let haddockFlags = mkHaddockFlags False True True False in CmdHaddock.selectPackageTargets haddockFlags) CmdHaddock.selectComponentTarget- CmdHaddock.TargetProblemCommon- [ ( flip CmdHaddock.TargetProblemNoneEnabled+ [ ( flip TargetProblemNoneEnabled [ AvailableTarget "p-0.1" (CBenchName "user-disabled") TargetDisabledByUser True , AvailableTarget "p-0.1" (CTestName "solver-disabled")@@ -1138,8 +1129,7 @@ (let haddockFlags = mkHaddockFlags False False False False in CmdHaddock.selectPackageTargets haddockFlags) CmdHaddock.selectComponentTarget- CmdHaddock.TargetProblemCommon- [ ( CmdHaddock.TargetProblemNoTargets, mkTargetPackage "p-0.1" )+ [ ( TargetProblemNoTargets, mkTargetPackage "p-0.1" ) ] reportSubCase "enabled component kinds"@@ -1151,7 +1141,6 @@ elaboratedPlan (CmdHaddock.selectPackageTargets haddockFlags) CmdHaddock.selectComponentTarget- CmdHaddock.TargetProblemCommon [ mkTargetPackage "p-0.1" ] [ ("p-0.1-inplace", (CLibName LMainLibName)) , ("p-0.1-inplace-a-benchmark", CBenchName "a-benchmark")@@ -1168,7 +1157,6 @@ elaboratedPlan (CmdHaddock.selectPackageTargets haddockFlags) CmdHaddock.selectComponentTarget- CmdHaddock.TargetProblemCommon [ mkTargetPackage "p-0.1" ] [ ("p-0.1-inplace", (CLibName LMainLibName)) ] @@ -1180,7 +1168,6 @@ elaboratedPlan (CmdHaddock.selectPackageTargets haddockFlags) CmdHaddock.selectComponentTarget- CmdHaddock.TargetProblemCommon [ TargetPackage TargetExplicitNamed ["p-0.1"] (Just FLibKind) , TargetPackage TargetExplicitNamed ["p-0.1"] (Just ExeKind) , TargetPackage TargetExplicitNamed ["p-0.1"] (Just TestKind)@@ -1203,16 +1190,14 @@ assertProjectDistinctTargets :: forall err. (Eq err, Show err) => ElaboratedInstallPlan- -> (forall k. TargetSelector -> [AvailableTarget k] -> Either err [k])- -> (forall k. SubComponentTarget -> AvailableTarget k -> Either err k )- -> (TargetProblemCommon -> err)+ -> (forall k. TargetSelector -> [AvailableTarget k] -> Either (TargetProblem err) [k])+ -> (forall k. SubComponentTarget -> AvailableTarget k -> Either (TargetProblem err) k ) -> [TargetSelector] -> [(UnitId, ComponentName)] -> Assertion assertProjectDistinctTargets elaboratedPlan selectPackageTargets selectComponentTarget- liftProblem targetSelectors expectedTargets | Right targets <- results@@ -1225,7 +1210,6 @@ results = resolveTargets selectPackageTargets selectComponentTarget- liftProblem elaboratedPlan Nothing targetSelectors@@ -1236,44 +1220,37 @@ FilePath -> ProjectConfig -> (forall k. TargetSelector -> [AvailableTarget k]- -> Either err [k])+ -> Either (TargetProblem err) [k]) -> (forall k. SubComponentTarget -> AvailableTarget k- -> Either err k )- -> (TargetProblemCommon -> err)- -> [(TargetSelector -> err, TargetSelector)]+ -> Either (TargetProblem err) k )+ -> [(TargetSelector -> TargetProblem err, TargetSelector)] -> Assertion assertProjectTargetProblems testdir config selectPackageTargets selectComponentTarget- liftProblem cases = do (_,elaboratedPlan,_) <- planProject testdir config assertTargetProblems elaboratedPlan selectPackageTargets selectComponentTarget- liftProblem cases assertTargetProblems :: forall err. (Eq err, Show err) => ElaboratedInstallPlan- -> (forall k. TargetSelector -> [AvailableTarget k] -> Either err [k])- -> (forall k. SubComponentTarget -> AvailableTarget k -> Either err k )- -> (TargetProblemCommon -> err)- -> [(TargetSelector -> err, TargetSelector)]+ -> (forall k. TargetSelector -> [AvailableTarget k] -> Either (TargetProblem err) [k])+ -> (forall k. SubComponentTarget -> AvailableTarget k -> Either (TargetProblem err) k )+ -> [(TargetSelector -> TargetProblem err, TargetSelector)] -> Assertion-assertTargetProblems elaboratedPlan- selectPackageTargets- selectComponentTarget- liftProblem =+assertTargetProblems elaboratedPlan selectPackageTargets selectComponentTarget = mapM_ (uncurry assertTargetProblem) where assertTargetProblem expected targetSelector = let res = resolveTargets selectPackageTargets selectComponentTarget- liftProblem elaboratedPlan Nothing+ elaboratedPlan Nothing [targetSelector] in case res of Left [problem] ->@@ -1327,7 +1304,7 @@ (_pkga1, failure) <- expectPackageFailed plan res pkgidA1 case buildFailureReason failure of ConfigureFailed _ -> return ()- _ -> assertFailure $ "expected ConfigureFailed, got " ++ show failure + _ -> assertFailure $ "expected ConfigureFailed, got " ++ show failure cleanProject testdir where testdir = "exception/configure"@@ -1440,8 +1417,11 @@ -- | See <https://github.com/haskell/cabal/issues/3324> --+-- This test just doesn't seem to work on Windows,+-- due filesystem woes.+-- testRegressionIssue3324 :: ProjectConfig -> Assertion-testRegressionIssue3324 config = do+testRegressionIssue3324 config = when (buildOS /= Windows) $ do -- expected failure first time due to missing dep (plan1, res1) <- executePlan =<< planProject testdir config (_pkgq, failure) <- expectPackageFailed plan1 res1 "q-0.1"@@ -1450,7 +1430,7 @@ -- add the missing dep, now it should work let qcabal = basedir </> testdir </> "q" </> "q.cabal" withFileFinallyRestore qcabal $ do- appendFile qcabal (" build-depends: p\n")+ tryFewTimes $ BS.appendFile qcabal (" build-depends: p\n") (plan2, res2) <- executePlan =<< planProject testdir config _ <- expectPackageInstalled plan2 res2 "p-0.1" _ <- expectPackageInstalled plan2 res2 "q-0.1"@@ -1536,7 +1516,7 @@ localPackages, _buildSettings) <- configureProject testdir cliConfig - (elaboratedPlan, _, elaboratedShared) <-+ (elaboratedPlan, _, elaboratedShared, _, _) <- rebuildInstallPlan verbosity distDirLayout cabalDirLayout projectConfig@@ -1725,9 +1705,30 @@ -- | Allow altering a file during a test, but then restore it afterwards --+-- We read into the memory, as filesystems are tricky. (especially Windows)+-- withFileFinallyRestore :: FilePath -> IO a -> IO a withFileFinallyRestore file action = do- copyFile file backup- action `finally` renameFile backup file+ originalContents <- BS.readFile file+ action `finally` handle onIOError (tryFewTimes $ BS.writeFile file originalContents) where- backup = file <.> "backup"+ onIOError :: IOException -> IO ()+ onIOError e = putStrLn $ "WARNING: Cannot restore " ++ file ++ "; " ++ show e++-- Hopefully works around some Windows file-locking things.+-- Use with care:+--+-- Try action 4 times, with small sleep in between,+-- retrying if it fails for 'IOException' reason.+--+tryFewTimes :: forall a. IO a -> IO a+tryFewTimes action = go (3 :: Int) where+ go :: Int -> IO a+ go !n | n <= 0 = action+ | otherwise = action `catch` onIOError n++ onIOError :: Int -> IOException -> IO a+ onIOError n e = do+ hPutStrLn stderr $ "Trying " ++ show n ++ " after " ++ show e+ threadDelay 10000+ go (n - 1)
cabal/cabal-install/tests/IntegrationTests2/targets/complex/q/q.cabal view
@@ -5,7 +5,8 @@ library exposed-modules: Q- build-depends: base, filepath+ -- we rely that filepath has filepath-tests component+ build-depends: base, filepath >=1.4.0.0 executable buildable-false main-is: Main.hs
+ cabal/cabal-install/tests/IntegrationTests2/targets/simple/app/Main.hs view
cabal/cabal-install/tests/IntegrationTests2/targets/simple/p.cabal view
@@ -10,3 +10,8 @@ executable pexe main-is: Main.hs other-modules: PMain++executable ppexe+ main-is: Main.hs+ hs-source-dirs: app+ other-modules: PMain
+ cabal/cabal-install/tests/IntegrationTests2/targets/simple/q/Q.hs view
cabal/cabal-install/tests/IntegrationTests2/targets/simple/q/q.cabal view
@@ -5,6 +5,7 @@ library exposed-modules: QQ+ other-modules: Q build-depends: base executable qexe
cabal/cabal-install/tests/UnitTests.hs view
@@ -13,11 +13,12 @@ import qualified UnitTests.Distribution.Solver.Modular.WeightedPSQ import qualified UnitTests.Distribution.Solver.Modular.Solver import qualified UnitTests.Distribution.Solver.Modular.RetryLog+import qualified UnitTests.Distribution.Client.BuildReport+import qualified UnitTests.Distribution.Client.Described import qualified UnitTests.Distribution.Client.FileMonitor import qualified UnitTests.Distribution.Client.Glob import qualified UnitTests.Distribution.Client.GZipUtils-import qualified UnitTests.Distribution.Client.Sandbox-import qualified UnitTests.Distribution.Client.Sandbox.Timestamp+import qualified UnitTests.Distribution.Client.Init.FileCreators import qualified UnitTests.Distribution.Client.Store import qualified UnitTests.Distribution.Client.Tar import qualified UnitTests.Distribution.Client.Targets@@ -54,10 +55,8 @@ UnitTests.Distribution.Client.Glob.tests , testGroup "Distribution.Client.GZipUtils" UnitTests.Distribution.Client.GZipUtils.tests- , testGroup "Distribution.Client.Sandbox"- UnitTests.Distribution.Client.Sandbox.tests- , testGroup "Distribution.Client.Sandbox.Timestamp"- UnitTests.Distribution.Client.Sandbox.Timestamp.tests+ , testGroup "Distribution.Client.Init.FileCreators"+ UnitTests.Distribution.Client.Init.FileCreators.tests , testGroup "Distribution.Client.Store" UnitTests.Distribution.Client.Store.tests , testGroup "Distribution.Client.Tar"@@ -78,6 +77,8 @@ UnitTests.Distribution.Client.VCS.tests mtimeChange , testGroup "UnitTests.Distribution.Client.Get" UnitTests.Distribution.Client.Get.tests+ , UnitTests.Distribution.Client.Described.tests+ , UnitTests.Distribution.Client.BuildReport.tests ] main :: IO ()@@ -93,4 +94,3 @@ defaultMainWithIngredients (includingOptions extraOptions : defaultIngredients) (tests mtimeChange')-
cabal/cabal-install/tests/UnitTests/Distribution/Client/ArbitraryInstances.hs view
@@ -1,6 +1,7 @@-{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE TypeOperators #-} {-# OPTIONS_GHC -fno-warn-orphans #-}- module UnitTests.Distribution.Client.ArbitraryInstances ( adjustSize, shortListOf,@@ -10,37 +11,108 @@ arbitraryShortToken, NonMEmpty(..), NoShrink(..),+ -- * Shrinker+ Shrinker,+ runShrinker,+ shrinker,+ shrinkerPP,+ shrinkerAla, ) where -import Data.Char-import Data.List-#if !MIN_VERSION_base(4,8,0)-import Data.Monoid-import Control.Applicative-#endif-import Control.Monad+import Distribution.Client.Compat.Prelude+import Prelude () -import Distribution.Version-import Distribution.Types.VersionRange.Internal-import Distribution.Types.Dependency-import Distribution.Types.PackageVersionConstraint-import Distribution.Types.UnqualComponentName-import Distribution.Types.LibraryName-import Distribution.Package-import Distribution.System-import Distribution.Verbosity+import Data.Char (isLetter)+import Data.List ((\\)) import Distribution.Simple.Setup-import Distribution.Simple.InstallDirs--import Distribution.Utils.NubList+import Distribution.Types.Flag (mkFlagAssignment) -import Distribution.Client.Types-import Distribution.Client.IndexUtils.Timestamp+import Distribution.Client.BuildReports.Types (BuildReport, InstallOutcome, Outcome, ReportLevel (..))+import Distribution.Client.CmdInstall.ClientInstallFlags (InstallMethod)+import Distribution.Client.Glob (FilePathGlob (..), FilePathGlobRel (..), FilePathRoot (..), GlobPiece (..))+import Distribution.Client.IndexUtils.ActiveRepos (ActiveRepoEntry (..), ActiveRepos (..), CombineStrategy (..))+import Distribution.Client.IndexUtils.IndexState (RepoIndexState (..), TotalIndexState, makeTotalIndexState)+import Distribution.Client.IndexUtils.Timestamp (Timestamp, epochTimeToTimestamp)+import Distribution.Client.Types.OverwritePolicy (OverwritePolicy)+import Distribution.Client.Targets+import Distribution.Client.Types (RepoName (..), WriteGhcEnvironmentFilesPolicy)+import Distribution.Client.Types.AllowNewer+import Distribution.Client.World (WorldPkgInfo (..))+import Distribution.Solver.Types.OptionalStanza (OptionalStanza (..))+import Distribution.Solver.Types.PackageConstraint (PackageProperty (..)) +import Data.Coerce (Coercible, coerce)+import Network.URI (URI (..), URIAuth (..), isUnreserved) import Test.QuickCheck+import Test.QuickCheck.GenericArbitrary+import Test.QuickCheck.Instances.Cabal () +-- note: there are plenty of instances defined in ProjectConfig test file.+-- they should be moved here or into Cabal-quickcheck +-------------------------------------------------------------------------------+-- Utilities+-------------------------------------------------------------------------------++data Shrinker a = Shrinker a [a]++instance Functor Shrinker where+ fmap f (Shrinker x xs) = Shrinker (f x) (map f xs)++instance Applicative Shrinker where+ pure x = Shrinker x []++ Shrinker f fs <*> Shrinker x xs = Shrinker (f x) (map f xs ++ map ($ x) fs)++runShrinker :: Shrinker a -> [a]+runShrinker (Shrinker _ xs) = xs++shrinker :: Arbitrary a => a -> Shrinker a+shrinker x = Shrinker x (shrink x)++shrinkerAla :: (Coercible a b, Arbitrary b) => (a -> b) -> a -> Shrinker a+shrinkerAla pack = shrinkerPP pack coerce++-- | shrinker with pre and post functions.+shrinkerPP :: Arbitrary b => (a -> b) -> (b -> a) -> a -> Shrinker a+shrinkerPP pack unpack x = Shrinker x (map unpack (shrink (pack x)))++-------------------------------------------------------------------------------+-- Non-Cabal instances+-------------------------------------------------------------------------------++instance Arbitrary URI where+ arbitrary =+ URI <$> elements ["file:", "http:", "https:"]+ <*> (Just <$> arbitrary)+ <*> (('/':) <$> arbitraryURIToken)+ <*> (('?':) <$> arbitraryURIToken)+ <*> pure ""++instance Arbitrary URIAuth where+ arbitrary =+ URIAuth <$> pure "" -- no password as this does not roundtrip+ <*> arbitraryURIToken+ <*> arbitraryURIPort++arbitraryURIToken :: Gen String+arbitraryURIToken =+ shortListOf1 6 (elements (filter isUnreserved ['\0'..'\255']))++arbitraryURIPort :: Gen String+arbitraryURIPort =+ oneof [ pure "", (':':) <$> shortListOf1 4 (choose ('0','9')) ]++-------------------------------------------------------------------------------+-- cabal-install (and Cabal) types+-------------------------------------------------------------------------------++shrinkBoundedEnum :: (Eq a, Enum a, Bounded a) => a -> [a]+shrinkBoundedEnum x+ | x == minBound = []+ | otherwise = [pred x]+ adjustSize :: (Int -> Int) -> Gen a -> Gen a adjustSize adjust gen = sized (\n -> resize (adjust n) gen) @@ -68,139 +140,262 @@ -- accepting Haskell list syntax [], ['a'] etc, just allow String syntax. -- Workaround, don't generate [] as this does not round trip. - shrink (ShortToken cs) = [ ShortToken cs' | cs' <- shrink cs, not (null cs') ] arbitraryShortToken :: Gen String arbitraryShortToken = getShortToken <$> arbitrary -instance Arbitrary Version where- arbitrary = do- branch <- shortListOf1 4 $- frequency [(3, return 0)- ,(3, return 1)- ,(2, return 2)- ,(1, return 3)]- return (mkVersion branch)- where+newtype NonMEmpty a = NonMEmpty { getNonMEmpty :: a }+ deriving (Eq, Ord, Show) - shrink ver = [ mkVersion branch' | branch' <- shrink (versionNumbers ver)- , not (null branch') ]+instance (Arbitrary a, Monoid a, Eq a) => Arbitrary (NonMEmpty a) where+ arbitrary = NonMEmpty <$> (arbitrary `suchThat` (/= mempty))+ shrink (NonMEmpty x) = [ NonMEmpty x' | x' <- shrink x, x' /= mempty ] -instance Arbitrary VersionRange where- arbitrary = canonicaliseVersionRange <$> sized verRangeExp- where- verRangeExp n = frequency $- [ (2, return anyVersion)- , (1, liftM thisVersion arbitrary)- , (1, liftM laterVersion arbitrary)- , (1, liftM orLaterVersion arbitrary)- , (1, liftM orLaterVersion' arbitrary)- , (1, liftM earlierVersion arbitrary)- , (1, liftM orEarlierVersion arbitrary)- , (1, liftM orEarlierVersion' arbitrary)- , (1, liftM withinVersion arbitrary)- , (2, liftM VersionRangeParens arbitrary)- ] ++ if n == 0 then [] else- [ (2, liftM2 unionVersionRanges verRangeExp2 verRangeExp2)- , (2, liftM2 intersectVersionRanges verRangeExp2 verRangeExp2)+newtype NoShrink a = NoShrink { getNoShrink :: a }+ deriving (Eq, Ord, Show)++instance Arbitrary a => Arbitrary (NoShrink a) where+ arbitrary = NoShrink <$> arbitrary+ shrink _ = []++instance Arbitrary Timestamp where+ -- note: no negative timestamps+ --+ -- >>> utcTimeToPOSIXSeconds $ UTCTime (fromGregorian 100000 01 01) 0+ -- >>> 3093527980800s+ --+ arbitrary = maybe (toEnum 0) id . epochTimeToTimestamp . (`mod` 3093527980800) . abs <$> arbitrary++instance Arbitrary RepoIndexState where+ arbitrary = frequency [ (1, pure IndexStateHead)+ , (50, IndexStateTime <$> arbitrary)+ ]++instance Arbitrary TotalIndexState where+ arbitrary = makeTotalIndexState <$> arbitrary <*> arbitrary++instance Arbitrary WriteGhcEnvironmentFilesPolicy where+ arbitrary = arbitraryBoundedEnum++arbitraryFlag :: Gen a -> Gen (Flag a)+arbitraryFlag = liftArbitrary++instance Arbitrary RepoName where+ arbitrary = RepoName <$> mk where+ mk = (:) <$> lead <*> rest+ lead = elements+ [ c | c <- [ '\NUL' .. '\255' ], isAlpha c || c `elem` "_-."]+ rest = listOf (elements+ [ c | c <- [ '\NUL' .. '\255' ], isAlphaNum c || c `elem` "_-."])++instance Arbitrary ReportLevel where+ arbitrary = arbitraryBoundedEnum++instance Arbitrary OverwritePolicy where+ arbitrary = arbitraryBoundedEnum++instance Arbitrary InstallMethod where+ arbitrary = arbitraryBoundedEnum++-------------------------------------------------------------------------------+-- ActiveRepos+-------------------------------------------------------------------------------++instance Arbitrary ActiveRepos where+ arbitrary = ActiveRepos <$> shortListOf 5 arbitrary++instance Arbitrary ActiveRepoEntry where+ arbitrary = frequency+ [ (10, ActiveRepo <$> arbitrary <*> arbitrary)+ , (1, ActiveRepoRest <$> arbitrary) ]- where- verRangeExp2 = verRangeExp (n `div` 2) - orLaterVersion' v =- unionVersionRanges (laterVersion v) (thisVersion v)- orEarlierVersion' v =- unionVersionRanges (earlierVersion v) (thisVersion v)+instance Arbitrary CombineStrategy where+ arbitrary = arbitraryBoundedEnum+ shrink = shrinkBoundedEnum - canonicaliseVersionRange = fromVersionIntervals . toVersionIntervals+-------------------------------------------------------------------------------+-- AllowNewer+------------------------------------------------------------------------------- -instance Arbitrary PackageName where- arbitrary = mkPackageName . intercalate "-" <$> shortListOf1 2 nameComponent- where- nameComponent = shortListOf1 5 (elements packageChars)- `suchThat` (not . all isDigit)- packageChars = filter isAlphaNum ['\0'..'\127']+instance Arbitrary AllowNewer where+ arbitrary = AllowNewer <$> arbitrary -instance Arbitrary Dependency where- arbitrary = Dependency- <$> arbitrary- <*> arbitrary- <*> fmap getNonMEmpty arbitrary+instance Arbitrary AllowOlder where+ arbitrary = AllowOlder <$> arbitrary -instance Arbitrary PackageVersionConstraint where- arbitrary = PackageVersionConstraint <$> arbitrary <*> arbitrary+instance Arbitrary RelaxDeps where+ arbitrary = oneof [ pure mempty+ , mkRelaxDepSome <$> shortListOf1 3 arbitrary+ , pure RelaxDepsAll+ ] -instance Arbitrary UnqualComponentName where- -- same rules as package names- arbitrary = packageNameToUnqualComponentName <$> arbitrary+instance Arbitrary RelaxDepMod where+ arbitrary = elements [RelaxDepModNone, RelaxDepModCaret] -instance Arbitrary LibraryName where- arbitrary =- elements- =<< sequenceA [ LSubLibName <$> arbitrary- , pure LMainLibName ]+ shrink RelaxDepModCaret = [RelaxDepModNone]+ shrink _ = [] -instance Arbitrary OS where- arbitrary = elements knownOSs+instance Arbitrary RelaxDepScope where+ arbitrary = genericArbitrary+ shrink = genericShrink -instance Arbitrary Arch where- arbitrary = elements knownArches+instance Arbitrary RelaxDepSubject where+ arbitrary = genericArbitrary+ shrink = genericShrink -instance Arbitrary Platform where- arbitrary = Platform <$> arbitrary <*> arbitrary+instance Arbitrary RelaxedDep where+ arbitrary = genericArbitrary+ shrink = genericShrink -instance Arbitrary a => Arbitrary (Flag a) where- arbitrary = arbitraryFlag arbitrary- shrink NoFlag = []- shrink (Flag x) = NoFlag : [ Flag x' | x' <- shrink x ]+-------------------------------------------------------------------------------+-- WorldPkgInfo+------------------------------------------------------------------------------- -arbitraryFlag :: Gen a -> Gen (Flag a)-arbitraryFlag genA =- sized $ \sz ->- case sz of- 0 -> pure NoFlag- _ -> frequency [ (1, pure NoFlag)- , (3, Flag <$> genA) ]+instance Arbitrary WorldPkgInfo where+ arbitrary = WorldPkgInfo <$> arbitrary <*> arbitrary+ shrink = genericShrink +-------------------------------------------------------------------------------+-- UserConstraint+------------------------------------------------------------------------------- -instance (Arbitrary a, Ord a) => Arbitrary (NubList a) where- arbitrary = toNubList <$> arbitrary- shrink xs = [ toNubList [] | (not . null) (fromNubList xs) ]- -- try empty, otherwise don't shrink as it can loop+instance Arbitrary UserConstraintScope where+ arbitrary = genericArbitrary+ shrink = genericShrink -instance Arbitrary Verbosity where+instance Arbitrary UserQualifier where+ arbitrary = oneof [ pure UserQualToplevel+ , UserQualSetup <$> arbitrary++ -- -- TODO: Re-enable UserQualExe tests once we decide on a syntax.+ -- , UserQualExe <$> arbitrary <*> arbitrary+ ]+++instance Arbitrary UserConstraint where+ arbitrary = genericArbitrary+ shrink = genericShrink++instance Arbitrary PackageProperty where+ arbitrary = oneof [ PackagePropertyVersion <$> arbitrary+ , pure PackagePropertyInstalled+ , pure PackagePropertySource+ , PackagePropertyFlags . mkFlagAssignment <$> shortListOf1 3 arbitrary+ , PackagePropertyStanzas . (\x->[x]) <$> arbitrary+ ]++instance Arbitrary OptionalStanza where arbitrary = elements [minBound..maxBound] -instance Arbitrary PathTemplate where- arbitrary = toPathTemplate <$> arbitraryShortToken- shrink t = [ toPathTemplate s- | s <- shrink (fromPathTemplate t)- , not (null s) ]+-------------------------------------------------------------------------------+-- BuildReport+------------------------------------------------------------------------------- +instance Arbitrary BuildReport where+ arbitrary = genericArbitrary+ shrink = genericShrink -newtype NonMEmpty a = NonMEmpty { getNonMEmpty :: a }- deriving (Eq, Ord, Show)+instance Arbitrary InstallOutcome where+ arbitrary = genericArbitrary+ shrink = genericShrink -instance (Arbitrary a, Monoid a, Eq a) => Arbitrary (NonMEmpty a) where- arbitrary = NonMEmpty <$> (arbitrary `suchThat` (/= mempty))- shrink (NonMEmpty x) = [ NonMEmpty x' | x' <- shrink x, x' /= mempty ]+instance Arbitrary Outcome where+ arbitrary = genericArbitrary+ shrink = genericShrink -newtype NoShrink a = NoShrink { getNoShrink :: a }- deriving (Eq, Ord, Show)+-------------------------------------------------------------------------------+-- Glob+------------------------------------------------------------------------------- -instance Arbitrary a => Arbitrary (NoShrink a) where- arbitrary = NoShrink <$> arbitrary- shrink _ = []+instance Arbitrary FilePathGlob where+ arbitrary = (FilePathGlob <$> arbitrary <*> arbitrary)+ `suchThat` validFilePathGlob -instance Arbitrary Timestamp where- arbitrary = (maybe (toEnum 0) id . epochTimeToTimestamp) <$> arbitrary+ shrink (FilePathGlob root pathglob) =+ [ FilePathGlob root' pathglob'+ | (root', pathglob') <- shrink (root, pathglob)+ , validFilePathGlob (FilePathGlob root' pathglob') ] -instance Arbitrary IndexState where- arbitrary = frequency [ (1, pure IndexStateHead)- , (50, IndexStateTime <$> arbitrary)- ]+validFilePathGlob :: FilePathGlob -> Bool+validFilePathGlob (FilePathGlob FilePathRelative pathglob) =+ case pathglob of+ GlobDirTrailing -> False+ GlobDir [Literal "~"] _ -> False+ GlobDir [Literal (d:":")] _+ | isLetter d -> False+ _ -> True+validFilePathGlob _ = True -instance Arbitrary WriteGhcEnvironmentFilesPolicy where- arbitrary = arbitraryBoundedEnum+instance Arbitrary FilePathRoot where+ arbitrary =+ frequency+ [ (3, pure FilePathRelative)+ , (1, pure (FilePathRoot unixroot))+ , (1, FilePathRoot <$> windrive)+ , (1, pure FilePathHomeDir)+ ]+ where+ unixroot = "/"+ windrive = do d <- choose ('A', 'Z'); return (d : ":\\")++ shrink FilePathRelative = []+ shrink (FilePathRoot _) = [FilePathRelative]+ shrink FilePathHomeDir = [FilePathRelative]+++instance Arbitrary FilePathGlobRel where+ arbitrary = sized $ \sz ->+ oneof $ take (max 1 sz)+ [ pure GlobDirTrailing+ , GlobFile <$> (getGlobPieces <$> arbitrary)+ , GlobDir <$> (getGlobPieces <$> arbitrary)+ <*> resize (sz `div` 2) arbitrary+ ]++ shrink GlobDirTrailing = []+ shrink (GlobFile glob) =+ GlobDirTrailing+ : [ GlobFile (getGlobPieces glob') | glob' <- shrink (GlobPieces glob) ]+ shrink (GlobDir glob pathglob) =+ pathglob+ : GlobFile glob+ : [ GlobDir (getGlobPieces glob') pathglob'+ | (glob', pathglob') <- shrink (GlobPieces glob, pathglob) ]++newtype GlobPieces = GlobPieces { getGlobPieces :: [GlobPiece] }+ deriving Eq++instance Arbitrary GlobPieces where+ arbitrary = GlobPieces . mergeLiterals <$> shortListOf1 5 arbitrary++ shrink (GlobPieces glob) =+ [ GlobPieces (mergeLiterals (getNonEmpty glob'))+ | glob' <- shrink (NonEmpty glob) ]++mergeLiterals :: [GlobPiece] -> [GlobPiece]+mergeLiterals (Literal a : Literal b : ps) = mergeLiterals (Literal (a++b) : ps)+mergeLiterals (Union as : ps) = Union (map mergeLiterals as) : mergeLiterals ps+mergeLiterals (p:ps) = p : mergeLiterals ps+mergeLiterals [] = []++instance Arbitrary GlobPiece where+ arbitrary = sized $ \sz ->+ frequency+ [ (3, Literal <$> shortListOf1 10 (elements globLiteralChars))+ , (1, pure WildCard)+ , (1, Union <$> resize (sz `div` 2) (shortListOf1 5 (shortListOf1 5 arbitrary)))+ ]++ shrink (Literal str) = [ Literal str'+ | str' <- shrink str+ , not (null str')+ , all (`elem` globLiteralChars) str' ]+ shrink WildCard = []+ shrink (Union as) = [ Union (map getGlobPieces (getNonEmpty as'))+ | as' <- shrink (NonEmpty (map GlobPieces as)) ]++globLiteralChars :: [Char]+globLiteralChars = ['\0'..'\128'] \\ "*{},/\\"
+ cabal/cabal-install/tests/UnitTests/Distribution/Client/BuildReport.hs view
@@ -0,0 +1,32 @@+module UnitTests.Distribution.Client.BuildReport (+ tests,+) where++import Distribution.Client.Compat.Prelude+import Prelude ()+import UnitTests.Distribution.Client.ArbitraryInstances ()+import UnitTests.Distribution.Client.TreeDiffInstances ()++import Data.TreeDiff.QuickCheck (ediffEq)+import Test.QuickCheck (Property, counterexample)+import Test.Tasty (TestTree, testGroup)+import Test.Tasty.QuickCheck (testProperty)++import Distribution.Client.BuildReports.Anonymous (BuildReport, parseBuildReport, showBuildReport)+import Distribution.Simple.Utils (toUTF8BS)++-- instances+import Test.QuickCheck.Instances.Cabal ()++tests :: TestTree+tests = testGroup "BuildReport"+ [ testProperty "test" roundtrip+ ]++roundtrip :: BuildReport -> Property+roundtrip br =+ counterexample str $+ Right br `ediffEq` parseBuildReport (toUTF8BS str)+ where+ str :: String+ str = showBuildReport br
+ cabal/cabal-install/tests/UnitTests/Distribution/Client/Described.hs view
@@ -0,0 +1,37 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}+module UnitTests.Distribution.Client.Described where++import Distribution.Client.Compat.Prelude+import Prelude ()+import Test.QuickCheck.Instances.Cabal ()+import UnitTests.Distribution.Client.ArbitraryInstances ()+import UnitTests.Distribution.Client.DescribedInstances ()++import Distribution.Described (testDescribed)+import Test.Tasty (TestTree, testGroup)++import Distribution.Client.BuildReports.Types (InstallOutcome, Outcome)+import Distribution.Client.IndexUtils.ActiveRepos (ActiveRepos)+import Distribution.Client.IndexUtils.IndexState (RepoIndexState, TotalIndexState)+import Distribution.Client.IndexUtils.Timestamp (Timestamp)+import Distribution.Client.Targets (UserConstraint)+import Distribution.Client.Types (RepoName)+import Distribution.Client.Types.AllowNewer (RelaxDepSubject, RelaxDeps, RelaxedDep)+import Distribution.Client.World (WorldPkgInfo)++tests :: TestTree+tests = testGroup "Described"+ [ testDescribed (Proxy :: Proxy Timestamp)+ , testDescribed (Proxy :: Proxy RepoIndexState)+ , testDescribed (Proxy :: Proxy TotalIndexState)+ , testDescribed (Proxy :: Proxy RepoName)+ , testDescribed (Proxy :: Proxy ActiveRepos)+ , testDescribed (Proxy :: Proxy RelaxDepSubject)+ , testDescribed (Proxy :: Proxy RelaxedDep)+ , testDescribed (Proxy :: Proxy RelaxDeps)+ , testDescribed (Proxy :: Proxy UserConstraint)+ , testDescribed (Proxy :: Proxy WorldPkgInfo)+ , testDescribed (Proxy :: Proxy InstallOutcome)+ , testDescribed (Proxy :: Proxy Outcome)+ ]
+ cabal/cabal-install/tests/UnitTests/Distribution/Client/DescribedInstances.hs view
@@ -0,0 +1,316 @@+{-# LANGUAGE OverloadedStrings #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+module UnitTests.Distribution.Client.DescribedInstances where++import Distribution.Client.Compat.Prelude++import Distribution.Described+import Data.List ((\\))++import Distribution.Types.Dependency (Dependency)+import Distribution.Types.PackageId (PackageIdentifier)+import Distribution.Types.PackageName (PackageName)+import Distribution.Types.VersionRange (VersionRange)++import Distribution.Client.BuildReports.Types (InstallOutcome, Outcome)+import Distribution.Client.IndexUtils.ActiveRepos (ActiveRepoEntry, ActiveRepos, CombineStrategy)+import Distribution.Client.IndexUtils.IndexState (RepoIndexState, TotalIndexState)+import Distribution.Client.IndexUtils.Timestamp (Timestamp)+import Distribution.Client.Targets (UserConstraint)+import Distribution.Client.Types (RepoName)+import Distribution.Client.Types.AllowNewer (RelaxDepSubject, RelaxDeps, RelaxedDep)+import Distribution.Client.World (WorldPkgInfo)+import Distribution.Client.Glob (FilePathGlob)++-------------------------------------------------------------------------------+-- BuildReport+-------------------------------------------------------------------------------++instance Described InstallOutcome where+ describe _ = REUnion+ [ "PlanningFailed"+ , "DependencyFailed" <> RESpaces1 <> describe (Proxy :: Proxy PackageIdentifier)+ , "DownloadFailed"+ , "UnpackFailed"+ , "SetupFailed"+ , "ConfigureFailed"+ , "BuildFailed"+ , "TestsFailed"+ , "InstallFailed"+ , "InstallOk"+ ]+instance Described Outcome where+ describe _ = REUnion+ [ fromString (prettyShow o)+ | o <- [minBound .. maxBound :: Outcome]+ ]++-------------------------------------------------------------------------------+-- Glob+-------------------------------------------------------------------------------++-- This instance is incorrect as it may generate C:\dir\{foo,bar}+instance Described FilePathGlob where+ describe _ = REUnion [ root, relative, homedir ] where+ root = REUnion+ [ fromString "/"+ , reChars (['a'..'z'] ++ ['A' .. 'Z']) <> ":" <> reChars "/\\"+ ] <> REOpt pieces+ homedir = "~/" <> REOpt pieces+ relative = pieces++ pieces :: GrammarRegex void+ pieces = REMunch1 sep piece <> REOpt "/"++ piece :: GrammarRegex void+ piece = RERec "glob" $ REMunch1 mempty $ REUnion+ [ normal+ , escape+ , wildcard+ , "{" <> REMunch1 "," (REVar Nothing) <> "}"+ ]++ sep :: GrammarRegex void+ sep = reChars "/\\"++ wildcard :: GrammarRegex void+ wildcard = "*"++ normal = reChars $ ['\0'..'\128'] \\ "*{},/\\"+ escape = fromString "\\" <> reChars "*{},"++-------------------------------------------------------------------------------+-- WorldPkgInfo+-------------------------------------------------------------------------------++instance Described WorldPkgInfo where+ describe _ =+ describe (Proxy :: Proxy Dependency)+ <> REOpt (RESpaces1 <> "--flags=\"" <> describeFlagAssignmentNonEmpty <> "\"")++-------------------------------------------------------------------------------+-- AllowNewer+-------------------------------------------------------------------------------++instance Described RelaxedDep where+ describe _ =+ REOpt (describeRelaxDepScope <> ":" <> REOpt ("^"))+ <> describe (Proxy :: Proxy RelaxDepSubject)+ where+ describeRelaxDepScope = REUnion+ [ "*"+ , "all"+ , RENamed "package-name" (describe (Proxy :: Proxy PackageName))+ , RENamed "package-id" (describe (Proxy :: Proxy PackageIdentifier))+ ]++instance Described RelaxDepSubject where+ describe _ = REUnion+ [ "*"+ , "all"+ , RENamed "package-name" (describe (Proxy :: Proxy PackageName))+ ]++instance Described RelaxDeps where+ describe _ = REUnion+ [ "*"+ , "all"+ , "none"+ , RECommaNonEmpty (describe (Proxy :: Proxy RelaxedDep))+ ]++-------------------------------------------------------------------------------+-- ActiveRepos+-------------------------------------------------------------------------------++instance Described ActiveRepos where+ describe _ = REUnion+ [ ":none"+ , RECommaNonEmpty (describe (Proxy :: Proxy ActiveRepoEntry))+ ]++instance Described ActiveRepoEntry where+ describe _ = REUnion+ [ ":rest" <> strategy+ , REOpt ":repo:" <> describe (Proxy :: Proxy RepoName) <> strategy+ ]+ where+ strategy = REOpt $ ":" <> describe (Proxy :: Proxy CombineStrategy)++instance Described CombineStrategy where+ describe _ = REUnion+ [ "merge"+ , "override"+ ]++-------------------------------------------------------------------------------+-- UserConstraint+-------------------------------------------------------------------------------++instance Described UserConstraint where+ describe _ = REAppend+ [ describeConstraintScope+ , describeConstraintProperty+ ]+ where+ describeConstraintScope :: GrammarRegex void+ describeConstraintScope = REUnion+ [ "any." <> describePN+ , "setup." <> describePN+ , describePN+ , describePN <> ":setup." <> describePN+ ]++ describeConstraintProperty :: GrammarRegex void+ describeConstraintProperty = REUnion+ [ RESpaces <> RENamed "version-range" (describe (Proxy :: Proxy VersionRange))+ , RESpaces1 <> describeConstraintProperty'+ ]++ describeConstraintProperty' :: GrammarRegex void+ describeConstraintProperty' = REUnion+ [ "installed"+ , "source"+ , "test"+ , "bench"+ , describeFlagAssignmentNonEmpty+ ]++ describePN :: GrammarRegex void+ describePN = RENamed "package-name" (describe (Proxy :: Proxy PackageName))++-------------------------------------------------------------------------------+-- IndexState+-------------------------------------------------------------------------------++instance Described TotalIndexState where+ describe _ = reCommaNonEmpty $ REUnion+ [ describe (Proxy :: Proxy RepoName) <> RESpaces1 <> ris+ , ris+ ]+ where+ ris = describe (Proxy :: Proxy RepoIndexState)++instance Described RepoName where+ describe _ = lead <> rest where+ lead = RECharSet $ csAlpha <> "_-."+ rest = reMunchCS $ csAlphaNum <> "_-."++instance Described RepoIndexState where+ describe _ = REUnion+ [ "HEAD"+ , RENamed "timestamp" (describe (Proxy :: Proxy Timestamp))+ ]++instance Described Timestamp where+ describe _ = REUnion+ [ posix+ , utc+ ]+ where+ posix = reChar '@' <> reMunch1CS "0123456789"+ utc = RENamed "date" date <> reChar 'T' <> RENamed "time" time <> reChar 'Z'++ date = REOpt digit <> REUnion+ [ leapYear <> reChar '-' <> leapMD+ , commonYear <> reChar '-' <> commonMD+ ]++ -- leap year: either+ -- * divisible by 400+ -- * not divisible by 100 and divisible by 4+ leapYear = REUnion+ [ div4 <> "00"+ , digit <> digit <> div4not0+ ]++ -- common year: either+ -- * not divisible by 400 but divisible by 100+ -- * not divisible by 4+ commonYear = REUnion+ [ notDiv4 <> "00"+ , digit <> digit <> notDiv4+ ]++ div4 = REUnion+ [ "0" <> reChars "048"+ , "1" <> reChars "26"+ , "2" <> reChars "048"+ , "3" <> reChars "26"+ , "4" <> reChars "048"+ , "5" <> reChars "26"+ , "6" <> reChars "048"+ , "7" <> reChars "26"+ , "8" <> reChars "048"+ , "9" <> reChars "26"+ ]++ div4not0 = REUnion+ [ "0" <> reChars "48" -- no zero+ , "1" <> reChars "26"+ , "2" <> reChars "048"+ , "3" <> reChars "26"+ , "4" <> reChars "048"+ , "5" <> reChars "26"+ , "6" <> reChars "048"+ , "7" <> reChars "26"+ , "8" <> reChars "048"+ , "9" <> reChars "26"+ ]++ notDiv4 = REUnion+ [ "0" <> reChars "1235679"+ , "1" <> reChars "01345789"+ , "2" <> reChars "1235679"+ , "3" <> reChars "01345789"+ , "4" <> reChars "1235679"+ , "5" <> reChars "01345789"+ , "6" <> reChars "1235679"+ , "7" <> reChars "01345789"+ , "8" <> reChars "1235679"+ , "9" <> reChars "01345789"+ ]++ leapMD = REUnion+ [ jan, fe', mar, apr, may, jun, jul, aug, sep, oct, nov, dec ]++ commonMD = REUnion+ [ jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec ]++ jan = "01-" <> d31+ feb = "02-" <> d28+ fe' = "02-" <> d29+ mar = "03-" <> d31+ apr = "04-" <> d30+ may = "05-" <> d31+ jun = "06-" <> d30+ jul = "07-" <> d31+ aug = "08-" <> d31+ sep = "09-" <> d30+ oct = "10-" <> d31+ nov = "11-" <> d30+ dec = "12-" <> d31++ d28 = REUnion+ [ "0" <> digit1, "1" <> digit, "2" <> reChars "012345678" ]+ d29 = REUnion+ [ "0" <> digit1, "1" <> digit, "2" <> digit ]+ d30 = REUnion+ [ "0" <> digit1, "1" <> digit, "2" <> digit, "30" ]+ d31 = REUnion+ [ "0" <> digit1, "1" <> digit, "2" <> digit, "30", "31" ]++ time = ho <> reChar ':' <> minSec <> reChar ':' <> minSec++ -- 0..23+ ho = REUnion+ [ "0" <> digit+ , "1" <> digit+ , "2" <> reChars "0123"+ ]++ -- 0..59+ minSec = reChars "012345" <> digit++ digit = reChars "0123456789"+ digit1 = reChars "123456789"
cabal/cabal-install/tests/UnitTests/Distribution/Client/FileMonitor.hs view
@@ -1,7 +1,8 @@ module UnitTests.Distribution.Client.FileMonitor (tests) where -import Distribution.Deprecated.Text (simpleParse)+import Distribution.Parsec (simpleParsec) +import Data.Proxy (Proxy (..)) import Control.Monad import Control.Exception import Control.Concurrent (threadDelay)@@ -17,6 +18,8 @@ import Distribution.Client.FileMonitor import Distribution.Compat.Time+import Distribution.Utils.Structured (structureHash, Structured)+import GHC.Fingerprint (Fingerprint (..)) import Test.Tasty import Test.Tasty.HUnit@@ -24,10 +27,15 @@ tests :: Int -> [TestTree] tests mtimeChange =- [ testCase "sanity check mtimes" $ testFileMTimeSanity mtimeChange+ [ testGroup "Structured hashes"+ [ testCase "MonitorStateFile" $ structureHash (Proxy :: Proxy MonitorStateFile) @?= Fingerprint 0xe4108804c34962f6 0x06e94f8fc9e48e13+ , testCase "MonitorStateGlob" $ structureHash (Proxy :: Proxy MonitorStateGlob) @?= Fingerprint 0xfd8f6be0e8258fe7 0xdb5fac737139bca6+ , testCase "MonitorStateFileSet" $ structureHash (Proxy :: Proxy MonitorStateFileSet) @?= Fingerprint 0xb745f4ea498389a5 0x70db6adb5078aa27+ ]+ , testCase "sanity check mtimes" $ testFileMTimeSanity mtimeChange , testCase "sanity check dirs" $ testDirChangeSanity mtimeChange , testCase "no monitor cache" testNoMonitorCache- , testCase "corrupt monitor cache" testCorruptMonitorCache+ , testCaseSteps "corrupt monitor cache" testCorruptMonitorCache , testCase "empty monitor" testEmptyMonitor , testCase "missing file" testMissingFile , testCase "change file" $ testChangedFile mtimeChange@@ -150,18 +158,21 @@ reason @?= MonitorFirstRun -- write garbage into the binary cache file-testCorruptMonitorCache :: Assertion-testCorruptMonitorCache =+testCorruptMonitorCache :: (String -> IO ()) -> Assertion+testCorruptMonitorCache step = withFileMonitor $ \root monitor -> do+ step "Writing broken file" IO.writeFile (fileMonitorCacheFile monitor) "broken" reason <- expectMonitorChanged root monitor () reason @?= MonitorCorruptCache + step "Updating file monitor" updateMonitor root monitor [] () () (res, files) <- expectMonitorUnchanged root monitor () res @?= () files @?= [] + step "Writing broken file again" IO.writeFile (fileMonitorCacheFile monitor) "broken" reason2 <- expectMonitorChanged root monitor () reason2 @?= MonitorCorruptCache@@ -808,11 +819,11 @@ monitorFileGlobStr :: String -> MonitorFilePath monitorFileGlobStr globstr- | Just glob <- simpleParse globstr = monitorFileGlob glob- | otherwise = error $ "Failed to parse " ++ globstr+ | Just glob <- simpleParsec globstr = monitorFileGlob glob+ | otherwise = error $ "Failed to parse " ++ globstr -expectMonitorChanged :: (Binary a, Binary b)+expectMonitorChanged :: (Binary a, Structured a, Binary b, Structured b) => RootPath -> FileMonitor a b -> a -> IO (MonitorChangedReason a) expectMonitorChanged root monitor key = do@@ -821,7 +832,7 @@ MonitorChanged reason -> return reason MonitorUnchanged _ _ -> throwIO $ HUnitFailure Nothing "expected change" -expectMonitorUnchanged :: (Binary a, Binary b)+expectMonitorUnchanged :: (Binary a, Structured a, Binary b, Structured b) => RootPath -> FileMonitor a b -> a -> IO (b, [MonitorFilePath]) expectMonitorUnchanged root monitor key = do@@ -830,19 +841,19 @@ MonitorChanged _reason -> throwIO $ HUnitFailure Nothing "expected no change" MonitorUnchanged b files -> return (b, files) -checkChanged :: (Binary a, Binary b)+checkChanged :: (Binary a, Structured a, Binary b, Structured b) => RootPath -> FileMonitor a b -> a -> IO (MonitorChanged a b) checkChanged (RootPath root) monitor key = checkFileMonitorChanged monitor root key -updateMonitor :: (Binary a, Binary b)+updateMonitor :: (Binary a, Structured a, Binary b, Structured b) => RootPath -> FileMonitor a b -> [MonitorFilePath] -> a -> b -> IO () updateMonitor (RootPath root) monitor files key result = updateFileMonitor monitor root Nothing files key result -updateMonitorWithTimestamp :: (Binary a, Binary b)+updateMonitorWithTimestamp :: (Binary a, Structured a, Binary b, Structured b) => RootPath -> FileMonitor a b -> MonitorTimestamp -> [MonitorFilePath] -> a -> b -> IO () updateMonitorWithTimestamp (RootPath root) monitor timestamp files key result =
cabal/cabal-install/tests/UnitTests/Distribution/Client/GZipUtils.hs view
@@ -2,17 +2,16 @@ tests ) where +import Prelude ()+import Distribution.Client.Compat.Prelude+ import Codec.Compression.GZip as GZip import Codec.Compression.Zlib as Zlib-import Control.Exception.Base (evaluate)-import Control.Exception (try, SomeException)-import Control.Monad (void)+import Control.Exception (try) import Data.ByteString as BS (null) import Data.ByteString.Lazy as BSL (pack, toChunks) import Data.ByteString.Lazy.Char8 as BSLL (pack, init, length)-import Data.Monoid ((<>)) import Distribution.Client.GZipUtils (maybeDecompress)-import Data.Word (Word8) import Test.Tasty import Test.Tasty.HUnit@@ -34,7 +33,7 @@ >> assertBool "decompress gzip (with show)" (show (maybeDecompress compressedGZip) == show original) >> assertBool "decompress zlib" (maybeDecompress compressedZlib == original) >> assertBool "decompress gzip" (maybeDecompress compressedGZip == original)- >> assertBool "have no empty chunks" (Prelude.all (not . BS.null) . BSL.toChunks . maybeDecompress $ compressedZlib)+ >> assertBool "have no empty chunks" (all (not . BS.null) . BSL.toChunks . maybeDecompress $ compressedZlib) >> (runBrokenStream >>= assertBool "decompress broken stream" . isLeft) where original = BSLL.pack "original uncompressed input"
− cabal/cabal-install/tests/UnitTests/Distribution/Client/GenericInstances.hs
@@ -1,10 +0,0 @@-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE StandaloneDeriving #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}--module UnitTests.Distribution.Client.GenericInstances () where--import Network.URI-import GHC.Generics--deriving instance Generic URIAuth
cabal/cabal-install/tests/UnitTests/Distribution/Client/Get.hs view
@@ -5,8 +5,8 @@ import Distribution.Types.PackageId import Distribution.Types.PackageName-import Distribution.Types.SourceRepo (SourceRepo (..), emptySourceRepo, RepoKind (..), RepoType (..))-import Distribution.Client.SourceRepo (SourceRepositoryPackage (..))+import Distribution.Types.SourceRepo (SourceRepo (..), emptySourceRepo, RepoKind (..), RepoType (..), KnownRepoType (..))+import Distribution.Client.Types.SourceRepo (SourceRepositoryPackage (..)) import Distribution.Verbosity as Verbosity import Distribution.Version @@ -120,7 +120,7 @@ repo = (emptySourceRepo RepoHead) { repoType = Just repotype }- repotype = Darcs+ repotype = KnownRepoType Darcs testSelectRepoKind :: Assertion@@ -165,7 +165,7 @@ where pkgrepos = [(pkgidfoo, [repo])] repo = (emptySourceRepo RepoHead) {- repoType = Just Darcs,+ repoType = Just (KnownRepoType Darcs), repoLocation = Just "" } @@ -175,11 +175,11 @@ withTestDir verbosity "repos" $ \tmpdir -> do let srcdir = tmpdir </> "src" repo = (emptySourceRepo RepoHead) {- repoType = Just Git,+ repoType = Just (KnownRepoType Git), repoLocation = Just srcdir } repo' = SourceRepositoryPackage- { srpType = Git+ { srpType = KnownRepoType Git , srpLocation = srcdir , srpTag = Nothing , srpBranch = Nothing@@ -195,7 +195,7 @@ testNetworkGitClone = withTestDir verbosity "repos" $ \tmpdir -> do let repo1 = (emptySourceRepo RepoHead) {- repoType = Just Git,+ repoType = Just (KnownRepoType Git), repoLocation = Just "https://github.com/haskell/zlib.git" } clonePackagesFromSourceRepo verbosity tmpdir Nothing@@ -203,7 +203,7 @@ assertFileContains (tmpdir </> "zlib1/zlib.cabal") ["name:", "zlib"] let repo2 = (emptySourceRepo RepoHead) {- repoType = Just Git,+ repoType = Just (KnownRepoType Git), repoLocation = Just (tmpdir </> "zlib1") } clonePackagesFromSourceRepo verbosity tmpdir Nothing@@ -211,7 +211,7 @@ assertFileContains (tmpdir </> "zlib2/zlib.cabal") ["name:", "zlib"] let repo3 = (emptySourceRepo RepoHead) {- repoType = Just Git,+ repoType = Just (KnownRepoType Git), repoLocation = Just (tmpdir </> "zlib1"), repoTag = Just "0.5.0.0" }
cabal/cabal-install/tests/UnitTests/Distribution/Client/Glob.hs view
@@ -3,38 +3,37 @@ module UnitTests.Distribution.Client.Glob (tests) where -#if !MIN_VERSION_base(4,8,0)-import Control.Applicative-#endif-import Data.Char-import Data.List-import Distribution.Deprecated.Text (display, parse, simpleParse)-import Distribution.Deprecated.ReadP+import Distribution.Client.Compat.Prelude hiding (last)+import Prelude () import Distribution.Client.Glob-import UnitTests.Distribution.Client.ArbitraryInstances+import Distribution.Utils.Structured (structureHash)+import UnitTests.Distribution.Client.ArbitraryInstances () import Test.Tasty import Test.Tasty.QuickCheck import Test.Tasty.HUnit-import Control.Exception-+import GHC.Fingerprint (Fingerprint (..)) tests :: [TestTree] tests = [ testProperty "print/parse roundtrip" prop_roundtrip_printparse , testCase "parse examples" testParseCases+ , testGroup "Structured hashes"+ [ testCase "GlobPiece" $ structureHash (Proxy :: Proxy GlobPiece) @?= Fingerprint 0xd5e5361866a30ea2 0x31fbfe7b58864782+ , testCase "FilePathGlobRel" $ structureHash (Proxy :: Proxy FilePathGlobRel) @?= Fingerprint 0x76fa5bcb865a8501 0xb152f68915316f98+ , testCase "FilePathRoot" $ structureHash (Proxy :: Proxy FilePathRoot) @?= Fingerprint 0x713373d51426ec64 0xda7376a38ecee5a5+ , testCase "FilePathGlob" $ structureHash (Proxy :: Proxy FilePathGlob) @?= Fingerprint 0x3c11c41f3f03a1f0 0x96e69d85c37d0024+ ] ] --TODO: [nice to have] tests for trivial globs, tests for matching, -- tests for windows style file paths -prop_roundtrip_printparse :: FilePathGlob -> Bool+prop_roundtrip_printparse :: FilePathGlob -> Property prop_roundtrip_printparse pathglob =- -- can't use simpleParse because it mis-handles trailing spaces- case [ x | (x, []) <- readP_to_S parse (display pathglob) ] of- xs@(_:_) -> last xs == pathglob- _ -> False+ counterexample (prettyShow pathglob) $+ eitherParsec (prettyShow pathglob) === Right pathglob -- first run, where we don't even call updateMonitor testParseCases :: Assertion@@ -72,6 +71,10 @@ (GlobDir [Literal "foo"] (GlobDir [Literal "bar"] GlobDirTrailing)) <- testparse "/foo/bar/" + FilePathGlob (FilePathRoot "C:\\")+ (GlobDir [Literal "foo"]+ (GlobDir [Literal "bar"] GlobDirTrailing)) <- testparse "C:\\foo\\bar\\"+ FilePathGlob FilePathRelative (GlobFile [WildCard]) <- testparse "*" @@ -101,103 +104,12 @@ testparse :: String -> IO FilePathGlob testparse s =- case simpleParse s of- Just p -> return p- Nothing -> throwIO $ HUnitFailure Nothing ("expected parse of: " ++ s)+ case eitherParsec s of+ Right p -> return p+ Left err -> throwIO $ HUnitFailure Nothing ("expected parse of: " ++ s ++ " -- " ++ err) parseFail :: String -> Assertion parseFail s =- case simpleParse s :: Maybe FilePathGlob of- Just _ -> throwIO $ HUnitFailure Nothing ("expected no parse of: " ++ s)- Nothing -> return ()--instance Arbitrary FilePathGlob where- arbitrary = (FilePathGlob <$> arbitrary <*> arbitrary)- `suchThat` validFilePathGlob-- shrink (FilePathGlob root pathglob) =- [ FilePathGlob root' pathglob'- | (root', pathglob') <- shrink (root, pathglob)- , validFilePathGlob (FilePathGlob root' pathglob') ]--validFilePathGlob :: FilePathGlob -> Bool-validFilePathGlob (FilePathGlob FilePathRelative pathglob) =- case pathglob of- GlobDirTrailing -> False- GlobDir [Literal "~"] _ -> False- GlobDir [Literal (d:":")] _ - | isLetter d -> False- _ -> True-validFilePathGlob _ = True--instance Arbitrary FilePathRoot where- arbitrary =- frequency- [ (3, pure FilePathRelative)- , (1, pure (FilePathRoot unixroot))- , (1, FilePathRoot <$> windrive)- , (1, pure FilePathHomeDir)- ]- where- unixroot = "/"- windrive = do d <- choose ('A', 'Z'); return (d : ":\\")-- shrink FilePathRelative = []- shrink (FilePathRoot _) = [FilePathRelative]- shrink FilePathHomeDir = [FilePathRelative]---instance Arbitrary FilePathGlobRel where- arbitrary = sized $ \sz ->- oneof $ take (max 1 sz)- [ pure GlobDirTrailing- , GlobFile <$> (getGlobPieces <$> arbitrary)- , GlobDir <$> (getGlobPieces <$> arbitrary)- <*> resize (sz `div` 2) arbitrary- ]-- shrink GlobDirTrailing = []- shrink (GlobFile glob) =- GlobDirTrailing- : [ GlobFile (getGlobPieces glob') | glob' <- shrink (GlobPieces glob) ]- shrink (GlobDir glob pathglob) =- pathglob- : GlobFile glob- : [ GlobDir (getGlobPieces glob') pathglob'- | (glob', pathglob') <- shrink (GlobPieces glob, pathglob) ]--newtype GlobPieces = GlobPieces { getGlobPieces :: [GlobPiece] }- deriving Eq--instance Arbitrary GlobPieces where- arbitrary = GlobPieces . mergeLiterals <$> shortListOf1 5 arbitrary-- shrink (GlobPieces glob) =- [ GlobPieces (mergeLiterals (getNonEmpty glob'))- | glob' <- shrink (NonEmpty glob) ]--mergeLiterals :: [GlobPiece] -> [GlobPiece]-mergeLiterals (Literal a : Literal b : ps) = mergeLiterals (Literal (a++b) : ps)-mergeLiterals (Union as : ps) = Union (map mergeLiterals as) : mergeLiterals ps-mergeLiterals (p:ps) = p : mergeLiterals ps-mergeLiterals [] = []--instance Arbitrary GlobPiece where- arbitrary = sized $ \sz ->- frequency- [ (3, Literal <$> shortListOf1 10 (elements globLiteralChars))- , (1, pure WildCard)- , (1, Union <$> resize (sz `div` 2) (shortListOf1 5 (shortListOf1 5 arbitrary)))- ]-- shrink (Literal str) = [ Literal str'- | str' <- shrink str- , not (null str')- , all (`elem` globLiteralChars) str' ]- shrink WildCard = []- shrink (Union as) = [ Union (map getGlobPieces (getNonEmpty as'))- | as' <- shrink (NonEmpty (map GlobPieces as)) ]--globLiteralChars :: [Char]-globLiteralChars = ['\0'..'\128'] \\ "*{},/\\"-+ case eitherParsec s :: Either String FilePathGlob of+ Right p -> throwIO $ HUnitFailure Nothing ("expected no parse of: " ++ s ++ " -- " ++ show p)+ Left _ -> return ()
cabal/cabal-install/tests/UnitTests/Distribution/Client/IndexUtils/Timestamp.hs view
@@ -1,6 +1,7 @@ module UnitTests.Distribution.Client.IndexUtils.Timestamp (tests) where -import Distribution.Deprecated.Text+import Distribution.Parsec (simpleParsec)+import Distribution.Pretty (prettyShow) import Data.Time import Data.Time.Clock.POSIX @@ -19,24 +20,24 @@ ] -- test unixtime format parsing-prop_timestamp1 :: Int -> Bool-prop_timestamp1 t0 = Just t == simpleParse ('@':show t0)+prop_timestamp1 :: NonNegative Int -> Bool+prop_timestamp1 (NonNegative t0) = Just t == simpleParsec ('@':show t0) where t = toEnum t0 :: Timestamp --- test display/simpleParse roundtrip+-- test prettyShow/simpleParse roundtrip prop_timestamp2 :: Int -> Bool prop_timestamp2 t0- | t /= nullTimestamp = simpleParse (display t) == Just t- | otherwise = display t == ""+ | t /= nullTimestamp = simpleParsec (prettyShow t) == Just t+ | otherwise = prettyShow t == "" where t = toEnum t0 :: Timestamp --- test display against reference impl+-- test prettyShow against reference impl prop_timestamp3 :: Int -> Bool prop_timestamp3 t0- | t /= nullTimestamp = refDisp t == display t- | otherwise = display t == ""+ | t /= nullTimestamp = refDisp t == prettyShow t+ | otherwise = prettyShow t == "" where t = toEnum t0 :: Timestamp
+ cabal/cabal-install/tests/UnitTests/Distribution/Client/Init/FileCreators.hs view
@@ -0,0 +1,184 @@+module UnitTests.Distribution.Client.Init.FileCreators (+ tests+ ) where++import Distribution.Client.Init.FileCreators+ ( generateCabalFile )++import Test.Tasty+import Test.Tasty.Golden (goldenVsString)++import System.FilePath+ ( (</>) )+import qualified Data.ByteString.Lazy as BS+import qualified Data.ByteString.Lazy.Char8 as BS8++import Distribution.Client.Init.Types+ ( InitFlags(..), PackageType(..), defaultInitFlags )+import Distribution.Simple.Setup+ ( Flag(..) )++import Distribution.CabalSpecVersion+ ( CabalSpecVersion(CabalSpecV2_4) )+import Distribution.Types.Dependency+ ( Dependency, mkDependency, mainLibSet )+import Distribution.Types.PackageName+ ( mkPackageName )+import Distribution.Types.VersionRange+ ( majorBoundVersion )+import Distribution.Types.Version+ ( mkVersion )+import qualified Distribution.ModuleName as ModuleName+ ( fromString )+import qualified Distribution.SPDX as SPDX+import Language.Haskell.Extension ( Language(..) )++tests :: [TestTree]+tests = [ testGroup "cabal init goldens"+ [ checkCabalFileGolden exeFlags "exe-only-golden.cabal"+ , checkCabalFileGolden libAndExeFlags "lib-and-exe-golden.cabal"+ , checkCabalFileGolden libExeAndTestFlags "lib-exe-and-test-golden.cabal"+ , checkCabalFileGolden libExeAndTestWithCommentsFlags "lib-exe-and-test-with-comments-golden.cabal"+ ]+ ]++checkCabalFileGolden :: InitFlags -> FilePath -> TestTree+checkCabalFileGolden flags goldenFileName =+ goldenVsString goldenFileName goldenFilePath generatedCabalFile+ where+ goldenFilePath :: FilePath+ goldenFilePath = "tests" </> "fixtures" </> "init" </> goldenFileName++ generatedCabalFile :: IO BS.ByteString+ generatedCabalFile = pure . BS8.pack $ generateCabalFile goldenFileName flags++-- ==================================================+-- Base flags to set common InitFlags values.++baseFlags :: InitFlags+baseFlags = defaultInitFlags {+ -- Values common to all (or most) test flags.+ packageName = Flag (mkPackageName "foo")+ , noComments = Flag False+ , minimal = Flag True+ , version = Flag (mkVersion [3,2,1])+ , synopsis = Flag "The foo package"+ , homepage = Flag "https://github.com/foo/foo"+ , license = Flag SPDX.NONE+ , author = Flag "me"+ , email = Flag "me@me.me"+ , category = Flag (Left "SomeCat")+ , cabalVersion = Flag CabalSpecV2_4+ , extraSrc = Just ["CHANGELOG.md"]+ , interactive = Flag False+ , otherModules = Nothing+ , otherExts = Nothing+ , language = Flag Haskell2010+ , buildTools = Nothing+ , dependencies = Just testDependencies+ , quiet = Flag True+ , packageDir = NoFlag+ , simpleProject = Flag False+ , initHcPath = NoFlag+ , overwrite = NoFlag++ -- Commonly overridden values in test InitFlags.+ -- It is fine to provide the same value in an overridden InitFlags+ -- to make it clear what that particular test case is differentiating+ -- from others.+ , packageType = Flag Executable+ , mainIs = Flag "Main.hs"+ , applicationDirs = Just ["app"]+ , sourceDirs = Nothing+ , exposedModules = Nothing+ , initializeTestSuite = Flag False+ , testDirs = Nothing+ }+++-- ==================================================+-- Simple exe.++exeFlags :: InitFlags+exeFlags = baseFlags {+ -- Create an executable only, with main living in app/Main.hs.+ packageType = Flag Executable+ , mainIs = Flag "Main.hs"+ , applicationDirs = Just ["app"]+ }+++-- ==================================================+-- Simple lib and exe (as created by `cabal init --libandexe`).+--+-- Specifically, having 'exposedModules = Just ["MyLib"]' is a special+-- case which results in the executable depending on the library from+-- the same package, i.e. 'build-depends = foo' with no version+-- constraints.++libAndExeFlags :: InitFlags+libAndExeFlags = baseFlags {+ -- Create a library and executable+ packageType = Flag LibraryAndExecutable++ -- Main living in app/Main.hs.+ , mainIs = Flag "Main.hs"+ , applicationDirs = Just ["app"]++ -- Library sources live in src/ and expose the module MyLib.+ , sourceDirs = Just ["src"]+ , exposedModules = Just (map ModuleName.fromString ["MyLib"])+ }+++-- ==================================================+-- Lib, exe, and test suite++libExeAndTestFlags :: InitFlags+libExeAndTestFlags = baseFlags {+ -- Create a library and executable+ packageType = Flag LibraryAndExecutable++ -- Main living in app/Main.hs.+ , mainIs = Flag "Main.hs"+ , applicationDirs = Just ["app"]++ -- Library sources live in src/ and expose the modules A and B.+ , sourceDirs = Just ["src"]+ , exposedModules = Just (map ModuleName.fromString ["A", "B"])++ -- Create a test suite living in tests/+ , initializeTestSuite = Flag True+ , testDirs = Just ["tests"]+ }++-- ==================================================+-- Lib, exe, and test suite with comments.++libExeAndTestWithCommentsFlags :: InitFlags+libExeAndTestWithCommentsFlags = libExeAndTestFlags {+ minimal = Flag False+ , noComments = Flag False+ , quiet = Flag False+ }++++-- ==================================================+-- Test dependency.++testDependencies :: [Dependency]+testDependencies =+ [ mkDependency+ (mkPackageName "base")+ (majorBoundVersion (mkVersion [4,13,0,0]))+ mainLibSet+ , mkDependency+ (mkPackageName "containers")+ (majorBoundVersion (mkVersion [5,7,0,0]))+ mainLibSet+ , mkDependency+ (mkPackageName "unordered-containers")+ (majorBoundVersion (mkVersion [2,7,0,0]))+ mainLibSet+ ]
cabal/cabal-install/tests/UnitTests/Distribution/Client/InstallPlan.hs view
@@ -3,6 +3,9 @@ {-# LANGUAGE ConstraintKinds #-} module UnitTests.Distribution.Client.InstallPlan (tests) where +import Distribution.Client.Compat.Prelude+import qualified Prelude as Unsafe (tail)+ import Distribution.Package import Distribution.Version import qualified Distribution.Client.InstallPlan as InstallPlan@@ -17,12 +20,11 @@ import Data.Graph import Data.Array hiding (index)-import Data.List+import Data.List ()+import Control.Monad (replicateM) import qualified Data.Map as Map import qualified Data.Set as Set-import Data.Set (Set) import Data.IORef-import Control.Monad import Control.Concurrent (threadDelay) import System.Random import Test.QuickCheck@@ -216,19 +218,19 @@ (ipkgvs, srcpkgvs) <- fmap ((\(ipkgs, srcpkgs) -> (map fst ipkgs, map fst srcpkgs)) . partition snd) $- sequence+ sequenceA [ do isipkg <- if isRoot then pick ipkgProportion else return False return (v, isipkg) | (v,n) <- assocs (outdegree graph) , let isRoot = n == 0 ] - ipkgs <- sequence+ ipkgs <- sequenceA [ mkIPkg pkgv depvs | pkgv <- ipkgvs , let depvs = graph ! pkgv ]- srcpkgs <- sequence+ srcpkgs <- sequenceA [ mkSrcPkg pkgv depvs | pkgv <- srcpkgvs , let depvs = graph ! pkgv@@ -256,9 +258,9 @@ nranks <- genNRanks rankSizes <- replicateM nranks genNPerRank let rankStarts = scanl (+) 0 rankSizes- rankRanges = drop 1 (zip rankStarts (tail rankStarts))+ rankRanges = drop 1 (zip rankStarts (Unsafe.tail rankStarts)) totalRange = sum rankSizes- rankEdges <- mapM (uncurry genRank) rankRanges+ rankEdges <- traverse (uncurry genRank) rankRanges return $ buildG (0, totalRange-1) (concat rankEdges) where genRank :: Vertex -> Vertex -> Gen [Edge]
cabal/cabal-install/tests/UnitTests/Distribution/Client/JobControl.hs view
@@ -3,13 +3,13 @@ import Distribution.Client.JobControl -import Data.List-import Data.Maybe-import Data.IORef-import Control.Monad+import Distribution.Client.Compat.Prelude+import Prelude ()++import Data.IORef (newIORef, atomicModifyIORef)+import Control.Monad (replicateM_, replicateM) import Control.Concurrent (threadDelay)-import Control.Exception (Exception, try, throwIO)-import Data.Typeable (Typeable)+import Control.Exception (try) import qualified Data.Set as Set import Test.Tasty@@ -75,13 +75,13 @@ prop_submit :: JobControl IO Int -> [Int] -> IO Bool prop_submit jobCtl xs = do- mapM_ (\x -> spawnJob jobCtl (return x)) xs- xs' <- mapM (\_ -> collectJob jobCtl) xs+ traverse_ (\x -> spawnJob jobCtl (return x)) xs+ xs' <- traverse (\_ -> collectJob jobCtl) xs return (sort xs == sort xs') prop_remaining :: JobControl IO Int -> [Int] -> IO Bool prop_remaining jobCtl xs = do- mapM_ (\x -> spawnJob jobCtl (return x)) xs+ traverse_ (\x -> spawnJob jobCtl (return x)) xs xs' <- collectRemainingJobs jobCtl return (sort xs == sort xs') @@ -97,7 +97,7 @@ prop_submit_interleaved :: JobControl IO (Maybe Int) -> [Int] -> IO Bool prop_submit_interleaved jobCtl xs = do- xs' <- sequence+ xs' <- sequenceA [ spawn >> collect | let spawns = map (\x -> spawnJob jobCtl (return (Just x))) xs ++ repeat (return ())@@ -148,8 +148,8 @@ prop_cancel_serial xs ys = ioProperty $ do jobCtl <- newSerialJobControl- mapM_ (\x -> spawnJob jobCtl (return x)) (xs++ys)- xs' <- mapM (\_ -> collectJob jobCtl) xs+ traverse_ (\x -> spawnJob jobCtl (return x)) (xs++ys)+ xs' <- traverse (\_ -> collectJob jobCtl) xs cancelJobs jobCtl ys' <- collectRemainingJobs jobCtl return (sort xs == sort xs' && null ys')@@ -158,8 +158,8 @@ prop_cancel_parallel (Positive (Small maxJobLimit)) xs ys = do ioProperty $ do jobCtl <- newParallelJobControl maxJobLimit- mapM_ (\x -> spawnJob jobCtl (threadDelay 100 >> return x)) (xs++ys)- xs' <- mapM (\_ -> collectJob jobCtl) xs+ traverse_ (\x -> spawnJob jobCtl (threadDelay 100 >> return x)) (xs++ys)+ xs' <- traverse (\_ -> collectJob jobCtl) xs cancelJobs jobCtl ys' <- collectRemainingJobs jobCtl return $ Set.fromList (xs'++ys') `Set.isSubsetOf` Set.fromList (xs++ys)@@ -183,7 +183,7 @@ prop_exception :: JobControl IO Int -> [Either Int Int] -> IO Bool prop_exception jobCtl xs = do- mapM_ (\x -> spawnJob jobCtl (either (throwIO . TestException) return x)) xs+ traverse_ (\x -> spawnJob jobCtl (either (throwIO . TestException) return x)) xs xs' <- replicateM (length xs) $ do mx <- try (collectJob jobCtl) return $ case mx of
cabal/cabal-install/tests/UnitTests/Distribution/Client/ProjectConfig.hs view
@@ -1,7 +1,13 @@ {-# LANGUAGE CPP #-} {-# LANGUAGE GADTs #-}+{-# LANGUAGE RecordWildCards #-} {-# OPTIONS_GHC -fno-warn-orphans #-} +-- simplifier goes nuts otherwise+#if __GLASGOW_HASKELL__ < 806+{-# OPTIONS_GHC -funfolding-use-threshold=30 #-}+#endif+ module UnitTests.Distribution.Client.ProjectConfig (tests) where #if !MIN_VERSION_base(4,8,0)@@ -11,36 +17,31 @@ import Data.Map (Map) import qualified Data.Map as Map import Data.List+import Network.URI (URI) import Distribution.Deprecated.ParseUtils-import Distribution.Deprecated.Text as Text import qualified Distribution.Deprecated.ReadP as Parse import Distribution.Package-import Distribution.PackageDescription hiding (Flag, SourceRepo)+import Distribution.PackageDescription import Distribution.Compiler import Distribution.Version-import Distribution.Simple.Compiler-import Distribution.Simple.Setup-import Distribution.Simple.InstallDirs-import Distribution.Simple.Utils import Distribution.Simple.Program.Types import Distribution.Simple.Program.Db import Distribution.Types.PackageVersionConstraint +import Distribution.Parsec+import Distribution.Pretty+ import Distribution.Client.Types import Distribution.Client.CmdInstall.ClientInstallFlags-import Distribution.Client.InstallSymlink import Distribution.Client.Dependency.Types-import Distribution.Client.BuildReports.Types import Distribution.Client.Targets-import Distribution.Client.SourceRepo+import Distribution.Client.Types.SourceRepo import Distribution.Utils.NubList-import Network.URI import Distribution.Solver.Types.PackageConstraint import Distribution.Solver.Types.ConstraintSource-import Distribution.Solver.Types.OptionalStanza import Distribution.Solver.Types.Settings import Distribution.Client.ProjectConfig@@ -101,7 +102,7 @@ roundtrip :: (Eq a, ToExpr a) => (a -> b) -> (b -> a) -> a -> Property roundtrip f f_inv x = let y = f x- in f_inv y `ediffEq` x -- no counterexample with y, as they not have ToExpr+ in x `ediffEq` f_inv y -- no counterexample with y, as they not have ToExpr roundtrip_legacytypes :: ProjectConfig -> Property roundtrip_legacytypes =@@ -154,13 +155,13 @@ roundtrip_printparse :: ProjectConfig -> Property roundtrip_printparse config =- case (fmap convertLegacyProjectConfig- . parseLegacyProjectConfig- . showLegacyProjectConfig- . convertToLegacyProjectConfig)- config of- ParseOk _ x -> x `ediffEq` config { projectConfigProvenance = mempty }+ case fmap convertLegacyProjectConfig (parseLegacyProjectConfig str) of+ ParseOk _ x -> counterexample ("shown: " ++ str) $+ x `ediffEq` config { projectConfigProvenance = mempty } ParseFailed err -> counterexample (show err) False+ where+ str :: String+ str = showLegacyProjectConfig (convertToLegacyProjectConfig config) prop_roundtrip_printparse_all :: ProjectConfig -> Property@@ -258,21 +259,22 @@ prop_parsePackageLocationTokenQ (PackageLocationString str) = runReadP parsePackageLocationTokenQ (renderPackageLocationToken str) == Just str -prop_roundtrip_printparse_RelaxedDep :: RelaxedDep -> Bool+prop_roundtrip_printparse_RelaxedDep :: RelaxedDep -> Property prop_roundtrip_printparse_RelaxedDep rdep =- runReadP Text.parse (Text.display rdep) == Just rdep+ counterexample (prettyShow rdep) $+ eitherParsec (prettyShow rdep) == Right rdep prop_roundtrip_printparse_RelaxDeps :: RelaxDeps -> Property prop_roundtrip_printparse_RelaxDeps rdep =- counterexample (Text.display rdep) $- runReadP Text.parse (Text.display rdep) `ediffEq` Just rdep+ counterexample (prettyShow rdep) $+ Right rdep `ediffEq` eitherParsec (prettyShow rdep) prop_roundtrip_printparse_RelaxDeps' :: RelaxDeps -> Property prop_roundtrip_printparse_RelaxDeps' rdep = counterexample rdep' $- runReadP Text.parse rdep' `ediffEq` Just rdep+ Right rdep `ediffEq` eitherParsec rdep' where- rdep' = go (Text.display rdep)+ rdep' = go (prettyShow rdep) -- replace 'all' tokens by '*' go :: String -> String@@ -356,12 +358,6 @@ braces s = "{" ++ s ++ "}" -instance Arbitrary OverwritePolicy where- arbitrary = arbitraryBoundedEnum--instance Arbitrary InstallMethod where- arbitrary = arbitraryBoundedEnum- instance Arbitrary ClientInstallFlags where arbitrary = ClientInstallFlags@@ -377,11 +373,11 @@ <$> arbitrary <*> arbitrary <*> arbitrary- <*> (toNubList <$> shortListOf 2 arbitrary) -- 4+ <*> (toNubList <$> shortListOf 2 arbitrary) <*> arbitrary <*> arbitrary <*> arbitrary- <*> (fmap getShortToken <$> arbitrary) -- 8+ <*> (fmap getShortToken <$> arbitrary) <*> arbitrary <*> arbitraryNumJobs <*> arbitrary@@ -446,104 +442,76 @@ postShrink_NumJobs = fmap (fmap getPositive) instance Arbitrary ProjectConfigShared where- arbitrary =- ProjectConfigShared- <$> arbitraryFlag arbitraryShortToken- <*> arbitraryFlag arbitraryShortToken- <*> arbitraryFlag arbitraryShortToken- <*> arbitrary- <*> arbitraryFlag arbitraryShortToken- <*> arbitraryFlag arbitraryShortToken- <*> arbitrary- <*> arbitrary- <*> (toNubList <$> listOf arbitraryShortToken)- <*> arbitrary- <*> arbitraryFlag arbitraryShortToken- <*> arbitraryConstraints- <*> shortListOf 2 arbitrary- <*> arbitrary <*> arbitrary- <*> arbitrary <*> arbitrary- <*> arbitrary <*> arbitrary- <*> arbitrary <*> arbitrary- <*> arbitrary <*> arbitrary- <*> arbitrary- <*> arbitrary- <*> arbitrary- <*> arbitrary- <*> (toNubList <$> listOf arbitraryShortToken)+ arbitrary = do+ projectConfigDistDir <- arbitraryFlag arbitraryShortToken+ projectConfigConfigFile <- arbitraryFlag arbitraryShortToken+ projectConfigProjectFile <- arbitraryFlag arbitraryShortToken+ projectConfigIgnoreProject <- arbitrary+ projectConfigHcFlavor <- arbitrary+ projectConfigHcPath <- arbitraryFlag arbitraryShortToken+ projectConfigHcPkg <- arbitraryFlag arbitraryShortToken+ projectConfigHaddockIndex <- arbitrary+ projectConfigRemoteRepos <- arbitrary+ projectConfigLocalNoIndexRepos <- arbitrary+ projectConfigActiveRepos <- arbitrary+ projectConfigIndexState <- arbitrary+ projectConfigStoreDir <- arbitraryFlag arbitraryShortToken+ projectConfigConstraints <- arbitraryConstraints+ projectConfigPreferences <- shortListOf 2 arbitrary+ projectConfigCabalVersion <- arbitrary+ projectConfigSolver <- arbitrary+ projectConfigAllowOlder <- arbitrary+ projectConfigAllowNewer <- arbitrary+ projectConfigWriteGhcEnvironmentFilesPolicy <- arbitrary+ projectConfigMaxBackjumps <- arbitrary+ projectConfigReorderGoals <- arbitrary+ projectConfigCountConflicts <- arbitrary+ projectConfigFineGrainedConflicts <- arbitrary+ projectConfigMinimizeConflictSet <- arbitrary+ projectConfigStrongFlags <- arbitrary+ projectConfigAllowBootLibInstalls <- arbitrary+ projectConfigOnlyConstrained <- arbitrary+ projectConfigPerComponent <- arbitrary+ projectConfigIndependentGoals <- arbitrary+ projectConfigProgPathExtra <- toNubList <$> listOf arbitraryShortToken+ return ProjectConfigShared {..} where arbitraryConstraints :: Gen [(UserConstraint, ConstraintSource)] arbitraryConstraints = fmap (\uc -> (uc, projectConfigConstraintSource)) <$> arbitrary - shrink ProjectConfigShared { projectConfigDistDir = x00- , projectConfigProjectFile = x01- , projectConfigHcFlavor = x02- , projectConfigHcPath = x03- , projectConfigHcPkg = x04- , projectConfigHaddockIndex = x05- , projectConfigRemoteRepos = x06- , projectConfigLocalRepos = x07- , projectConfigIndexState = x08- , projectConfigConstraints = x09- , projectConfigPreferences = x10- , projectConfigCabalVersion = x11- , projectConfigSolver = x12- , projectConfigAllowOlder = x13- , projectConfigAllowNewer = x14- , projectConfigWriteGhcEnvironmentFilesPolicy = x15- , projectConfigMaxBackjumps = x16- , projectConfigReorderGoals = x17- , projectConfigCountConflicts = x18- , projectConfigMinimizeConflictSet = x19- , projectConfigStrongFlags = x20- , projectConfigAllowBootLibInstalls = x21- , projectConfigOnlyConstrained = x22- , projectConfigPerComponent = x23- , projectConfigIndependentGoals = x24- , projectConfigConfigFile = x25- , projectConfigProgPathExtra = x26- , projectConfigStoreDir = x27 } =- [ ProjectConfigShared { projectConfigDistDir = x00'- , projectConfigProjectFile = x01'- , projectConfigHcFlavor = x02'- , projectConfigHcPath = fmap getNonEmpty x03'- , projectConfigHcPkg = fmap getNonEmpty x04'- , projectConfigHaddockIndex = x05'- , projectConfigRemoteRepos = x06'- , projectConfigLocalRepos = x07'- , projectConfigIndexState = x08'- , projectConfigConstraints = postShrink_Constraints x09'- , projectConfigPreferences = x10'- , projectConfigCabalVersion = x11'- , projectConfigSolver = x12'- , projectConfigAllowOlder = x13'- , projectConfigAllowNewer = x14'- , projectConfigWriteGhcEnvironmentFilesPolicy = x15'- , projectConfigMaxBackjumps = x16'- , projectConfigReorderGoals = x17'- , projectConfigCountConflicts = x18'- , projectConfigMinimizeConflictSet = x19'- , projectConfigStrongFlags = x20'- , projectConfigAllowBootLibInstalls = x21'- , projectConfigOnlyConstrained = x22'- , projectConfigPerComponent = x23'- , projectConfigIndependentGoals = x24'- , projectConfigConfigFile = x25'- , projectConfigProgPathExtra = x26'- , projectConfigStoreDir = x27' }- | ((x00', x01', x02', x03', x04'),- (x05', x06', x07', x08', x09'),- (x10', x11', x12', x13', x14', x15'),- (x16', x17', x18', x19', x20', x21'),- x22', x23', x24', x25', x26', x27')- <- shrink- ((x00, x01, x02, fmap NonEmpty x03, fmap NonEmpty x04),- (x05, x06, x07, x08, preShrink_Constraints x09),- (x10, x11, x12, x13, x14, x15),- (x16, x17, x18, x19, x20, x21),- x22, x23, x24, x25, x26, x27)- ]+ shrink ProjectConfigShared {..} = runShrinker $ pure ProjectConfigShared+ <*> shrinker projectConfigDistDir+ <*> shrinker projectConfigConfigFile+ <*> shrinker projectConfigProjectFile+ <*> shrinker projectConfigIgnoreProject+ <*> shrinker projectConfigHcFlavor+ <*> shrinkerAla (fmap NonEmpty) projectConfigHcPath+ <*> shrinkerAla (fmap NonEmpty) projectConfigHcPkg+ <*> shrinker projectConfigHaddockIndex+ <*> shrinker projectConfigRemoteRepos+ <*> shrinker projectConfigLocalNoIndexRepos+ <*> shrinker projectConfigActiveRepos+ <*> shrinker projectConfigIndexState+ <*> shrinker projectConfigStoreDir+ <*> shrinkerPP preShrink_Constraints postShrink_Constraints projectConfigConstraints+ <*> shrinker projectConfigPreferences+ <*> shrinker projectConfigCabalVersion+ <*> shrinker projectConfigSolver+ <*> shrinker projectConfigAllowOlder+ <*> shrinker projectConfigAllowNewer+ <*> shrinker projectConfigWriteGhcEnvironmentFilesPolicy+ <*> shrinker projectConfigMaxBackjumps+ <*> shrinker projectConfigReorderGoals+ <*> shrinker projectConfigCountConflicts+ <*> shrinker projectConfigFineGrainedConflicts+ <*> shrinker projectConfigMinimizeConflictSet+ <*> shrinker projectConfigStrongFlags+ <*> shrinker projectConfigAllowBootLibInstalls+ <*> shrinker projectConfigOnlyConstrained+ <*> shrinker projectConfigPerComponent+ <*> shrinker projectConfigIndependentGoals+ <*> shrinker projectConfigProgPathExtra where preShrink_Constraints = map fst postShrink_Constraints = map (\uc -> (uc, projectConfigConstraintSource))@@ -555,9 +523,6 @@ instance Arbitrary ProjectConfigProvenance where arbitrary = elements [Implicit, Explicit "cabal.project"] -instance Arbitrary FlagAssignment where- arbitrary = mkFlagAssignment <$> arbitrary- instance Arbitrary PackageConfig where arbitrary = PackageConfig@@ -761,11 +726,7 @@ . Map.map (map getNonEmpty . getNonEmpty) . Map.mapKeys getNoShrink -instance Arbitrary HaddockTarget where- arbitrary = elements [ForHackage, ForDevelopment] -instance Arbitrary TestShowDetails where- arbitrary = arbitraryBoundedEnum instance f ~ [] => Arbitrary (SourceRepositoryPackage f) where arbitrary = SourceRepositoryPackage@@ -786,77 +747,25 @@ (x1, ShortToken x2, fmap ShortToken x3, fmap ShortToken x4, fmap ShortToken x5) ] -instance Arbitrary RepoType where- arbitrary = elements knownRepoTypes--instance Arbitrary ReportLevel where- arbitrary = elements [NoReports .. DetailedReports]--instance Arbitrary CompilerFlavor where- arbitrary = elements knownCompilerFlavors--instance Arbitrary a => Arbitrary (InstallDirs a) where- arbitrary =- InstallDirs- <$> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary -- 4- <*> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary -- 8- <*> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary -- 12- <*> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary -- 16--instance Arbitrary PackageDB where- arbitrary = oneof [ pure GlobalPackageDB- , pure UserPackageDB- , SpecificPackageDB . getShortToken <$> arbitrary- ]- instance Arbitrary RemoteRepo where arbitrary = RemoteRepo- <$> arbitraryShortToken `suchThat` (not . (":" `isPrefixOf`))+ <$> arbitrary <*> arbitrary -- URI <*> arbitrary <*> listOf arbitraryRootKey- <*> (fmap getNonNegative arbitrary)+ <*> fmap getNonNegative arbitrary <*> pure False where arbitraryRootKey = shortListOf1 5 (oneof [ choose ('0', '9') , choose ('a', 'f') ]) -instance Arbitrary UserConstraintScope where- arbitrary = oneof [ UserQualified <$> arbitrary <*> arbitrary- , UserAnySetupQualifier <$> arbitrary- , UserAnyQualifier <$> arbitrary- ]--instance Arbitrary UserQualifier where- arbitrary = oneof [ pure UserQualToplevel- , UserQualSetup <$> arbitrary-- -- -- TODO: Re-enable UserQualExe tests once we decide on a syntax.- -- , UserQualExe <$> arbitrary <*> arbitrary- ]--instance Arbitrary UserConstraint where- arbitrary = UserConstraint <$> arbitrary <*> arbitrary--instance Arbitrary PackageProperty where- arbitrary = oneof [ PackagePropertyVersion <$> arbitrary- , pure PackagePropertyInstalled- , pure PackagePropertySource- , PackagePropertyFlags . mkFlagAssignment <$> shortListOf1 3 arbitrary- , PackagePropertyStanzas . (\x->[x]) <$> arbitrary- ]--instance Arbitrary OptionalStanza where- arbitrary = elements [minBound..maxBound]--instance Arbitrary FlagName where- arbitrary = mkFlagName <$> flagident- where- flagident = lowercase <$> shortListOf1 5 (elements flagChars)- `suchThat` (("-" /=) . take 1)- flagChars = "-_" ++ ['a'..'z']+instance Arbitrary LocalRepo where+ arbitrary = LocalRepo+ <$> arbitrary+ <*> elements ["/tmp/foo", "/tmp/bar"] -- TODO: generate valid absolute paths+ <*> arbitrary instance Arbitrary PreSolver where arbitrary = elements [minBound..maxBound]@@ -867,6 +776,9 @@ instance Arbitrary CountConflicts where arbitrary = CountConflicts <$> arbitrary +instance Arbitrary FineGrainedConflicts where+ arbitrary = FineGrainedConflicts <$> arbitrary+ instance Arbitrary MinimizeConflictSet where arbitrary = MinimizeConflictSet <$> arbitrary @@ -883,63 +795,3 @@ arbitrary = oneof [ pure OnlyConstrainedAll , pure OnlyConstrainedNone ]--instance Arbitrary AllowNewer where- arbitrary = AllowNewer <$> arbitrary--instance Arbitrary AllowOlder where- arbitrary = AllowOlder <$> arbitrary--instance Arbitrary RelaxDeps where- arbitrary = oneof [ pure mempty- , RelaxDepsSome <$> shortListOf1 3 arbitrary- , pure RelaxDepsAll- ]--instance Arbitrary RelaxDepMod where- arbitrary = elements [RelaxDepModNone, RelaxDepModCaret]--instance Arbitrary RelaxDepScope where- arbitrary = oneof [ pure RelaxDepScopeAll- , RelaxDepScopePackage <$> arbitrary- , RelaxDepScopePackageId <$> (PackageIdentifier <$> arbitrary <*> arbitrary)- ]--instance Arbitrary RelaxDepSubject where- arbitrary = oneof [ pure RelaxDepSubjectAll- , RelaxDepSubjectPkg <$> arbitrary- ]--instance Arbitrary RelaxedDep where- arbitrary = RelaxedDep <$> arbitrary <*> arbitrary <*> arbitrary--instance Arbitrary ProfDetailLevel where- arbitrary = elements [ d | (_,_,d) <- knownProfDetailLevels ]--instance Arbitrary OptimisationLevel where- arbitrary = elements [minBound..maxBound]--instance Arbitrary DebugInfoLevel where- arbitrary = elements [minBound..maxBound]--instance Arbitrary URI where- arbitrary =- URI <$> elements ["file:", "http:", "https:"]- <*> (Just <$> arbitrary)- <*> (('/':) <$> arbitraryURIToken)- <*> (('?':) <$> arbitraryURIToken)- <*> pure ""--instance Arbitrary URIAuth where- arbitrary =- URIAuth <$> pure "" -- no password as this does not roundtrip- <*> arbitraryURIToken- <*> arbitraryURIPort--arbitraryURIToken :: Gen String-arbitraryURIToken =- shortListOf1 6 (elements (filter isUnreserved ['\0'..'\255']))--arbitraryURIPort :: Gen String-arbitraryURIPort =- oneof [ pure "", (':':) <$> shortListOf1 4 (choose ('0','9')) ]
− cabal/cabal-install/tests/UnitTests/Distribution/Client/Sandbox.hs
@@ -1,28 +0,0 @@-module UnitTests.Distribution.Client.Sandbox (- tests- ) where--import Distribution.Client.Sandbox (withSandboxBinDirOnSearchPath)--import Test.Tasty-import Test.Tasty.HUnit--import System.FilePath (getSearchPath, (</>))--tests :: [TestTree]-tests = [ testCase "sandboxBinDirOnSearchPath" sandboxBinDirOnSearchPathTest- , testCase "oldSearchPathRestored" oldSearchPathRestoreTest- ]--sandboxBinDirOnSearchPathTest :: Assertion-sandboxBinDirOnSearchPathTest =- withSandboxBinDirOnSearchPath "foo" $ do- r <- getSearchPath- assertBool "'foo/bin' not on search path" $ ("foo" </> "bin") `elem` r--oldSearchPathRestoreTest :: Assertion-oldSearchPathRestoreTest = do- r <- getSearchPath- withSandboxBinDirOnSearchPath "foo" $ return ()- r' <- getSearchPath- assertEqual "Old search path wasn't restored" r r'
− cabal/cabal-install/tests/UnitTests/Distribution/Client/Sandbox/Timestamp.hs
@@ -1,63 +0,0 @@-module UnitTests.Distribution.Client.Sandbox.Timestamp (tests) where--import System.FilePath--import Distribution.Simple.Utils (withTempDirectory)-import Distribution.Verbosity--import Distribution.Compat.Time-import Distribution.Client.Sandbox.Timestamp--import Test.Tasty-import Test.Tasty.HUnit--tests :: [TestTree]-tests =- [ testCase "timestamp record version 1 can be read" timestampReadTest_v1- , testCase "timestamp record version 2 can be read" timestampReadTest_v2- , testCase "written timestamp record can be read" timestampReadWriteTest ]--timestampRecord_v1 :: String-timestampRecord_v1 =- "[(\"i386-linux-ghc-8.0.0.20160204\",[(\"/foo/bar/Baz\",1455350946)])" ++- ",(\"i386-linux-ghc-7.10.3\",[(\"/foo/bar/Baz\",1455484719)])]\n"--timestampRecord_v2 :: String-timestampRecord_v2 =- "2\n" ++- "[(\"i386-linux-ghc-8.0.0.20160204\",[(\"/foo/bar/Baz\",1455350946)])" ++- ",(\"i386-linux-ghc-7.10.3\",[(\"/foo/bar/Baz\",1455484719)])]"--timestampReadTest_v1 :: Assertion-timestampReadTest_v1 =- timestampReadTest timestampRecord_v1 $- map (\(i, ts) ->- (i, map (\(p, ModTime t) ->- (p, posixSecondsToModTime . fromIntegral $ t)) ts))- timestampRecord--timestampReadTest_v2 :: Assertion-timestampReadTest_v2 = timestampReadTest timestampRecord_v2 timestampRecord--timestampReadTest :: FilePath -> [TimestampFileRecord] -> Assertion-timestampReadTest fileContent expected =- withTempDirectory silent "." "cabal-timestamp-" $ \dir -> do- let fileName = dir </> "timestamp-record"- writeFile fileName fileContent- tRec <- readTimestampFile normal fileName- assertEqual "expected timestamp records to be equal"- expected tRec--timestampRecord :: [TimestampFileRecord]-timestampRecord =- [("i386-linux-ghc-8.0.0.20160204",[("/foo/bar/Baz",ModTime 1455350946)])- ,("i386-linux-ghc-7.10.3",[("/foo/bar/Baz",ModTime 1455484719)])]--timestampReadWriteTest :: Assertion-timestampReadWriteTest =- withTempDirectory silent "." "cabal-timestamp-" $ \dir -> do- let fileName = dir </> "timestamp-record"- writeTimestampFile fileName timestampRecord- tRec <- readTimestampFile normal fileName- assertEqual "expected timestamp records to be equal"- timestampRecord tRec
cabal/cabal-install/tests/UnitTests/Distribution/Client/Tar.hs view
@@ -30,8 +30,9 @@ filterTest = do let e1 = getFileEntry "file1" "x" e2 = getFileEntry "file2" "y"- p = (\e -> let (NormalFile dta _) = entryContent e- str = BS.Char8.unpack dta+ p = (\e -> let str = BS.Char8.unpack $ case entryContent e of+ NormalFile dta _ -> dta+ _ -> error "Invalid entryContent" in str /= "y") assertEqual "Unexpected result for filter" "xz" $ entriesToString $ filterEntries p $ Next e1 $ Next e2 Done@@ -44,8 +45,9 @@ filterMTest = do let e1 = getFileEntry "file1" "x" e2 = getFileEntry "file2" "y"- p = (\e -> let (NormalFile dta _) = entryContent e- str = BS.Char8.unpack dta+ p = (\e -> let str = BS.Char8.unpack $ case entryContent e of+ NormalFile dta _ -> dta+ _ -> error "Invalid entryContent" in tell "t" >> return (str /= "y")) (r, w) <- runWriterT $ filterEntriesM p $ Next e1 $ Next e2 Done@@ -70,6 +72,7 @@ entriesToString :: Entries String -> String entriesToString =- foldEntries (\e acc -> let (NormalFile dta _) = entryContent e- str = BS.Char8.unpack dta+ foldEntries (\e acc -> let str = BS.Char8.unpack $ case entryContent e of+ NormalFile dta _ -> dta+ _ -> error "Invalid entryContent" in str ++ acc) "z" id
cabal/cabal-install/tests/UnitTests/Distribution/Client/Targets.hs view
@@ -9,9 +9,7 @@ import Distribution.PackageDescription (mkFlagName, mkFlagAssignment) import Distribution.Version (anyVersion, thisVersion, mkVersion) -import Distribution.Deprecated.ReadP (readP_to_S)-import Distribution.Deprecated.ParseUtils (parseCommaList)-import Distribution.Deprecated.Text (parse)+import Distribution.Parsec (explicitEitherParsec, parsec, parsecCommaList) import Distribution.Solver.Types.PackageConstraint (PackageProperty(..)) import Distribution.Solver.Types.OptionalStanza (OptionalStanza(..))@@ -19,7 +17,6 @@ import Test.Tasty import Test.Tasty.HUnit -import Data.Char (isSpace) import Data.List (intercalate) -- Helper function: makes a test group by mapping each element@@ -51,7 +48,7 @@ UserConstraint (UserQualified UserQualToplevel (pn "template-haskell")) PackagePropertyInstalled) - , ("bytestring -any",+ , ("bytestring >= 0", UserConstraint (UserQualified UserQualToplevel (pn "bytestring")) (PackagePropertyVersion anyVersion)) @@ -67,7 +64,8 @@ UserConstraint (UserQualified (UserQualSetup (pn "process")) (pn "bytestring")) (PackagePropertyVersion (thisVersion (mkVersion [5, 2])))) - , ("network:setup.containers +foo -bar baz",+ -- flag MUST be prefixed with - or ++ , ("network:setup.containers +foo -bar +baz", UserConstraint (UserQualified (UserQualSetup (pn "network")) (pn "containers")) (PackagePropertyFlags (mkFlagAssignment [(fn "foo", True),@@ -88,21 +86,19 @@ readUserConstraintTest str uc = assertEqual ("Couldn't read constraint: '" ++ str ++ "'") expected actual where- expected = uc- actual = let Right r = readUserConstraint str in r+ expected = Right uc+ actual = readUserConstraint str parseUserConstraintTest :: String -> UserConstraint -> Assertion parseUserConstraintTest str uc = assertEqual ("Couldn't parse constraint: '" ++ str ++ "'") expected actual where- expected = [uc]- actual = [ x | (x, ys) <- readP_to_S parse str- , all isSpace ys]+ expected = Right uc+ actual = explicitEitherParsec parsec str readUserConstraintsTest :: String -> [UserConstraint] -> Assertion readUserConstraintsTest str ucs = assertEqual ("Couldn't read constraints: '" ++ str ++ "'") expected actual where- expected = [ucs]- actual = [ x | (x, ys) <- readP_to_S (parseCommaList parse) str- , all isSpace ys]+ expected = Right ucs+ actual = explicitEitherParsec (parsecCommaList parsec) str
cabal/cabal-install/tests/UnitTests/Distribution/Client/TreeDiffInstances.hs view
@@ -3,25 +3,6 @@ module UnitTests.Distribution.Client.TreeDiffInstances () where -import Distribution.Compiler-import Distribution.Simple.Compiler- ( ProfDetailLevel, OptimisationLevel, DebugInfoLevel )-import Distribution.Simple.Flag-import Distribution.Simple.InstallDirs-import Distribution.Simple.InstallDirs.Internal-import Distribution.Simple.Setup (HaddockTarget, TestShowDetails)-import Distribution.Types.Flag (FlagName, FlagAssignment)-import Distribution.Types.PackageId-import Distribution.Types.PackageName-import Distribution.Types.PackageVersionConstraint-import Distribution.Types.SourceRepo-import Distribution.Types.Version-import Distribution.Types.VersionRange.Internal-import Distribution.Utils.NubList-import Distribution.Utils.ShortText-import Distribution.Verbosity-import Distribution.Verbosity.Internal- import Distribution.Solver.Types.ConstraintSource import Distribution.Solver.Types.OptionalStanza import Distribution.Solver.Types.PackageConstraint@@ -30,80 +11,68 @@ import Distribution.Client.BuildReports.Types import Distribution.Client.CmdInstall.ClientInstallFlags import Distribution.Client.Dependency.Types+import Distribution.Client.IndexUtils.ActiveRepos+import Distribution.Client.IndexUtils.IndexState import Distribution.Client.IndexUtils.Timestamp-import Distribution.Client.InstallSymlink import Distribution.Client.ProjectConfig.Types import Distribution.Client.Targets-import Distribution.Client.SourceRepo (SourceRepositoryPackage) import Distribution.Client.Types--import UnitTests.Distribution.Client.GenericInstances ()+import Distribution.Client.Types.OverwritePolicy (OverwritePolicy)+import Distribution.Client.Types.SourceRepo (SourceRepositoryPackage) -import Network.URI import Data.TreeDiff.Class+import Data.TreeDiff.Instances.Cabal ()+import Network.URI instance (ToExpr k, ToExpr v) => ToExpr (MapMappend k v) instance (ToExpr k, ToExpr v) => ToExpr (MapLast k v)-instance (ToExpr a) => ToExpr (NubList a)-instance (ToExpr a) => ToExpr (Flag a) +instance ToExpr (f FilePath) => ToExpr (SourceRepositoryPackage f)++instance ToExpr ActiveRepoEntry+instance ToExpr ActiveRepos instance ToExpr AllowBootLibInstalls instance ToExpr AllowNewer instance ToExpr AllowOlder+instance ToExpr BuildReport instance ToExpr ClientInstallFlags-instance ToExpr CompilerFlavor+instance ToExpr CombineStrategy instance ToExpr ConstraintSource instance ToExpr CountConflicts-instance ToExpr DebugInfoLevel-instance ToExpr FlagAssignment-instance ToExpr FlagName where toExpr = defaultExprViaShow-instance ToExpr HaddockTarget+instance ToExpr FineGrainedConflicts instance ToExpr IndependentGoals-instance ToExpr IndexState instance ToExpr InstallMethod+instance ToExpr InstallOutcome+instance ToExpr LocalRepo instance ToExpr MinimizeConflictSet instance ToExpr OnlyConstrained-instance ToExpr OptimisationLevel instance ToExpr OptionalStanza+instance ToExpr Outcome instance ToExpr OverwritePolicy instance ToExpr PackageConfig-instance ToExpr PackageIdentifier-instance ToExpr PackageName where toExpr = defaultExprViaShow instance ToExpr PackageProperty-instance ToExpr PackageVersionConstraint-instance ToExpr PathComponent-instance ToExpr PathTemplate-instance ToExpr PathTemplateVariable instance ToExpr PreSolver-instance ToExpr ProfDetailLevel instance ToExpr ProjectConfig instance ToExpr ProjectConfigBuildOnly instance ToExpr ProjectConfigProvenance instance ToExpr ProjectConfigShared instance ToExpr RelaxDepMod+instance ToExpr RelaxDeps instance ToExpr RelaxDepScope instance ToExpr RelaxDepSubject-instance ToExpr RelaxDeps instance ToExpr RelaxedDep instance ToExpr RemoteRepo instance ToExpr ReorderGoals-instance ToExpr RepoKind-instance ToExpr RepoType+instance ToExpr RepoIndexState+instance ToExpr RepoName instance ToExpr ReportLevel-instance ToExpr ShortText-instance ToExpr SourceRepo-instance ToExpr (f FilePath) => ToExpr (SourceRepositoryPackage f) instance ToExpr StrongFlags-instance ToExpr TestShowDetails instance ToExpr Timestamp-instance ToExpr URI-instance ToExpr URIAuth+instance ToExpr TotalIndexState instance ToExpr UserConstraint instance ToExpr UserConstraintScope instance ToExpr UserQualifier-instance ToExpr Verbosity-instance ToExpr VerbosityFlag-instance ToExpr VerbosityLevel-instance ToExpr Version where toExpr = defaultExprViaShow-instance ToExpr VersionRange instance ToExpr WriteGhcEnvironmentFilesPolicy++instance ToExpr URI+instance ToExpr URIAuth
cabal/cabal-install/tests/UnitTests/Distribution/Client/VCS.hs view
@@ -7,7 +7,7 @@ ( execRebuild ) import Distribution.Simple.Program import Distribution.Verbosity as Verbosity-import Distribution.Client.SourceRepo (SourceRepositoryPackage (..), SourceRepoProxy)+import Distribution.Client.Types.SourceRepo (SourceRepositoryPackage (..), SourceRepoProxy) import Data.List import Data.Tuple@@ -47,29 +47,26 @@ -- tests :: MTimeChange -> [TestTree] tests mtimeChange =- [ testGroup "check VCS test framework" $- [ testProperty "git" prop_framework_git- ] ++- [ testProperty "darcs" (prop_framework_darcs mtimeChange)- | enableDarcsTests+ [ testGroup "git"+ [ testProperty "check VCS test framework" prop_framework_git+ , testProperty "cloneSourceRepo" prop_cloneRepo_git+ , testProperty "syncSourceRepos" prop_syncRepos_git ]- , testGroup "cloneSourceRepo" $- [ testProperty "git" prop_cloneRepo_git- ] ++- [ testProperty "darcs" (prop_cloneRepo_darcs mtimeChange)- | enableDarcsTests++ -- for the moment they're not yet working+ , testGroup "darcs" $ const []+ [ testProperty "check VCS test framework" $ prop_framework_darcs mtimeChange+ , testProperty "cloneSourceRepo" $ prop_cloneRepo_darcs mtimeChange+ , testProperty "syncSourceRepos" $ prop_syncRepos_darcs mtimeChange ]- , testGroup "syncSourceRepos" $- [ testProperty "git" prop_syncRepos_git- ] ++- [ testProperty "darcs" (prop_syncRepos_darcs mtimeChange)- | enableDarcsTests++ , testGroup "pijul" $ const []+ [ testProperty "check VCS test framework" prop_framework_pijul+ , testProperty "cloneSourceRepo" prop_cloneRepo_pijul+ , testProperty "syncSourceRepos" prop_syncRepos_pijul ]- ]- where- -- for the moment they're not yet working- enableDarcsTests = False + ] prop_framework_git :: BranchingRepoRecipe -> Property prop_framework_git =@@ -83,6 +80,12 @@ . prop_framework vcsDarcs (vcsTestDriverDarcs mtimeChange) . WithoutBranchingSupport +prop_framework_pijul :: BranchingRepoRecipe -> Property+prop_framework_pijul =+ ioProperty+ . prop_framework vcsPijul vcsTestDriverPijul+ . WithBranchingSupport+ prop_cloneRepo_git :: BranchingRepoRecipe -> Property prop_cloneRepo_git = ioProperty@@ -96,6 +99,12 @@ . prop_cloneRepo vcsDarcs (vcsTestDriverDarcs mtimeChange) . WithoutBranchingSupport +prop_cloneRepo_pijul :: BranchingRepoRecipe -> Property+prop_cloneRepo_pijul =+ ioProperty+ . prop_cloneRepo vcsPijul vcsTestDriverPijul+ . WithBranchingSupport+ prop_syncRepos_git :: RepoDirSet -> SyncTargetIterations -> PrngSeed -> BranchingRepoRecipe -> Property prop_syncRepos_git destRepoDirs syncTargetSetIterations seed =@@ -113,6 +122,13 @@ destRepoDirs syncTargetSetIterations seed . WithoutBranchingSupport +prop_syncRepos_pijul :: RepoDirSet -> SyncTargetIterations -> PrngSeed+ -> BranchingRepoRecipe -> Property+prop_syncRepos_pijul destRepoDirs syncTargetSetIterations seed =+ ioProperty+ . prop_syncRepos vcsPijul vcsTestDriverPijul+ destRepoDirs syncTargetSetIterations seed+ . WithBranchingSupport -- ------------------------------------------------------------ -- * General test setup@@ -693,3 +709,47 @@ } darcs = runProgramInvocation verbosity . darcsInvocation ++vcsTestDriverPijul :: Verbosity -> VCS ConfiguredProgram+ -> FilePath -> VCSTestDriver+vcsTestDriverPijul verbosity vcs repoRoot =+ VCSTestDriver {+ vcsVCS = vcs++ , vcsRepoRoot = repoRoot++ , vcsIgnoreFiles = Set.empty++ , vcsInit =+ pijul $ ["init"]++ , vcsAddFile = \_ filename ->+ pijul ["add", filename]++ , vcsCommitChanges = \_state -> do+ pijul $ ["record", "-a", "-m 'a patch'"+ , "-A 'A <a@example.com>'"+ ]+ commit <- pijul' ["log"]+ let commit' = takeWhile (not . isSpace) commit+ return (Just commit')++ -- tags work differently in pijul...+ -- so this is wrong+ , vcsTagState = \_ tagname ->+ pijul ["tag", tagname]++ , vcsSwitchBranch = \_ branchname -> do+-- unless (branchname `Map.member` allBranches) $+-- pijul ["from-branch", branchname]+ pijul $ ["checkout", branchname]++ , vcsCheckoutTag = Left $ \tagname ->+ pijul $ ["checkout", tagname]+ }+ where+ gitInvocation args = (programInvocation (vcsProgram vcs) args) {+ progInvokeCwd = Just repoRoot+ }+ pijul = runProgramInvocation verbosity . gitInvocation+ pijul' = getProgramInvocationOutput verbosity . gitInvocation
cabal/cabal-install/tests/UnitTests/Distribution/Solver/Modular/DSL/TestCaseUtils.hs view
@@ -4,6 +4,7 @@ SolverTest , SolverResult(..) , maxBackjumps+ , disableFineGrainedConflicts , minimizeConflictSet , independentGoals , allowBootLibInstalls@@ -30,7 +31,6 @@ import Distribution.Solver.Compat.Prelude import Data.List (elemIndex)-import Data.Ord (comparing) -- test-framework import Test.Tasty as TF@@ -38,7 +38,6 @@ -- Cabal import qualified Distribution.PackageDescription as C-import qualified Distribution.Types.PackageName as C import Language.Haskell.Extension (Extension(..), Language(..)) import Distribution.Verbosity @@ -54,6 +53,10 @@ maxBackjumps :: Maybe Int -> SolverTest -> SolverTest maxBackjumps mbj test = test { testMaxBackjumps = mbj } +disableFineGrainedConflicts :: SolverTest -> SolverTest+disableFineGrainedConflicts test =+ test { testFineGrainedConflicts = FineGrainedConflicts False }+ minimizeConflictSet :: SolverTest -> SolverTest minimizeConflictSet test = test { testMinimizeConflictSet = MinimizeConflictSet True }@@ -105,6 +108,7 @@ , testTargets :: [String] , testResult :: SolverResult , testMaxBackjumps :: Maybe Int+ , testFineGrainedConflicts :: FineGrainedConflicts , testMinimizeConflictSet :: MinimizeConflictSet , testIndepGoals :: IndependentGoals , testAllowBootLibInstalls :: AllowBootLibInstalls@@ -201,6 +205,7 @@ , testTargets = targets , testResult = result , testMaxBackjumps = Nothing+ , testFineGrainedConflicts = FineGrainedConflicts True , testMinimizeConflictSet = MinimizeConflictSet False , testIndepGoals = IndependentGoals False , testAllowBootLibInstalls = AllowBootLibInstalls False@@ -224,8 +229,8 @@ let progress = exResolve testDb testSupportedExts testSupportedLangs testPkgConfigDb testTargets testMaxBackjumps (CountConflicts True)- testMinimizeConflictSet testIndepGoals- (ReorderGoals False) testAllowBootLibInstalls+ testFineGrainedConflicts testMinimizeConflictSet+ testIndepGoals (ReorderGoals False) testAllowBootLibInstalls testOnlyConstrained testEnableBackjumping testSolveExecutables (sortGoals <$> testGoalOrder) testConstraints testSoftConstraints testVerbosity testEnableAllTests
cabal/cabal-install/tests/UnitTests/Distribution/Solver/Modular/MemoryUsage.hs view
@@ -17,12 +17,14 @@ -- | This test solves for n packages that each have two versions. There is no -- solution, because the nth package depends on another package that doesn't fit--- its version constraint. Backjumping is disabled, so the solver must explore a--- search tree of size 2^n. It should fail if memory usage is proportional to--- the size of the tree.+-- its version constraint. Backjumping and fine grained conflicts are disabled,+-- so the solver must explore a search tree of size 2^n. It should fail if+-- memory usage is proportional to the size of the tree. basicTest :: String -> SolverTest basicTest name =- disableBackjumping $ mkTest pkgs name ["target"] anySolverFailure+ disableBackjumping $+ disableFineGrainedConflicts $+ mkTest pkgs name ["target"] anySolverFailure where n :: Int n = 18@@ -44,6 +46,7 @@ flagsTest :: String -> SolverTest flagsTest name = disableBackjumping $+ disableFineGrainedConflicts $ goalOrder orderedFlags $ mkTest pkgs name ["pkg"] anySolverFailure where n :: Int@@ -69,14 +72,16 @@ -- has a long chain of dependencies (pkg-1 through pkg-n). However, pkg-n -- depends on pkg-n+1, which doesn't exist, so there is no solution. Since each -- dependency has two versions, the solver must try 2^n combinations when--- backjumping is disabled. These combinations create large search trees under--- each of the two choices for target-setup.setup-dep. Although the choice to--- not link is disallowed by the Single Instance Restriction, the solver doesn't--- know that until it has explored (and evaluated) the whole tree under the--- choice to link. If the two trees are shared, memory usage spikes.+-- backjumping and fine grained conflicts are disabled. These combinations+-- create large search trees under each of the two choices for+-- target-setup.setup-dep. Although the choice to not link is disallowed by the+-- Single Instance Restriction, the solver doesn't know that until it has+-- explored (and evaluated) the whole tree under the choice to link. If the two+-- trees are shared, memory usage spikes. issue2899 :: String -> SolverTest issue2899 name = disableBackjumping $+ disableFineGrainedConflicts $ goalOrder goals $ mkTest pkgs name ["target"] anySolverFailure where n :: Int@@ -145,7 +150,7 @@ pkgs :: ExampleDb pkgs = [ Right $ exAv "A" 1 (dependencyTree 1)- , Right $ exAv "B" 1 [] `withExe` ExExe "exe" []+ , Right $ exAv "B" 1 [] `withExe` exExe "exe" [] ] dependencyTree :: Int -> [ExampleDependency]@@ -173,7 +178,7 @@ pkgs :: ExampleDb pkgs = [ Right $ exAv "A" 1 (dependencyTree 1)- , Right $ exAv "B" 1 [] `withExe` ExExe "exe" []+ , Right $ exAv "B" 1 [] `withExe` exExe "exe" [] ] dependencyTree :: Int -> [ExampleDependency]
cabal/cabal-install/tests/UnitTests/Distribution/Solver/Modular/QuickCheck.hs view
@@ -9,23 +9,22 @@ import Distribution.Client.Compat.Prelude import Control.Arrow ((&&&))-import Control.DeepSeq (force) import Data.Either (lefts)-import Data.Function (on) import Data.Hashable (Hashable(..)) import Data.List (groupBy, isInfixOf)-import Data.Ord (comparing) import Text.Show.Pretty (parseValue, valToStr) import Test.Tasty (TestTree)-import Test.Tasty.QuickCheck+import Test.QuickCheck (Arbitrary (..), Gen, Positive (..), frequency, oneof, shrinkList, shuffle, listOf, shrinkNothing, vectorOf, elements, sublistOf, counterexample, (===), (==>), Blind (..))+import Test.QuickCheck.Instances.Cabal () import Distribution.Types.Flag (FlagName) import Distribution.Utils.ShortText (ShortText) import Distribution.Client.Setup (defaultMaxBackjumps) +import Distribution.Types.LibraryVisibility import Distribution.Types.PackageName import Distribution.Types.UnqualComponentName @@ -57,8 +56,8 @@ let r1 = solve' mGoalOrder1 test r2 = solve' mGoalOrder2 test { testTargets = targets2 } solve' goalOrder =- solve (EnableBackjumping True) (ReorderGoals False)- (CountConflicts True) indepGoals+ solve (EnableBackjumping True) (FineGrainedConflicts True)+ (ReorderGoals False) (CountConflicts True) indepGoals (getBlind <$> goalOrder) targets = testTargets test targets2 = case targetOrder of@@ -73,8 +72,9 @@ \test reorderGoals -> let r1 = solve' (IndependentGoals False) test r2 = solve' (IndependentGoals True) test- solve' indep = solve (EnableBackjumping True) reorderGoals- (CountConflicts True) indep Nothing+ solve' indep =+ solve (EnableBackjumping True) (FineGrainedConflicts True)+ reorderGoals (CountConflicts True) indep Nothing in counterexample (showResults r1 r2) $ noneReachedBackjumpLimit [r1, r2] ==> isRight (resultPlan r1) `implies` isRight (resultPlan r2)@@ -83,29 +83,55 @@ \test reorderGoals indepGoals -> let r1 = solve' (EnableBackjumping True) test r2 = solve' (EnableBackjumping False) test- solve' enableBj = solve enableBj reorderGoals- (CountConflicts True) indepGoals Nothing+ solve' enableBj =+ solve enableBj (FineGrainedConflicts False) reorderGoals+ (CountConflicts True) indepGoals Nothing in counterexample (showResults r1 r2) $ noneReachedBackjumpLimit [r1, r2] ==> isRight (resultPlan r1) === isRight (resultPlan r2) - -- This test uses --no-count-conflicts, because the goal order used with- -- --count-conflicts depends on the total set of conflicts seen by the+ , testPropertyWithSeed "fine-grained conflicts does not affect solvability" $+ \test reorderGoals indepGoals ->+ let r1 = solve' (FineGrainedConflicts True) test+ r2 = solve' (FineGrainedConflicts False) test+ solve' fineGrainedConflicts =+ solve (EnableBackjumping True) fineGrainedConflicts+ reorderGoals (CountConflicts True) indepGoals Nothing+ in counterexample (showResults r1 r2) $+ noneReachedBackjumpLimit [r1, r2] ==>+ isRight (resultPlan r1) === isRight (resultPlan r2)++ -- The next two tests use --no-count-conflicts, because the goal order used+ -- with --count-conflicts depends on the total set of conflicts seen by the -- solver. The solver explores more of the tree and encounters more -- conflicts when it doesn't backjump. The different goal orders can lead to -- different solutions and cause the test to fail. -- TODO: Find a faster way to randomly sort goals, and then use a random- -- goal order in this test.+ -- goal order in these tests.+ , testPropertyWithSeed "backjumping does not affect the result (with static goal order)" $ \test reorderGoals indepGoals -> let r1 = solve' (EnableBackjumping True) test r2 = solve' (EnableBackjumping False) test- solve' enableBj = solve enableBj reorderGoals- (CountConflicts False) indepGoals Nothing+ solve' enableBj =+ solve enableBj (FineGrainedConflicts False) reorderGoals+ (CountConflicts False) indepGoals Nothing in counterexample (showResults r1 r2) $ noneReachedBackjumpLimit [r1, r2] ==> resultPlan r1 === resultPlan r2++ , testPropertyWithSeed+ "fine-grained conflicts does not affect the result (with static goal order)" $+ \test reorderGoals indepGoals ->+ let r1 = solve' (FineGrainedConflicts True) test+ r2 = solve' (FineGrainedConflicts False) test+ solve' fineGrainedConflicts =+ solve (EnableBackjumping True) fineGrainedConflicts+ reorderGoals (CountConflicts False) indepGoals Nothing+ in counterexample (showResults r1 r2) $+ noneReachedBackjumpLimit [r1, r2] ==>+ resultPlan r1 === resultPlan r2 ] where noneReachedBackjumpLimit :: [Result] -> Bool@@ -132,10 +158,15 @@ unVarOrdering :: Variable P.QPN -> Variable P.QPN -> Ordering } -solve :: EnableBackjumping -> ReorderGoals -> CountConflicts -> IndependentGoals+solve :: EnableBackjumping+ -> FineGrainedConflicts+ -> ReorderGoals+ -> CountConflicts+ -> IndependentGoals -> Maybe VarOrdering- -> SolverTest -> Result-solve enableBj reorder countConflicts indep goalOrder test =+ -> SolverTest+ -> Result+solve enableBj fineGrainedConflicts reorder countConflicts indep goalOrder test = let (lg, result) = runProgress $ exResolve (unTestDb (testDb test)) Nothing Nothing (pkgConfigDbFromList [])@@ -143,7 +174,8 @@ -- The backjump limit prevents individual tests from using -- too much time and memory. (Just defaultMaxBackjumps)- countConflicts (MinimizeConflictSet False) indep reorder+ countConflicts fineGrainedConflicts+ (MinimizeConflictSet False) indep reorder (AllowBootLibInstalls False) OnlyConstrainedNone enableBj (SolveExecutables True) (unVarOrdering <$> goalOrder) (testConstraints test) (testPreferences test) normal@@ -277,8 +309,8 @@ deps <- randomSubset numDeps pkgs return $ ExInst (unPN pn) (unPV v) pkgHash (map exInstHash deps) -arbitraryComponentDeps :: PN -> TestDb -> Gen (ComponentDeps [ExampleDependency])-arbitraryComponentDeps _ (TestDb []) = return $ CD.fromLibraryDeps []+arbitraryComponentDeps :: PN -> TestDb -> Gen (ComponentDeps Dependencies)+arbitraryComponentDeps _ (TestDb []) = return $ CD.fromLibraryDeps (dependencies []) arbitraryComponentDeps pn db = do -- dedupComponentNames removes components with duplicate names, for example, -- 'ComponentExe x' and 'ComponentTest x', and then CD.fromList combines@@ -288,7 +320,7 @@ return $ if isCompleteComponentDeps cds then cds else -- Add a library if the ComponentDeps isn't complete.- CD.fromLibraryDeps [] <> cds+ CD.fromLibraryDeps (dependencies []) <> cds where isValid :: Component -> Bool isValid (ComponentSubLib name) = name /= mkUnqualComponentName (unPN pn)@@ -319,14 +351,21 @@ completesPkg (ComponentFLib _) = False completesPkg ComponentSetup = False -arbitraryComponentDep :: TestDb -> Gen (ComponentDep [ExampleDependency])+arbitraryComponentDep :: TestDb -> Gen (ComponentDep Dependencies) arbitraryComponentDep db = do comp <- arbitrary deps <- case comp of ComponentSetup -> smallListOf (arbitraryExDep db SetupDep) _ -> boundedListOf 5 (arbitraryExDep db NonSetupDep)- return (comp, deps)+ return ( comp+ , Dependencies {+ depsExampleDependencies = deps + -- TODO: Test different values for visibility and buildability.+ , depsVisibility = LibraryVisibilityPublic+ , depsIsBuildable = True+ } )+ -- | Location of an 'ExampleDependency'. It determines which values are valid. data ExDepLocation = SetupDep | NonSetupDep @@ -354,8 +393,8 @@ arbitraryDeps :: TestDb -> Gen Dependencies arbitraryDeps db = frequency- [ (1, return NotBuildable)- , (20, Buildable <$> smallListOf (arbitraryExDep db NonSetupDep))+ [ (1, return unbuildableDependencies)+ , (20, dependencies <$> smallListOf (arbitraryExDep db NonSetupDep)) ] arbitraryFlagName :: Gen String@@ -399,27 +438,27 @@ shrink (IndependentGoals indep) = [IndependentGoals False | indep] -instance Arbitrary UnqualComponentName where- -- The "component-" prefix prevents component names and build-depends- -- dependency names from overlapping.- -- TODO: Remove the prefix once the QuickCheck tests support dependencies on- -- internal libraries.- arbitrary =- mkUnqualComponentName <$> (\c -> "component-" ++ [c]) <$> elements "ABC"- instance Arbitrary Component where arbitrary = oneof [ return ComponentLib- , ComponentSubLib <$> arbitrary- , ComponentExe <$> arbitrary- , ComponentFLib <$> arbitrary- , ComponentTest <$> arbitrary- , ComponentBench <$> arbitrary+ , ComponentSubLib <$> arbitraryUQN+ , ComponentExe <$> arbitraryUQN+ , ComponentFLib <$> arbitraryUQN+ , ComponentTest <$> arbitraryUQN+ , ComponentBench <$> arbitraryUQN , return ComponentSetup ] shrink ComponentLib = [] shrink _ = [ComponentLib] +-- The "component-" prefix prevents component names and build-depends+-- dependency names from overlapping.+-- TODO: Remove the prefix once the QuickCheck tests support dependencies on+-- internal libraries.+arbitraryUQN :: Gen UnqualComponentName+arbitraryUQN =+ mkUnqualComponentName <$> (\c -> "component-" ++ [c]) <$> elements "ABC"+ instance Arbitrary ExampleInstalled where arbitrary = error "arbitrary not implemented: ExampleInstalled" @@ -443,19 +482,18 @@ shrink (ExFix "base" _) = [] -- preserve bounds on base shrink (ExFix pn _) = [ExAny pn] shrink (ExFlagged flag th el) =- deps th ++ deps el+ depsExampleDependencies th ++ depsExampleDependencies el ++ [ExFlagged flag th' el | th' <- shrink th] ++ [ExFlagged flag th el' | el' <- shrink el]- where- deps NotBuildable = []- deps (Buildable ds) = ds shrink dep = error $ "Dependency not handled: " ++ show dep instance Arbitrary Dependencies where arbitrary = error "arbitrary not implemented: Dependencies" - shrink NotBuildable = [Buildable []]- shrink (Buildable deps) = map Buildable (shrink deps)+ shrink deps =+ [ deps { depsVisibility = v } | v <- shrink $ depsVisibility deps ]+ ++ [ deps { depsIsBuildable = b } | b <- shrink $ depsIsBuildable deps ]+ ++ [ deps { depsExampleDependencies = ds } | ds <- shrink $ depsExampleDependencies deps ] instance Arbitrary ExConstraint where arbitrary = error "arbitrary not implemented: ExConstraint"@@ -478,11 +516,6 @@ shrink BenchStanzas = [TestStanzas] shrink TestStanzas = []--instance Arbitrary VersionRange where- arbitrary = error "arbitrary not implemented: VersionRange"-- shrink vr = [noVersion | vr /= noVersion] -- Randomly sorts solver variables using 'hash'. -- TODO: Sorting goals with this function is very slow.
cabal/cabal-install/tests/UnitTests/Distribution/Solver/Modular/Solver.hs view
@@ -281,23 +281,79 @@ , runTest $ mkTest dbBJ7 "bj7" ["A"] (solverSuccess [("A", 1), ("B", 1), ("C", 1)]) , runTest $ indep $ mkTest dbBJ8 "bj8" ["A", "B"] (solverSuccess [("A", 1), ("B", 1), ("C", 1)]) ]- , testGroup "library dependencies" [- let db = [Right $ exAvNoLibrary "A" 1 `withExe` ExExe "exe" []]+ , testGroup "main library dependencies" [+ let db = [Right $ exAvNoLibrary "A" 1 `withExe` exExe "exe" []] in runTest $ mkTest db "install build target without a library" ["A"] $ solverSuccess [("A", 1)] , let db = [ Right $ exAv "A" 1 [ExAny "B"]- , Right $ exAvNoLibrary "B" 1 `withExe` ExExe "exe" [] ]+ , Right $ exAvNoLibrary "B" 1 `withExe` exExe "exe" [] ] in runTest $ mkTest db "reject build-depends dependency with no library" ["A"] $ solverFailure (isInfixOf "rejecting: B-1.0.0 (does not contain library, which is required by A)") - , let exe = ExExe "exe" []+ , let exe = exExe "exe" [] db = [ Right $ exAv "A" 1 [ExAny "B"] , Right $ exAvNoLibrary "B" 2 `withExe` exe , Right $ exAv "B" 1 [] `withExe` exe ] in runTest $ mkTest db "choose version of build-depends dependency that has a library" ["A"] $ solverSuccess [("A", 1), ("B", 1)] ]+ , testGroup "sub-library dependencies" [+ let db = [ Right $ exAv "A" 1 [ExSubLibAny "B" "sub-lib"]+ , Right $ exAv "B" 1 [] ]+ in runTest $+ mkTest db "reject package that is missing required sub-library" ["A"] $+ solverFailure $ isInfixOf $+ "rejecting: B-1.0.0 (does not contain library 'sub-lib', which is required by A)"++ , let db = [ Right $ exAv "A" 1 [ExSubLibAny "B" "sub-lib"]+ , Right $ exAvNoLibrary "B" 1 `withSubLibrary` exSubLib "sub-lib" [] ]+ in runTest $+ mkTest db "reject package with private but required sub-library" ["A"] $+ solverFailure $ isInfixOf $+ "rejecting: B-1.0.0 (library 'sub-lib' is private, but it is required by A)"++ , let db = [ Right $ exAv "A" 1 [ExSubLibAny "B" "sub-lib"]+ , Right $ exAvNoLibrary "B" 1+ `withSubLibrary` exSubLib "sub-lib" [ExFlagged "make-lib-private" (dependencies []) publicDependencies] ]+ in runTest $ constraints [ExFlagConstraint (ScopeAnyQualifier "B") "make-lib-private" True] $+ mkTest db "reject package with sub-library made private by flag constraint" ["A"] $+ solverFailure $ isInfixOf $+ "rejecting: B-1.0.0 (library 'sub-lib' is private, but it is required by A)"++ , let db = [ Right $ exAv "A" 1 [ExSubLibAny "B" "sub-lib"]+ , Right $ exAvNoLibrary "B" 1+ `withSubLibrary` exSubLib "sub-lib" [ExFlagged "make-lib-private" (dependencies []) publicDependencies] ]+ in runTest $+ mkTest db "treat sub-library as visible even though flag choice could make it private" ["A"] $+ solverSuccess [("A", 1), ("B", 1)]++ , let db = [ Right $ exAv "A" 1 [ExAny "B"]+ , Right $ exAv "B" 1 [] `withSubLibrary` exSubLib "sub-lib" []+ , Right $ exAv "C" 1 [ExSubLibAny "B" "sub-lib"] ]+ goals :: [ExampleVar]+ goals = [+ P QualNone "A"+ , P QualNone "B"+ , P QualNone "C"+ ]+ in runTest $ goalOrder goals $+ mkTest db "reject package that requires a private sub-library" ["A", "C"] $+ solverFailure $ isInfixOf $+ "rejecting: C-1.0.0 (requires library 'sub-lib' from B, but the component is private)"++ , let db = [ Right $ exAv "A" 1 [ExSubLibAny "B" "sub-lib-v1"]+ , Right $ exAv "B" 2 [] `withSubLibrary` ExSubLib "sub-lib-v2" publicDependencies+ , Right $ exAv "B" 1 [] `withSubLibrary` ExSubLib "sub-lib-v1" publicDependencies ]+ in runTest $ mkTest db "choose version of package containing correct sub-library" ["A"] $+ solverSuccess [("A", 1), ("B", 1)]++ , let db = [ Right $ exAv "A" 1 [ExSubLibAny "B" "sub-lib"]+ , Right $ exAv "B" 2 [] `withSubLibrary` ExSubLib "sub-lib" (dependencies [])+ , Right $ exAv "B" 1 [] `withSubLibrary` ExSubLib "sub-lib" publicDependencies ]+ in runTest $ mkTest db "choose version of package with public sub-library" ["A"] $+ solverSuccess [("A", 1), ("B", 1)]+ ] -- build-tool-depends dependencies , testGroup "build-tool-depends" [ runTest $ mkTest dbBuildTools "simple exe dependency" ["A"] (solverSuccess [("A", 1), ("bt-pkg", 2)])@@ -331,7 +387,7 @@ -- and an executable conflict apply to the same package version. "[__1] rejecting: H:bt-pkg:exe.bt-pkg-4.0.0 (conflict: H => H:bt-pkg:exe.bt-pkg (exe exe1)==3.0.0)\n" ++ "[__1] rejecting: H:bt-pkg:exe.bt-pkg-3.0.0 (does not contain executable 'exe1', which is required by H)\n"- ++ "[__1] rejecting: H:bt-pkg:exe.bt-pkg-2.0.0, H:bt-pkg:exe.bt-pkg-1.0.0 (conflict: H => H:bt-pkg:exe.bt-pkg (exe exe1)==3.0.0)"+ ++ "[__1] rejecting: H:bt-pkg:exe.bt-pkg-2.0.0 (conflict: H => H:bt-pkg:exe.bt-pkg (exe exe1)==3.0.0)" , runTest $ chooseExeAfterBuildToolsPackage True "choose exe after choosing its package - success" @@ -370,19 +426,19 @@ , testGroup "Components that are unbuildable in the current environment" $ let flagConstraint = ExFlagConstraint . ScopeAnyQualifier in [- let db = [ Right $ exAv "A" 1 [ExFlagged "build-lib" (Buildable []) NotBuildable] ]+ let db = [ Right $ exAv "A" 1 [ExFlagged "build-lib" (dependencies []) unbuildableDependencies] ] in runTest $ constraints [flagConstraint "A" "build-lib" False] $ mkTest db "install unbuildable library" ["A"] $ solverSuccess [("A", 1)] , let db = [ Right $ exAvNoLibrary "A" 1- `withExe` ExExe "exe" [ExFlagged "build-exe" (Buildable []) NotBuildable] ]+ `withExe` exExe "exe" [ExFlagged "build-exe" (dependencies []) unbuildableDependencies] ] in runTest $ constraints [flagConstraint "A" "build-exe" False] $ mkTest db "install unbuildable exe" ["A"] $ solverSuccess [("A", 1)] , let db = [ Right $ exAv "A" 1 [ExAny "B"]- , Right $ exAv "B" 1 [ExFlagged "build-lib" (Buildable []) NotBuildable] ]+ , Right $ exAv "B" 1 [ExFlagged "build-lib" (dependencies []) unbuildableDependencies] ] in runTest $ constraints [flagConstraint "B" "build-lib" False] $ mkTest db "reject library dependency with unbuildable library" ["A"] $ solverFailure $ isInfixOf $@@ -390,15 +446,15 @@ ++ "current environment, but it is required by A)" , let db = [ Right $ exAv "A" 1 [ExBuildToolAny "B" "bt"]- , Right $ exAv "B" 1 [ExFlagged "build-lib" (Buildable []) NotBuildable]- `withExe` ExExe "bt" [] ]+ , Right $ exAv "B" 1 [ExFlagged "build-lib" (dependencies []) unbuildableDependencies]+ `withExe` exExe "bt" [] ] in runTest $ constraints [flagConstraint "B" "build-lib" False] $ mkTest db "allow build-tool dependency with unbuildable library" ["A"] $ solverSuccess [("A", 1), ("B", 1)] , let db = [ Right $ exAv "A" 1 [ExBuildToolAny "B" "bt"] , Right $ exAv "B" 1 []- `withExe` ExExe "bt" [ExFlagged "build-exe" (Buildable []) NotBuildable] ]+ `withExe` exExe "bt" [ExFlagged "build-exe" (dependencies []) unbuildableDependencies] ] in runTest $ constraints [flagConstraint "B" "build-exe" False] $ mkTest db "reject build-tool dependency with unbuildable exe" ["A"] $ solverFailure $ isInfixOf $@@ -408,6 +464,266 @@ chooseUnbuildableExeAfterBuildToolsPackage "choose unbuildable exe after choosing its package" ]++ , testGroup "--fine-grained-conflicts" [++ -- Skipping a version because of a problematic dependency:+ --+ -- When the solver explores A-4, it finds that it cannot satisfy B's+ -- dependencies. This allows the solver to skip the subsequent+ -- versions of A that also depend on B.+ runTest $+ let db = [+ Right $ exAv "A" 4 [ExAny "B"]+ , Right $ exAv "A" 3 [ExAny "B"]+ , Right $ exAv "A" 2 [ExAny "B"]+ , Right $ exAv "A" 1 []+ , Right $ exAv "B" 2 [ExAny "unknown1"]+ , Right $ exAv "B" 1 [ExAny "unknown2"]+ ]+ msg = [+ "[__0] trying: A-4.0.0 (user goal)"+ , "[__1] trying: B-2.0.0 (dependency of A)"+ , "[__2] unknown package: unknown1 (dependency of B)"+ , "[__2] fail (backjumping, conflict set: B, unknown1)"+ , "[__1] trying: B-1.0.0"+ , "[__2] unknown package: unknown2 (dependency of B)"+ , "[__2] fail (backjumping, conflict set: B, unknown2)"+ , "[__1] fail (backjumping, conflict set: A, B, unknown1, unknown2)"+ , "[__0] skipping: A-3.0.0, A-2.0.0 (has the same characteristics that "+ ++ "caused the previous version to fail: depends on 'B')"+ , "[__0] trying: A-1.0.0"+ , "[__1] done"+ ]+ in setVerbose $+ mkTest db "skip version due to problematic dependency" ["A"] $+ SolverResult (isInfixOf msg) $ Right [("A", 1)]++ , -- Skipping a version because of a restrictive constraint on a+ -- dependency:+ --+ -- The solver rejects A-4 because its constraint on B excludes B-1.+ -- Then the solver is able to skip A-3 and A-2 because they also+ -- exclude B-1, even though they don't have the exact same constraints+ -- on B.+ runTest $+ let db = [+ Right $ exAv "A" 4 [ExFix "B" 14]+ , Right $ exAv "A" 3 [ExFix "B" 13]+ , Right $ exAv "A" 2 [ExFix "B" 12]+ , Right $ exAv "A" 1 [ExFix "B" 11]+ , Right $ exAv "B" 11 []+ ]+ msg = [+ "[__0] trying: A-4.0.0 (user goal)"+ , "[__1] next goal: B (dependency of A)"+ , "[__1] rejecting: B-11.0.0 (conflict: A => B==14.0.0)"+ , "[__1] fail (backjumping, conflict set: A, B)"+ , "[__0] skipping: A-3.0.0, A-2.0.0 (has the same characteristics that "+ ++ "caused the previous version to fail: depends on 'B' but excludes "+ ++ "version 11.0.0)"+ , "[__0] trying: A-1.0.0"+ , "[__1] next goal: B (dependency of A)"+ , "[__1] trying: B-11.0.0"+ , "[__2] done"+ ]+ in setVerbose $+ mkTest db "skip version due to restrictive constraint on its dependency" ["A"] $+ SolverResult (isInfixOf msg) $ Right [("A", 1), ("B", 11)]++ , -- This test tests the case where the solver chooses a version for one+ -- package, B, before choosing a version for one of its reverse+ -- dependencies, C. While the solver is exploring the subtree rooted+ -- at B-3, it finds that C-2's dependency on B conflicts with B-3.+ -- Then the solver is able to skip C-1, because it also excludes B-3.+ --+ -- --fine-grained-conflicts could have a benefit in this case even+ -- though the solver would have found the conflict between B-3 and C-1+ -- immediately after trying C-1 anyway. It prevents C-1 from+ -- introducing any other conflicts which could increase the size of+ -- the conflict set.+ runTest $+ let db = [+ Right $ exAv "A" 1 [ExAny "B", ExAny "C"]+ , Right $ exAv "B" 3 []+ , Right $ exAv "B" 2 []+ , Right $ exAv "B" 1 []+ , Right $ exAv "C" 2 [ExFix "B" 2]+ , Right $ exAv "C" 1 [ExFix "B" 1]+ ]+ goals = [P QualNone pkg | pkg <- ["A", "B", "C"]]+ expectedMsg = [+ "[__0] trying: A-1.0.0 (user goal)"+ , "[__1] trying: B-3.0.0 (dependency of A)"+ , "[__2] next goal: C (dependency of A)"+ , "[__2] rejecting: C-2.0.0 (conflict: B==3.0.0, C => B==2.0.0)"+ , "[__2] skipping: C-1.0.0 (has the same characteristics that caused the "+ ++ "previous version to fail: excludes 'B' version 3.0.0)"+ , "[__2] fail (backjumping, conflict set: A, B, C)"+ , "[__1] trying: B-2.0.0"+ , "[__2] next goal: C (dependency of A)"+ , "[__2] trying: C-2.0.0"+ , "[__3] done"+ ]+ in setVerbose $ goalOrder goals $+ mkTest db "skip version that excludes dependency that was already chosen" ["A"] $+ SolverResult (isInfixOf expectedMsg) $ Right [("A", 1), ("B", 2), ("C", 2)]++ , -- This test tests how the solver merges conflicts when it has+ -- multiple reasons to add a variable to the conflict set. In this+ -- case, package A conflicts with B and C. The solver should take the+ -- union of the conflicts and then only skip a version if it does not+ -- resolve any of the conflicts.+ --+ -- The solver rejects A-3 because it can't find consistent versions for+ -- its two dependencies, B and C. Then it skips A-2 because A-2 also+ -- depends on B and C. This test ensures that the solver considers+ -- A-1 even though A-1 only resolves one of the conflicts (A-1 removes+ -- the dependency on C).+ runTest $+ let db = [+ Right $ exAv "A" 3 [ExAny "B", ExAny "C"]+ , Right $ exAv "A" 2 [ExAny "B", ExAny "C"]+ , Right $ exAv "A" 1 [ExAny "B"]+ , Right $ exAv "B" 1 [ExFix "D" 1]+ , Right $ exAv "C" 1 [ExFix "D" 2]+ , Right $ exAv "D" 1 []+ , Right $ exAv "D" 2 []+ ]+ goals = [P QualNone pkg | pkg <- ["A", "B", "C", "D"]]+ msg = [+ "[__0] trying: A-3.0.0 (user goal)"+ , "[__1] trying: B-1.0.0 (dependency of A)"+ , "[__2] trying: C-1.0.0 (dependency of A)"+ , "[__3] next goal: D (dependency of B)"+ , "[__3] rejecting: D-2.0.0 (conflict: B => D==1.0.0)"+ , "[__3] rejecting: D-1.0.0 (conflict: C => D==2.0.0)"+ , "[__3] fail (backjumping, conflict set: B, C, D)"+ , "[__2] fail (backjumping, conflict set: A, B, C, D)"+ , "[__1] fail (backjumping, conflict set: A, B, C, D)"+ , "[__0] skipping: A-2.0.0 (has the same characteristics that caused the "+ ++ "previous version to fail: depends on 'B'; depends on 'C')"+ , "[__0] trying: A-1.0.0"+ , "[__1] trying: B-1.0.0 (dependency of A)"+ , "[__2] next goal: D (dependency of B)"+ , "[__2] rejecting: D-2.0.0 (conflict: B => D==1.0.0)"+ , "[__2] trying: D-1.0.0"+ , "[__3] done"+ ]+ in setVerbose $ goalOrder goals $+ mkTest db "only skip a version if it resolves none of the previous conflicts" ["A"] $+ SolverResult (isInfixOf msg) $ Right [("A", 1), ("B", 1), ("D", 1)]++ , -- This test ensures that the solver log doesn't show all conflicts+ -- that the solver encountered in a subtree. The solver should only+ -- show the conflicts that are contained in the current conflict set.+ --+ -- The goal order forces the solver to try A-4, encounter a conflict+ -- with B-2, try B-1, and then try C. A-4 conflicts with the only+ -- version of C, so the solver backjumps with a conflict set of+ -- {A, C}. When the solver skips the next version of A, the log should+ -- mention the conflict with C but not B.+ runTest $+ let db = [+ Right $ exAv "A" 4 [ExFix "B" 1, ExFix "C" 1]+ , Right $ exAv "A" 3 [ExFix "B" 1, ExFix "C" 1]+ , Right $ exAv "A" 2 [ExFix "C" 1]+ , Right $ exAv "A" 1 [ExFix "C" 2]+ , Right $ exAv "B" 2 []+ , Right $ exAv "B" 1 []+ , Right $ exAv "C" 2 []+ ]+ goals = [P QualNone pkg | pkg <- ["A", "B", "C"]]+ msg = [+ "[__0] trying: A-4.0.0 (user goal)"+ , "[__1] next goal: B (dependency of A)"+ , "[__1] rejecting: B-2.0.0 (conflict: A => B==1.0.0)"+ , "[__1] trying: B-1.0.0"+ , "[__2] next goal: C (dependency of A)"+ , "[__2] rejecting: C-2.0.0 (conflict: A => C==1.0.0)"+ , "[__2] fail (backjumping, conflict set: A, C)"+ , "[__0] skipping: A-3.0.0, A-2.0.0 (has the same characteristics that caused the "+ ++ "previous version to fail: depends on 'C' but excludes version 2.0.0)"+ , "[__0] trying: A-1.0.0"+ , "[__1] next goal: C (dependency of A)"+ , "[__1] trying: C-2.0.0"+ , "[__2] done"+ ]+ in setVerbose $ goalOrder goals $+ mkTest db "don't show conflicts that aren't part of the conflict set" ["A"] $+ SolverResult (isInfixOf msg) $ Right [("A", 1), ("C", 2)]++ , -- Tests that the conflict set is properly updated when a version is+ -- skipped due to being excluded by one of its reverse dependencies'+ -- constraints.+ runTest $+ let db = [+ Right $ exAv "A" 2 [ExFix "B" 3]+ , Right $ exAv "A" 1 [ExFix "B" 1]+ , Right $ exAv "B" 2 []+ , Right $ exAv "B" 1 []+ ]+ msg = [+ "[__0] trying: A-2.0.0 (user goal)"+ , "[__1] next goal: B (dependency of A)"++ -- During this step, the solver adds A and B to the+ -- conflict set, with the details of each package's+ -- conflict:+ --+ -- A: A's constraint rejected B-2.+ -- B: B was rejected by A's B==3 constraint+ , "[__1] rejecting: B-2.0.0 (conflict: A => B==3.0.0)"++ -- When the solver skips B-1, it cannot simply reuse the+ -- previous conflict set. It also needs to update A's+ -- entry to say that A also rejected B-1. Otherwise, the+ -- solver wouldn't know that A-1 could resolve one of+ -- the conflicts encountered while exploring A-2. The+ -- solver would skip A-1, even though it leads to the+ -- solution.+ , "[__1] skipping: B-1.0.0 (has the same characteristics that caused "+ ++ "the previous version to fail: excluded by constraint '==3.0.0' from 'A')"++ , "[__1] fail (backjumping, conflict set: A, B)"+ , "[__0] trying: A-1.0.0"+ , "[__1] next goal: B (dependency of A)"+ , "[__1] rejecting: B-2.0.0 (conflict: A => B==1.0.0)"+ , "[__1] trying: B-1.0.0"+ , "[__2] done"+ ]+ in setVerbose $+ mkTest db "update conflict set after skipping version - 1" ["A"] $+ SolverResult (isInfixOf msg) $ Right [("A", 1), ("B", 1)]++ , -- Tests that the conflict set is properly updated when a version is+ -- skipped due to excluding a version of one of its dependencies.+ -- This test is similar the previous one, with the goal order reversed.+ runTest $+ let db = [+ Right $ exAv "A" 2 []+ , Right $ exAv "A" 1 []+ , Right $ exAv "B" 2 [ExFix "A" 3]+ , Right $ exAv "B" 1 [ExFix "A" 1]+ ]+ goals = [P QualNone pkg | pkg <- ["A", "B"]]+ msg = [+ "[__0] trying: A-2.0.0 (user goal)"+ , "[__1] next goal: B (user goal)"+ , "[__1] rejecting: B-2.0.0 (conflict: A==2.0.0, B => A==3.0.0)"+ , "[__1] skipping: B-1.0.0 (has the same characteristics that caused "+ ++ "the previous version to fail: excludes 'A' version 2.0.0)"+ , "[__1] fail (backjumping, conflict set: A, B)"+ , "[__0] trying: A-1.0.0"+ , "[__1] next goal: B (user goal)"+ , "[__1] rejecting: B-2.0.0 (conflict: A==1.0.0, B => A==3.0.0)"+ , "[__1] trying: B-1.0.0"+ , "[__2] done"+ ]+ in setVerbose $ goalOrder goals $+ mkTest db "update conflict set after skipping version - 2" ["A", "B"] $+ SolverResult (isInfixOf msg) $ Right [("A", 1), ("B", 1)]+ ] -- Tests for the contents of the solver's log , testGroup "Solver log" [ -- See issue #3203. The solver should only choose a version for A once.@@ -428,16 +744,15 @@ , testSummarizedLog "show conflicts from final conflict set after exhaustive search" Nothing $ "Could not resolve dependencies:\n" ++ "[__0] trying: A-1.0.0 (user goal)\n"- ++ "[__1] unknown package: D (dependency of A)\n"- ++ "[__1] fail (backjumping, conflict set: A, D)\n"+ ++ "[__1] unknown package: F (dependency of A)\n"+ ++ "[__1] fail (backjumping, conflict set: A, F)\n" ++ "After searching the rest of the dependency tree exhaustively, "- ++ "these were the goals I've had most trouble fulfilling: A, D"+ ++ "these were the goals I've had most trouble fulfilling: A, F" , testSummarizedLog "show first conflicts after inexhaustive search" (Just 3) $ "Could not resolve dependencies:\n" ++ "[__0] trying: A-1.0.0 (user goal)\n" ++ "[__1] trying: B-3.0.0 (dependency of A)\n"- ++ "[__2] next goal: C (dependency of B)\n"- ++ "[__2] rejecting: C-1.0.0 (conflict: B => C==3.0.0)\n"+ ++ "[__2] unknown package: C (dependency of B)\n" ++ "[__2] fail (backjumping, conflict set: B, C)\n" ++ "Backjump limit reached (currently 3, change with --max-backjumps " ++ "or try to run with --reorder-goals).\n"@@ -449,6 +764,18 @@ "minimize conflict set with --minimize-conflict-set" , testNoMinimizeConflictSet "show original conflict set with --no-minimize-conflict-set"+ , runTest $+ let db = [ Right $ exAv "my-package" 1 [ExFix "other-package" 3]+ , Left $ exInst "other-package" 2 "other-package-2.0.0" []]+ msg = "rejecting: other-package-2.0.0/installed-2.0.0"+ in mkTest db "show full installed package version (issue #5892)" ["my-package"] $+ solverFailure (isInfixOf msg)+ , runTest $+ let db = [ Right $ exAv "my-package" 1 [ExFix "other-package" 3]+ , Left $ exInst "other-package" 2 "other-package-AbCdEfGhIj0123456789" [] ]+ msg = "rejecting: other-package-2.0.0/installed-AbCdEfGhIj0123456789"+ in mkTest db "show full installed package ABI hash (issue #5892)" ["my-package"] $+ solverFailure (isInfixOf msg) ] ] where@@ -603,11 +930,11 @@ Right $ exAv "A" 1 [] , Right $ exAv "A" 2 [] , Right $ exAv "B" 1 []- , Right $ exAv "C" 1 [] `withTest` ExTest "testC" [ExAny "A"]- , Right $ exAv "D" 1 [] `withTest` ExTest "testD" [ExFix "B" 2]- , Right $ exAv "E" 1 [ExFix "A" 1] `withTest` ExTest "testE" [ExAny "A"]- , Right $ exAv "F" 1 [ExFix "A" 1] `withTest` ExTest "testF" [ExFix "A" 2]- , Right $ exAv "G" 1 [ExFix "A" 2] `withTest` ExTest "testG" [ExAny "A"]+ , Right $ exAv "C" 1 [] `withTest` exTest "testC" [ExAny "A"]+ , Right $ exAv "D" 1 [] `withTest` exTest "testD" [ExFix "B" 2]+ , Right $ exAv "E" 1 [ExFix "A" 1] `withTest` exTest "testE" [ExAny "A"]+ , Right $ exAv "F" 1 [ExFix "A" 1] `withTest` exTest "testF" [ExFix "A" 2]+ , Right $ exAv "G" 1 [ExFix "A" 2] `withTest` exTest "testG" [ExAny "A"] ] -- Now the _dependencies_ have test suites@@ -622,7 +949,7 @@ db6 = [ Right $ exAv "A" 1 [] , Right $ exAv "A" 2 []- , Right $ exAv "B" 1 [] `withTest` ExTest "testA" [ExAny "A"]+ , Right $ exAv "B" 1 [] `withTest` exTest "testA" [ExAny "A"] , Right $ exAv "C" 1 [ExFix "A" 1, ExAny "B"] , Right $ exAv "D" 1 [ExAny "B"] ]@@ -644,7 +971,7 @@ db = [ Right $ exAv "A" 1 [] `withTest`- ExTest "test" [exFlagged "flag" [ExFix "B" 2] []]+ exTest "test" [exFlagged "flag" [ExFix "B" 2] []] , Right $ exAv "B" 1 [] ] @@ -815,13 +1142,13 @@ dbStanzaPreferences1 :: ExampleDb dbStanzaPreferences1 = [- Right $ exAv "pkg" 1 [] `withTest` ExTest "test" [ExAny "test-dep"]+ Right $ exAv "pkg" 1 [] `withTest` exTest "test" [ExAny "test-dep"] , Right $ exAv "test-dep" 1 [] ] dbStanzaPreferences2 :: ExampleDb dbStanzaPreferences2 = [- Right $ exAv "pkg" 1 [] `withTest` ExTest "test" [ExAny "unknown"]+ Right $ exAv "pkg" 1 [] `withTest` exTest "test" [ExAny "unknown"] ] -- | This is a test case for a bug in stanza preferences (#3930). The solver@@ -837,7 +1164,7 @@ [] [ExAny "unknown-pkg1"]] `withTest`- ExTest "test" [exFlagged "flag"+ exTest "test" [exFlagged "flag" [ExAny "unknown-pkg2"] []] goals = [@@ -1007,8 +1334,8 @@ where db :: ExampleDb db = [- Right $ exAv "A" 1 [ExAny "C"] `withTest` ExTest "test" [ExFix "D" 1]- , Right $ exAv "B" 1 [ExAny "C"] `withTest` ExTest "test" [ExFix "D" 1]+ Right $ exAv "A" 1 [ExAny "C"] `withTest` exTest "test" [ExFix "D" 1]+ , Right $ exAv "B" 1 [ExAny "C"] `withTest` exTest "test" [ExFix "D" 1] , Right $ exAv "C" 1 [ExAny "D"] , Right $ exAv "D" 1 [] , Right $ exAv "D" 2 []@@ -1189,7 +1516,7 @@ db = [ Right $ exAv "A" 1 [ExFix "E" 2] , Right $ exAv "B" 1 [ExAny "D"]- , Right $ exAv "C" 1 [ExAny "D"] `withTest` ExTest "test" [ExFix "E" 1]+ , Right $ exAv "C" 1 [ExAny "D"] `withTest` exTest "test" [ExFix "E" 1] , Right $ exAv "D" 1 [ExAny "E"] , Right $ exAv "E" 1 [] , Right $ exAv "E" 2 []@@ -1346,8 +1673,8 @@ [ExAny "true-dep"] [ExAny "false-dep"]] `withExe`- ExExe "exe" [ unavailableDep- , ExFlagged "enable-exe" (Buildable []) NotBuildable ]+ exExe "exe" [ unavailableDep+ , ExFlagged "enable-exe" (dependencies []) unbuildableDependencies ] , Right $ exAv "true-dep" 1 [] , Right $ exAv "false-dep" 1 [] ]@@ -1360,15 +1687,15 @@ [ exFlagged "flag1" [ExAny "flag1-true"] [ExAny "flag1-false"] , exFlagged "flag2" [ExAny "flag2-true"] [ExAny "flag2-false"]] `withExes`- [ ExExe "exe1"+ [ exExe "exe1" [ ExAny "unknown"- , ExFlagged "flag1" (Buildable []) NotBuildable- , ExFlagged "flag2" (Buildable []) NotBuildable]- , ExExe "exe2"+ , ExFlagged "flag1" (dependencies []) unbuildableDependencies+ , ExFlagged "flag2" (dependencies []) unbuildableDependencies]+ , exExe "exe2" [ ExAny "unknown" , ExFlagged "flag1"- (Buildable [])- (Buildable [ExFlagged "flag2" NotBuildable (Buildable [])])]+ (dependencies [])+ (dependencies [ExFlagged "flag2" unbuildableDependencies (dependencies [])])] ] , Right $ exAv "flag1-true" 1 [] , Right $ exAv "flag1-false" 1 []@@ -1383,9 +1710,9 @@ , Right $ exAv "B" 1 [ExAny "unknown"] , Right $ exAv "B" 2 [] `withExe`- ExExe "exe"+ exExe "exe" [ ExAny "unknown"- , ExFlagged "disable-exe" NotBuildable (Buildable [])+ , ExFlagged "disable-exe" unbuildableDependencies (dependencies []) ] , Right $ exAv "B" 3 [ExAny "unknown"] ]@@ -1399,28 +1726,27 @@ , Right $ exAv "C" 1 [ExAny "B"] ] --- | Test for the solver's summarized log. The final conflict set is {A, D},+-- | Test for the solver's summarized log. The final conflict set is {A, F}, -- though the goal order forces the solver to find the (avoidable) conflict--- between B >= 2 and C first. When the solver reaches the backjump limit, it--- should only show the log to the first conflict. When the backjump limit is--- high enough to allow an exhaustive search, the solver should make use of the--- final conflict set to only show the conflict between A and D in the--- summarized log.+-- between B and C first. When the solver reaches the backjump limit, it should+-- only show the log to the first conflict. When the backjump limit is high+-- enough to allow an exhaustive search, the solver should make use of the final+-- conflict set to only show the conflict between A and F in the summarized log. testSummarizedLog :: String -> Maybe Int -> String -> TestTree testSummarizedLog testName mbj expectedMsg = runTest $ maxBackjumps mbj $ goalOrder goals $ mkTest db testName ["A"] $ solverFailure (== expectedMsg) where db = [- Right $ exAv "A" 1 [ExAny "B", ExAny "D"]- , Right $ exAv "B" 3 [ExFix "C" 3]- , Right $ exAv "B" 2 [ExFix "C" 2]- , Right $ exAv "B" 1 [ExAny "C"]- , Right $ exAv "C" 1 []+ Right $ exAv "A" 1 [ExAny "B", ExAny "F"]+ , Right $ exAv "B" 3 [ExAny "C"]+ , Right $ exAv "B" 2 [ExAny "D"]+ , Right $ exAv "B" 1 [ExAny "E"]+ , Right $ exAv "E" 1 [] ] goals :: [ExampleVar]- goals = [P QualNone pkg | pkg <- ["A", "B", "C", "D"]]+ goals = [P QualNone pkg | pkg <- ["A", "B", "C", "D", "E", "F"]] dbMinimizeConflictSet :: ExampleDb dbMinimizeConflictSet = [@@ -1453,9 +1779,7 @@ , "Trying to remove variable \"A\" from the conflict set." , "Failed to remove \"A\" from the conflict set. Continuing with {A, B, C, D}." , "Trying to remove variable \"B\" from the conflict set."- , "Successfully removed \"B\" from the conflict set. Continuing with {A, C, D}."- , "Trying to remove variable \"C\" from the conflict set."- , "Successfully removed \"C\" from the conflict set. Continuing with {A, D}."+ , "Successfully removed \"B\" from the conflict set. Continuing with {A, D}." , "Trying to remove variable \"D\" from the conflict set." , "Failed to remove \"D\" from the conflict set. Continuing with {A, D}." ]@@ -1467,7 +1791,7 @@ ++ "[__1] rejecting: D-1.0.0 (conflict: A => D==2.0.0)\n" ++ "[__1] fail (backjumping, conflict set: A, D)\n" ++ "After searching the rest of the dependency tree exhaustively, these "- ++ "were the goals I've had most trouble fulfilling: A (7), D (6)"+ ++ "were the goals I've had most trouble fulfilling: A (5), D (4)" goals :: [ExampleVar] goals = [P QualNone pkg | pkg <- ["A", "B", "C", "D"]]@@ -1602,17 +1926,17 @@ Right $ exAv "A" 1 [ExBuildToolAny "bt-pkg" "exe1"] , Right $ exAv "B" 1 [exFlagged "flagB" [ExAny "unknown"] [ExBuildToolAny "bt-pkg" "exe1"]]- , Right $ exAv "C" 1 [] `withTest` ExTest "testC" [ExBuildToolAny "bt-pkg" "exe1"]+ , Right $ exAv "C" 1 [] `withTest` exTest "testC" [ExBuildToolAny "bt-pkg" "exe1"] , Right $ exAv "D" 1 [ExBuildToolAny "bt-pkg" "unknown-exe"] , Right $ exAv "E" 1 [ExBuildToolAny "unknown-pkg" "exe1"] , Right $ exAv "F" 1 [exFlagged "flagF" [ExBuildToolAny "bt-pkg" "unknown-exe"] [ExAny "unknown"]]- , Right $ exAv "G" 1 [] `withTest` ExTest "testG" [ExBuildToolAny "bt-pkg" "unknown-exe"]+ , Right $ exAv "G" 1 [] `withTest` exTest "testG" [ExBuildToolAny "bt-pkg" "unknown-exe"] , Right $ exAv "H" 1 [ExBuildToolFix "bt-pkg" "exe1" 3] , Right $ exAv "bt-pkg" 4 []- , Right $ exAv "bt-pkg" 3 [] `withExe` ExExe "exe2" []- , Right $ exAv "bt-pkg" 2 [] `withExe` ExExe "exe1" []+ , Right $ exAv "bt-pkg" 3 [] `withExe` exExe "exe2" []+ , Right $ exAv "bt-pkg" 2 [] `withExe` exExe "exe1" [] , Right $ exAv "bt-pkg" 1 [] ] @@ -1656,7 +1980,7 @@ [ExAny "unknown"]] , Right $ exAv "B" 1 [] `withExes`- [ExExe exe [] | exe <- if shouldSucceed then ["exe1", "exe2"] else ["exe1"]]+ [exExe exe [] | exe <- if shouldSucceed then ["exe1", "exe2"] else ["exe1"]] ] goals :: [ExampleVar]@@ -1684,7 +2008,7 @@ , Right $ exAv "B" 1 [] `withExes` exes ] - exes = [ExExe "exe1" [], ExExe "exe2" []]+ exes = [exExe "exe1" [], exExe "exe2" []] -- | This test is similar to the failure case for -- chooseExeAfterBuildToolsPackage, except that the build tool is unbuildable@@ -1704,8 +2028,8 @@ [ExAny "unknown"]] , Right $ exAvNoLibrary "B" 1 `withExes`- [ ExExe "bt1" []- , ExExe "bt2" [ExFlagged "build-bt2" (Buildable []) NotBuildable]+ [ exExe "bt1" []+ , exExe "bt2" [ExFlagged "build-bt2" (dependencies []) unbuildableDependencies] ] ] @@ -1721,7 +2045,7 @@ -------------------------------------------------------------------------------} dbLegacyBuildTools1 :: ExampleDb dbLegacyBuildTools1 = [- Right $ exAv "alex" 1 [] `withExe` ExExe "alex" [],+ Right $ exAv "alex" 1 [] `withExe` exExe "alex" [], Right $ exAv "A" 1 [ExLegacyBuildToolAny "alex"] ] @@ -1729,8 +2053,8 @@ -- package and the executable. This db has no solution. dbLegacyBuildTools2 :: ExampleDb dbLegacyBuildTools2 = [- Right $ exAv "alex" 1 [] `withExe` ExExe "other-exe" [],- Right $ exAv "other-package" 1 [] `withExe` ExExe "alex" [],+ Right $ exAv "alex" 1 [] `withExe` exExe "other-exe" [],+ Right $ exAv "other-package" 1 [] `withExe` exExe "alex" [], Right $ exAv "A" 1 [ExLegacyBuildToolAny "alex"] ] @@ -1744,8 +2068,8 @@ -- Test that we can solve for different versions of executables dbLegacyBuildTools4 :: ExampleDb dbLegacyBuildTools4 = [- Right $ exAv "alex" 1 [] `withExe` ExExe "alex" [],- Right $ exAv "alex" 2 [] `withExe` ExExe "alex" [],+ Right $ exAv "alex" 1 [] `withExe` exExe "alex" [],+ Right $ exAv "alex" 2 [] `withExe` exExe "alex" [], Right $ exAv "A" 1 [ExLegacyBuildToolFix "alex" 1], Right $ exAv "B" 1 [ExLegacyBuildToolFix "alex" 2], Right $ exAv "C" 1 [ExAny "A", ExAny "B"]@@ -1754,7 +2078,7 @@ -- Test that exe is not related to library choices dbLegacyBuildTools5 :: ExampleDb dbLegacyBuildTools5 = [- Right $ exAv "alex" 1 [ExFix "A" 1] `withExe` ExExe "alex" [],+ Right $ exAv "alex" 1 [ExFix "A" 1] `withExe` exExe "alex" [], Right $ exAv "A" 1 [], Right $ exAv "A" 2 [], Right $ exAv "B" 1 [ExLegacyBuildToolFix "alex" 1, ExFix "A" 2]@@ -1763,8 +2087,8 @@ -- Test that build-tools on build-tools works dbLegacyBuildTools6 :: ExampleDb dbLegacyBuildTools6 = [- Right $ exAv "alex" 1 [] `withExe` ExExe "alex" [],- Right $ exAv "happy" 1 [ExLegacyBuildToolAny "alex"] `withExe` ExExe "happy" [],+ Right $ exAv "alex" 1 [] `withExe` exExe "alex" [],+ Right $ exAv "happy" 1 [ExLegacyBuildToolAny "alex"] `withExe` exExe "happy" [], Right $ exAv "A" 1 [ExLegacyBuildToolAny "happy"] ] @@ -1775,7 +2099,7 @@ Right $ exAv "warp" 1 [], -- NB: the warp build-depends refers to the package, not the internal -- executable!- Right $ exAv "A" 2 [ExFix "warp" 1] `withExe` ExExe "warp" [ExAny "A"],+ Right $ exAv "A" 2 [ExFix "warp" 1] `withExe` exExe "warp" [ExAny "A"], Right $ exAv "B" 2 [ExAny "A", ExAny "warp"] ]
cabal/cabal-testsuite/LICENSE view
@@ -1,5 +1,8 @@-Copyright (c) 2003-2017, Cabal Development Team.+Copyright (c) 2003-2020, Cabal Development Team. See the AUTHORS file for the full list of copyright holders.++See */LICENSE for the copyright holders of the subcomponents.+ All rights reserved. Redistribution and use in source and binary forms, with or without
cabal/cabal-testsuite/PackageTests/Ambiguity/reexport/reexport.cabal view
@@ -4,7 +4,7 @@ author: Edward Z. Yang maintainer: ezyang@cs.stanford.edu build-type: Simple-cabal-version: >=1.21+cabal-version: 1.22 library reexported-modules: p:Dupe as PDupe, q:Dupe as QDupe
cabal/cabal-testsuite/PackageTests/Ambiguity/setup-package-import.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring p-0.1.0.0... # Setup build Preprocessing library for p-0.1.0.0..@@ -9,7 +8,6 @@ # Setup register Registering library for p-0.1.0.0.. # Setup configure-Resolving dependencies... Configuring q-0.1.0.0... # Setup build Preprocessing library for q-0.1.0.0..@@ -19,7 +17,6 @@ # Setup register Registering library for q-0.1.0.0.. # Setup configure-Resolving dependencies... Configuring package-import-0.1.0.0... # Setup build Preprocessing executable 'package-import' for package-import-0.1.0.0..
cabal/cabal-testsuite/PackageTests/Ambiguity/setup-reexport.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring p-0.1.0.0... # Setup build Preprocessing library for p-0.1.0.0..@@ -9,7 +8,6 @@ # Setup register Registering library for p-0.1.0.0.. # Setup configure-Resolving dependencies... Configuring q-0.1.0.0... # Setup build Preprocessing library for q-0.1.0.0..@@ -19,7 +17,6 @@ # Setup register Registering library for q-0.1.0.0.. # Setup configure-Resolving dependencies... Configuring reexport-0.1.0.0... # Setup build Preprocessing library for reexport-0.1.0.0..@@ -29,7 +26,6 @@ # Setup register Registering library for reexport-0.1.0.0.. # Setup configure-Resolving dependencies... Configuring reexport-test-0.1.0.0... # Setup build Preprocessing executable 'reexport-test' for reexport-test-0.1.0.0..
cabal/cabal-testsuite/PackageTests/AutoconfBadPaths/cabal.test.hs view
@@ -49,5 +49,5 @@ (Just (testCurrentDir env)) (testEnvironment env) (programPath configured_prog)- args+ args Nothing recordLog r
cabal/cabal-testsuite/PackageTests/AutogenModules/Package/my.cabal view
@@ -7,7 +7,7 @@ synopsis: AutogenModules category: PackageTests build-type: Simple-cabal-version: 1.25+cabal-version: 2.0 description: Check that Cabal recognizes the autogen-modules fields below.
cabal/cabal-testsuite/PackageTests/AutogenModules/Package/setup.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring AutogenModules-0.1... cabal: An 'autogen-module' is neither on 'exposed-modules' or 'other-modules'. @@ -17,6 +16,5 @@ Packages using 'cabal-version: 2.0' and the autogenerated module Paths_* must include it also on the 'autogen-modules' field besides 'exposed-modules' and 'other-modules'. This specifies that the module does not come with the package and is generated on setup. Modules built with a custom Setup.hs script also go here to ensure that commands like sdist don't fail. The filename ./my.cabal does not match package name (expected: AutogenModules.cabal) Note: the public hackage server would reject this package.-Warning: Cannot run preprocessors. Run 'configure' command first. Building source dist for AutogenModules-0.1... cabal: Error: Could not find module: MyLibHelperModule with any suffix: ["gc","chs","hsc","x","y","ly","cpphs","hs","lhs","hsig","lhsig"]. If the module is autogenerated it should be added to 'autogen-modules'.
cabal/cabal-testsuite/PackageTests/AutogenModules/Package/setup.out view
@@ -16,6 +16,5 @@ Packages using 'cabal-version: 2.0' and the autogenerated module Paths_* must include it also on the 'autogen-modules' field besides 'exposed-modules' and 'other-modules'. This specifies that the module does not come with the package and is generated on setup. Modules built with a custom Setup.hs script also go here to ensure that commands like sdist don't fail. The filename ./my.cabal does not match package name (expected: AutogenModules.cabal) Note: the public hackage server would reject this package.-Warning: Cannot run preprocessors. Run 'configure' command first. Building source dist for AutogenModules-0.1... setup: Error: Could not find module: MyLibHelperModule with any suffix: ["gc","chs","hsc","x","y","ly","cpphs","hs","lhs","hsig","lhsig"]. If the module is autogenerated it should be added to 'autogen-modules'.
cabal/cabal-testsuite/PackageTests/AutogenModules/SrcDist/AutogenModules.cabal view
@@ -7,7 +7,7 @@ synopsis: AutogenModules category: PackageTests build-type: Simple-cabal-version: 1.24+cabal-version: 2.0 description: Check that Cabal recognizes the autogen-modules fields below.@@ -22,6 +22,7 @@ other-modules: MyLibModule autogen-modules:+ Paths_AutogenModules MyLibHelperModule Executable Exe@@ -33,6 +34,7 @@ Paths_AutogenModules MyExeHelperModule autogen-modules:+ Paths_AutogenModules MyExeHelperModule Test-Suite Test@@ -45,6 +47,7 @@ Paths_AutogenModules MyTestHelperModule autogen-modules:+ Paths_AutogenModules MyTestHelperModule Benchmark Bench@@ -57,4 +60,5 @@ Paths_AutogenModules MyBenchHelperModule autogen-modules:+ Paths_AutogenModules MyBenchHelperModule
cabal/cabal-testsuite/PackageTests/AutogenModules/SrcDist/setup.cabal.out view
@@ -1,11 +1,7 @@ # Setup configure-Resolving dependencies... Configuring AutogenModules-0.1... # Setup sdist Building source dist for AutogenModules-0.1...-Preprocessing executable 'Exe' for AutogenModules-0.1..-Preprocessing library for AutogenModules-0.1.. Source tarball created: setup.cabal.dist/work/dist/AutogenModules-0.1.tar.gz # Setup sdist-List of package sources written to file '<ROOT>/setup.cabal.dist/work/./dist/list-sources.txt' List of package sources written to file '<ROOT>/setup.cabal.dist/work/./dist/list-sources.txt'
cabal/cabal-testsuite/PackageTests/AutogenModules/SrcDist/setup.out view
@@ -2,8 +2,6 @@ Configuring AutogenModules-0.1... # Setup sdist Building source dist for AutogenModules-0.1...-Preprocessing executable 'Exe' for AutogenModules-0.1..-Preprocessing library for AutogenModules-0.1.. Source tarball created: setup.dist/work/dist/AutogenModules-0.1.tar.gz # Setup sdist List of package sources written to file '<ROOT>/setup.dist/work/./dist/list-sources.txt'
cabal/cabal-testsuite/PackageTests/AutogenModules/SrcDist/setup.test.hs view
@@ -25,16 +25,16 @@ let gotTestSuite = head $ testSuites (localPkgDescr lbi) let gotBenchmark = head $ benchmarks (localPkgDescr lbi) assertEqual "library 'autogen-modules' field does not match expected"- [fromString "MyLibHelperModule"]+ [fromString "Paths_AutogenModules", fromString "MyLibHelperModule"] (libModulesAutogen gotLibrary) assertEqual "executable 'autogen-modules' field does not match expected"- [fromString "MyExeHelperModule"]+ [fromString "Paths_AutogenModules", fromString "MyExeHelperModule"] (exeModulesAutogen gotExecutable) assertEqual "test-suite 'autogen-modules' field does not match expected"- [fromString "MyTestHelperModule"]+ [fromString "Paths_AutogenModules", fromString "MyTestHelperModule"] (testModulesAutogen gotTestSuite) assertEqual "benchmark 'autogen-modules' field does not match expected"- [fromString "MyBenchHelperModule"]+ [fromString "Paths_AutogenModules", fromString "MyBenchHelperModule"] (benchmarkModulesAutogen gotBenchmark) -- Package check messages.
cabal/cabal-testsuite/PackageTests/Backpack/Fail1/Fail1.cabal view
@@ -4,7 +4,7 @@ author: Edward Z. Yang maintainer: ezyang@cs.stanford.edu build-type: Simple-cabal-version: >=1.25+cabal-version: 2.0 library sig signatures: A
cabal/cabal-testsuite/PackageTests/Backpack/Fail1/setup.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring Fail1-0.1.0.0... Error: The library 'sig' from package 'Fail1-0.1.0.0' does not require:
cabal/cabal-testsuite/PackageTests/Backpack/Fail2/Fail2.cabal view
@@ -4,7 +4,7 @@ author: Edward Z. Yang maintainer: ezyang@cs.stanford.edu build-type: Simple-cabal-version: >=1.25+cabal-version: 2.0 library mixins: non-existent
cabal/cabal-testsuite/PackageTests/Backpack/Fail2/setup.cabal.out view
@@ -1,6 +1,5 @@ # Setup configure-Resolving dependencies... Configuring Fail2-0.1.0.0... Error:- Mix-in refers to non-existent package 'non-existent'+ Mix-in refers to non-existent library 'non-existent' (did you forget to add the package to build-depends?)
cabal/cabal-testsuite/PackageTests/Backpack/Fail2/setup.out view
@@ -1,5 +1,5 @@ # Setup configure Configuring Fail2-0.1.0.0... Error:- Mix-in refers to non-existent package 'non-existent'+ Mix-in refers to non-existent library 'non-existent' (did you forget to add the package to build-depends?)
cabal/cabal-testsuite/PackageTests/Backpack/Fail3/Fail3.cabal view
@@ -4,7 +4,7 @@ author: Edward Z. Yang maintainer: ezyang@cs.stanford.edu build-type: Simple-cabal-version: >=1.25+cabal-version: 2.0 library signatures: UnfilledSig
cabal/cabal-testsuite/PackageTests/Backpack/Fail3/setup.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring Fail1-0.1.0.0... Error: Non-library component has unfilled requirements: UnfilledSig
cabal/cabal-testsuite/PackageTests/Backpack/Includes1/Includes1.cabal view
@@ -4,7 +4,7 @@ author: Edward Z. Yang maintainer: ezyang@cs.stanford.edu build-type: Simple-cabal-version: >=1.25+cabal-version: 2.0 library build-depends: base, containers
cabal/cabal-testsuite/PackageTests/Backpack/Includes1/setup.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring Includes1-0.1.0.0... # Setup build Preprocessing library for Includes1-0.1.0.0..
cabal/cabal-testsuite/PackageTests/Backpack/Includes2/Includes2.cabal view
@@ -4,7 +4,7 @@ author: Edward Z. Yang maintainer: ezyang@cs.stanford.edu build-type: Simple-cabal-version: >=1.25+cabal-version: 2.0 library mylib build-depends: base
cabal/cabal-testsuite/PackageTests/Backpack/Includes2/Includes2.cabal.fail view
@@ -4,7 +4,7 @@ author: Edward Z. Yang maintainer: ezyang@cs.stanford.edu build-type: Simple-cabal-version: >=1.25+cabal-version: 2.0 library mylib build-depends: base
cabal/cabal-testsuite/PackageTests/Backpack/Includes2/cabal-internal.out view
@@ -34,11 +34,11 @@ Database = Includes2-0.1.0.0-inplace-postgresql:Database.PostgreSQL for Includes2-0.1.0.0.. Configuring library for Includes2-0.1.0.0..-Warning: The package has an extraneous version range for a dependency on an internal library: Includes2 -any && ==0.1.0.0 && ==0.1.0.0 && ==0.1.0.0. This version range includes the current package but isn't needed as the current package's library will always be used.+Warning: The package has an extraneous version range for a dependency on an internal library: Includes2:{mylib, mysql, postgresql} (((>=0 && >=0 && >=0) && ==0.1.0.0) && ==0.1.0.0) && ==0.1.0.0, Includes2 ((>=0 && ==0.1.0.0) && ==0.1.0.0) && ==0.1.0.0. This version range includes the current package but isn't needed as the current package's library will always be used. Preprocessing library for Includes2-0.1.0.0.. Building library for Includes2-0.1.0.0.. Configuring executable 'exe' for Includes2-0.1.0.0..-Warning: The package has an extraneous version range for a dependency on an internal library: Includes2 -any && ==0.1.0.0. This version range includes the current package but isn't needed as the current package's library will always be used.+Warning: The package has an extraneous version range for a dependency on an internal library: Includes2:{mylib, mysql, postgresql} (>=0 && >=0 && >=0) && ==0.1.0.0, Includes2 >=0 && ==0.1.0.0. This version range includes the current package but isn't needed as the current package's library will always be used. Preprocessing executable 'exe' for Includes2-0.1.0.0.. Building executable 'exe' for Includes2-0.1.0.0.. # Includes2 exe
cabal/cabal-testsuite/PackageTests/Backpack/Includes2/exe/exe.cabal view
@@ -4,7 +4,7 @@ author: Edward Z. Yang maintainer: ezyang@cs.stanford.edu build-type: Simple-cabal-version: >=1.25+cabal-version: 2.0 executable exe build-depends: base, src
cabal/cabal-testsuite/PackageTests/Backpack/Includes2/mylib/mylib.cabal view
@@ -4,7 +4,7 @@ author: Edward Z. Yang maintainer: ezyang@cs.stanford.edu build-type: Simple-cabal-version: >=1.25+cabal-version: 2.0 library build-depends: base
cabal/cabal-testsuite/PackageTests/Backpack/Includes2/mysql/mysql.cabal view
@@ -4,7 +4,7 @@ author: Edward Z. Yang maintainer: ezyang@cs.stanford.edu build-type: Simple-cabal-version: >=1.25+cabal-version: 2.0 library build-depends: base
cabal/cabal-testsuite/PackageTests/Backpack/Includes2/postgresql/postgresql.cabal view
@@ -4,7 +4,7 @@ author: Edward Z. Yang maintainer: ezyang@cs.stanford.edu build-type: Simple-cabal-version: >=1.25+cabal-version: 2.0 library build-depends: base
cabal/cabal-testsuite/PackageTests/Backpack/Includes2/setup-external.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring mylib-0.1.0.0... # Setup build Preprocessing library for mylib-0.1.0.0..@@ -16,7 +15,6 @@ Registering library instantiated with Database = <Database> for mylib-0.1.0.0.. # Setup configure-Resolving dependencies... Configuring mysql-0.1.0.0... # Setup build Preprocessing library for mysql-0.1.0.0..@@ -30,7 +28,6 @@ # Setup register Registering library for mysql-0.1.0.0.. # Setup configure-Resolving dependencies... Configuring postgresql-0.1.0.0... # Setup build Preprocessing library for postgresql-0.1.0.0..@@ -44,7 +41,6 @@ # Setup register Registering library for postgresql-0.1.0.0.. # Setup configure-Resolving dependencies... Configuring mylib-0.1.0.0... # Setup build Preprocessing library for mylib-0.1.0.0..@@ -62,7 +58,6 @@ Registering library instantiated with Database = mysql-0.1.0.0:Database.MySQL for mylib-0.1.0.0.. # Setup configure-Resolving dependencies... Configuring mylib-0.1.0.0... # Setup build Preprocessing library for mylib-0.1.0.0..@@ -82,7 +77,6 @@ Database = postgresql-0.1.0.0:Database.PostgreSQL for mylib-0.1.0.0.. # Setup configure-Resolving dependencies... Configuring src-0.1.0.0... # Setup build Preprocessing library for src-0.1.0.0..@@ -96,15 +90,6 @@ # Setup register Registering library for src-0.1.0.0.. # Setup configure-Resolving dependencies...-Warning: solver failed to find a solution:-Could not resolve dependencies:-[__0] trying: exe-0.1.0.0 (user goal)-[__1] next goal: src (dependency of exe)-[__1] rejecting: src-<VERSION>/installed-<HASH>... (conflict: src => mylib==0.1.0.0/installed-0.1..., src => mylib==0.1.0.0/installed-0.1...)-[__1] fail (backjumping, conflict set: exe, src)-After searching the rest of the dependency tree exhaustively, these were the goals I've had most trouble fulfilling: exe (2), src (2)-Trying configure anyway. Configuring exe-0.1.0.0... # Setup build Preprocessing executable 'exe' for exe-0.1.0.0..
cabal/cabal-testsuite/PackageTests/Backpack/Includes2/setup-internal-fail.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring fail-0.1.0.0... Error: - Cannot match module names
cabal/cabal-testsuite/PackageTests/Backpack/Includes2/setup-internal.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring Includes2-0.1.0.0... # Setup build Preprocessing library 'postgresql' for Includes2-0.1.0.0..
cabal/cabal-testsuite/PackageTests/Backpack/Includes2/src/src.cabal view
@@ -4,7 +4,7 @@ author: Edward Z. Yang maintainer: ezyang@cs.stanford.edu build-type: Simple-cabal-version: >=1.25+cabal-version: 2.0 library build-depends: base, mysql, postgresql, mylib
cabal/cabal-testsuite/PackageTests/Backpack/Includes3/Includes3.cabal view
@@ -4,7 +4,7 @@ author: Edward Z. Yang maintainer: ezyang@cs.stanford.edu build-type: Simple-cabal-version: 1.25+cabal-version: 2.0 library sigs build-depends: base
cabal/cabal-testsuite/PackageTests/Backpack/Includes3/repo/exe-0.1.0.0/exe.cabal view
@@ -4,7 +4,7 @@ author: Edward Z. Yang maintainer: ezyang@cs.stanford.edu build-type: Simple-cabal-version: >=1.25+cabal-version: 2.0 executable exe build-depends: base, containers, indef
cabal/cabal-testsuite/PackageTests/Backpack/Includes3/repo/indef-0.1.0.0/indef.cabal view
@@ -4,7 +4,7 @@ author: Edward Z. Yang maintainer: ezyang@cs.stanford.edu build-type: Simple-cabal-version: >=1.25+cabal-version: 2.0 library build-depends: base, sigs
cabal/cabal-testsuite/PackageTests/Backpack/Includes3/repo/sigs-0.1.0.0/sigs.cabal view
@@ -4,7 +4,7 @@ author: Edward Z. Yang maintainer: ezyang@cs.stanford.edu build-type: Simple-cabal-version: >=1.25+cabal-version: 2.0 library build-depends: base
cabal/cabal-testsuite/PackageTests/Backpack/Includes3/setup-external-fail.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring sigs-0.1.0.0... # Setup build Preprocessing library for sigs-0.1.0.0..@@ -11,7 +10,6 @@ Registering library instantiated with Data.Map = <Data.Map> for sigs-0.1.0.0.. # Setup configure-Resolving dependencies... Configuring indef-0.1.0.0... # Setup build Preprocessing library for indef-0.1.0.0..
cabal/cabal-testsuite/PackageTests/Backpack/Includes3/setup-external-ok.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring sigs-0.1.0.0... # Setup build Preprocessing library for sigs-0.1.0.0..@@ -16,7 +15,6 @@ Registering library instantiated with Data.Map = <Data.Map> for sigs-0.1.0.0.. # Setup configure-Resolving dependencies... Configuring indef-0.1.0.0... # Setup build Preprocessing library for indef-0.1.0.0..@@ -33,7 +31,6 @@ Registering library instantiated with Data.Map = <Data.Map> for indef-0.1.0.0.. # Setup configure-Resolving dependencies... Configuring sigs-0.1.0.0... # Setup build Preprocessing library for sigs-0.1.0.0..@@ -51,7 +48,6 @@ Registering library instantiated with Data.Map = containers-<VERSION>:Data.Map for sigs-0.1.0.0.. # Setup configure-Resolving dependencies... Configuring indef-0.1.0.0... # Setup build Preprocessing library for indef-0.1.0.0..@@ -69,7 +65,6 @@ Registering library instantiated with Data.Map = containers-<VERSION>:Data.Map for indef-0.1.0.0.. # Setup configure-Resolving dependencies... Configuring exe-0.1.0.0... # Setup build Preprocessing executable 'exe' for exe-0.1.0.0..
cabal/cabal-testsuite/PackageTests/Backpack/Includes3/setup-internal.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring Includes3-0.1.0.0... # Setup build Preprocessing library 'sigs' for Includes3-0.1.0.0..
cabal/cabal-testsuite/PackageTests/Backpack/Includes3/setup-internal.test.hs view
@@ -3,7 +3,7 @@ skipUnless =<< ghcVersionIs (>= mkVersion [8,1]) withPackageDb $ do setup_install []- _ <- runM "touch" ["repo/indef-0.1.0.0/Foo.hs"]+ _ <- runM "touch" ["repo/indef-0.1.0.0/Foo.hs"] Nothing setup "build" [] runExe' "exe" [] >>= assertOutputContains "fromList [(0,2),(2,4)]"
cabal/cabal-testsuite/PackageTests/Backpack/Includes4/Includes4.cabal view
@@ -4,7 +4,7 @@ author: Edward Z. Yang maintainer: ezyang@cs.stanford.edu build-type: Simple-cabal-version: >=1.25+cabal-version: 2.0 library indef build-depends: base
cabal/cabal-testsuite/PackageTests/Backpack/Includes4/setup.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring Includes4-0.1.0.0... # Setup build Preprocessing library 'indef' for Includes4-0.1.0.0..
cabal/cabal-testsuite/PackageTests/Backpack/Includes5/Includes5.cabal view
@@ -4,7 +4,7 @@ author: Edward Z. Yang maintainer: ezyang@cs.stanford.edu build-type: Simple-cabal-version: >=1.25+cabal-version: 2.0 library impl build-depends: base
cabal/cabal-testsuite/PackageTests/Backpack/Includes5/setup.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring Includes5-0.1.0.0... # Setup build Preprocessing library 'impl' for Includes5-0.1.0.0..
cabal/cabal-testsuite/PackageTests/Backpack/Indef1/Indef1.cabal view
@@ -4,7 +4,7 @@ author: Edward Z. Yang maintainer: ezyang@cs.stanford.edu build-type: Simple-cabal-version: >=1.25+cabal-version: 2.0 library exposed-modules: Provide
cabal/cabal-testsuite/PackageTests/Backpack/Indef2/Indef2.cabal view
@@ -4,7 +4,7 @@ author: Edward Z. Yang maintainer: ezyang@cs.stanford.edu build-type: Simple-cabal-version: >=1.25+cabal-version: 2.0 library asig1 signatures: A
cabal/cabal-testsuite/PackageTests/Backpack/Indef2/setup.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring Indef2-0.1.0.0... # Setup build Preprocessing library 'asig1' for Indef2-0.1.0.0..
cabal/cabal-testsuite/PackageTests/Backpack/Reexport1/p/p.cabal view
@@ -4,7 +4,7 @@ author: Edward Z. Yang maintainer: ezyang@cs.stanford.edu build-type: Simple-cabal-version: >=1.25+cabal-version: 2.0 library mixins: containers (Data.Map as Map)
cabal/cabal-testsuite/PackageTests/Backpack/Reexport1/setup.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring p-0.1.0.0... # Setup build Preprocessing library for p-0.1.0.0..@@ -13,7 +12,6 @@ # Setup register Registering library for p-0.1.0.0.. # Setup configure-Resolving dependencies... Configuring q-0.1.0.0... # Setup build Preprocessing library for q-0.1.0.0..
cabal/cabal-testsuite/PackageTests/Backpack/Reexport2/Reexport2.cabal view
@@ -1,7 +1,7 @@ name: Reexport2 version: 1.0 build-type: Simple-cabal-version: >= 1.25+cabal-version: 2.0 library signatures: Asdf
cabal/cabal-testsuite/PackageTests/Backpack/Reexport2/setup.cabal.out view
@@ -1,4 +1,3 @@ # Setup configure-Resolving dependencies... Configuring Reexport2-1.0... cabal: Duplicate modules in library: Asdf
cabal/cabal-testsuite/PackageTests/Backpack/T4447/T4447.cabal view
@@ -1,6 +1,6 @@ name: T4447 version: 1.0-cabal-version: >= 2.0+cabal-version: 2.0 build-type: Simple library foo-indef
cabal/cabal-testsuite/PackageTests/Backpack/T4447/setup.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring T4447-1.0... Error: Cannot instantiate requirement 'A' brought into scope by build-depends: T4447:foo-indef
cabal/cabal-testsuite/PackageTests/Backpack/T4754/p.cabal view
@@ -1,14 +1,16 @@ name: p version: 0.1-cabal-version: >= 2.0+cabal-version: 2.0 build-type: Simple library+ default-language: Haskell2010 exposed-modules: P signatures: Sig build-depends: base executable pexe+ default-language: Haskell2010 build-depends: p, base mixins: base, base (Prelude as Sig) main-is: PExe.hs
cabal/cabal-testsuite/PackageTests/Backpack/T4754/setup.cabal.out view
@@ -1,7 +1,5 @@ # Setup configure-Resolving dependencies... Configuring p-0.1...-Warning: Packages using 'cabal-version: >= 1.10' must specify the 'default-language' field for each component (e.g. Haskell98 or Haskell2010). If a component uses different languages in different modules then list the other ones in the 'other-languages' field. # Setup build Preprocessing library for p-0.1.. Building library instantiated with Sig = <Sig>
cabal/cabal-testsuite/PackageTests/Backpack/T4754/setup.out view
@@ -1,6 +1,5 @@ # Setup configure Configuring p-0.1...-Warning: Packages using 'cabal-version: >= 1.10' must specify the 'default-language' field for each component (e.g. Haskell98 or Haskell2010). If a component uses different languages in different modules then list the other ones in the 'other-languages' field. # Setup build Preprocessing library for p-0.1.. Building library instantiated with Sig = <Sig>
cabal/cabal-testsuite/PackageTests/Backpack/T5634/T5634.cabal view
@@ -1,9 +1,10 @@ name: th-backpack-failure version: 1.0 build-type: Simple-cabal-version: >= 2.0+cabal-version: 2.0 library+ default-language: Haskell2010 build-depends: base, impl, sig-with-th hs-source-dirs: . mixins: sig-with-th requires (Sig as Impl)@@ -11,12 +12,14 @@ exposed-modules: Go library sig-with-th+ default-language: Haskell2010 build-depends: base hs-source-dirs: sig-with-th signatures: Sig exposed-modules: THFuns library impl+ default-language: Haskell2010 build-depends: base hs-source-dirs: impl exposed-modules: Impl
cabal/cabal-testsuite/PackageTests/Backpack/T5634/setup.cabal.out view
@@ -1,7 +1,5 @@ # Setup configure-Resolving dependencies... Configuring th-backpack-failure-1.0...-Warning: Packages using 'cabal-version: >= 1.10' must specify the 'default-language' field for each component (e.g. Haskell98 or Haskell2010). If a component uses different languages in different modules then list the other ones in the 'other-languages' field. # Setup build Preprocessing library 'sig-with-th' for th-backpack-failure-1.0.. Building library 'sig-with-th' instantiated with Sig = <Sig>
cabal/cabal-testsuite/PackageTests/Backpack/T5634/setup.out view
@@ -1,6 +1,5 @@ # Setup configure Configuring th-backpack-failure-1.0...-Warning: Packages using 'cabal-version: >= 1.10' must specify the 'default-language' field for each component (e.g. Haskell98 or Haskell2010). If a component uses different languages in different modules then list the other ones in the 'other-languages' field. # Setup build Preprocessing library 'sig-with-th' for th-backpack-failure-1.0.. Building library 'sig-with-th' instantiated with Sig = <Sig>
cabal/cabal-testsuite/PackageTests/Backpack/TemplateHaskell/bkpth.cabal view
@@ -1,7 +1,7 @@ name: bkpth version: 1.0 build-type: Simple-cabal-version: >= 1.25+cabal-version: 2.0 library helper signatures: A
cabal/cabal-testsuite/PackageTests/Backpack/TemplateHaskell/setup.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring bkpth-1.0... # Setup build Preprocessing library 'helper' for bkpth-1.0..
cabal/cabal-testsuite/PackageTests/BenchmarkExeV10/my.cabal view
@@ -1,14 +1,16 @@ name: my version: 0.1 license: BSD3-cabal-version: >= 1.9.2+cabal-version: >= 1.10 build-type: Simple library+ default-language: Haskell2010 exposed-modules: Foo build-depends: base benchmark bench-Foo+ default-language: Haskell2010 type: exitcode-stdio-1.0 hs-source-dirs: benchmarks main-is: bench-Foo.hs
cabal/cabal-testsuite/PackageTests/BenchmarkExeV10/setup.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring my-0.1... # Setup build Preprocessing library for my-0.1..
cabal/cabal-testsuite/PackageTests/BenchmarkOptions/BenchmarkOptions.cabal view
@@ -5,16 +5,18 @@ stability: stable category: PackageTests build-type: Simple-cabal-version: >= 1.9.2+cabal-version: >= 1.10 description: Check that Cabal passes the correct test options to test suites. executable dummy+ default-language: Haskell2010 main-is: test-BenchmarkOptions.hs build-depends: base benchmark test-BenchmarkOptions+ default-language: Haskell2010 main-is: test-BenchmarkOptions.hs type: exitcode-stdio-1.0 build-depends: base
cabal/cabal-testsuite/PackageTests/BenchmarkOptions/setup.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring BenchmarkOptions-0.1... # Setup build Preprocessing benchmark 'test-BenchmarkOptions' for BenchmarkOptions-0.1..@@ -7,14 +6,10 @@ Preprocessing executable 'dummy' for BenchmarkOptions-0.1.. Building executable 'dummy' for BenchmarkOptions-0.1.. # Setup bench-Preprocessing benchmark 'test-BenchmarkOptions' for BenchmarkOptions-0.1..-Building benchmark 'test-BenchmarkOptions' for BenchmarkOptions-0.1.. Running 1 benchmarks... Benchmark test-BenchmarkOptions: RUNNING... Benchmark test-BenchmarkOptions: FINISH # Setup bench-Preprocessing benchmark 'test-BenchmarkOptions' for BenchmarkOptions-0.1..-Building benchmark 'test-BenchmarkOptions' for BenchmarkOptions-0.1.. Running 1 benchmarks... Benchmark test-BenchmarkOptions: RUNNING... Benchmark test-BenchmarkOptions: FINISH
cabal/cabal-testsuite/PackageTests/BenchmarkStanza/my.cabal view
@@ -11,10 +11,12 @@ Check that Cabal recognizes the benchmark stanza defined below. Library+ default-language: Haskell2010 exposed-modules: MyLibrary build-depends: base benchmark dummy+ default-language: Haskell2010 main-is: dummy.hs type: exitcode-stdio-1.0 build-depends: base
cabal/cabal-testsuite/PackageTests/BenchmarkStanza/setup.cabal.out view
@@ -1,4 +1,2 @@ # Setup configure-Resolving dependencies... Configuring BenchmarkStanza-0.1...-Warning: Packages using 'cabal-version: >= 1.10' must specify the 'default-language' field for each component (e.g. Haskell98 or Haskell2010). If a component uses different languages in different modules then list the other ones in the 'other-languages' field.
cabal/cabal-testsuite/PackageTests/BenchmarkStanza/setup.out view
@@ -1,3 +1,2 @@ # Setup configure Configuring BenchmarkStanza-0.1...-Warning: Packages using 'cabal-version: >= 1.10' must specify the 'default-language' field for each component (e.g. Haskell98 or Haskell2010). If a component uses different languages in different modules then list the other ones in the 'other-languages' field.
cabal/cabal-testsuite/PackageTests/BuildDeps/DepCycle/setup.cabal.out view
@@ -1,6 +1,5 @@ # Setup configure-Resolving dependencies... Configuring DepCycle-1.0... Error:- Components in the package depend on each other in a cyclic way:- 'library 'bar'' depends on 'library 'foo'' depends on 'library 'bar''+ Components in the package DepCycle-1.0 depend on each other in a cyclic way:+ 'library 'bar'' depends on 'library 'foo'' depends on 'library 'bar''
cabal/cabal-testsuite/PackageTests/BuildDeps/DepCycle/setup.out view
@@ -1,5 +1,5 @@ # Setup configure Configuring DepCycle-1.0... Error:- Components in the package depend on each other in a cyclic way:- 'library 'bar'' depends on 'library 'foo'' depends on 'library 'bar''+ Components in the package DepCycle-1.0 depend on each other in a cyclic way:+ 'library 'bar'' depends on 'library 'foo'' depends on 'library 'bar''
cabal/cabal-testsuite/PackageTests/BuildDeps/InternalLibrary0/setup.cabal.out view
@@ -1,4 +1,3 @@ # Setup configure-Resolving dependencies... Configuring InternalLibrary0-0.1... cabal: The field 'build-depends: InternalLibrary0' refers to a library which is defined within the same package. To use this feature the package must specify at least 'cabal-version: >= 1.8'.
cabal/cabal-testsuite/PackageTests/BuildDeps/InternalLibrary1/cabal.out view
@@ -2,9 +2,12 @@ Resolving dependencies... Build profile: -w ghc-<GHCVER> -O1 In order, the following will be built:+ - InternalLibrary1-0.1 (lib) (first run) - InternalLibrary1-0.1 (exe:lemon) (first run)-Configuring InternalLibrary1-0.1...+Configuring library for InternalLibrary1-0.1.. Preprocessing library for InternalLibrary1-0.1.. Building library for InternalLibrary1-0.1..+Configuring executable 'lemon' for InternalLibrary1-0.1..+Warning: The package has an extraneous version range for a dependency on an internal library: InternalLibrary1 >=0 && ==0.1. This version range includes the current package but isn't needed as the current package's library will always be used. Preprocessing executable 'lemon' for InternalLibrary1-0.1.. Building executable 'lemon' for InternalLibrary1-0.1..
cabal/cabal-testsuite/PackageTests/BuildDeps/InternalLibrary1/my.cabal view
@@ -1,7 +1,7 @@ name: InternalLibrary1 version: 0.1 license: BSD3-cabal-version: >= 1.7.1+cabal-version: >= 1.8 author: Stephen Blackheath stability: stable category: PackageTests
cabal/cabal-testsuite/PackageTests/BuildDeps/InternalLibrary1/setup.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring InternalLibrary1-0.1... # Setup build Preprocessing library for InternalLibrary1-0.1..
cabal/cabal-testsuite/PackageTests/BuildDeps/InternalLibrary2/setup.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring InternalLibrary2-0.1... # Setup build Preprocessing library for InternalLibrary2-0.1..@@ -9,7 +8,6 @@ # Setup register Registering library for InternalLibrary2-0.1.. # Setup configure-Resolving dependencies... Configuring InternalLibrary2-0.1... # Setup build Preprocessing library for InternalLibrary2-0.1..
cabal/cabal-testsuite/PackageTests/BuildDeps/InternalLibrary3/setup.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring InternalLibrary3-0.2... # Setup build Preprocessing library for InternalLibrary3-0.2..@@ -9,7 +8,6 @@ # Setup register Registering library for InternalLibrary3-0.2.. # Setup configure-Resolving dependencies... Configuring InternalLibrary3-0.1... # Setup build Preprocessing library for InternalLibrary3-0.1..
cabal/cabal-testsuite/PackageTests/BuildDeps/SameDepsAllRound/setup.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring SameDepsAllRound-0.1... # Setup build Preprocessing executable 'pineapple' for SameDepsAllRound-0.1..
cabal/cabal-testsuite/PackageTests/BuildDeps/TargetSpecificDeps1/setup.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring TargetSpecificDeps1-0.1... # Setup build Preprocessing executable 'lemon' for TargetSpecificDeps1-0.1..
cabal/cabal-testsuite/PackageTests/BuildDeps/TargetSpecificDeps2/setup.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring TargetSpecificDeps1-0.1... # Setup build Preprocessing executable 'lemon' for TargetSpecificDeps1-0.1..
cabal/cabal-testsuite/PackageTests/BuildDeps/TargetSpecificDeps3/setup.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring test-0.1... # Setup build Preprocessing executable 'lemon' for test-0.1..
cabal/cabal-testsuite/PackageTests/BuildTargetErrors/BuildTargetErrors.cabal view
@@ -1,10 +1,12 @@ name: BuildTargetErrors version: 1.0 build-type: Simple-cabal-version: >= 1.9+cabal-version: >= 1.10 library+ default-language: Haskell2010 executable not-buildable-exe+ default-language: Haskell2010 main-is: Main.hs buildable: False
cabal/cabal-testsuite/PackageTests/BuildToolDependsInternalMissing/setup.cabal.out view
@@ -1,4 +1,3 @@ # Setup configure-Resolving dependencies... Configuring build-tool-depends-missing-0.1.0.0... cabal: The package depends on a missing internal executable:
cabal/cabal-testsuite/PackageTests/BuildTools/Foreign/setup.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring build-tools-path-foreign-0.1.0.0... # Setup build Preprocessing library for build-tools-path-foreign-0.1.0.0..
cabal/cabal-testsuite/PackageTests/BuildTools/Internal/cabal.out view
@@ -12,6 +12,6 @@ Preprocessing library for foo-0.1.0.0.. Building library for foo-0.1.0.0.. Configuring executable 'hello-world' for foo-0.1.0.0..-Warning: The package has an extraneous version range for a dependency on an internal library: foo -any && ==0.1.0.0. This version range includes the current package but isn't needed as the current package's library will always be used.+Warning: The package has an extraneous version range for a dependency on an internal library: foo >=0 && ==0.1.0.0. This version range includes the current package but isn't needed as the current package's library will always be used. Preprocessing executable 'hello-world' for foo-0.1.0.0.. Building executable 'hello-world' for foo-0.1.0.0..
cabal/cabal-testsuite/PackageTests/BuildTools/Internal/setup.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring foo-0.1.0.0... # Setup build Preprocessing executable 'my-cpp' for foo-0.1.0.0..
cabal/cabal-testsuite/PackageTests/CMain/my.cabal view
@@ -1,10 +1,11 @@ name: my version: 0.1 license: BSD3-cabal-version: >= 1.9.2+cabal-version: >= 1.10 build-type: Simple executable foo+ default-language: Haskell2010 main-is: foo.c other-modules: Bar build-depends: base
cabal/cabal-testsuite/PackageTests/CMain/setup.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring my-0.1... # Setup build Preprocessing executable 'foo' for my-0.1..
cabal/cabal-testsuite/PackageTests/COnlyMain/my.cabal view
@@ -1,4 +1,4 @@-cabal-version: 2.1+cabal-version: 2.2 name: my version: 0.1 license: BSD-3-Clause
cabal/cabal-testsuite/PackageTests/COnlyMain/setup.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring my-0.1... # Setup build Preprocessing executable 'foo' for my-0.1..
+ cabal/cabal-testsuite/PackageTests/CabalMacros/Mdl.hs view
@@ -0,0 +1,5 @@+{-# LANGUAGE CPP #-}+module Mdl where++answer :: Int+answer = 42
+ cabal/cabal-testsuite/PackageTests/CabalMacros/my.cabal view
@@ -0,0 +1,16 @@+cabal-version: 2.2+name: CabalMacros+version: 0.1+license: BSD-3-Clause+author: Oleg Grenrus+stability: stable+category: PackageTests+build-type: Simple++description:+ Check that the generated cabal_macros.h is intact.++Library+ exposed-modules: Mdl+ build-depends: base+ default-language: Haskell2010
+ cabal/cabal-testsuite/PackageTests/CabalMacros/setup.cabal.out view
@@ -0,0 +1,15 @@+# Setup configure+Configuring CabalMacros-0.1...+# Setup build+Preprocessing library for CabalMacros-0.1..+Building library for CabalMacros-0.1..+# cabal_macros.h+#ifndef CURRENT_PACKAGE_KEY+#define CURRENT_PACKAGE_KEY "CabalMacros-0.1"+#endif /* CURRENT_packageKey */+#ifndef CURRENT_COMPONENT_ID+#define CURRENT_COMPONENT_ID "CabalMacros-0.1"+#endif /* CURRENT_COMPONENT_ID */+#ifndef CURRENT_PACKAGE_VERSION+#define CURRENT_PACKAGE_VERSION "0.1"+#endif /* CURRENT_PACKAGE_VERSION */
+ cabal/cabal-testsuite/PackageTests/CabalMacros/setup.out view
@@ -0,0 +1,15 @@+# Setup configure+Configuring CabalMacros-0.1...+# Setup build+Preprocessing library for CabalMacros-0.1..+Building library for CabalMacros-0.1..+# cabal_macros.h+#ifndef CURRENT_PACKAGE_KEY+#define CURRENT_PACKAGE_KEY "CabalMacros-0.1"+#endif /* CURRENT_packageKey */+#ifndef CURRENT_COMPONENT_ID+#define CURRENT_COMPONENT_ID "CabalMacros-0.1"+#endif /* CURRENT_COMPONENT_ID */+#ifndef CURRENT_PACKAGE_VERSION+#define CURRENT_PACKAGE_VERSION "0.1"+#endif /* CURRENT_PACKAGE_VERSION */
+ cabal/cabal-testsuite/PackageTests/CabalMacros/setup.test.hs view
@@ -0,0 +1,18 @@+import Test.Cabal.Prelude+import qualified Data.ByteString.Char8 as BS8++main = setupAndCabalTest $ do+ env <- getTestEnv+ let mode = testRecordMode env++ setup_build []+ let autogenDir = testDistDir env </> "build" </> "autogen"++ defaultRecordMode RecordAll $ recordHeader ["cabal_macros.h"]+ contents <- liftIO $ BS8.readFile $ autogenDir </> "cabal_macros.h"+ -- we are only interested in CURRENT_ lines+ -- others change a lot based on available tools in the environment+ let contents' = BS8.unlines+ $ filter (BS8.isInfixOf $ BS8.pack "CURRENT")+ $ BS8.lines contents+ liftIO $ BS8.appendFile (testActualFile env) contents'
cabal/cabal-testsuite/PackageTests/CaretOperator/my.cabal view
@@ -4,7 +4,7 @@ author: HVR category: PackageTests build-type: Simple-cabal-version: >= 1.25+cabal-version: 2.0 description: Check that Cabal recognizes the caret operator
cabal/cabal-testsuite/PackageTests/Check/DifferentGhcOptions/cabal.out view
@@ -3,6 +3,6 @@ Warning: 'ghc-shared-options: -hide-package' is never needed. Cabal hides all packages. Warning: The following errors will cause portability problems on other environments: Warning: 'ghc-options: -fasm' is unnecessary and will not work on CPU architectures other than x86, x86-64, ppc or sparc.-Warning: 'ghc-prof-options: -fhpc' is not not necessary. Use the configure flag --enable-coverage instead.+Warning: 'ghc-prof-options: -fhpc' is not necessary. Use the configure flag --enable-coverage instead. Warning: 'ghc-shared-options: -Wall -Werror' makes the package very easy to break with future GHC versions because new GHC versions often add new warnings. Use just 'ghc-shared-options: -Wall' instead. Alternatively, if you want to use this, make it conditional based on a Cabal configuration flag (with 'manual: True' and 'default: False') and enable that flag during development. Warning: Hackage would reject this package.
+ cabal/cabal-testsuite/PackageTests/CmmSources/cabal.out view
@@ -0,0 +1,13 @@+# cabal v2-run+Resolving dependencies...+Build profile: -w ghc-<GHCVER> -O1+In order, the following will be built:+ - cmmexperiment-0 (lib) (first run)+ - cmmexperiment-0 (exe:demo) (first run)+Configuring library for cmmexperiment-0..+Preprocessing library for cmmexperiment-0..+Building library for cmmexperiment-0..+Configuring executable 'demo' for cmmexperiment-0..+Warning: The package has an extraneous version range for a dependency on an internal library: cmmexperiment >=0 && ==0. This version range includes the current package but isn't needed as the current package's library will always be used.+Preprocessing executable 'demo' for cmmexperiment-0..+Building executable 'demo' for cmmexperiment-0..
+ cabal/cabal-testsuite/PackageTests/CmmSources/cabal.project view
@@ -0,0 +1,1 @@+packages: .
+ cabal/cabal-testsuite/PackageTests/CmmSources/cabal.test.hs view
@@ -0,0 +1,6 @@+import Test.Cabal.Prelude++main = cabalTest $ do+ res <- cabal' "v2-run" ["demo"]+ assertOutputContains "= Post common block elimination =" res+ assertOutputContains "In Box we have 0x" res
+ cabal/cabal-testsuite/PackageTests/CmmSources/cbits/HeapPrim.cmm view
@@ -0,0 +1,6 @@+#include "Cmm.h"++aToMyWordzh (P_ clos)+{+ return (clos);+}
+ cabal/cabal-testsuite/PackageTests/CmmSources/cmmexperiment.cabal view
@@ -0,0 +1,27 @@+cabal-version: 3.0+name: cmmexperiment+version: 0+build-type: Simple++-- This code is extracted form ghc-heap+-- Copyright (c) 2012-2013, Joachim Breitner+-- (and probably -2020 GHC Team)+-- Under BSD-3-Clause++library + default-language: Haskell2010+ hs-source-dirs: src+ build-depends: base+ exposed-modules: Demo++ cmm-sources: cbits/HeapPrim.cmm+ if impl(ghc >=8.2)+ cmm-options: -ddump-cmm-verbose+ else+ cmm-options: -ddump-cmm++executable demo+ default-language: Haskell2010+ main-is: Main.hs+ hs-source-dirs: demo+ build-depends: base, cmmexperiment
+ cabal/cabal-testsuite/PackageTests/CmmSources/demo/Main.hs view
@@ -0,0 +1,2 @@+module Main (main) where+import Demo (main)
+ cabal/cabal-testsuite/PackageTests/CmmSources/setup.out view
@@ -0,0 +1,7 @@+# Setup configure+Configuring cmmexperiment-0...+# Setup build+Preprocessing library for cmmexperiment-0..+Building library for cmmexperiment-0..+Preprocessing executable 'demo' for cmmexperiment-0..+Building executable 'demo' for cmmexperiment-0..
+ cabal/cabal-testsuite/PackageTests/CmmSources/setup.test.hs view
@@ -0,0 +1,7 @@+import Test.Cabal.Prelude++main = setupTest $ do+ skipIf =<< ghcVersionIs (< mkVersion [7,8])+ setup "configure" []+ res <- setup' "build" []+ assertOutputContains "= Post common block elimination =" res
+ cabal/cabal-testsuite/PackageTests/CmmSources/src/Demo.hs view
@@ -0,0 +1,37 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE ForeignFunctionInterface #-}+{-# LANGUAGE GHCForeignImportPrim #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE UnliftedFFITypes #-}+module Demo (main) where++#include "MachDeps.h"++import Data.Bits+import GHC.Exts+import Numeric (showHex)++foreign import prim "aToMyWordzh" aToWord# :: Any -> Word#++tAG_MASK :: Int+tAG_MASK = (1 `shift` TAG_BITS) - 1++data Box = Box Any++instance Show Box where+ showsPrec _ (Box a) rs =+ -- unsafePerformIO (print "↓" >> pClosure a) `seq`+ pad_out (showHex addr "") ++ (if tag>0 then "/" ++ show tag else "") ++ rs+ where+ ptr = W# (aToWord# a)+ tag = ptr .&. fromIntegral tAG_MASK -- ((1 `shiftL` TAG_BITS) -1)+ addr = ptr - tag+ pad_out ls = '0':'x':ls++asBox :: a -> Box+asBox x = Box (unsafeCoerce# x)++main :: IO ()+main = do+ let box = asBox "foobar"+ putStrLn $ "In Box we have " ++ show box
+ cabal/cabal-testsuite/PackageTests/Configure/cabal.out view
@@ -0,0 +1,8 @@+# cabal v2-build+Resolving dependencies...+Build profile: -w ghc-<GHCVER> -O1+In order, the following will be built:+ - zlib-1.1 (lib:zlib) (first run)+Configuring zlib-1.1...+Preprocessing library for zlib-1.1..+Building library for zlib-1.1..
+ cabal/cabal-testsuite/PackageTests/Configure/cabal.project view
@@ -0,0 +1,2 @@+-- remove me when `v2-build -z` is implemented+packages: .
+ cabal/cabal-testsuite/PackageTests/Configure/cabal.test.hs view
@@ -0,0 +1,10 @@+import Test.Cabal.Prelude+import Control.Monad.IO.Class+import Data.Maybe+import System.Directory+-- Test for 'build-type: Configure' example from the setup manual.+main = cabalTest $ do+ hasAutoreconf <- liftIO $ fmap isJust $ findExecutable "autoreconf"+ skipUnless hasAutoreconf+ _ <- shell "autoreconf" ["-i"]+ cabal "v2-build" []
cabal/cabal-testsuite/PackageTests/Configure/setup.test.hs view
@@ -3,7 +3,7 @@ import Data.Maybe import System.Directory -- Test for 'build-type: Configure' example from the setup manual.-main = setupAndCabalTest $ do+main = setupTest $ do hasAutoreconf <- liftIO $ fmap isJust $ findExecutable "autoreconf" skipUnless hasAutoreconf _ <- shell "autoreconf" ["-i"]
cabal/cabal-testsuite/PackageTests/ConfigureComponent/Exe/setup.cabal.out view
@@ -1,12 +1,4 @@ # Setup configure-Resolving dependencies...-Warning: solver failed to find a solution:-Could not resolve dependencies:-[__0] trying: Exe-0.1.0.0 (user goal)-[__1] unknown package: totally-impossible-dependency-to-fill (dependency of Exe)-[__1] fail (backjumping, conflict set: Exe, totally-impossible-dependency-to-fill)-After searching the rest of the dependency tree exhaustively, these were the goals I've had most trouble fulfilling: Exe (2), totally-impossible-dependency-to-fill (1)-Trying configure anyway. Configuring executable 'goodexe' for Exe-0.1.0.0.. # Setup build Preprocessing executable 'goodexe' for Exe-0.1.0.0..
cabal/cabal-testsuite/PackageTests/ConfigureComponent/SubLib/setup-explicit-fail.out view
@@ -10,4 +10,4 @@ # Setup configure Configuring executable 'exe' for Lib-0.1.0.0.. setup: Encountered missing or private dependencies:- sublib -any+ Lib:sublib
cabal/cabal-testsuite/PackageTests/ConfigureComponent/SubLib/setup-explicit.test.hs view
@@ -5,6 +5,6 @@ base_id <- getIPID "base" setup_install ["sublib", "--cid", "sublib-0.1-abc"] setup_install [ "exe", "--exact-configuration"- , "--dependency", "sublib:sublib=sublib-0.1-abc"+ , "--dependency", "Lib:sublib=sublib-0.1-abc" , "--dependency", "base=" ++ base_id ] runExe' "exe" [] >>= assertOutputContains "OK"
cabal/cabal-testsuite/PackageTests/CopyComponent/Exe/setup.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring myprog-0.1.0.0... # Setup build Preprocessing executable 'myprog' for myprog-0.1.0.0..
cabal/cabal-testsuite/PackageTests/CopyComponent/Lib/setup.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring p-0.1.0.0... # Setup build Preprocessing library for p-0.1.0.0..
− cabal/cabal-testsuite/PackageTests/CustomDep/sandbox.out
@@ -1,5 +0,0 @@-# cabal v1-sandbox init-Writing a default package environment file to <ROOT>/sandbox.dist/cabal.sandbox.config-Creating a new sandbox at <ROOT>/sandbox.dist/sandbox-# cabal v1-sandbox add-source-# cabal v1-sandbox add-source
− cabal/cabal-testsuite/PackageTests/CustomDep/sandbox.test.hs
@@ -1,22 +0,0 @@-import Test.Cabal.Prelude-main = cabalTest $ do- osx <- isOSX- win <- isWindows- -- On Travis OSX, Cabal shipped with GHC 7.8 does not work- -- with error "setup: /usr/bin/ar: permission denied"; see- -- also https://github.com/haskell/cabal/issues/3938- -- This is a hack to make the test not run in this case.- when osx $ skipUnless =<< ghcVersionIs (>= mkVersion [7,10])- -- On Appveyor, for some reason this test fails sometimes- -- due to missing symbols in Cabal 1.24. The solution is to- -- use a newer version of GHC that bundles a newer version- -- of Cabal, but for now, we skip.- when win $ skipUnless =<< ghcVersionIs (>= mkVersion [8,2])- withSandbox $ do- cabal_sandbox "add-source" ["custom"]- cabal_sandbox "add-source" ["client"]- -- NB: This test relies critically on the Setup script being- -- built against GHC's bundled Cabal. This means that the- -- output we see may vary between tests, so we don't record this.- recordMode DoNotRecord $- cabal "v1-install" ["client"]
cabal/cabal-testsuite/PackageTests/CustomPlain/setup.test.hs view
@@ -1,5 +1,5 @@ import Test.Cabal.Prelude-main = setupAndCabalTest $ do+main = setupTest $ do skipUnless =<< hasCabalForGhc -- On Travis OSX, Cabal shipped with GHC 7.8 does not work -- with error "setup: /usr/bin/ar: permission denied"; see
cabal/cabal-testsuite/PackageTests/CustomPreProcess/Setup.hs view
@@ -1,5 +1,14 @@+{-# LANGUAGE CPP #-} {-# OPTIONS_GHC -Wall #-} +-- The logic here is tricky.+-- If this is compiled by cabal-install, then the MIN_VERSION_Cabal is set+-- otherwise, we are compiling against Cabal library under test,+-- which is new!+#ifndef MIN_VERSION_Cabal+#define MIN_VERSION_Cabal(x,y,z) 1+#endif+ import Distribution.PackageDescription import Distribution.Simple import Distribution.Simple.LocalBuildInfo@@ -13,8 +22,13 @@ main = defaultMainWithHooks simpleUserHooks { hookedPreProcessors = [("pre", myCustomPreprocessor)] } where+#if MIN_VERSION_Cabal(2,0,0) myCustomPreprocessor :: BuildInfo -> LocalBuildInfo -> ComponentLocalBuildInfo -> PreProcessor myCustomPreprocessor _bi lbi _clbi =+#else+ myCustomPreprocessor :: BuildInfo -> LocalBuildInfo -> PreProcessor+ myCustomPreprocessor _bi lbi =+#endif PreProcessor { platformIndependent = True, runPreProcessor = mkSimplePreProcessor $ \inFile outFile verbosity ->
+ cabal/cabal-testsuite/PackageTests/CustomPreProcess/cabal.out view
@@ -0,0 +1,2 @@+# internal-preprocessor-test hello-world+hello from A
+ cabal/cabal-testsuite/PackageTests/CustomPreProcess/cabal.project view
@@ -0,0 +1,2 @@+-- remove me when `v2-build -z` is implemented+packages: .
+ cabal/cabal-testsuite/PackageTests/CustomPreProcess/cabal.test.hs view
@@ -0,0 +1,13 @@+import Test.Cabal.Prelude+-- Test internal custom preprocessor+main = cabalTest $ do+ skipUnless =<< hasCabalForGhc++ -- old Cabal's ./Setup.hs output is difficult to normalise+ recordMode DoNotRecord $+ cabal "v2-build" []++ -- here, we only care that result works:+ withPlan $ do+ r <- runPlanExe' "internal-preprocessor-test" "hello-world" []+ assertOutputContains "hello from A" r
cabal/cabal-testsuite/PackageTests/CustomPreProcess/internal-preprocessor-test.cabal view
@@ -9,6 +9,9 @@ build-type: Custom cabal-version: >=1.10 +custom-setup+ setup-depends: Cabal, base, process, filepath+ -- Note that exe comes before the library. -- The reason is backwards compat: old versions of Cabal (< 1.18) -- don't have a proper component build graph, so components are
cabal/cabal-testsuite/PackageTests/CustomPreProcess/setup.test.hs view
@@ -1,6 +1,6 @@ import Test.Cabal.Prelude -- Test internal custom preprocessor-main = setupAndCabalTest $ do+main = setupTest $ do skipUnless =<< hasCabalForGhc setup_build [] runExe' "hello-world" []
cabal/cabal-testsuite/PackageTests/DeterministicAr/my.cabal view
@@ -1,7 +1,7 @@ name: DeterministicAr version: 0 license: BSD3-cabal-version: >= 1.9.1+cabal-version: >= 1.10 author: Liyang HU stability: stable category: PackageTests@@ -12,6 +12,7 @@ all metadata in the resulting .a archive match the default. Library+ default-language: Haskell2010 exposed-modules: Lib build-depends: base
cabal/cabal-testsuite/PackageTests/DeterministicAr/setup-default-ar.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring DeterministicAr-0... # Setup build Preprocessing library for DeterministicAr-0..
cabal/cabal-testsuite/PackageTests/DeterministicAr/setup-old-ar-without-at-args.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring DeterministicAr-0... # Setup build Preprocessing library for DeterministicAr-0..
cabal/cabal-testsuite/PackageTests/DuplicateModuleName/setup.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring DuplicateModuleName-0.1.0.0... # Setup build Preprocessing library for DuplicateModuleName-0.1.0.0..@@ -9,20 +8,12 @@ Preprocessing test suite 'foo2' for DuplicateModuleName-0.1.0.0.. Building test suite 'foo2' for DuplicateModuleName-0.1.0.0.. # Setup test-Preprocessing library for DuplicateModuleName-0.1.0.0..-Building library for DuplicateModuleName-0.1.0.0..-Preprocessing test suite 'foo' for DuplicateModuleName-0.1.0.0..-Building test suite 'foo' for DuplicateModuleName-0.1.0.0.. Running 1 test suites... Test suite foo: RUNNING... Test suite foo: FAIL Test suite logged to: setup.cabal.dist/work/dist/test/DuplicateModuleName-0.1.0.0-foo.log 0 of 1 test suites (0 of 2 test cases) passed. # Setup test-Preprocessing library for DuplicateModuleName-0.1.0.0..-Building library for DuplicateModuleName-0.1.0.0..-Preprocessing test suite 'foo2' for DuplicateModuleName-0.1.0.0..-Building test suite 'foo2' for DuplicateModuleName-0.1.0.0.. Running 1 test suites... Test suite foo2: RUNNING... Test suite foo2: FAIL
cabal/cabal-testsuite/PackageTests/EmptyLib/setup.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring emptyLib-1.0... # Setup build Preprocessing library for emptyLib-1.0..
− cabal/cabal-testsuite/PackageTests/Exec/T4049/UseLib.c
@@ -1,9 +0,0 @@-#include <stdio.h>--int main()-{- myForeignLibInit();- sayHi();- myForeignLibExit();- return 0;-}
− cabal/cabal-testsuite/PackageTests/Exec/T4049/csrc/MyForeignLibWrapper.c
@@ -1,23 +0,0 @@-#include <stdlib.h>-#include "HsFFI.h"--HsBool myForeignLibInit(void){- int argc = 2;- char *argv[] = { "+RTS", "-A32m", NULL };- char **pargv = argv;-- // Initialize Haskell runtime- hs_init(&argc, &pargv);-- // do any other initialization here and- // return false if there was a problem- return HS_BOOL_TRUE;-}--void myForeignLibExit(void){- hs_exit();-}--int cFoo2() {- return 1234;-}
− cabal/cabal-testsuite/PackageTests/Exec/T4049/my-foreign-lib.cabal
@@ -1,19 +0,0 @@-name: my-foreign-lib-version: 0.1.0.0-author: Edsko de Vries-maintainer: edsko@well-typed.com-build-type: Simple-cabal-version: >=1.10--foreign-library myforeignlib- type: native-shared-- if os(windows)- options: standalone-- other-modules: MyForeignLib.Hello- MyForeignLib.SomeBindings- build-depends: base- hs-source-dirs: src- c-sources: csrc/MyForeignLibWrapper.c- default-language: Haskell2010
− cabal/cabal-testsuite/PackageTests/Exec/T4049/sandbox.out
@@ -1,12 +0,0 @@-# cabal v1-sandbox init-Writing a default package environment file to <ROOT>/sandbox.dist/cabal.sandbox.config-Creating a new sandbox at <ROOT>/sandbox.dist/sandbox-# cabal v1-install-Resolving dependencies...-Configuring my-foreign-lib-0.1.0.0...-Preprocessing foreign library 'myforeignlib' for my-foreign-lib-0.1.0.0..-Building foreign library 'myforeignlib' for my-foreign-lib-0.1.0.0..-Installing foreign library myforeignlib in <PATH>-Completed my-foreign-lib-0.1.0.0-# cabal v1-exec-Hi from a foreign library! Foo has value 5678
− cabal/cabal-testsuite/PackageTests/Exec/T4049/sandbox.test.hs
@@ -1,20 +0,0 @@-import Test.Cabal.Prelude-main = cabalTest $ do- skipUnless =<< ghcVersionIs (>= mkVersion [7,8])- withSandbox $ do- cabal "v1-install" ["--enable-shared"]- env <- getTestEnv- is_windows <- isWindows- let sandbox_dir = testSandboxDir env- work_dir = testWorkDir env- lib_dir =- -- This is dumb but it's been this way for a long time.- if is_windows- then sandbox_dir- else sandbox_dir </> "lib"- gcc [ "UseLib.c"- , "-o", work_dir </> "UseLib"- , "-l" ++ "myforeignlib"- , "-L" ++ lib_dir ]- recordMode RecordAll $- cabal "v1-exec" ["-v0", work_dir </> "UseLib"]
− cabal/cabal-testsuite/PackageTests/Exec/T4049/src/MyForeignLib/Hello.hs
@@ -1,10 +0,0 @@--- | Module with single foreign export-module MyForeignLib.Hello (sayHi) where--import MyForeignLib.SomeBindings--foreign export ccall sayHi :: IO ()---- | Say hi!-sayHi :: IO ()-sayHi = putStrLn $ "Hi from a foreign library! Foo has value " ++ show valueOfFoo
− cabal/cabal-testsuite/PackageTests/Exec/T4049/src/MyForeignLib/SomeBindings.hsc
@@ -1,10 +0,0 @@--- | Module that needs the hsc2hs preprocessor-module MyForeignLib.SomeBindings where--#define FOO 1--#ifdef FOO--- | Value guarded by a CPP flag-valueOfFoo :: Int-valueOfFoo = 5678-#endif
− cabal/cabal-testsuite/PackageTests/Exec/sandbox-ghc-pkg.out
@@ -1,16 +0,0 @@-# cabal v1-sandbox init-Writing a default package environment file to <ROOT>/sandbox-ghc-pkg.dist/cabal.sandbox.config-Creating a new sandbox at <ROOT>/sandbox-ghc-pkg.dist/sandbox-# cabal v1-exec-cabal: The program 'my-executable' is required but it could not be found.-# cabal v1-install-Resolving dependencies...-Configuring my-0.1...-Preprocessing executable 'my-executable' for my-0.1..-Building executable 'my-executable' for my-0.1..-Preprocessing library for my-0.1..-Building library for my-0.1..-Installing executable my-executable in <PATH>-Installing library in <PATH>-Completed my-0.1-# cabal v1-exec
− cabal/cabal-testsuite/PackageTests/Exec/sandbox-ghc-pkg.test.hs
@@ -1,12 +0,0 @@-import Test.Cabal.Prelude-import Data.Maybe-main = cabalTest $ do- withPackageDb $ do- withSandbox $ do- fails $ cabal "v1-exec" ["my-executable"]- cabal "v1-install" []- -- The library should not be available outside the sandbox- ghcPkg' "list" [] >>= assertOutputDoesNotContain "my-0.1"- -- Execute ghc-pkg inside the sandbox; it should find my-0.1- cabal' "v1-exec" ["ghc-pkg", "list"]- >>= assertOutputContains "my-0.1"
− cabal/cabal-testsuite/PackageTests/Exec/sandbox-hc-pkg.out
@@ -1,16 +0,0 @@-# cabal v1-sandbox init-Writing a default package environment file to <ROOT>/sandbox-hc-pkg.dist/cabal.sandbox.config-Creating a new sandbox at <ROOT>/sandbox-hc-pkg.dist/sandbox-# cabal v1-exec-cabal: The program 'my-executable' is required but it could not be found.-# cabal v1-install-Resolving dependencies...-Configuring my-0.1...-Preprocessing executable 'my-executable' for my-0.1..-Building executable 'my-executable' for my-0.1..-Preprocessing library for my-0.1..-Building library for my-0.1..-Installing executable my-executable in <PATH>-Installing library in <PATH>-Completed my-0.1-# cabal v1-exec
− cabal/cabal-testsuite/PackageTests/Exec/sandbox-hc-pkg.test.hs
@@ -1,26 +0,0 @@-import Test.Cabal.Prelude-import Data.Maybe-import Distribution.Compat.Directory-import Control.Monad.IO.Class--main = cabalTest $ do- withPackageDb $ do- withSandbox $ do- fails $ cabal "v1-exec" ["my-executable"]- cabal "v1-install" []- -- The library should not be available outside the sandbox- ghcPkg' "list" [] >>= assertOutputDoesNotContain "my-0.1"- -- When run inside 'cabal-exec' the 'sandbox hc-pkg list' sub-command- -- should find the library.- env <- getTestEnv- -- NB: cabal_path might be relative, so we have to- -- turn it absolute- rel_cabal_path <- programPathM cabalProgram- cabal_path <- liftIO $ makeAbsolute rel_cabal_path- cabal' "v1-exec" ["sh", "--", "-c"- , "cd subdir && " ++ show cabal_path ++- -- TODO: Ugh. Test abstractions leaking- -- through- " --sandbox-config-file " ++ show (testSandboxConfigFile env) ++- " v1-sandbox hc-pkg list"]- >>= assertOutputContains "my-0.1"
− cabal/cabal-testsuite/PackageTests/Exec/sandbox-path.out
@@ -1,16 +0,0 @@-# cabal v1-sandbox init-Writing a default package environment file to <ROOT>/sandbox-path.dist/cabal.sandbox.config-Creating a new sandbox at <ROOT>/sandbox-path.dist/sandbox-# cabal v1-exec-cabal: The program 'my-executable' is required but it could not be found.-# cabal v1-install-Resolving dependencies...-Configuring my-0.1...-Preprocessing executable 'my-executable' for my-0.1..-Building executable 'my-executable' for my-0.1..-Preprocessing library for my-0.1..-Building library for my-0.1..-Installing executable my-executable in <PATH>-Installing library in <PATH>-Completed my-0.1-# cabal v1-exec
− cabal/cabal-testsuite/PackageTests/Exec/sandbox-path.test.hs
@@ -1,8 +0,0 @@-import Test.Cabal.Prelude-main = cabalTest $ do- withSandbox $ do- fails $ cabal "v1-exec" ["my-executable"]- cabal "v1-install" []- -- Execute indirectly via bash to ensure that we go through $PATH- cabal' "v1-exec" ["sh", "--", "-c", "my-executable"]- >>= assertOutputContains "This is my-executable"
− cabal/cabal-testsuite/PackageTests/Exec/sandbox.out
@@ -1,16 +0,0 @@-# cabal v1-sandbox init-Writing a default package environment file to <ROOT>/sandbox.dist/cabal.sandbox.config-Creating a new sandbox at <ROOT>/sandbox.dist/sandbox-# cabal v1-exec-cabal: The program 'my-executable' is required but it could not be found.-# cabal v1-install-Resolving dependencies...-Configuring my-0.1...-Preprocessing executable 'my-executable' for my-0.1..-Building executable 'my-executable' for my-0.1..-Preprocessing library for my-0.1..-Building library for my-0.1..-Installing executable my-executable in <PATH>-Installing library in <PATH>-Completed my-0.1-# cabal v1-exec
− cabal/cabal-testsuite/PackageTests/Exec/sandbox.test.hs
@@ -1,7 +0,0 @@-import Test.Cabal.Prelude-main = cabalTest $ do- withSandbox $ do- fails $ cabal "v1-exec" ["my-executable"]- cabal "v1-install" []- cabal' "v1-exec" ["my-executable"]- >>= assertOutputContains "This is my-executable"
cabal/cabal-testsuite/PackageTests/ForeignLibs/setup.test.hs view
@@ -39,6 +39,7 @@ , "UseLib.c" , "-l", "myforeignlib" , "-L", flibdir installDirs ]+ Nothing -- Run the C program let ldPath = case hostPlatform lbi of@@ -48,7 +49,7 @@ oldLdPath <- liftIO $ getEnv' ldPath withEnv [ (ldPath, Just $ flibdir installDirs ++ [searchPathSeparator] ++ oldLdPath) ] $ do cwd <- fmap testCurrentDir getTestEnv- result <- runM (cwd </> "uselib") []+ result <- runM (cwd </> "uselib") [] Nothing assertOutputContains "5678" result assertOutputContains "189" result @@ -70,7 +71,7 @@ objInfo <- runM (programPath objdump) [ "-x" , libdir </> libraryName- ]+ ] Nothing assertBool "SONAME of 'libversionedlib.so.5.4.3' incorrect" $ elem "libversionedlib.so.5" $ words $ resultOutput objInfo _ -> return ()
cabal/cabal-testsuite/PackageTests/Freeze/freeze.test.hs view
@@ -1,8 +1,6 @@ import Test.Cabal.Prelude main = cabalTest $ do withRepo "repo" . withSourceCopy $ do- -- TODO: test this with a sandbox-installed package- -- that is not depended upon cabal "v1-freeze" [] cwd <- fmap testCurrentDir getTestEnv assertFileDoesNotContain (cwd </> "cabal.config") "exceptions"
cabal/cabal-testsuite/PackageTests/Freeze/my.cabal view
@@ -1,20 +1,23 @@ name: my version: 0.1 license: BSD3-cabal-version: >= 1.20.0+cabal-version: 1.20 build-type: Simple library+ default-language: Haskell2010 exposed-modules: Foo build-depends: base test-suite test-Foo+ default-language: Haskell2010 type: exitcode-stdio-1.0 hs-source-dirs: tests main-is: test-Foo.hs build-depends: base, my, test-framework benchmark bench-Foo+ default-language: Haskell2010 type: exitcode-stdio-1.0 hs-source-dirs: benchmarks main-is: benchmark-Foo.hs
cabal/cabal-testsuite/PackageTests/GhcPkgGuess/SameDirectory/setup.cabal.out view
@@ -1,2 +1,3 @@ # Setup configure+Configuring SameDirectory-0.1.0.0... cabal: Version mismatch between ghc and ghc-pkg: <ROOT>/./ghc is version <GHCVER> <ROOT>/./ghc-pkg is version 9999999
cabal/cabal-testsuite/PackageTests/GhcPkgGuess/SameDirectoryGhcVersion/setup.cabal.out view
@@ -1,2 +1,3 @@ # Setup configure+Configuring SameDirectory-0.1.0.0... cabal: Version mismatch between ghc and ghc-pkg: <ROOT>/./ghc-7.10 is version <GHCVER> <ROOT>/./ghc-pkg-ghc-7.10 is version 9999999
cabal/cabal-testsuite/PackageTests/GhcPkgGuess/SameDirectoryVersion/setup.cabal.out view
@@ -1,2 +1,3 @@ # Setup configure+Configuring SameDirectory-0.1.0.0... cabal: Version mismatch between ghc and ghc-pkg: <ROOT>/./ghc-7.10 is version <GHCVER> <ROOT>/./ghc-pkg-7.10 is version 9999999
cabal/cabal-testsuite/PackageTests/GhcPkgGuess/Symlink/setup.cabal.out view
@@ -1,2 +1,3 @@ # Setup configure+Configuring SameDirectory-0.1.0.0... cabal: Version mismatch between ghc and ghc-pkg: <ROOT>/./ghc is version <GHCVER> <ROOT>/bin/ghc-pkg is version 9999999
cabal/cabal-testsuite/PackageTests/GhcPkgGuess/SymlinkGhcVersion/setup.cabal.out view
@@ -1,2 +1,3 @@ # Setup configure+Configuring SameDirectory-0.1.0.0... cabal: Version mismatch between ghc and ghc-pkg: <ROOT>/./ghc is version <GHCVER> <ROOT>/bin/ghc-pkg-7.10 is version 9999999
cabal/cabal-testsuite/PackageTests/GhcPkgGuess/SymlinkVersion/setup.cabal.out view
@@ -1,2 +1,3 @@ # Setup configure+Configuring SameDirectory-0.1.0.0... cabal: Version mismatch between ghc and ghc-pkg: <ROOT>/./ghc is version <GHCVER> <ROOT>/bin/ghc-pkg-ghc-7.10 is version 9999999
cabal/cabal-testsuite/PackageTests/Haddock/my.cabal view
@@ -5,12 +5,13 @@ stability: stable category: PackageTests build-type: Simple-Cabal-version: >= 1.2+Cabal-version: >= 1.10 description: Check that Cabal successfully invokes Haddock. Library+ default-language: Haskell2010 exposed-modules: CPP, Literate, NoCPP, Simple other-extensions: CPP build-depends: base
cabal/cabal-testsuite/PackageTests/Haddock/setup.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring Haddock-0.1... # Setup haddock Preprocessing library for Haddock-0.1..
cabal/cabal-testsuite/PackageTests/HaddockNewline/setup.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring HaddockNewline-0.1.0.0... # Setup haddock Preprocessing library for HaddockNewline-0.1.0.0..
cabal/cabal-testsuite/PackageTests/InternalLibraries/Executable/foo.cabal view
@@ -4,7 +4,7 @@ author: Edward Z. Yang maintainer: ezyang@cs.stanford.edu build-type: Simple-cabal-version: >=1.23+cabal-version: 1.24 library foo-internal exposed-modules: Foo
cabal/cabal-testsuite/PackageTests/InternalLibraries/Executable/setup-static.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring foo-0.1.0.0... # Setup build Preprocessing library 'foo-internal' for foo-0.1.0.0..@@ -17,7 +16,6 @@ # foo 46 # Setup configure-Resolving dependencies... Configuring foo-0.1.0.0... # Setup build Preprocessing library 'foo-internal' for foo-0.1.0.0..
cabal/cabal-testsuite/PackageTests/InternalLibraries/Library/foolib/foolib.cabal view
@@ -4,9 +4,10 @@ author: Edward Z. Yang maintainer: ezyang@cs.stanford.edu build-type: Simple-cabal-version: >=1.23+cabal-version: 1.24 library foolib-internal+ default-language: Haskell2010 exposed-modules: Internal hs-source-dirs: private build-depends: base
cabal/cabal-testsuite/PackageTests/InternalLibraries/Library/setup.cabal.out view
@@ -1,7 +1,5 @@ # Setup configure-Resolving dependencies... Configuring foolib-0.1.0.0...-Warning: Packages using 'cabal-version: >= 1.10' must specify the 'default-language' field for each component (e.g. Haskell98 or Haskell2010). If a component uses different languages in different modules then list the other ones in the 'other-languages' field. # Setup build Preprocessing library 'foolib-internal' for foolib-0.1.0.0.. Building library 'foolib-internal' for foolib-0.1.0.0..@@ -14,7 +12,6 @@ Registering library 'foolib-internal' for foolib-0.1.0.0.. Registering library for foolib-0.1.0.0.. # Setup configure-Resolving dependencies... Configuring fooexe-0.1.0.0... # Setup build Preprocessing executable 'fooexe' for fooexe-0.1.0.0..
cabal/cabal-testsuite/PackageTests/InternalLibraries/Library/setup.out view
@@ -1,6 +1,5 @@ # Setup configure Configuring foolib-0.1.0.0...-Warning: Packages using 'cabal-version: >= 1.10' must specify the 'default-language' field for each component (e.g. Haskell98 or Haskell2010). If a component uses different languages in different modules then list the other ones in the 'other-languages' field. # Setup build Preprocessing library 'foolib-internal' for foolib-0.1.0.0.. Building library 'foolib-internal' for foolib-0.1.0.0..
cabal/cabal-testsuite/PackageTests/InternalLibraries/cabal.out view
@@ -9,8 +9,10 @@ Preprocessing library 'q' for p-0.1.0.0.. Building library 'q' for p-0.1.0.0.. Configuring executable 'foo' for p-0.1.0.0..+Warning: The package has an extraneous version range for a dependency on an internal library: p:q >=0 && ==0.1.0.0, p:q >=0 && ==0.1.0.0. This version range includes the current package but isn't needed as the current package's library will always be used. Preprocessing executable 'foo' for p-0.1.0.0.. Building executable 'foo' for p-0.1.0.0.. Configuring library for p-0.1.0.0..+Warning: The package has an extraneous version range for a dependency on an internal library: p:q >=0 && ==0.1.0.0, p:q >=0 && ==0.1.0.0. This version range includes the current package but isn't needed as the current package's library will always be used. Preprocessing library for p-0.1.0.0.. Building library for p-0.1.0.0..
cabal/cabal-testsuite/PackageTests/InternalLibraries/p/p.cabal view
@@ -4,7 +4,7 @@ author: Edward Z. Yang maintainer: ezyang@cs.stanford.edu build-type: Simple-cabal-version: >=1.23+cabal-version: 1.24 library q build-depends: base
− cabal/cabal-testsuite/PackageTests/InternalLibraries/sandbox-shadow.out
@@ -1,18 +0,0 @@-# cabal v1-sandbox init-Writing a default package environment file to <ROOT>/sandbox-shadow.dist/cabal.sandbox.config-Creating a new sandbox at <ROOT>/sandbox-shadow.dist/sandbox-# cabal v1-sandbox add-source-# cabal v1-sandbox add-source-# cabal v1-install-Resolving dependencies...-Configuring p-0.1.0.0...-Preprocessing library 'q' for p-0.1.0.0..-Building library 'q' for p-0.1.0.0..-Preprocessing executable 'foo' for p-0.1.0.0..-Building executable 'foo' for p-0.1.0.0..-Preprocessing library for p-0.1.0.0..-Building library for p-0.1.0.0..-Installing internal library q in <PATH>-Installing executable foo in <PATH>-Installing library in <PATH>-Completed p-0.1.0.0
− cabal/cabal-testsuite/PackageTests/InternalLibraries/sandbox-shadow.test.hs
@@ -1,6 +0,0 @@-import Test.Cabal.Prelude-main = cabalTest $ do- withSandbox $ do- cabal_sandbox "add-source" ["p"]- cabal_sandbox "add-source" ["q"]- cabal "v1-install" ["p"]
− cabal/cabal-testsuite/PackageTests/InternalLibraries/sandbox.out
@@ -1,17 +0,0 @@-# cabal v1-sandbox init-Writing a default package environment file to <ROOT>/sandbox.dist/cabal.sandbox.config-Creating a new sandbox at <ROOT>/sandbox.dist/sandbox-# cabal v1-sandbox add-source-# cabal v1-install-Resolving dependencies...-Configuring p-0.1.0.0...-Preprocessing library 'q' for p-0.1.0.0..-Building library 'q' for p-0.1.0.0..-Preprocessing executable 'foo' for p-0.1.0.0..-Building executable 'foo' for p-0.1.0.0..-Preprocessing library for p-0.1.0.0..-Building library for p-0.1.0.0..-Installing internal library q in <PATH>-Installing executable foo in <PATH>-Installing library in <PATH>-Completed p-0.1.0.0
− cabal/cabal-testsuite/PackageTests/InternalLibraries/sandbox.test.hs
@@ -1,5 +0,0 @@-import Test.Cabal.Prelude-main = cabalTest $ do- withSandbox $ do- cabal_sandbox "add-source" ["p"]- cabal "v1-install" ["p"]
cabal/cabal-testsuite/PackageTests/InternalLibraries/setup-gen-pkg-config.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring p-0.1.0.0... # Setup build Preprocessing library 'q' for p-0.1.0.0..@@ -15,7 +14,6 @@ Installing library in <PATH> # Setup register # Setup configure-Resolving dependencies... Configuring r-0.1.0.0... # Setup build Preprocessing library for r-0.1.0.0..
cabal/cabal-testsuite/PackageTests/InternalLibraries/setup-gen-script.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring p-0.1.0.0... # Setup build Preprocessing library 'q' for p-0.1.0.0..@@ -15,7 +14,6 @@ Installing library in <PATH> # Setup register # Setup configure-Resolving dependencies... Configuring r-0.1.0.0... # Setup build Preprocessing library for r-0.1.0.0..
cabal/cabal-testsuite/PackageTests/InternalLibraries/setup.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring q-0.1.0.0... # Setup build Preprocessing library for q-0.1.0.0..@@ -9,7 +8,6 @@ # Setup register Registering library for q-0.1.0.0.. # Setup configure-Resolving dependencies... Configuring p-0.1.0.0... # Setup build Preprocessing library 'q' for p-0.1.0.0..
cabal/cabal-testsuite/PackageTests/InternalVersions/BuildDependsBad/setup.cabal.out view
@@ -1,11 +1,3 @@ # Setup configure-Resolving dependencies...-Warning: solver failed to find a solution:-Could not resolve dependencies:-[__0] next goal: build-depends-bad-version (user goal)-[__0] rejecting: build-depends-bad-version-0.1.0.0 (conflict: build-depends-bad-version==0.1.0.0, build-depends-bad-version => build-depends-bad-version>=2)-[__0] fail (backjumping, conflict set: build-depends-bad-version)-After searching the rest of the dependency tree exhaustively, these were the goals I've had most trouble fulfilling: build-depends-bad-version (2)-Trying configure anyway. Configuring build-depends-bad-version-0.1.0.0... cabal: The package has an impossible version range for a dependency on an internal library: build-depends-bad-version >=2. This version range does not include the current package, and must be removed as the current package's library will always be used.
cabal/cabal-testsuite/PackageTests/InternalVersions/BuildDependsExtra/setup.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring build-depends-extra-version-0.1.0.0... Warning: The package has an extraneous version range for a dependency on an internal library: build-depends-extra-version >=0.0.0.1. This version range includes the current package but isn't needed as the current package's library will always be used. # Setup sdist@@ -11,6 +10,4 @@ A 'license-file' is not specified. Note: the public hackage server would reject this package. Building source dist for build-depends-extra-version-0.1.0.0...-Preprocessing library for build-depends-extra-version-0.1.0.0..-Preprocessing executable 'bar' for build-depends-extra-version-0.1.0.0.. Source tarball created: setup.cabal.dist/work/dist/build-depends-extra-version-0.1.0.0.tar.gz
cabal/cabal-testsuite/PackageTests/InternalVersions/BuildDependsExtra/setup.out view
@@ -10,6 +10,4 @@ A 'license-file' is not specified. Note: the public hackage server would reject this package. Building source dist for build-depends-extra-version-0.1.0.0...-Preprocessing library for build-depends-extra-version-0.1.0.0..-Preprocessing executable 'bar' for build-depends-extra-version-0.1.0.0.. Source tarball created: setup.dist/work/dist/build-depends-extra-version-0.1.0.0.tar.gz
cabal/cabal-testsuite/PackageTests/InternalVersions/BuildToolDependsBad/setup.cabal.out view
@@ -1,4 +1,3 @@ # Setup configure-Resolving dependencies... Configuring build-tool-depends-bad-version-0.1.0.0... cabal: The package has an impossible version range for a dependency on an internal executable: build-tool-depends-bad-version:hello-world >=2. This version range does not include the current package, and must be removed as the current package's executable will always be used.
cabal/cabal-testsuite/PackageTests/InternalVersions/BuildToolDependsExtra/setup.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring build-tool-depends-extra-version-0.1.0.0... Warning: The package has an extraneous version range for a dependency on an internal executable: build-tool-depends-extra-version:hello-world >=0.0.0.1. This version range includes the current package but isn't needed as the current package's executable will always be used. # Setup sdist@@ -11,6 +10,4 @@ A 'license-file' is not specified. Note: the public hackage server would reject this package. Building source dist for build-tool-depends-extra-version-0.1.0.0...-Preprocessing executable 'hello-world' for build-tool-depends-extra-version-0.1.0.0..-Preprocessing library for build-tool-depends-extra-version-0.1.0.0.. Source tarball created: setup.cabal.dist/work/dist/build-tool-depends-extra-version-0.1.0.0.tar.gz
cabal/cabal-testsuite/PackageTests/InternalVersions/BuildToolDependsExtra/setup.out view
@@ -10,6 +10,4 @@ A 'license-file' is not specified. Note: the public hackage server would reject this package. Building source dist for build-tool-depends-extra-version-0.1.0.0...-Preprocessing executable 'hello-world' for build-tool-depends-extra-version-0.1.0.0..-Preprocessing library for build-tool-depends-extra-version-0.1.0.0.. Source tarball created: setup.dist/work/dist/build-tool-depends-extra-version-0.1.0.0.tar.gz
cabal/cabal-testsuite/PackageTests/InternalVersions/BuildToolsBad/setup.cabal.out view
@@ -1,4 +1,3 @@ # Setup configure-Resolving dependencies... Configuring build-tools-bad-version-0.1.0.0... cabal: The package has an impossible version range for a dependency on an internal executable: build-tools-bad-version:hello-world >=2. This version range does not include the current package, and must be removed as the current package's executable will always be used.
cabal/cabal-testsuite/PackageTests/InternalVersions/BuildToolsExtra/setup.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring build-tools-extra-version-0.1.0.0... Warning: The package has an extraneous version range for a dependency on an internal executable: build-tools-extra-version:hello-world >=0.0.0.1. This version range includes the current package but isn't needed as the current package's executable will always be used. # Setup sdist@@ -11,6 +10,4 @@ A 'license-file' is not specified. Note: the public hackage server would reject this package. Building source dist for build-tools-extra-version-0.1.0.0...-Preprocessing executable 'hello-world' for build-tools-extra-version-0.1.0.0..-Preprocessing library for build-tools-extra-version-0.1.0.0.. Source tarball created: setup.cabal.dist/work/dist/build-tools-extra-version-0.1.0.0.tar.gz
cabal/cabal-testsuite/PackageTests/InternalVersions/BuildToolsExtra/setup.out view
@@ -10,6 +10,4 @@ A 'license-file' is not specified. Note: the public hackage server would reject this package. Building source dist for build-tools-extra-version-0.1.0.0...-Preprocessing executable 'hello-world' for build-tools-extra-version-0.1.0.0..-Preprocessing library for build-tools-extra-version-0.1.0.0.. Source tarball created: setup.dist/work/dist/build-tools-extra-version-0.1.0.0.tar.gz
cabal/cabal-testsuite/PackageTests/Macros/setup.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring macros-0.1.0.0... # Setup build Preprocessing library for macros-0.1.0.0..
cabal/cabal-testsuite/PackageTests/Manpage/cabal.out view
@@ -1,1 +1,1 @@-# cabal manpage+# cabal man
cabal/cabal-testsuite/PackageTests/Manpage/cabal.test.hs view
@@ -1,5 +1,5 @@ import Test.Cabal.Prelude main = cabalTest $ do- r <- cabal' "manpage" []+ r <- cabal' "man" ["--raw"] assertOutputContains ".B cabal install" r assertOutputDoesNotContain ".B cabal manpage" r
+ cabal/cabal-testsuite/PackageTests/MultipleLibraries/Failing/cabal.out view
@@ -0,0 +1,8 @@+# cabal v2-build+Resolving dependencies...+cabal: Could not resolve dependencies:+[__0] trying: d-0.1.0.0 (user goal)+[__1] next goal: p (user goal)+[__1] rejecting: p-0.1.0.0 (requires library 'privatelib' from d, but the component is private)+[__1] fail (backjumping, conflict set: d, p)+After searching the rest of the dependency tree exhaustively, these were the goals I've had most trouble fulfilling: d (2), p (2)
+ cabal/cabal-testsuite/PackageTests/MultipleLibraries/Failing/cabal.project view
@@ -0,0 +1,4 @@+packages:+ d+ p+
+ cabal/cabal-testsuite/PackageTests/MultipleLibraries/Failing/cabal.test.hs view
@@ -0,0 +1,4 @@+import Test.Cabal.Prelude+main = cabalTest $+ void $ fails (cabal' "v2-build" ["p"])+
+ cabal/cabal-testsuite/PackageTests/MultipleLibraries/Failing/d/d.cabal view
@@ -0,0 +1,12 @@+cabal-version: 3.0+name: d+version: 0.1.0.0++-- See issue #6038+library+ default-language: Haskell2010++library privatelib+ visibility: private+ default-language: Haskell2010+
+ cabal/cabal-testsuite/PackageTests/MultipleLibraries/Failing/p/p.cabal view
@@ -0,0 +1,8 @@+cabal-version: 3.0+name: p+version: 0.1.0.0++library+ build-depends: d:privatelib+ default-language: Haskell2010+
+ cabal/cabal-testsuite/PackageTests/MultipleLibraries/Successful/cabal.out view
@@ -0,0 +1,14 @@+# cabal v2-run+Resolving dependencies...+Build profile: -w ghc-<GHCVER> -O1+In order, the following will be built:+ - pkg-def-0.1.0.0 (lib:publib) (first run)+ - pkg-abc-0.1.0.0 (exe:program) (first run)+Warning: pkg-def.cabal:10:27: visibility is experimental feature (issue #5660)+Configuring library 'publib' for pkg-def-0.1.0.0..+Preprocessing library 'publib' for pkg-def-0.1.0.0..+Building library 'publib' for pkg-def-0.1.0.0..+Warning: pkg-abc.cabal:10:15: colon specifier is experimental feature (issue #5660)+Configuring executable 'program' for pkg-abc-0.1.0.0..+Preprocessing executable 'program' for pkg-abc-0.1.0.0..+Building executable 'program' for pkg-abc-0.1.0.0..
+ cabal/cabal-testsuite/PackageTests/MultipleLibraries/Successful/cabal.project view
@@ -0,0 +1,4 @@+packages:+ pkg-abc+ pkg-def+
+ cabal/cabal-testsuite/PackageTests/MultipleLibraries/Successful/cabal.test.hs view
@@ -0,0 +1,4 @@+import Test.Cabal.Prelude+main = cabalTest $+ cabal' "v2-run" ["pkg-abc:program"] >>= assertOutputContains "pkg-def:publib"+
+ cabal/cabal-testsuite/PackageTests/MultipleLibraries/Successful/pkg-abc/Main.hs view
@@ -0,0 +1,5 @@+module Main (main) where+import PkgDef (defValue)++main :: IO ()+main = print defValue
+ cabal/cabal-testsuite/PackageTests/MultipleLibraries/Successful/pkg-abc/pkg-abc.cabal view
@@ -0,0 +1,10 @@+cabal-version: 3.0+name: pkg-abc+version: 0.1.0.0++executable program+ default-language: Haskell2010+ main-is: Main.hs+ build-depends:+ , base+ , pkg-def:publib
+ cabal/cabal-testsuite/PackageTests/MultipleLibraries/Successful/pkg-def/pkg-def.cabal view
@@ -0,0 +1,14 @@+cabal-version: 3.0+name: pkg-def+version: 0.1.0.0++-- there was public library. But we shouldn't need one.+-- https://github.com/haskell/cabal/issues/6038++library publib+ default-language: Haskell2010+ visibility: public+ hs-source-dirs: publib+ build-depends: base+ exposed-modules: PkgDef+
+ cabal/cabal-testsuite/PackageTests/MultipleLibraries/Successful/pkg-def/publib/PkgDef.hs view
@@ -0,0 +1,4 @@+module PkgDef (defValue) where++defValue :: String+defValue = "pkg-def:publib"
+ cabal/cabal-testsuite/PackageTests/MultipleLibraries/Successful/pkg-def/src/PkgDef.hs view
@@ -0,0 +1,4 @@+module PkgDef (defValue) where++defValue :: String+defValue = "pkg-def:pkg-def"
+ cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083Post/cabal.out view
@@ -0,0 +1,15 @@+# cabal v2-run+Resolving dependencies...+Build profile: -w ghc-<GHCVER> -O1+In order, the following will be built:+ - pkg-def-0.1.0.0 (lib) (first run)+ - pkg-abc-0.1.0.0 (exe:program) (first run)+Warning: pkg-def.cabal:13:27: visibility is experimental feature (issue #5660)+Configuring library for pkg-def-0.1.0.0..+Preprocessing library for pkg-def-0.1.0.0..+Building library for pkg-def-0.1.0.0..+Warning: pkg-abc.cabal:19:15: colon specifier is experimental feature (issue #5660)+Configuring executable 'program' for pkg-abc-0.1.0.0..+Warning: The package has an extraneous version range for a dependency on an internal library: pkg-def >=0 && ==0.1.0.0. This version range includes the current package but isn't needed as the current package's library will always be used.+Preprocessing executable 'program' for pkg-abc-0.1.0.0..+Building executable 'program' for pkg-abc-0.1.0.0..
+ cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083Post/cabal.project view
@@ -0,0 +1,4 @@+packages:+ pkg-abc+ pkg-def+
+ cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083Post/cabal.test.hs view
@@ -0,0 +1,6 @@+import Test.Cabal.Prelude++-- https://github.com/haskell/cabal/issues/6083+-- see pkg-abc.cabal+main = cabalTest $+ cabal' "v2-run" ["pkg-abc:program"] >>= assertOutputContains "pkg-def:pkg-def"
+ cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083Post/pkg-abc/exe/Main.hs view
@@ -0,0 +1,5 @@+module Main (main) where+import PkgDef (defValue)++main :: IO ()+main = print defValue
+ cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083Post/pkg-abc/pkg-abc.cabal view
@@ -0,0 +1,19 @@+cabal-version: 3.4+name: pkg-abc+version: 0.1.0.0++library pkg-def+ default-language: Haskell2010+ hs-source-dirs: pkg-def+ build-depends: base+ exposed-modules: PkgDef++executable program+ default-language: Haskell2010+ hs-source-dirs: exe+ main-is: Main.hs++ -- we want that to resolve to pkg-def main library.+ build-depends:+ , base+ , pkg-def:pkg-def
+ cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083Post/pkg-abc/pkg-def/PkgDef.hs view
@@ -0,0 +1,4 @@+module PkgDef (defValue) where++defValue :: String+defValue = "pkg-abc:pkg-def"
+ cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083Post/pkg-def/pkg-def.cabal view
@@ -0,0 +1,17 @@+cabal-version: 3.0+name: pkg-def+version: 0.1.0.0++library+ default-language: Haskell2010+ hs-source-dirs: src+ build-depends: base+ exposed-modules: PkgDef++library publib+ default-language: Haskell2010+ visibility: public+ hs-source-dirs: publib+ build-depends: base+ exposed-modules: PkgDef+
+ cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083Post/pkg-def/publib/PkgDef.hs view
@@ -0,0 +1,4 @@+module PkgDef (defValue) where++defValue :: String+defValue = "pkg-def:publib"
+ cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083Post/pkg-def/src/PkgDef.hs view
@@ -0,0 +1,4 @@+module PkgDef (defValue) where++defValue :: String+defValue = "pkg-def:pkg-def"
+ cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083PostMixin/cabal.out view
@@ -0,0 +1,16 @@+# cabal v2-run+Resolving dependencies...+Build profile: -w ghc-<GHCVER> -O1+In order, the following will be built:+ - pkg-def-0.1.0.0 (lib) (first run)+ - pkg-abc-0.1.0.0 (exe:program) (first run)+Warning: pkg-def.cabal:13:27: visibility is experimental feature (issue #5660)+Configuring library for pkg-def-0.1.0.0..+Preprocessing library for pkg-def-0.1.0.0..+Building library for pkg-def-0.1.0.0..+Warning: pkg-abc.cabal:15:29: colon specifier is experimental feature (issue #5660)+Warning: pkg-abc.cabal:20:15: colon specifier is experimental feature (issue #5660)+Configuring executable 'program' for pkg-abc-0.1.0.0..+Warning: The package has an extraneous version range for a dependency on an internal library: pkg-def >=0 && ==0.1.0.0. This version range includes the current package but isn't needed as the current package's library will always be used.+Preprocessing executable 'program' for pkg-abc-0.1.0.0..+Building executable 'program' for pkg-abc-0.1.0.0..
+ cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083PostMixin/cabal.project view
@@ -0,0 +1,4 @@+packages:+ pkg-abc+ pkg-def+
+ cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083PostMixin/cabal.test.hs view
@@ -0,0 +1,6 @@+import Test.Cabal.Prelude++-- This is like T6083Pre, but also goes via mixins+--+main = cabalTest $+ cabal' "v2-run" ["pkg-abc:program"] >>= assertOutputContains "pkg-def:pkg-def"
+ cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083PostMixin/pkg-abc/exe/Main.hs view
@@ -0,0 +1,5 @@+module Main (main) where+import Mixin (defValue)++main :: IO ()+main = print defValue
+ cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083PostMixin/pkg-abc/pkg-abc.cabal view
@@ -0,0 +1,20 @@+cabal-version: 3.4+name: pkg-abc+version: 0.1.0.0++library pkg-def+ default-language: Haskell2010+ hs-source-dirs: pkg-def+ build-depends: base+ exposed-modules: PkgDef++executable program+ default-language: Haskell2010+ hs-source-dirs: exe+ main-is: Main.hs+ mixins: pkg-def:pkg-def (PkgDef as Mixin)++ -- we want that to resolve to pkg-def main library.+ build-depends:+ , base+ , pkg-def:pkg-def
+ cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083PostMixin/pkg-abc/pkg-def/PkgDef.hs view
@@ -0,0 +1,4 @@+module PkgDef (defValue) where++defValue :: String+defValue = "pkg-abc:pkg-def"
+ cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083PostMixin/pkg-def/pkg-def.cabal view
@@ -0,0 +1,17 @@+cabal-version: 3.0+name: pkg-def+version: 0.1.0.0++library+ default-language: Haskell2010+ hs-source-dirs: src+ build-depends: base+ exposed-modules: PkgDef++library publib+ default-language: Haskell2010+ visibility: public+ hs-source-dirs: publib+ build-depends: base+ exposed-modules: PkgDef+
+ cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083PostMixin/pkg-def/publib/PkgDef.hs view
@@ -0,0 +1,4 @@+module PkgDef (defValue) where++defValue :: String+defValue = "pkg-def:publib"
+ cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083PostMixin/pkg-def/src/PkgDef.hs view
@@ -0,0 +1,4 @@+module PkgDef (defValue) where++defValue :: String+defValue = "pkg-def:pkg-def"
+ cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083Pre/cabal.out view
@@ -0,0 +1,14 @@+# cabal v2-run+Resolving dependencies...+Build profile: -w ghc-<GHCVER> -O1+In order, the following will be built:+ - pkg-abc-0.1.0.0 (lib:pkg-def) (first run)+ - pkg-abc-0.1.0.0 (exe:program) (first run)+Warning: pkg-abc.cabal:19:15: colon specifier is experimental feature (issue #5660)+Configuring library 'pkg-def' for pkg-abc-0.1.0.0..+Preprocessing library 'pkg-def' for pkg-abc-0.1.0.0..+Building library 'pkg-def' for pkg-abc-0.1.0.0..+Warning: pkg-abc.cabal:19:15: colon specifier is experimental feature (issue #5660)+Configuring executable 'program' for pkg-abc-0.1.0.0..+Preprocessing executable 'program' for pkg-abc-0.1.0.0..+Building executable 'program' for pkg-abc-0.1.0.0..
+ cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083Pre/cabal.project view
@@ -0,0 +1,4 @@+packages:+ pkg-abc+ pkg-def+
+ cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083Pre/cabal.test.hs view
@@ -0,0 +1,6 @@+import Test.Cabal.Prelude++-- https://github.com/haskell/cabal/issues/6083+-- see pkg-abc.cabal+main = cabalTest $+ cabal' "v2-run" ["pkg-abc:program"] >>= assertOutputContains "pkg-abc:pkg-def"
+ cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083Pre/pkg-abc/exe/Main.hs view
@@ -0,0 +1,5 @@+module Main (main) where+import PkgDef (defValue)++main :: IO ()+main = print defValue
+ cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083Pre/pkg-abc/pkg-abc.cabal view
@@ -0,0 +1,19 @@+cabal-version: 3.0+name: pkg-abc+version: 0.1.0.0++library pkg-def+ default-language: Haskell2010+ hs-source-dirs: pkg-def+ build-depends: base+ exposed-modules: PkgDef++executable program+ default-language: Haskell2010+ hs-source-dirs: exe+ main-is: Main.hs++ -- we want that to resolve to pkg-def main library.+ build-depends:+ , base+ , pkg-def:pkg-def
+ cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083Pre/pkg-abc/pkg-def/PkgDef.hs view
@@ -0,0 +1,4 @@+module PkgDef (defValue) where++defValue :: String+defValue = "pkg-abc:pkg-def"
+ cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083Pre/pkg-def/pkg-def.cabal view
@@ -0,0 +1,17 @@+cabal-version: 3.0+name: pkg-def+version: 0.1.0.0++library+ default-language: Haskell2010+ hs-source-dirs: src+ build-depends: base+ exposed-modules: PkgDef++library publib+ default-language: Haskell2010+ visibility: public+ hs-source-dirs: publib+ build-depends: base+ exposed-modules: PkgDef+
+ cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083Pre/pkg-def/publib/PkgDef.hs view
@@ -0,0 +1,4 @@+module PkgDef (defValue) where++defValue :: String+defValue = "pkg-def:publib"
+ cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083Pre/pkg-def/src/PkgDef.hs view
@@ -0,0 +1,4 @@+module PkgDef (defValue) where++defValue :: String+defValue = "pkg-def:pkg-def"
+ cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083PreMixin/cabal.out view
@@ -0,0 +1,14 @@+# cabal v2-run+Resolving dependencies...+Build profile: -w ghc-<GHCVER> -O1+In order, the following will be built:+ - pkg-abc-0.1.0.0 (lib:pkg-def) (first run)+ - pkg-abc-0.1.0.0 (exe:program) (first run)+Warning: pkg-abc.cabal:20:15: colon specifier is experimental feature (issue #5660)+Configuring library 'pkg-def' for pkg-abc-0.1.0.0..+Preprocessing library 'pkg-def' for pkg-abc-0.1.0.0..+Building library 'pkg-def' for pkg-abc-0.1.0.0..+Warning: pkg-abc.cabal:20:15: colon specifier is experimental feature (issue #5660)+Configuring executable 'program' for pkg-abc-0.1.0.0..+Preprocessing executable 'program' for pkg-abc-0.1.0.0..+Building executable 'program' for pkg-abc-0.1.0.0..
+ cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083PreMixin/cabal.project view
@@ -0,0 +1,4 @@+packages:+ pkg-abc+ pkg-def+
+ cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083PreMixin/cabal.test.hs view
@@ -0,0 +1,6 @@+import Test.Cabal.Prelude++-- This is like T6083Pre, but also goes via mixins+--+main = cabalTest $+ cabal' "v2-run" ["pkg-abc:program"] >>= assertOutputContains "pkg-abc:pkg-def"
+ cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083PreMixin/pkg-abc/exe/Main.hs view
@@ -0,0 +1,5 @@+module Main (main) where+import Mixin (defValue)++main :: IO ()+main = print defValue
+ cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083PreMixin/pkg-abc/pkg-abc.cabal view
@@ -0,0 +1,20 @@+cabal-version: 3.0+name: pkg-abc+version: 0.1.0.0++library pkg-def+ default-language: Haskell2010+ hs-source-dirs: pkg-def+ build-depends: base+ exposed-modules: PkgDef++executable program+ default-language: Haskell2010+ hs-source-dirs: exe+ main-is: Main.hs+ mixins: pkg-def (PkgDef as Mixin)++ -- we want that to resolve to pkg-def main library.+ build-depends:+ , base+ , pkg-def:pkg-def
+ cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083PreMixin/pkg-abc/pkg-def/PkgDef.hs view
@@ -0,0 +1,4 @@+module PkgDef (defValue) where++defValue :: String+defValue = "pkg-abc:pkg-def"
+ cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083PreMixin/pkg-def/pkg-def.cabal view
@@ -0,0 +1,17 @@+cabal-version: 3.0+name: pkg-def+version: 0.1.0.0++library+ default-language: Haskell2010+ hs-source-dirs: src+ build-depends: base+ exposed-modules: PkgDef++library publib+ default-language: Haskell2010+ visibility: public+ hs-source-dirs: publib+ build-depends: base+ exposed-modules: PkgDef+
+ cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083PreMixin/pkg-def/publib/PkgDef.hs view
@@ -0,0 +1,4 @@+module PkgDef (defValue) where++defValue :: String+defValue = "pkg-def:publib"
+ cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6083PreMixin/pkg-def/src/PkgDef.hs view
@@ -0,0 +1,4 @@+module PkgDef (defValue) where++defValue :: String+defValue = "pkg-def:pkg-def"
+ cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6894/Bar.hs view
@@ -0,0 +1,1 @@+module Bar where
+ cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6894/Foo.hs view
@@ -0,0 +1,1 @@+module Foo where
+ cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6894/cabal.out view
@@ -0,0 +1,15 @@+# cabal v2-build+Resolving dependencies...+Build profile: -w ghc-<GHCVER> -O1+In order, the following will be built:+ - issue-6894 (lib:sublib) (first run)+ - issue-6894 (lib) (first run)+Warning: issue.cabal:7:30: colon specifier is experimental feature (issue #5660)+Configuring library 'sublib' for issue-6894..+Preprocessing library 'sublib' for issue-6894..+Building library 'sublib' for issue-6894..+Warning: issue.cabal:7:30: colon specifier is experimental feature (issue #5660)+Configuring library for issue-6894..+Warning: The package has an extraneous version range for a dependency on an internal library: issue:sublib >=0 && ==6894. This version range includes the current package but isn't needed as the current package's library will always be used.+Preprocessing library for issue-6894..+Building library for issue-6894..
+ cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6894/cabal.project view
@@ -0,0 +1,1 @@+packages: .
+ cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6894/cabal.test.hs view
@@ -0,0 +1,3 @@+import Test.Cabal.Prelude+main = cabalTest $+ cabal "v2-build" ["issue"]
+ cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6894/issue.cabal view
@@ -0,0 +1,13 @@+cabal-version: 3.0+name: issue+version: 6894++library+ default-language: Haskell2010+ build-depends: base, issue:sublib+ exposed-modules: Foo++library sublib+ default-language: Haskell2010+ build-depends: base+ exposed-modules: Bar
+ cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6894/setup.cabal.out view
@@ -0,0 +1,8 @@+# Setup configure+Warning: issue.cabal:7:30: colon specifier is experimental feature (issue #5660)+Configuring issue-6894...+# Setup build+Preprocessing library 'sublib' for issue-6894..+Building library 'sublib' for issue-6894..+Preprocessing library for issue-6894..+Building library for issue-6894..
+ cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6894/setup.out view
@@ -0,0 +1,8 @@+# Setup configure+Warning: issue.cabal:7:30: colon specifier is experimental feature (issue #5660)+Configuring issue-6894...+# Setup build+Preprocessing library 'sublib' for issue-6894..+Building library 'sublib' for issue-6894..+Preprocessing library for issue-6894..+Building library for issue-6894..
+ cabal/cabal-testsuite/PackageTests/MultipleLibraries/T6894/setup.test.hs view
@@ -0,0 +1,3 @@+import Test.Cabal.Prelude+main = setupAndCabalTest $ do+ setup_build []
− cabal/cabal-testsuite/PackageTests/MultipleLibraries/cabal.out
@@ -1,12 +0,0 @@-# cabal v2-build-Resolving dependencies...-Build profile: -w ghc-<GHCVER> -O1-In order, the following will be built:- - d-0.1.0.0 (lib:privatelib) (first run)- - p-0.1.0.0 (lib) (first run)-Configuring library 'privatelib' for d-0.1.0.0..-Preprocessing library 'privatelib' for d-0.1.0.0..-Building library 'privatelib' for d-0.1.0.0..-Configuring library for p-0.1.0.0..-cabal: Encountered missing or private dependencies:- d : {privatelib} ==0.1.0.0
− cabal/cabal-testsuite/PackageTests/MultipleLibraries/cabal.project
@@ -1,4 +0,0 @@-packages:- d- p-
− cabal/cabal-testsuite/PackageTests/MultipleLibraries/cabal.test.hs
@@ -1,4 +0,0 @@-import Test.Cabal.Prelude-main = cabalTest $- void $ fails (cabal' "v2-build" ["p"])-
− cabal/cabal-testsuite/PackageTests/MultipleLibraries/d/d.cabal
@@ -1,12 +0,0 @@-cabal-version: 3.0-name: d-version: 0.1.0.0---- See issue #6038-library- default-language: Haskell2010--library privatelib- visibility: private- default-language: Haskell2010-
− cabal/cabal-testsuite/PackageTests/MultipleLibraries/p/p.cabal
@@ -1,8 +0,0 @@-cabal-version: 3.0-name: p-version: 0.1.0.0--library- build-depends: d:privatelib- default-language: Haskell2010-
cabal/cabal-testsuite/PackageTests/NewBuild/CmdRun/Script/script.hs view
@@ -1,11 +1,11 @@-#! /usr/bin/env cabal -{- cabal: -build-depends: base >= 4.3 && <5 --} -{-# LANGUAGE BangPatterns #-} -{-# LANGUAGE ScopedTypeVariables #-} - -import Prelude - -main :: IO () -main = putStrLn "Hello World" +#! /usr/bin/env cabal+{- cabal:+build-depends: base >= 4.3 && <5+-}+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE ScopedTypeVariables #-}++import Prelude++main :: IO ()+main = putStrLn "Hello World"
cabal/cabal-testsuite/PackageTests/NewConfigure/LocalConfigOverwrite/cabal.out view
@@ -1,6 +1,31 @@ # cabal v2-configure-'cabal.project.local' file already exists. Now overwriting it.+'cabal.project.local' already exists, backing it up to 'cabal.project.local~'. Resolving dependencies...+Build profile: -w ghc-<GHCVER> -O1+In order, the following would be built:+ - NewConfigure-0.1.0.0 (lib) (first run)+# cabal v2-configure+'cabal.project.local' already exists, backing it up to 'cabal.project.local~0'.+Build profile: -w ghc-<GHCVER> -O1+In order, the following would be built:+ - NewConfigure-0.1.0.0 (lib) (first run)+# cabal v2-configure+'cabal.project.local' already exists, backing it up to 'cabal.project.local~1'.+Build profile: -w ghc-<GHCVER> -O1+In order, the following would be built:+ - NewConfigure-0.1.0.0 (lib) (first run)+# cabal v2-configure+'foo.project.local' already exists, backing it up to 'foo.project.local~'.+Build profile: -w ghc-<GHCVER> -O1+In order, the following would be built:+ - NewConfigure-0.1.0.0 (lib) (first run)+# cabal v2-configure+'foo.project.local' already exists, backing it up to 'foo.project.local~0'.+Build profile: -w ghc-<GHCVER> -O1+In order, the following would be built:+ - NewConfigure-0.1.0.0 (lib) (first run)+# cabal v2-configure+'foo.project.local' already exists, backing it up to 'foo.project.local~1'. Build profile: -w ghc-<GHCVER> -O1 In order, the following would be built: - NewConfigure-0.1.0.0 (lib) (first run)
cabal/cabal-testsuite/PackageTests/NewConfigure/LocalConfigOverwrite/cabal.test.hs view
@@ -2,5 +2,20 @@ main = cabalTest $ withSourceCopy $ do- r <- cabal' "v2-configure" []- assertOutputContains "Now overwriting it" r+ cabal' "v2-configure" [] >>=+ assertOutputContains "backing it up to 'cabal.project.local~'"+ cabal' "v2-configure" [] >>=+ assertOutputContains "backing it up to 'cabal.project.local~0'"+ cabal' "v2-configure" [] >>=+ assertOutputContains "backing it up to 'cabal.project.local~1'"++ -- With --project-file+ cabal' "v2-configure" ["--project-file", "foo.project"] >>=+ assertOutputContains+ "'foo.project.local' already exists, backing it up to 'foo.project.local~'"+ cabal' "v2-configure" ["--project-file", "foo.project"] >>=+ assertOutputContains+ "'foo.project.local' already exists, backing it up to 'foo.project.local~0'"+ cabal' "v2-configure" ["--project-file", "foo.project"] >>=+ assertOutputContains+ "'foo.project.local' already exists, backing it up to 'foo.project.local~1'"
+ cabal/cabal-testsuite/PackageTests/NewConfigure/LocalConfigOverwrite/foo.project view
@@ -0,0 +1,1 @@+packages: .
+ cabal/cabal-testsuite/PackageTests/NewConfigure/LocalConfigOverwrite/foo.project.local view
cabal/cabal-testsuite/PackageTests/NewSdist/DeterministicTrivial/deterministic.test.hs view
@@ -11,7 +11,13 @@ let dir = testCurrentDir env knownSdist = dir </> "deterministic-0.tar.gz" mySdist = dir </> "dist-newstyle" </> "sdist" </> "deterministic-0.tar.gz"- ++ -- This helps to understand why this test fails, if it does:+ --+ -- shell "tar" ["-tzvf", knownSdist]+ -- shell "tar" ["-tzvf", mySdist]+ --+ known <- liftIO (BS.readFile knownSdist) unknown <- liftIO (BS.readFile mySdist)
cabal/cabal-testsuite/PackageTests/OrderFlags/my.cabal view
@@ -5,12 +5,13 @@ stability: stable category: PackageTests build-type: Simple-cabal-version: >=1.9.2+cabal-version: >=1.10 description: Check that Cabal correctly orders flags that are passed to GHC. library+ default-language: Haskell2010 exposed-modules: Foo build-depends: base
cabal/cabal-testsuite/PackageTests/OrderFlags/setup.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring OrderFlags-0.1... # Setup build Preprocessing library for OrderFlags-0.1..
cabal/cabal-testsuite/PackageTests/Outdated/my.cabal view
@@ -1,14 +1,16 @@ name: my version: 0.1 license: BSD3-cabal-version: >= 1.20.0+cabal-version: 1.20 build-type: Simple library+ default-language: Haskell2010 exposed-modules: Foo build-depends: base >= 3 && < 4 test-suite tests-Foo+ default-language: Haskell2010 type: exitcode-stdio-1.0 hs-source-dirs: tests main-is: test-Foo.hs
cabal/cabal-testsuite/PackageTests/PathsModule/Executable/setup.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring PathsModule-0.1... # Setup build Preprocessing executable 'TestPathsModule' for PathsModule-0.1..
cabal/cabal-testsuite/PackageTests/PathsModule/Library/my.cabal view
@@ -1,4 +1,4 @@-Cabal-version: 2.1+Cabal-version: 2.2 name: PathsModule version: 0.1 license: BSD-3-Clause
cabal/cabal-testsuite/PackageTests/PathsModule/Library/setup.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring PathsModule-0.1... # Setup build Preprocessing library for PathsModule-0.1..
cabal/cabal-testsuite/PackageTests/PreProcess/setup.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring PreProcess-0.1... # Setup build Preprocessing test suite 'my-test-suite' for PreProcess-0.1..
cabal/cabal-testsuite/PackageTests/PreProcessExtraSources/setup.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring PreProcessExtraSources-0.1... # Setup build Preprocessing test suite 'my-test-suite' for PreProcessExtraSources-0.1..
cabal/cabal-testsuite/PackageTests/QuasiQuotes/dynamic/setup.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring quasiQuotes-0.1... # Setup build Preprocessing executable 'main' for quasiQuotes-0.1..
cabal/cabal-testsuite/PackageTests/QuasiQuotes/profiling/setup.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring quasiQuotes-0.1... # Setup build Preprocessing executable 'main' for quasiQuotes-0.1..
cabal/cabal-testsuite/PackageTests/QuasiQuotes/vanilla/setup.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring quasiQuotes-0.1... # Setup build Preprocessing executable 'main' for quasiQuotes-0.1..
cabal/cabal-testsuite/PackageTests/ReexportedModules/p/p.cabal view
@@ -3,7 +3,7 @@ author: Edward Z. Yang maintainer: ezyang@cs.stanford.edu build-type: Simple-cabal-version: >=1.21+cabal-version: 1.22 library exposed-modules: Public
cabal/cabal-testsuite/PackageTests/ReexportedModules/p/p.cabal.fail-ambiguous view
@@ -3,7 +3,7 @@ author: Edward Z. Yang maintainer: ezyang@cs.stanford.edu build-type: Simple-cabal-version: >=1.21+cabal-version: 1.22 library build-depends: base, containers, containers-dupe
cabal/cabal-testsuite/PackageTests/ReexportedModules/p/p.cabal.fail-missing view
@@ -3,7 +3,7 @@ author: Edward Z. Yang maintainer: ezyang@cs.stanford.edu build-type: Simple-cabal-version: >=1.21+cabal-version: 1.22 library build-depends: base
cabal/cabal-testsuite/PackageTests/ReexportedModules/p/p.cabal.fail-other view
@@ -3,7 +3,7 @@ author: Edward Z. Yang maintainer: ezyang@cs.stanford.edu build-type: Simple-cabal-version: >=1.21+cabal-version: 1.22 library exposed-modules: Public
cabal/cabal-testsuite/PackageTests/ReexportedModules/setup-fail-ambiguous.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring containers-dupe-0.1.0.0... # Setup build Preprocessing library for containers-dupe-0.1.0.0..@@ -9,7 +8,6 @@ # Setup register Registering library for containers-dupe-0.1.0.0.. # Setup configure-Resolving dependencies... Configuring p-0.1.0.0... Error: Problem with module re-exports:
cabal/cabal-testsuite/PackageTests/ReexportedModules/setup-fail-missing.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring p-0.1.0.0... Error: Problem with module re-exports:
cabal/cabal-testsuite/PackageTests/ReexportedModules/setup-fail-other.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring p-0.1.0.0... Error: Problem with module re-exports:
cabal/cabal-testsuite/PackageTests/ReexportedModules/setup.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring p-0.1.0.0... # Setup build Preprocessing library for p-0.1.0.0..@@ -9,7 +8,6 @@ # Setup register Registering library for p-0.1.0.0.. # Setup configure-Resolving dependencies... Configuring q-0.1.0.0... # Setup build Preprocessing library for q-0.1.0.0..
cabal/cabal-testsuite/PackageTests/Regression/T2755/setup.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring test-t2755-0.1.0.0... # Setup test-Package has no buildable test suites.+Package has no test suites.
cabal/cabal-testsuite/PackageTests/Regression/T2971/setup.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring p-0.1.0.0... # Setup build Preprocessing library for p-0.1.0.0..@@ -9,7 +8,6 @@ # Setup register Registering library for p-0.1.0.0.. # Setup configure-Resolving dependencies... Configuring q-0.1.0.0... # Setup build Preprocessing executable 'foo' for q-0.1.0.0..
cabal/cabal-testsuite/PackageTests/Regression/T2971a/setup.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring T2971a-0.1.0.0... # Setup build Preprocessing library for T2971a-0.1.0.0..
− cabal/cabal-testsuite/PackageTests/Regression/T3199/Cabal/Cabal.cabal
@@ -1,8 +0,0 @@-name: Cabal-version: 2.0.0.0-build-type: Simple-cabal-version: >= 1.10--library- build-depends: base- default-language: Haskell2010
− cabal/cabal-testsuite/PackageTests/Regression/T3199/Main.hs
@@ -1,4 +0,0 @@-module Main where--main :: IO ()-main = putStrLn "Hello, Haskell!"
− cabal/cabal-testsuite/PackageTests/Regression/T3199/Setup.hs
@@ -1,2 +0,0 @@-import Distribution.Simple-main = defaultMain
− cabal/cabal-testsuite/PackageTests/Regression/T3199/sandbox.out
@@ -1,8 +0,0 @@-# cabal v1-sandbox init-Writing a default package environment file to <ROOT>/sandbox.dist/cabal.sandbox.config-Creating a new sandbox at <ROOT>/sandbox.dist/sandbox-# cabal v1-sandbox add-source-# cabal v1-install-Resolving dependencies...-In order, the following would be installed:-Cabal-2.0.0.0 (new version)
− cabal/cabal-testsuite/PackageTests/Regression/T3199/sandbox.test.hs
@@ -1,11 +0,0 @@-import Test.Cabal.Prelude-main = cabalTest $ do- -- 8.0 and up come with sufficiently recent versions of- -- Cabal which don't have this bug.- skipUnless =<< ghcVersionIs (< mkVersion [8,0])- withSandbox $ do- cabal_sandbox "add-source" ["Cabal"]- cabal "v1-install"- -- Ignore the Cabal library that is under test- ["--package-db=clear", "--package-db=global"- ,"--only-dep", "--dry-run"]
− cabal/cabal-testsuite/PackageTests/Regression/T3199/test-3199.cabal
@@ -1,27 +0,0 @@-name: test-t3199-version: 0.1.0.0-license: BSD3-author: Mikhail Glushenkov-maintainer: mikhail.glushenkov@gmail.com-category: Test-build-type: Custom-cabal-version: >=1.10--flag exe_2- description: Build second exe- default: False--executable test-3199-1- main-is: Main.hs- build-depends: base- default-language: Haskell2010--executable test-3199-2- main-is: Main.hs- build-depends: base, ansi-terminal- default-language: Haskell2010-- if flag(exe_2)- buildable: True- else- buildable: False
cabal/cabal-testsuite/PackageTests/Regression/T3294/setup.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring T3294-0.1.0.0... # Setup build Preprocessing executable 'T3294' for T3294-0.1.0.0..
− cabal/cabal-testsuite/PackageTests/Regression/T3436/Cabal-1.2/Cabal.cabal
@@ -1,8 +0,0 @@-name: Cabal-version: 1.2-build-type: Simple-cabal-version: >= 1.2--library- build-depends: base- exposed-modules: CabalMessage
− cabal/cabal-testsuite/PackageTests/Regression/T3436/Cabal-1.2/CabalMessage.hs
@@ -1,3 +0,0 @@-module CabalMessage where--message = "This is Cabal-1.2"
− cabal/cabal-testsuite/PackageTests/Regression/T3436/Cabal-2.0/Cabal.cabal
@@ -1,8 +0,0 @@-name: Cabal-version: 2.0-build-type: Simple-cabal-version: >= 1.2--library- build-depends: base- exposed-modules: CabalMessage
− cabal/cabal-testsuite/PackageTests/Regression/T3436/Cabal-2.0/CabalMessage.hs
@@ -1,3 +0,0 @@-module CabalMessage where--message = "This is Cabal-2.0"
− cabal/cabal-testsuite/PackageTests/Regression/T3436/cabal.out
@@ -1,9 +0,0 @@-# cabal v2-build-Resolving dependencies...-Build profile: -w ghc-<GHCVER> -O1-In order, the following will be built:- - Cabal-2.0 (lib:Cabal) (first run)- - custom-setup-1.0 (lib:custom-setup) (first run)-Configuring Cabal-2.0...-Preprocessing library for Cabal-2.0..-Building library for Cabal-2.0..
− cabal/cabal-testsuite/PackageTests/Regression/T3436/cabal.project
@@ -1,1 +0,0 @@-packages: custom-setup Cabal-2.0
− cabal/cabal-testsuite/PackageTests/Regression/T3436/custom-setup/Setup.hs
@@ -1,5 +0,0 @@-import CabalMessage (message)-import System.Exit-import System.IO--main = hPutStrLn stderr message >> exitFailure
− cabal/cabal-testsuite/PackageTests/Regression/T3436/custom-setup/custom-setup.cabal
@@ -1,9 +0,0 @@-cabal-version: 2.0-name: custom-setup-version: 1.0-build-type: Custom--custom-setup- setup-depends: base, Cabal >= 2.0--library
− cabal/cabal-testsuite/PackageTests/Regression/T3436/sandbox.out
@@ -1,22 +0,0 @@-# cabal v1-sandbox init-Writing a default package environment file to <ROOT>/sandbox.dist/cabal.sandbox.config-Creating a new sandbox at <ROOT>/sandbox.dist/sandbox-# cabal v1-install-Resolving dependencies...-Configuring Cabal-1.2...-Preprocessing library for Cabal-1.2..-Building library for Cabal-1.2..-Installing library in <PATH>-Completed Cabal-1.2-# cabal v1-sandbox add-source-# cabal v1-install-Resolving dependencies...-Configuring Cabal-2.0...-Preprocessing library for Cabal-2.0..-Building library for Cabal-2.0..-Installing library in <PATH>-Completed Cabal-2.0-Failed to install custom-setup-1.0-cabal: Error: some packages failed to install:-custom-setup-1.0-KL06TzJxSBkDtcPp9Xd2v1 failed during the configure step. The exception was:- ExitFailure 1
− cabal/cabal-testsuite/PackageTests/Regression/T3436/sandbox.test.hs
@@ -1,21 +0,0 @@-import Test.Cabal.Prelude---- Regression test for issue #3436------ #3436 occurred when a package with a custom setup specified a 'cabal-version'--- that was newer than the version of the installed Cabal library, even though--- the solver didn't choose the installed Cabal for the package's setup script.------ This test installs a fake Cabal-1.2 and then tries to build the package--- custom-setup, which depends on a fake Cabal-2.0 (through cabal-version and--- setup-depends).-main = cabalTest $ do- withSandbox $ do- cabal "v1-install" ["./Cabal-1.2"]- cabal_sandbox "add-source" ["Cabal-2.0"]-- -- cabal should build custom-setup's setup script with Cabal-2.0, but- -- then configure should fail because Setup just prints an error message- -- imported from Cabal and exits.- r <- fails $ cabal' "v1-install" ["custom-setup/"]- assertOutputContains "This is Cabal-2.0" r
cabal/cabal-testsuite/PackageTests/Regression/T3847/T3847.cabal view
@@ -1,11 +1,13 @@ name: T3847 version: 1.0 build-type: Simple-cabal-version: >= 1.8+cabal-version: >= 1.10 library+ default-language: Haskell2010 test-suite tests+ default-language: Haskell2010 other-extensions: ThisDoesNotExist type: exitcode-stdio-1.0 main-is: Main.hs
cabal/cabal-testsuite/PackageTests/Regression/T3847/setup.cabal.out view
@@ -1,4 +1,3 @@ # Setup configure-Resolving dependencies... Configuring T3847-1.0... Warning: Unknown extensions: ThisDoesNotExist
cabal/cabal-testsuite/PackageTests/Regression/T4025/T4025.cabal view
@@ -4,10 +4,12 @@ cabal-version: >= 1.10 library+ default-language: Haskell2010 build-depends: base exposed-modules: A executable exe+ default-language: Haskell2010 build-depends: T4025, base hs-source-dirs: exe main-is: Main.hs
cabal/cabal-testsuite/PackageTests/Regression/T4025/setup.cabal.out view
@@ -1,7 +1,5 @@ # Setup configure-Resolving dependencies... Configuring T4025-1.0...-Warning: Packages using 'cabal-version: >= 1.10' must specify the 'default-language' field for each component (e.g. Haskell98 or Haskell2010). If a component uses different languages in different modules then list the other ones in the 'other-languages' field. # Setup build Preprocessing library for T4025-1.0.. Building library for T4025-1.0..
cabal/cabal-testsuite/PackageTests/Regression/T4025/setup.out view
@@ -1,6 +1,5 @@ # Setup configure Configuring T4025-1.0...-Warning: Packages using 'cabal-version: >= 1.10' must specify the 'default-language' field for each component (e.g. Haskell98 or Haskell2010). If a component uses different languages in different modules then list the other ones in the 'other-languages' field. # Setup build Preprocessing library for T4025-1.0.. Building library for T4025-1.0..
cabal/cabal-testsuite/PackageTests/Regression/T4270/T4270.cabal view
@@ -5,15 +5,17 @@ stability: stable category: PackageTests build-type: Simple-cabal-version: >= 1.9.2+cabal-version: >= 1.10 description: Check type detailed-0.9 test suites with dynamic linking. library+ default-language: Haskell2010 exposed-modules: Lib build-depends: base test-suite test+ default-language: Haskell2010 type: detailed-0.9 test-module: Test build-depends: base, Cabal, T4270
cabal/cabal-testsuite/PackageTests/Regression/T4270/setup.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring T4270-0.1... # Setup build Preprocessing library for T4270-0.1..@@ -7,10 +6,6 @@ Preprocessing test suite 'test' for T4270-0.1.. Building test suite 'test' for T4270-0.1.. # Setup test-Preprocessing library for T4270-0.1..-Building library for T4270-0.1..-Preprocessing test suite 'test' for T4270-0.1..-Building test suite 'test' for T4270-0.1.. Running 1 test suites... Test suite test: RUNNING... Test suite test: PASS
cabal/cabal-testsuite/PackageTests/Regression/T4291/dependee/dependee.cabal view
@@ -3,7 +3,7 @@ author: Zejun Wu maintainer: watashi@watashi.ws build-type: Simple-cabal-version: >=2.0+cabal-version: 2.0 library build-depends: base
cabal/cabal-testsuite/PackageTests/Regression/T4291/depender/depender.cabal view
@@ -3,7 +3,7 @@ author: Zejun Wu maintainer: watashi@watashi.ws build-type: Simple-cabal-version: >=2.0+cabal-version: 2.0 library build-depends: base, dependee
cabal/cabal-testsuite/PackageTests/Regression/T4291/setup.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring dependee-0.1.0.0... # Setup build Preprocessing library for dependee-0.1.0.0..@@ -9,7 +8,6 @@ # Setup register Registering library for dependee-0.1.0.0.. # Setup configure-Resolving dependencies... Configuring depender-0.1.0.0... # Setup build Preprocessing library for depender-0.1.0.0..
cabal/cabal-testsuite/PackageTests/Regression/T4449/setup.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring test-t4449-0.1.0.0... # Setup build Preprocessing library for test-t4449-0.1.0.0..
cabal/cabal-testsuite/PackageTests/Regression/T5309/cabal.out view
@@ -12,7 +12,7 @@ Preprocessing executable 'exe-no-lib' for T5309-1.0.0.0.. Building executable 'exe-no-lib' for T5309-1.0.0.0.. Configuring executable 'exe-with-lib' for T5309-1.0.0.0..-Warning: The package has an extraneous version range for a dependency on an internal library: T5309 -any && ==1.0.0.0, T5309 -any && ==1.0.0.0, T5309 -any && ==1.0.0.0. This version range includes the current package but isn't needed as the current package's library will always be used.+Warning: The package has an extraneous version range for a dependency on an internal library: T5309 >=0 && ==1.0.0.0, T5309 >=0 && ==1.0.0.0, T5309 >=0 && ==1.0.0.0. This version range includes the current package but isn't needed as the current package's library will always be used. Preprocessing executable 'exe-with-lib' for T5309-1.0.0.0.. Building executable 'exe-with-lib' for T5309-1.0.0.0.. # cabal v2-test@@ -29,7 +29,7 @@ Test suite logged to: <ROOT>/cabal.dist/work/./dist/build/<ARCH>/ghc-<GHCVER>/T5309-1.0.0.0/t/test-no-lib/test/T5309-1.0.0.0-test-no-lib.log 1 of 1 test suites (1 of 1 test cases) passed. Configuring test suite 'test-with-lib' for T5309-1.0.0.0..-Warning: The package has an extraneous version range for a dependency on an internal library: T5309 -any && ==1.0.0.0, T5309 -any && ==1.0.0.0, T5309 -any && ==1.0.0.0. This version range includes the current package but isn't needed as the current package's library will always be used.+Warning: The package has an extraneous version range for a dependency on an internal library: T5309 >=0 && ==1.0.0.0, T5309 >=0 && ==1.0.0.0, T5309 >=0 && ==1.0.0.0. This version range includes the current package but isn't needed as the current package's library will always be used. Preprocessing test suite 'test-with-lib' for T5309-1.0.0.0.. Building test suite 'test-with-lib' for T5309-1.0.0.0.. Running 1 test suites...@@ -49,7 +49,7 @@ Benchmark bench-no-lib: RUNNING... Benchmark bench-no-lib: FINISH Configuring benchmark 'bench-with-lib' for T5309-1.0.0.0..-Warning: The package has an extraneous version range for a dependency on an internal library: T5309 -any && ==1.0.0.0, T5309 -any && ==1.0.0.0, T5309 -any && ==1.0.0.0. This version range includes the current package but isn't needed as the current package's library will always be used.+Warning: The package has an extraneous version range for a dependency on an internal library: T5309 >=0 && ==1.0.0.0, T5309 >=0 && ==1.0.0.0, T5309 >=0 && ==1.0.0.0. This version range includes the current package but isn't needed as the current package's library will always be used. Preprocessing benchmark 'bench-with-lib' for T5309-1.0.0.0.. Building benchmark 'bench-with-lib' for T5309-1.0.0.0.. Running 1 benchmarks...
cabal/cabal-testsuite/PackageTests/Regression/T5309/memoized-tcm/costMatrix.h view
@@ -139,7 +139,7 @@ * the median for the two. Puts the median and alphabet size into retMedian, * which must therefore by necessity be allocated elsewhere. *- * This functin allocates _if necessary_. So freeing inputs after a call will not+ * This function allocates _if necessary_. So freeing inputs after a call will not * cause invalid reads from the cost matrix. */ int getSetCostMedian(dcElement_t* left, dcElement_t* right, dcElement_t* retMedian);
cabal/cabal-testsuite/PackageTests/Regression/T5318/sdist-list-sources.out view
@@ -1,3 +1,2 @@-# cabal v1-sdist-List of package sources written to file '<TMPDIR>/sources'-List of package sources written to file '<TMPDIR>/sources'+# cabal v2-sdist+Wrote source list to <TMPDIR>/empty-data-dir-0.list
cabal/cabal-testsuite/PackageTests/Regression/T5318/sdist-list-sources.test.hs view
@@ -1,7 +1,7 @@ import Test.Cabal.Prelude main = cabalTest $ do tmpdir <- fmap testTmpDir getTestEnv- let fn = tmpdir </> "sources"- cabal "v1-sdist" ["--list-sources=" ++ fn]+ let fn = tmpdir </> "empty-data-dir-0.list"+ cabal "v2-sdist" ["--ignore-project", "--list-only", "--output-directory", tmpdir] -- --list-sources outputs with slashes on posix and backslashes on Windows. 'normalise' converts our needle to the necessary format. assertFileDoesContain fn $ normalise "foo.dat"
cabal/cabal-testsuite/PackageTests/Regression/T5677/cabal.out view
@@ -24,6 +24,6 @@ Building library instantiated with Sig = impl-0-inplace:Sig for prog-0.. Configuring executable 'prog' for prog-0..-Warning: The package has an extraneous version range for a dependency on an internal library: prog -any && ==0. This version range includes the current package but isn't needed as the current package's library will always be used.+Warning: The package has an extraneous version range for a dependency on an internal library: prog >=0 && ==0. This version range includes the current package but isn't needed as the current package's library will always be used. Preprocessing executable 'prog' for prog-0.. Building executable 'prog' for prog-0..
cabal/cabal-testsuite/PackageTests/Regression/T5677/prog/prog.cabal view
@@ -13,7 +13,7 @@ executable prog default-language: Haskell2010- main-is: prog.hs+ main-is: program.hs ghc-options: -Wmissing-export-lists -Werror build-depends: base, impl, prog
− cabal/cabal-testsuite/PackageTests/Regression/T5677/prog/prog.hs
@@ -1,5 +0,0 @@-module Main (main) where--import qualified Prog--main = Prog.main
+ cabal/cabal-testsuite/PackageTests/Regression/T5677/prog/program.hs view
@@ -0,0 +1,5 @@+module Main (main) where++import qualified Prog++main = Prog.main
cabal/cabal-testsuite/PackageTests/Regression/T6125/setup.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring myprog-0... # Setup build Preprocessing executable 'myprog' for myprog-0..
+ cabal/cabal-testsuite/PackageTests/Regression/T6853/cabal.out view
@@ -0,0 +1,8 @@+# cabal v2-build+Resolving dependencies...+Build profile: -w ghc-<GHCVER> -O1+In order, the following will be built:+ - pkg-foo-0 (lib) (first run)+Configuring library for pkg-foo-0..+Preprocessing library for pkg-foo-0..+Building library for pkg-foo-0..
+ cabal/cabal-testsuite/PackageTests/Regression/T6853/cabal.project view
@@ -0,0 +1,1 @@+packages: pkg-foo/
+ cabal/cabal-testsuite/PackageTests/Regression/T6853/cabal.test.hs view
@@ -0,0 +1,3 @@+import Test.Cabal.Prelude+main = cabalTest $+ cabal "v2-build" ["all"]
+ cabal/cabal-testsuite/PackageTests/Regression/T6853/pkg-foo/Foo.hs view
@@ -0,0 +1,1 @@+module Foo where
+ cabal/cabal-testsuite/PackageTests/Regression/T6853/pkg-foo/pkg-foo.cabal view
@@ -0,0 +1,17 @@+cabal-version: 2.2+name: pkg-foo+version: 0++flag foo-bar+ description: Should be toggled+ manual: False+ default: False++library+ default-language: Haskell2010+ build-depends: base+ exposed-modules: Foo++ -- this says "toggle me"+ if !flag(foo-bar)+ build-depends: base <0
+ cabal/cabal-testsuite/PackageTests/ReplCSources/Lib.hs view
@@ -0,0 +1,5 @@+module Lib where++foreign import ccall "foo" foo :: Int++bar = foo
+ cabal/cabal-testsuite/PackageTests/ReplCSources/cabal-csrc-repl.cabal view
@@ -0,0 +1,8 @@+cabal-version: 2.4+name: cabal-csrc-repl+version: 0.1.0.0+library+ exposed-modules: Lib+ build-depends: base+ C-sources: foo.c+ default-language: Haskell2010
+ cabal/cabal-testsuite/PackageTests/ReplCSources/cabal.out view
@@ -0,0 +1,2 @@+# cabal clean+# cabal repl
+ cabal/cabal-testsuite/PackageTests/ReplCSources/cabal.project view
@@ -0,0 +1,1 @@+packages: .
+ cabal/cabal-testsuite/PackageTests/ReplCSources/cabal.test.hs view
@@ -0,0 +1,9 @@+import Test.Cabal.Prelude++main = cabalTest $ do+ cabal' "clean" []+ res <- cabalWithStdin "repl" ["-v2"] "foo"+ -- Make sure we don't get this ghci error+ -- *Lib> ghc: ^^ Could not load '_foo', dependency unresolved. See top entry above.+ assertOutputDoesNotContain "Could not load" res+ assertOutputContains "Building C Sources..." res
+ cabal/cabal-testsuite/PackageTests/ReplCSources/foo.c view
@@ -0,0 +1,1 @@+int foo() { return 42; }
cabal/cabal-testsuite/PackageTests/SDist/T5195/cabal.out view
@@ -1,2 +1,2 @@-# cabal v1-sdist+# cabal v2-sdist cabal: filepath wildcard './actually-a-directory' does not match any files.
cabal/cabal-testsuite/PackageTests/SDist/T5195/cabal.test.hs view
@@ -1,6 +1,5 @@ import Test.Cabal.Prelude main = cabalTest $ do tmpdir <- fmap testTmpDir getTestEnv- let fn = tmpdir </> "sources"- res <- fails $ cabal' "v1-sdist" ["--list-sources=" ++ fn]+ res <- fails $ cabal' "v2-sdist" ["--ignore-project", "--list-only", "--output-directory", tmpdir] assertOutputContains "filepath wildcard './actually-a-directory' does not match any files" res
cabal/cabal-testsuite/PackageTests/SPDX/cabal-old-build.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring my-0... # Setup build Preprocessing library for my-0..
cabal/cabal-testsuite/PackageTests/SPDX/cabal-old-build.test.hs view
@@ -1,8 +1,5 @@ import Test.Cabal.Prelude main = setupAndCabalTest $ withPackageDb $ do- -- skip for GHC-8.4 and GHC-head until their Cabal modules are updated.- skipUnless =<< ghcVersionIs (< mkVersion [8,3])- setup_install [] recordMode DoNotRecord $ do ghc84 <- ghcVersionIs (>= mkVersion [8,4])
cabal/cabal-testsuite/PackageTests/SPDX/my.cabal view
@@ -1,4 +1,4 @@-cabal-version: 2.1+cabal-version: 2.2 name: my version: 0 build-type: Simple
− cabal/cabal-testsuite/PackageTests/Sandbox/MultipleSources/cabal.out
@@ -1,12 +0,0 @@-# cabal v1-sandbox init-Writing a default package environment file to <ROOT>/cabal.dist/cabal.sandbox.config-Creating a new sandbox at <ROOT>/cabal.dist/sandbox-# cabal v1-sandbox add-source-# cabal v1-sandbox add-source-# cabal v1-install-Resolving dependencies...-Configuring q-0.1.0.0...-Preprocessing library for q-0.1.0.0..-Building library for q-0.1.0.0..-Installing library in <PATH>-Completed q-0.1.0.0
− cabal/cabal-testsuite/PackageTests/Sandbox/MultipleSources/cabal.test.hs
@@ -1,6 +0,0 @@-import Test.Cabal.Prelude-main = cabalTest $ do- withSandbox $ do- cabal_sandbox "add-source" ["p"]- cabal_sandbox "add-source" ["q"]- cabal "v1-install" ["q"]
− cabal/cabal-testsuite/PackageTests/Sandbox/MultipleSources/p/LICENSE
− cabal/cabal-testsuite/PackageTests/Sandbox/MultipleSources/p/Setup.hs
@@ -1,2 +0,0 @@-import Distribution.Simple-main = defaultMain
− cabal/cabal-testsuite/PackageTests/Sandbox/MultipleSources/p/p.cabal
@@ -1,11 +0,0 @@-name: p-version: 0.1.0.0-license-file: LICENSE-author: Edward Z. Yang-maintainer: ezyang@cs.stanford.edu-build-type: Simple-cabal-version: >=1.10--library- build-depends: base- default-language: Haskell2010
− cabal/cabal-testsuite/PackageTests/Sandbox/MultipleSources/q/LICENSE
− cabal/cabal-testsuite/PackageTests/Sandbox/MultipleSources/q/Setup.hs
@@ -1,2 +0,0 @@-import Distribution.Simple-main = defaultMain
− cabal/cabal-testsuite/PackageTests/Sandbox/MultipleSources/q/q.cabal
@@ -1,11 +0,0 @@-name: q-version: 0.1.0.0-license-file: LICENSE-author: Edward Z. Yang-maintainer: ezyang@cs.stanford.edu-build-type: Simple-cabal-version: >=1.10--library- build-depends: base- default-language: Haskell2010
− cabal/cabal-testsuite/PackageTests/Sandbox/Reinstall/p/Main.hs
@@ -1,7 +0,0 @@-import Q (message)--main :: IO ()-main = do- putStrLn "-----BEGIN CABAL OUTPUT-----"- putStrLn message- putStrLn "-----END CABAL OUTPUT-----"
− cabal/cabal-testsuite/PackageTests/Sandbox/Reinstall/p/p.cabal
@@ -1,8 +0,0 @@-name: p-version: 1.0-build-type: Simple-cabal-version: >= 1.2--executable p- main-is: Main.hs- build-depends: q, base
− cabal/cabal-testsuite/PackageTests/Sandbox/Reinstall/q/Q.hs
@@ -1,4 +0,0 @@-module Q where--message :: String-message = "message"
− cabal/cabal-testsuite/PackageTests/Sandbox/Reinstall/q/Q.hs.in2
@@ -1,4 +0,0 @@-module Q where--message :: String-message = "message updated"
− cabal/cabal-testsuite/PackageTests/Sandbox/Reinstall/q/q.cabal
@@ -1,8 +0,0 @@-name: q-version: 1.0-build-type: Simple-cabal-version: >= 1.2--library- build-depends: base- exposed-modules: Q
− cabal/cabal-testsuite/PackageTests/Sandbox/Reinstall/sandbox.out
@@ -1,15 +0,0 @@-# cabal v1-sandbox init-Writing a default package environment file to <ROOT>/sandbox.dist/cabal.sandbox.config-Creating a new sandbox at <ROOT>/sandbox.dist/sandbox-# cabal v1-sandbox add-source-# cabal v1-install-Resolving dependencies...-Configuring q-1.0...-Preprocessing library for q-1.0..-Building library for q-1.0..-Installing library in <PATH>-Completed q-1.0-# cabal v1-run-message-# cabal v1-run-message updated
− cabal/cabal-testsuite/PackageTests/Sandbox/Reinstall/sandbox.test.hs
@@ -1,9 +0,0 @@-import Test.Cabal.Prelude-main = cabalTest $ do- withSourceCopy . withDelay . withDirectory "p" . withSandbox $ do- cabal_sandbox "add-source" ["../q"]- cabal "v1-install" ["--only-dependencies"]- recordMode RecordMarked $ cabal "v1-run" ["p", "-v0"]- delay- copySourceFileTo "../q/Q.hs.in2" "../q/Q.hs"- recordMode RecordMarked $ cabal "v1-run" ["p", "-v0"]
− cabal/cabal-testsuite/PackageTests/Sandbox/Sources/p/LICENSE
− cabal/cabal-testsuite/PackageTests/Sandbox/Sources/p/Setup.hs
@@ -1,2 +0,0 @@-import Distribution.Simple-main = defaultMain
− cabal/cabal-testsuite/PackageTests/Sandbox/Sources/p/p.cabal
@@ -1,11 +0,0 @@-name: p-version: 0.1.0.0-license-file: LICENSE-author: Edward Z. Yang-maintainer: ezyang@cs.stanford.edu-build-type: Simple-cabal-version: >=1.10--library- build-depends: base- default-language: Haskell2010
− cabal/cabal-testsuite/PackageTests/Sandbox/Sources/q/LICENSE
− cabal/cabal-testsuite/PackageTests/Sandbox/Sources/q/Setup.hs
@@ -1,2 +0,0 @@-import Distribution.Simple-main = defaultMain
− cabal/cabal-testsuite/PackageTests/Sandbox/Sources/q/q.cabal
@@ -1,11 +0,0 @@-name: q-version: 0.1.0.0-license-file: LICENSE-author: Edward Z. Yang-maintainer: ezyang@cs.stanford.edu-build-type: Simple-cabal-version: >=1.10--library- build-depends: base- default-language: Haskell2010
− cabal/cabal-testsuite/PackageTests/Sandbox/Sources/sandbox.out
@@ -1,15 +0,0 @@-# cabal v1-sandbox init-Writing a default package environment file to <ROOT>/sandbox.dist/cabal.sandbox.config-Creating a new sandbox at <ROOT>/sandbox.dist/sandbox-# cabal v1-sandbox add-source-# cabal v1-sandbox delete-source-Warning: Sources not registered: "q"--cabal: The sources with the above errors were skipped. ("q")-# cabal v1-sandbox add-source-# cabal v1-sandbox delete-source-Success deleting sources: "p" "q"--Note: 'sandbox delete-source' only unregisters the source dependency, but does not remove the package from the sandbox package DB.--Use 'sandbox hc-pkg -- unregister' to do that.
− cabal/cabal-testsuite/PackageTests/Sandbox/Sources/sandbox.test.hs
@@ -1,7 +0,0 @@-import Test.Cabal.Prelude-main = cabalTest $ do- withSandbox $ do- cabal_sandbox "add-source" ["p"]- fails $ cabal_sandbox "delete-source" ["q"]- cabal_sandbox "add-source" ["q"]- cabal_sandbox "delete-source" ["p", "q"]
cabal/cabal-testsuite/PackageTests/SimpleDefault/my.cabal view
@@ -1,4 +1,4 @@-cabal-version: 2.1+cabal-version: 2.2 name: my version: 0 -- tests whether the default is `build-type: Simple`
cabal/cabal-testsuite/PackageTests/TemplateHaskell/dynamic/setup.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring templateHaskell-0.1... # Setup build Preprocessing executable 'main' for templateHaskell-0.1..
cabal/cabal-testsuite/PackageTests/TemplateHaskell/profiling/setup.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring templateHaskell-0.1... # Setup build Preprocessing executable 'main' for templateHaskell-0.1..
cabal/cabal-testsuite/PackageTests/TemplateHaskell/vanilla/setup.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring templateHaskell-0.1... # Setup build Preprocessing executable 'main' for templateHaskell-0.1..
cabal/cabal-testsuite/PackageTests/TestNameCollision/setup.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring parent-0.1... # Setup build Preprocessing library for parent-0.1..@@ -9,7 +8,6 @@ # Setup register Registering library for parent-0.1.. # Setup configure-Resolving dependencies... Configuring child-0.1... # Setup build Preprocessing library for child-0.1..@@ -17,10 +15,6 @@ Preprocessing test suite 'parent' for child-0.1.. Building test suite 'parent' for child-0.1.. # Setup test-Preprocessing library for child-0.1..-Building library for child-0.1..-Preprocessing test suite 'parent' for child-0.1..-Building test suite 'parent' for child-0.1.. Running 1 test suites... Test suite parent: RUNNING... Test suite parent: PASS
cabal/cabal-testsuite/PackageTests/TestOptions/TestOptions.cabal view
@@ -5,16 +5,18 @@ stability: stable category: PackageTests build-type: Simple-cabal-version: >= 1.9.2+cabal-version: >= 1.10 description: Check that Cabal passes the correct test options to test suites. executable dummy+ default-language: Haskell2010 main-is: test-TestOptions.hs build-depends: base test-suite test-TestOptions+ default-language: Haskell2010 main-is: test-TestOptions.hs type: exitcode-stdio-1.0 build-depends: base
cabal/cabal-testsuite/PackageTests/TestOptions/setup.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring TestOptions-0.1... # Setup build Preprocessing test suite 'test-TestOptions' for TestOptions-0.1..@@ -7,16 +6,12 @@ Preprocessing executable 'dummy' for TestOptions-0.1.. Building executable 'dummy' for TestOptions-0.1.. # Setup test-Preprocessing test suite 'test-TestOptions' for TestOptions-0.1..-Building test suite 'test-TestOptions' for TestOptions-0.1.. Running 1 test suites... Test suite test-TestOptions: RUNNING... Test suite test-TestOptions: PASS Test suite logged to: setup.cabal.dist/work/dist/test/TestOptions-0.1-test-TestOptions.log 1 of 1 test suites (1 of 1 test cases) passed. # Setup test-Preprocessing test suite 'test-TestOptions' for TestOptions-0.1..-Building test suite 'test-TestOptions' for TestOptions-0.1.. Running 1 test suites... Test suite test-TestOptions: RUNNING... Test suite test-TestOptions: PASS
cabal/cabal-testsuite/PackageTests/TestStanza/setup.cabal.out view
@@ -1,3 +1,2 @@ # Setup configure-Resolving dependencies... Configuring TestStanza-0.1...
cabal/cabal-testsuite/PackageTests/TestSuiteTests/ExeV10/cabal.out view
@@ -9,7 +9,7 @@ Preprocessing library for my-0.1.. Building library for my-0.1.. Configuring test suite 'test-Short' for my-0.1..-Warning: The package has an extraneous version range for a dependency on an internal library: my -any && ==0.1, my -any && ==0.1. This version range includes the current package but isn't needed as the current package's library will always be used.+Warning: The package has an extraneous version range for a dependency on an internal library: my >=0 && ==0.1, my >=0 && ==0.1. This version range includes the current package but isn't needed as the current package's library will always be used. Preprocessing test suite 'test-Short' for my-0.1.. Building test suite 'test-Short' for my-0.1.. Running 1 test suites...@@ -18,7 +18,7 @@ Test suite logged to: <ROOT>/cabal.dist/work/./dist/build/<ARCH>/ghc-<GHCVER>/my-0.1/t/test-Short/test/my-0.1-test-Short.log 1 of 1 test suites (1 of 1 test cases) passed. Configuring test suite 'test-Foo' for my-0.1..-Warning: The package has an extraneous version range for a dependency on an internal library: my -any && ==0.1, my -any && ==0.1. This version range includes the current package but isn't needed as the current package's library will always be used.+Warning: The package has an extraneous version range for a dependency on an internal library: my >=0 && ==0.1, my >=0 && ==0.1. This version range includes the current package but isn't needed as the current package's library will always be used. Preprocessing test suite 'test-Foo' for my-0.1.. Building test suite 'test-Foo' for my-0.1.. Running 1 test suites...
cabal/cabal-testsuite/PackageTests/TestSuiteTests/ExeV10/my.cabal view
@@ -1,20 +1,23 @@ name: my version: 0.1 license: BSD3-cabal-version: >= 1.9.2+cabal-version: >= 1.10 build-type: Simple library+ default-language: Haskell2010 exposed-modules: Foo build-depends: base test-suite test-Foo+ default-language: Haskell2010 type: exitcode-stdio-1.0 hs-source-dirs: tests main-is: test-Foo.hs build-depends: base, my test-suite test-Short+ default-language: Haskell2010 type: exitcode-stdio-1.0 hs-source-dirs: tests main-is: test-Short.hs
cabal/cabal-testsuite/PackageTests/TestSuiteTests/ExeV10/setup-no-markup.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring my-0.1... # Setup build Preprocessing library for my-0.1..@@ -9,10 +8,6 @@ Preprocessing test suite 'test-Short' for my-0.1.. Building test suite 'test-Short' for my-0.1.. # Setup test-Preprocessing library for my-0.1..-Building library for my-0.1..-Preprocessing test suite 'test-Short' for my-0.1..-Building test suite 'test-Short' for my-0.1.. Running 1 test suites... Test suite test-Short: RUNNING... Test suite test-Short: PASS
cabal/cabal-testsuite/PackageTests/TestSuiteTests/ExeV10/setup-no-tix.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring my-0.1... # Setup build Preprocessing library for my-0.1..@@ -9,10 +8,6 @@ Preprocessing test suite 'test-Short' for my-0.1.. Building test suite 'test-Short' for my-0.1.. # Setup test-Preprocessing library for my-0.1..-Building library for my-0.1..-Preprocessing test suite 'test-Short' for my-0.1..-Building test suite 'test-Short' for my-0.1.. Running 1 test suites... Test suite test-Short: RUNNING... Test suite test-Short: PASS
cabal/cabal-testsuite/PackageTests/TestSuiteTests/LibV09/LibV09.cabal view
@@ -5,15 +5,17 @@ stability: stable category: PackageTests build-type: Simple-cabal-version: >= 1.9.2+cabal-version: >= 1.10 description: Check type detailed-0.9 test suites. library+ default-language: Haskell2010 exposed-modules: Lib build-depends: base, Cabal test-suite LibV09-Deadlock+ default-language: Haskell2010 type: detailed-0.9 hs-source-dirs: tests test-module: Deadlock
cabal/cabal-testsuite/PackageTests/TestSuiteTests/LibV09/setup-deadlock.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring LibV09-0.1... # Setup build Preprocessing library for LibV09-0.1..@@ -7,10 +6,6 @@ Preprocessing test suite 'LibV09-Deadlock' for LibV09-0.1.. Building test suite 'LibV09-Deadlock' for LibV09-0.1.. # Setup test-Preprocessing library for LibV09-0.1..-Building library for LibV09-0.1..-Preprocessing test suite 'LibV09-Deadlock' for LibV09-0.1..-Building test suite 'LibV09-Deadlock' for LibV09-0.1.. Running 1 test suites... Test suite LibV09-Deadlock: RUNNING... Test suite LibV09-Deadlock: FAIL
cabal/cabal-testsuite/PackageTests/TestSuiteTests/LibV09/setup.cabal.out view
@@ -1,5 +1,4 @@ # Setup configure-Resolving dependencies... Configuring LibV09-0.1... # Setup build Preprocessing library for LibV09-0.1..
cabal/cabal-testsuite/PackageTests/UniqueIPID/setup.cabal.out view
@@ -1,8 +1,6 @@ # Setup configure-Resolving dependencies... Configuring UniqueIPID-0.1... # Setup configure-Resolving dependencies... Configuring UniqueIPID-0.1... # Setup build Preprocessing library for UniqueIPID-0.1..
− cabal/cabal-testsuite/Test/Cabal/CheckArMetadata.hs
@@ -1,87 +0,0 @@-------------------------------------------------------------------------------- |--- Module : Test.Cabal.CheckArMetadata--- Created : 8 July 2017------ Check well-formedness of metadata of .a files that @ar@ command produces.--- One of the crucial properties of .a files is that they must be--- deterministic - i.e. they must not include creation date as their--- contents to facilitate deterministic builds.-------------------------------------------------------------------------------{-# LANGUAGE OverloadedStrings #-}--module Test.Cabal.CheckArMetadata (checkMetadata) where--import Test.Cabal.Prelude--import qualified Data.ByteString as BS-import qualified Data.ByteString.Char8 as BS8-import Data.Char (isSpace)-import System.IO--import Distribution.Compiler (CompilerFlavor(..), CompilerId(..))-import Distribution.Package (getHSLibraryName)-import Distribution.Simple.Compiler (compilerId)-import Distribution.Simple.LocalBuildInfo (LocalBuildInfo, compiler, localUnitId)---- Almost a copypasta of Distribution.Simple.Program.Ar.wipeMetadata-checkMetadata :: LocalBuildInfo -> FilePath -> IO ()-checkMetadata lbi dir = withBinaryFile path ReadMode $ \ h ->- hFileSize h >>= checkArchive h- where- path = dir </> "lib" ++ getHSLibraryName (localUnitId lbi) ++ ".a"-- _ghc_7_10 = case compilerId (compiler lbi) of- CompilerId GHC version | version >= mkVersion [7, 10] -> True- _ -> False-- checkError msg = assertFailure (- "PackageTests.DeterministicAr.checkMetadata: " ++ msg ++- " in " ++ path) >> undefined- archLF = "!<arch>\x0a" -- global magic, 8 bytes- x60LF = "\x60\x0a" -- header magic, 2 bytes- metadata = BS.concat- [ "0 " -- mtime, 12 bytes- , "0 " -- UID, 6 bytes- , "0 " -- GID, 6 bytes- , "0644 " -- mode, 8 bytes- ]- headerSize = 60-- -- http://en.wikipedia.org/wiki/Ar_(Unix)#File_format_details- checkArchive :: Handle -> Integer -> IO ()- checkArchive h archiveSize = do- global <- BS.hGet h (BS.length archLF)- unless (global == archLF) $ checkError "Bad global header"- checkHeader (toInteger $ BS.length archLF)-- where- checkHeader :: Integer -> IO ()- checkHeader offset = case compare offset archiveSize of- EQ -> return ()- GT -> checkError (atOffset "Archive truncated")- LT -> do- header <- BS.hGet h headerSize- unless (BS.length header == headerSize) $- checkError (atOffset "Short header")- let magic = BS.drop 58 header- unless (magic == x60LF) . checkError . atOffset $- "Bad magic " ++ show magic ++ " in header"-- unless (metadata == BS.take 32 (BS.drop 16 header))- . checkError . atOffset $ "Metadata has changed"-- let size = BS.take 10 $ BS.drop 48 header- objSize <- case reads (BS8.unpack size) of- [(n, s)] | all isSpace s -> return n- _ -> checkError (atOffset "Bad file size in header")-- let nextHeader = offset + toInteger headerSize +- -- Odd objects are padded with an extra '\x0a'- if odd objSize then objSize + 1 else objSize- hSeek h AbsoluteSeek nextHeader- checkHeader nextHeader-- where- atOffset msg = msg ++ " at offset " ++ show offset
− cabal/cabal-testsuite/Test/Cabal/Monad.hs
@@ -1,677 +0,0 @@-{-# LANGUAGE ScopedTypeVariables #-}---- | The test monad-module Test.Cabal.Monad (- -- * High-level runners- setupAndCabalTest,- setupTest,- cabalTest,- -- * The monad- TestM,- runTestM,- -- * Helper functions- programPathM,- requireProgramM,- isAvailableProgram,- hackageRepoToolProgram,- gitProgram,- cabalProgram,- diffProgram,- -- * The test environment- TestEnv(..),- getTestEnv,- -- * Recording mode- RecordMode(..),- testRecordMode,- -- * Regex utility (move me somewhere else)- resub,- -- * Derived values from 'TestEnv'- testCurrentDir,- testWorkDir,- testPrefixDir,- testDistDir,- testPackageDbDir,- testSandboxDir,- testSandboxConfigFile,- testRepoDir,- testKeysDir,- testSourceCopyDir,- testCabalDir,- testUserCabalConfigFile,- testActualFile,- -- * Skipping tests- skip,- skipIf,- skipUnless,- skipExitCode,- -- * Known broken tests- expectedBroken,- unexpectedSuccess,- expectedBrokenExitCode,- unexpectedSuccessExitCode,- -- whenHasSharedLibraries,- -- * Arguments (TODO: move me)- CommonArgs(..),- renderCommonArgs,- commonArgParser,-) where--import Test.Cabal.Script-import Test.Cabal.Plan--import Distribution.Simple.Compiler- ( PackageDBStack, PackageDB(..), compilerFlavor- , Compiler, compilerVersion )-import Distribution.System-import Distribution.Simple.Program.Db-import Distribution.Simple.Program-import Distribution.Simple.Configure- ( configCompilerEx )-import Distribution.Version-import Distribution.Text-import Distribution.Package--import Distribution.Verbosity--import qualified Control.Exception as E-import Control.Monad-import Control.Monad.Trans.Reader-import Control.Monad.IO.Class-import Data.Maybe-import Control.Applicative-import Data.Monoid-import qualified Data.Foldable as F-import System.Directory-import System.Exit-import System.FilePath-import System.IO-import System.IO.Error (isDoesNotExistError)-import System.IO.Temp (withSystemTempDirectory)-import System.Process hiding (env)-import Options.Applicative-import Text.Regex--data CommonArgs = CommonArgs {- argCabalInstallPath :: Maybe FilePath,- argGhcPath :: Maybe FilePath,- argHackageRepoToolPath :: Maybe FilePath,- argHaddockPath :: Maybe FilePath,- argAccept :: Bool,- argSkipSetupTests :: Bool- }--commonArgParser :: Parser CommonArgs-commonArgParser = CommonArgs- <$> optional (option str- ( help "Path to cabal-install executable to test"- <> long "with-cabal"- <> metavar "PATH"- ))- <*> optional (option str- ( help "GHC to ask Cabal to use via --with-ghc flag"- <> short 'w'- <> long "with-ghc"- <> metavar "PATH"- ))- <*> optional (option str- ( help "Path to hackage-repo-tool to use for repository manipulation"- <> long "with-hackage-repo-tool"- <> metavar "PATH"- ))- <*> optional (option str- ( help "Path to haddock to use for --with-haddock flag"- <> long "with-haddock"- <> metavar "PATH"- ))- <*> switch- ( long "accept"- <> help "Accept output"- )- <*> switch (long "skip-setup-tests" <> help "Skip setup tests")--renderCommonArgs :: CommonArgs -> [String]-renderCommonArgs args =- maybe [] (\x -> ["--with-cabal", x]) (argCabalInstallPath args) ++- maybe [] (\x -> ["--with-ghc", x]) (argGhcPath args) ++- maybe [] (\x -> ["--with-haddock", x]) (argHaddockPath args) ++- maybe [] (\x -> ["--with-hackage-repo-tool", x]) (argHackageRepoToolPath args) ++- (if argAccept args then ["--accept"] else []) ++- (if argSkipSetupTests args then ["--skip-setup-tests"] else [])--data TestArgs = TestArgs {- testArgDistDir :: FilePath,- testArgScriptPath :: FilePath,- testCommonArgs :: CommonArgs- }--testArgParser :: Parser TestArgs-testArgParser = TestArgs- <$> option str- ( help "Build directory of cabal-testsuite"- <> long "builddir"- <> metavar "DIR")- <*> argument str ( metavar "FILE")- <*> commonArgParser--skip :: TestM ()-skip = liftIO $ do- putStrLn "SKIP"- exitWith (ExitFailure skipExitCode)--skipIf :: Bool -> TestM ()-skipIf b = when b skip--skipUnless :: Bool -> TestM ()-skipUnless b = unless b skip--expectedBroken :: TestM ()-expectedBroken = liftIO $ do- putStrLn "EXPECTED FAIL"- exitWith (ExitFailure expectedBrokenExitCode)--unexpectedSuccess :: TestM ()-unexpectedSuccess = liftIO $ do- putStrLn "UNEXPECTED OK"- exitWith (ExitFailure unexpectedSuccessExitCode)--skipExitCode :: Int-skipExitCode = 64--expectedBrokenExitCode :: Int-expectedBrokenExitCode = 65--unexpectedSuccessExitCode :: Int-unexpectedSuccessExitCode = 66--catchSkip :: IO a -> IO a -> IO a-catchSkip m r = m `E.catch` \e ->- case e of- ExitFailure c | c == skipExitCode- -> r- _ -> E.throwIO e--setupAndCabalTest :: TestM () -> IO ()-setupAndCabalTest m = do- r1 <- (setupTest m >> return False) `catchSkip` return True- r2 <- (cabalTest' "cabal" m >> return False) `catchSkip` return True- when (r1 && r2) $ do- putStrLn "SKIP"- exitWith (ExitFailure skipExitCode)--setupTest :: TestM () -> IO ()-setupTest m = runTestM "" $ do- env <- getTestEnv- skipIf (testSkipSetupTests env)- m--cabalTest :: TestM () -> IO ()-cabalTest = cabalTest' ""--cabalTest' :: String -> TestM () -> IO ()-cabalTest' mode m = runTestM mode $ do- skipUnless =<< isAvailableProgram cabalProgram- withReaderT (\nenv -> nenv { testCabalInstallAsSetup = True }) m--type TestM = ReaderT TestEnv IO--gitProgram :: Program-gitProgram = simpleProgram "git"--hackageRepoToolProgram :: Program-hackageRepoToolProgram = simpleProgram "hackage-repo-tool"--cabalProgram :: Program-cabalProgram = (simpleProgram "cabal") {- -- Do NOT search for executable named cabal, it's probably- -- not the one you were intending to test- programFindLocation = \_ _ -> return Nothing- }--diffProgram :: Program-diffProgram = simpleProgram "diff"---- | Run a test in the test monad according to program's arguments.-runTestM :: String -> TestM a -> IO a-runTestM mode m = withSystemTempDirectory "cabal-testsuite" $ \tmp_dir -> do- args <- execParser (info testArgParser mempty)- let dist_dir = testArgDistDir args- (script_dir0, script_filename) = splitFileName (testArgScriptPath args)- script_base = dropExtensions script_filename- -- Canonicalize this so that it is stable across working directory changes- script_dir <- canonicalizePath script_dir0- let verbosity = normal -- TODO: configurable- senv <- mkScriptEnv verbosity- -- Add test suite specific programs- let program_db0 =- addKnownPrograms- ([gitProgram, hackageRepoToolProgram, cabalProgram, diffProgram] ++ builtinPrograms)- (runnerProgramDb senv)- -- Reconfigure according to user flags- let cargs = testCommonArgs args-- -- Reconfigure GHC- (comp, platform, program_db2) <- case argGhcPath cargs of- Nothing -> return (runnerCompiler senv, runnerPlatform senv, program_db0)- Just ghc_path -> do- -- All the things that get updated paths from- -- configCompilerEx. The point is to make sure- -- we reconfigure these when we need them.- let program_db1 = unconfigureProgram "ghc"- . unconfigureProgram "ghc-pkg"- . unconfigureProgram "hsc2hs"- . unconfigureProgram "haddock"- . unconfigureProgram "hpc"- . unconfigureProgram "runghc"- . unconfigureProgram "gcc"- . unconfigureProgram "ld"- . unconfigureProgram "ar"- . unconfigureProgram "strip"- $ program_db0- -- TODO: this actually leaves a pile of things unconfigured.- -- Optimal strategy for us is to lazily configure them, so- -- we don't pay for things we don't need. A bit difficult- -- to do in the current design.- configCompilerEx- (Just (compilerFlavor (runnerCompiler senv)))- (Just ghc_path)- Nothing- program_db1- verbosity-- program_db3 <-- reconfigurePrograms verbosity- ([("cabal", p) | p <- maybeToList (argCabalInstallPath cargs)] ++- [("hackage-repo-tool", p)- | p <- maybeToList (argHackageRepoToolPath cargs)] ++- [("haddock", p) | p <- maybeToList (argHaddockPath cargs)])- [] -- --prog-options not supported ATM- program_db2- -- configCompilerEx only marks some programs as known, so to pick- -- them up we must configure them- program_db <- configureAllKnownPrograms verbosity program_db3-- let db_stack =- case argGhcPath (testCommonArgs args) of- Nothing -> runnerPackageDbStack senv -- NB: canonicalized- -- Can't use the build package db stack since they- -- are all for the wrong versions! TODO: Make- -- this configurable- Just _ -> [GlobalPackageDB]- env = TestEnv {- testSourceDir = script_dir,- testTmpDir = tmp_dir,- testSubName = script_base,- testMode = mode,- testProgramDb = program_db,- testPlatform = platform,- testCompiler = comp,- testPackageDBStack = db_stack,- testVerbosity = verbosity,- testMtimeChangeDelay = Nothing,- testScriptEnv = senv,- testSetupPath = dist_dir </> "build" </> "setup" </> "setup",- testSkipSetupTests = argSkipSetupTests (testCommonArgs args),- testHaveCabalShared = runnerWithSharedLib senv,- testEnvironment =- -- Try to avoid Unicode output- [ ("LC_ALL", Just "C")- -- Hermetic builds (knot-tied)- , ("HOME", Just (testHomeDir env))- -- Set CABAL_DIR in addition to HOME, since HOME has no- -- effect on Windows.- , ("CABAL_DIR", Just (testCabalDir env))],- testShouldFail = False,- testRelativeCurrentDir = ".",- testHavePackageDb = False,- testHaveSandbox = False,- testHaveRepo = False,- testHaveSourceCopy = False,- testCabalInstallAsSetup = False,- testCabalProjectFile = "cabal.project",- testPlan = Nothing,- testRecordDefaultMode = DoNotRecord,- testRecordUserMode = Nothing,- testRecordNormalizer = id,- testSourceCopyRelativeDir = "source"- }- let go = do cleanup- r <- m- check_expect (argAccept (testCommonArgs args))- return r- runReaderT go env- where- cleanup = do- env <- getTestEnv- onlyIfExists . removeDirectoryRecursive $ testWorkDir env- -- NB: it's important to initialize this ourselves, as- -- the default configuration hardcodes Hackage, which we do- -- NOT want to assume for these tests (no test should- -- hit Hackage.)- liftIO $ createDirectoryIfMissing True (testCabalDir env)- ghc_path <- programPathM ghcProgram- liftIO $ writeFile (testUserCabalConfigFile env)- $ unlines [ "with-compiler: " ++ ghc_path ]-- check_expect accept = do- env <- getTestEnv- actual_raw <- liftIO $ readFileOrEmpty (testActualFile env)- expect <- liftIO $ readFileOrEmpty (testExpectFile env)- norm_env <- mkNormalizerEnv- let actual = normalizeOutput norm_env actual_raw- when (words actual /= words expect) $ do- -- First try whitespace insensitive diff- let actual_fp = testNormalizedActualFile env- expect_fp = testNormalizedExpectFile env- liftIO $ writeFile actual_fp actual- liftIO $ writeFile expect_fp expect- liftIO $ putStrLn "Actual output differs from expected:"- b <- diff ["-uw"] expect_fp actual_fp- unless b . void $ diff ["-u"] expect_fp actual_fp- if accept- then do liftIO $ putStrLn "Accepting new output."- liftIO $ writeFileNoCR (testExpectFile env) actual- else liftIO $ exitWith (ExitFailure 1)--readFileOrEmpty :: FilePath -> IO String-readFileOrEmpty f = readFile f `E.catch` \e ->- if isDoesNotExistError e- then return ""- else E.throwIO e---- | Runs 'diff' with some arguments on two files, outputting the--- diff to stderr, and returning true if the two files differ-diff :: [String] -> FilePath -> FilePath -> TestM Bool-diff args path1 path2 = do- diff_path <- programPathM diffProgram- (_,_,_,h) <- liftIO $- createProcess (proc diff_path (args ++ [path1, path2])) {- std_out = UseHandle stderr- }- r <- liftIO $ waitForProcess h- return (r /= ExitSuccess)---- | Write a file with no CRs, always.-writeFileNoCR :: FilePath -> String -> IO ()-writeFileNoCR f s =- withFile f WriteMode $ \h -> do- hSetNewlineMode h noNewlineTranslation- hPutStr h s--normalizeOutput :: NormalizerEnv -> String -> String-normalizeOutput nenv =- -- Munge away .exe suffix on filenames (Windows)- resub "([A-Za-z0-9.-]+)\\.exe" "\\1"- -- Normalize backslashes to forward slashes to normalize- -- file paths- . map (\c -> if c == '\\' then '/' else c)- -- Install path frequently has architecture specific elements, so- -- nub it out- . resub "Installing (.+) in .+" "Installing \\1 in <PATH>"- -- Things that look like libraries- . resub "libHS[A-Za-z0-9.-]+\\.(so|dll|a|dynlib)" "<LIBRARY>"- -- This is dumb but I don't feel like pulling in another dep for- -- string search-replace. Make sure we do this before backslash- -- normalization!- . resub (posixRegexEscape (normalizerRoot nenv)) "<ROOT>/"- . resub (posixRegexEscape (normalizerTmpDir nenv)) "<TMPDIR>/"- . appEndo (F.fold (map (Endo . packageIdRegex) (normalizerKnownPackages nenv)))- -- Look for foo-0.1/installed-0d6...- -- These installed packages will vary depending on GHC version- -- Makes assumption that installed packages don't have numbers- -- in package name segment.- -- Apply this before packageIdRegex, otherwise this regex doesn't match.- . resub "([a-zA-Z]+(-[a-zA-Z])*)-[0-9]+(\\.[0-9]+)*/installed-[A-Za-z0-9.]+"- "\\1-<VERSION>/installed-<HASH>..."- -- Normalize architecture- . resub (posixRegexEscape (display (normalizerPlatform nenv))) "<ARCH>"- -- Some GHC versions are chattier than others- . resub "^ignoring \\(possibly broken\\) abi-depends field for packages" ""- -- Normalize the current GHC version. Apply this BEFORE packageIdRegex,- -- which will pick up the install ghc library (which doesn't have the- -- date glob).- . (if normalizerGhcVersion nenv /= nullVersion- then resub (posixRegexEscape (display (normalizerGhcVersion nenv))- -- Also glob the date, for nightly GHC builds- ++ "(\\.[0-9]+)?")- "<GHCVER>"- else id)- where- packageIdRegex pid =- resub (posixRegexEscape (display pid) ++ "(-[A-Za-z0-9.-]+)?")- ((display (packageName pid)) ++ "-<VERSION>")--data NormalizerEnv = NormalizerEnv {- normalizerRoot :: FilePath,- normalizerTmpDir :: FilePath,- normalizerGhcVersion :: Version,- normalizerKnownPackages :: [PackageId],- normalizerPlatform :: Platform- }--mkNormalizerEnv :: TestM NormalizerEnv-mkNormalizerEnv = do- env <- getTestEnv- ghc_pkg_program <- requireProgramM ghcPkgProgram- -- Arguably we should use Cabal's APIs but I am too lazy- -- to remember what it is- list_out <- liftIO $ readProcess (programPath ghc_pkg_program)- ["list", "--global", "--simple-output"] ""- return NormalizerEnv {- normalizerRoot- = addTrailingPathSeparator (testSourceDir env),- normalizerTmpDir- = addTrailingPathSeparator (testTmpDir env),- normalizerGhcVersion- = compilerVersion (testCompiler env),- normalizerKnownPackages- = mapMaybe simpleParse (words list_out),- normalizerPlatform- = testPlatform env- }--posixSpecialChars :: [Char]-posixSpecialChars = ".^$*+?()[{\\|"--posixRegexEscape :: String -> String-posixRegexEscape = concatMap (\c -> if c `elem` posixSpecialChars then ['\\', c] else [c])--resub :: String {- search -} -> String {- replace -} -> String {- input -} -> String-resub search replace s =- subRegex (mkRegex search) s replace--requireProgramM :: Program -> TestM ConfiguredProgram-requireProgramM program = do- env <- getTestEnv- (configured_program, _) <- liftIO $- requireProgram (testVerbosity env) program (testProgramDb env)- return configured_program--programPathM :: Program -> TestM FilePath-programPathM program = do- fmap programPath (requireProgramM program)--isAvailableProgram :: Program -> TestM Bool-isAvailableProgram program = do- env <- getTestEnv- case lookupProgram program (testProgramDb env) of- Just _ -> return True- Nothing -> do- -- It might not have been configured. Try to configure.- progdb <- liftIO $ configureProgram (testVerbosity env) program (testProgramDb env)- case lookupProgram program progdb of- Just _ -> return True- Nothing -> return False---- | Run an IO action, and suppress a "does not exist" error.-onlyIfExists :: MonadIO m => IO () -> m ()-onlyIfExists m =- liftIO $ E.catch m $ \(e :: IOError) ->- unless (isDoesNotExistError e) $ E.throwIO e--data TestEnv = TestEnv- -- UNCHANGING:-- {- -- | Path to the test directory, as specified by path to test- -- script.- testSourceDir :: FilePath- -- | Somewhere to stow temporary files needed by the test.- , testTmpDir :: FilePath- -- | Test sub-name, used to qualify dist/database directory to avoid- -- conflicts.- , testSubName :: String- -- | Test mode, further qualifies multiple invocations of the- -- same test source code.- , testMode :: String- -- | Program database to use when we want ghc, ghc-pkg, etc.- , testProgramDb :: ProgramDb- -- | Compiler we are running tests for- , testCompiler :: Compiler- -- | Platform we are running tests on- , testPlatform :: Platform- -- | Package database stack (actually this changes lol)- , testPackageDBStack :: PackageDBStack- -- | How verbose to be- , testVerbosity :: Verbosity- -- | How long we should 'threadDelay' to make sure the file timestamp is- -- updated correctly for recompilation tests. Nothing if we haven't- -- calibrated yet.- , testMtimeChangeDelay :: Maybe Int- -- | Script environment for runghc- , testScriptEnv :: ScriptEnv- -- | Setup script path- , testSetupPath :: FilePath- -- | Skip Setup tests?- , testSkipSetupTests :: Bool- -- | Do we have shared libraries for the Cabal-under-tests?- -- This is used for example to determine whether we can build- -- detailed-0.9 tests dynamically, since they link against Cabal-under-test.- , testHaveCabalShared :: Bool-- -- CHANGING:-- -- | Environment override- , testEnvironment :: [(String, Maybe String)]- -- | When true, we invert the meaning of command execution failure- , testShouldFail :: Bool- -- | The current working directory, relative to 'testSourceDir'- , testRelativeCurrentDir :: FilePath- -- | Says if we've initialized the per-test package DB- , testHavePackageDb :: Bool- -- | Says if we're working in a sandbox- , testHaveSandbox :: Bool- -- | Says if we've setup a repository- , testHaveRepo :: Bool- -- | Says if we've copied the source to a hermetic directory- , testHaveSourceCopy :: Bool- -- | Says if we're testing cabal-install as setup- , testCabalInstallAsSetup :: Bool- -- | Says what cabal.project file to use (probed)- , testCabalProjectFile :: FilePath- -- | Cached record of the plan metadata from a new-build- -- invocation; controlled by 'withPlan'.- , testPlan :: Maybe Plan- -- | If user mode is not set, this is the record mode we default to.- , testRecordDefaultMode :: RecordMode- -- | User explicitly set record mode. Not implemented ATM.- , testRecordUserMode :: Maybe RecordMode- -- | Function to normalize recorded output- , testRecordNormalizer :: String -> String- -- | Name of the subdirectory we copied the test's sources to,- -- relative to 'testSourceDir'- , testSourceCopyRelativeDir :: FilePath- }--testRecordMode :: TestEnv -> RecordMode-testRecordMode env = fromMaybe (testRecordDefaultMode env) (testRecordUserMode env)--data RecordMode = DoNotRecord | RecordMarked | RecordAll- deriving (Show, Eq, Ord)--getTestEnv :: TestM TestEnv-getTestEnv = ask----------------------------------------------------------------------------- * Directories---- | The absolute path to the root of the package directory; it's--- where the Cabal file lives. This is what you want the CWD of cabal--- calls to be.-testCurrentDir :: TestEnv -> FilePath-testCurrentDir env =- (if testHaveSourceCopy env- then testSourceCopyDir env- else testSourceDir env) </> testRelativeCurrentDir env--testName :: TestEnv -> String-testName env = testSubName env <.> testMode env---- | The absolute path to the directory containing all the--- files for ALL tests associated with a test (respecting--- subtests.) To clean, you ONLY need to delete this directory.-testWorkDir :: TestEnv -> FilePath-testWorkDir env =- testSourceDir env </> (testName env <.> "dist")---- | The absolute prefix where installs go.-testPrefixDir :: TestEnv -> FilePath-testPrefixDir env = testWorkDir env </> "usr"---- | The absolute path to the build directory that should be used--- for the current package in a test.-testDistDir :: TestEnv -> FilePath-testDistDir env = testWorkDir env </> "work" </> testRelativeCurrentDir env </> "dist"---- | The absolute path to the shared package database that should--- be used by all packages in this test.-testPackageDbDir :: TestEnv -> FilePath-testPackageDbDir env = testWorkDir env </> "packagedb"---- | The absolute prefix where our simulated HOME directory is.-testHomeDir :: TestEnv -> FilePath-testHomeDir env = testWorkDir env </> "home"---- | The absolute prefix of our sandbox directory-testSandboxDir :: TestEnv -> FilePath-testSandboxDir env = testWorkDir env </> "sandbox"---- | The sandbox configuration file-testSandboxConfigFile :: TestEnv -> FilePath-testSandboxConfigFile env = testWorkDir env </> "cabal.sandbox.config"---- | The absolute prefix of our local secure repository, which we--- use to simulate "external" packages-testRepoDir :: TestEnv -> FilePath-testRepoDir env = testWorkDir env </> "repo"---- | The absolute prefix of keys for the test.-testKeysDir :: TestEnv -> FilePath-testKeysDir env = testWorkDir env </> "keys"---- | If 'withSourceCopy' is used, where the source files go.-testSourceCopyDir :: TestEnv -> FilePath-testSourceCopyDir env = testWorkDir env </> testSourceCopyRelativeDir env---- | The user cabal directory-testCabalDir :: TestEnv -> FilePath-testCabalDir env = testHomeDir env </> ".cabal"---- | The user cabal config file-testUserCabalConfigFile :: TestEnv -> FilePath-testUserCabalConfigFile env = testCabalDir env </> "config"---- | The file where the expected output of the test lives-testExpectFile :: TestEnv -> FilePath-testExpectFile env = testSourceDir env </> testName env <.> "out"---- | Where we store the actual output-testActualFile :: TestEnv -> FilePath-testActualFile env = testWorkDir env </> testName env <.> "comp.out"---- | Where we will write the normalized actual file (for diffing)-testNormalizedActualFile :: TestEnv -> FilePath-testNormalizedActualFile env = testActualFile env <.> "normalized"---- | Where we will write the normalized expected file (for diffing)-testNormalizedExpectFile :: TestEnv -> FilePath-testNormalizedExpectFile env = testWorkDir env </> testName env <.> "out.normalized"
− cabal/cabal-testsuite/Test/Cabal/Plan.hs
@@ -1,88 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}--- | Utilities for understanding @plan.json@.-module Test.Cabal.Plan (- Plan,- planDistDir,-) where--import Distribution.Parsec (simpleParsec)-import Distribution.Pretty (prettyShow)-import Distribution.Types.ComponentName-import Distribution.Package-import qualified Data.Text as Text-import Data.Aeson-import Data.Aeson.Types-import Control.Monad---- TODO: index this-data Plan = Plan { planInstallPlan :: [InstallItem] }--data InstallItem- = APreExisting- | AConfiguredGlobal- | AConfiguredInplace ConfiguredInplace---- local or inplace package-data ConfiguredInplace = ConfiguredInplace- { configuredInplaceDistDir :: FilePath- , configuredInplacePackageName :: PackageName- , configuredInplaceComponentName :: Maybe ComponentName }--instance FromJSON Plan where- parseJSON (Object v) = fmap Plan (v .: "install-plan")- parseJSON invalid = typeMismatch "Plan" invalid--instance FromJSON InstallItem where- parseJSON obj@(Object v) = do- t <- v .: "type"- case t :: String of- "pre-existing" -> return APreExisting- "configured" -> do- s <- v .: "style"- case s :: String of- "global" -> return AConfiguredGlobal- "inplace" -> AConfiguredInplace `fmap` parseJSON obj- "local" -> AConfiguredInplace `fmap` parseJSON obj- _ -> fail $ "unrecognized value of 'style' field: " ++ s- _ -> fail "unrecognized value of 'type' field"- parseJSON invalid = typeMismatch "InstallItem" invalid--instance FromJSON ConfiguredInplace where- parseJSON (Object v) = do- dist_dir <- v .: "dist-dir"- pkg_name <- v .: "pkg-name"- component_name <- v .:? "component-name"- return (ConfiguredInplace dist_dir pkg_name component_name)- parseJSON invalid = typeMismatch "ConfiguredInplace" invalid--instance FromJSON PackageName where- parseJSON (String t) = return (mkPackageName (Text.unpack t))- parseJSON invalid = typeMismatch "PackageName" invalid--instance FromJSON ComponentName where- parseJSON (String t) =- case simpleParsec s of- Nothing -> fail ("could not parse component-name: " ++ s)- Just r -> return r- where s = Text.unpack t- parseJSON invalid = typeMismatch "ComponentName" invalid--planDistDir :: Plan -> PackageName -> ComponentName -> FilePath-planDistDir plan pkg_name cname =- case concatMap p (planInstallPlan plan) of- [x] -> x- [] -> error $ "planDistDir: component " ++ prettyShow cname- ++ " of package " ++ prettyShow pkg_name ++ " either does not"- ++ " exist in the install plan or does not have a dist-dir"- _ -> error $ "planDistDir: found multiple copies of component " ++ prettyShow cname- ++ " of package " ++ prettyShow pkg_name ++ " in install plan"- where- p APreExisting = []- p AConfiguredGlobal = []- p (AConfiguredInplace conf) = do- guard (configuredInplacePackageName conf == pkg_name)- guard $ case configuredInplaceComponentName conf of- Nothing -> True- Just cname' -> cname == cname'- return (configuredInplaceDistDir conf)
− cabal/cabal-testsuite/Test/Cabal/Prelude.hs
@@ -1,1028 +0,0 @@-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE NamedFieldPuns #-}-{-# LANGUAGE NondecreasingIndentation #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE CPP #-}---- | Generally useful definitions that we expect most test scripts--- to use.-module Test.Cabal.Prelude (- module Test.Cabal.Prelude,- module Test.Cabal.Monad,- module Test.Cabal.Run,- module System.FilePath,- module Control.Monad,- module Control.Monad.IO.Class,- module Distribution.Version,- module Distribution.Simple.Program,-) where--import Test.Cabal.Script-import Test.Cabal.Run-import Test.Cabal.Monad-import Test.Cabal.Plan--import Distribution.Compat.Time (calibrateMtimeChangeDelay)-import Distribution.Simple.Compiler (PackageDBStack, PackageDB(..))-import Distribution.Simple.Program.Types-import Distribution.Simple.Program.Db-import Distribution.Simple.Program-import Distribution.System (OS(Windows,Linux,OSX), buildOS)-import Distribution.Simple.Utils- ( withFileContents, withTempDirectory, tryFindPackageDesc )-import Distribution.Simple.Configure- ( getPersistBuildConfig )-import Distribution.Version-import Distribution.Package-import Distribution.Types.UnqualComponentName-import Distribution.Types.LocalBuildInfo-import Distribution.PackageDescription-import Distribution.PackageDescription.Parsec-import Distribution.Verbosity (normal)--import Distribution.Compat.Stack--import Text.Regex.TDFA--import Control.Concurrent.Async-import qualified Data.Aeson as JSON-import qualified Data.ByteString.Lazy as BSL-import Control.Monad-import Control.Monad.Trans.Reader-import Control.Monad.IO.Class-import qualified Data.ByteString.Char8 as C-import Data.List-import Data.Maybe-import System.Exit-import System.FilePath-import Control.Concurrent (threadDelay)-import qualified Data.Char as Char-import System.Directory--#ifndef mingw32_HOST_OS-import Control.Monad.Catch ( bracket_ )-import System.Posix.Files ( createSymbolicLink )-import System.Posix.Resource-#endif----------------------------------------------------------------------------- * Utilities--runM :: FilePath -> [String] -> TestM Result-runM path args = do- env <- getTestEnv- r <- liftIO $ run (testVerbosity env)- (Just (testCurrentDir env))- (testEnvironment env)- path- args- recordLog r- requireSuccess r--runProgramM :: Program -> [String] -> TestM Result-runProgramM prog args = do- configured_prog <- requireProgramM prog- -- TODO: Consider also using other information from- -- ConfiguredProgram, e.g., env and args- runM (programPath configured_prog) args--getLocalBuildInfoM :: TestM LocalBuildInfo-getLocalBuildInfoM = do- env <- getTestEnv- liftIO $ getPersistBuildConfig (testDistDir env)----------------------------------------------------------------------------- * Changing parameters--withDirectory :: FilePath -> TestM a -> TestM a-withDirectory f = withReaderT- (\env -> env { testRelativeCurrentDir = testRelativeCurrentDir env </> f })---- We append to the environment list, as per 'getEffectiveEnvironment'--- which prefers the latest override.-withEnv :: [(String, Maybe String)] -> TestM a -> TestM a-withEnv e = withReaderT (\env -> env { testEnvironment = testEnvironment env ++ e })---- HACK please don't use me-withEnvFilter :: (String -> Bool) -> TestM a -> TestM a-withEnvFilter p = withReaderT (\env -> env { testEnvironment = filter (p . fst) (testEnvironment env) })----------------------------------------------------------------------------- * Running Setup--marked_verbose :: String-marked_verbose = "-vverbose +markoutput +nowrap"--setup :: String -> [String] -> TestM ()-setup cmd args = void (setup' cmd args)--setup' :: String -> [String] -> TestM Result-setup' = setup'' "."--setup''- :: FilePath- -- ^ Subdirectory to find the @.cabal@ file in.- -> String- -- ^ Command name- -> [String]- -- ^ Arguments- -> TestM Result-setup'' prefix cmd args = do- env <- getTestEnv- when ((cmd == "register" || cmd == "copy") && not (testHavePackageDb env)) $- error "Cannot register/copy without using 'withPackageDb'"- ghc_path <- programPathM ghcProgram- haddock_path <- programPathM haddockProgram- let args' = case cmd of- "configure" ->- -- If the package database is empty, setting --global- -- here will make us error loudly if we try to install- -- into a bad place.- [ "--global"- -- NB: technically unnecessary with Cabal, but- -- definitely needed for Setup, which doesn't- -- respect cabal.config- , "--with-ghc", ghc_path- , "--with-haddock", haddock_path- -- This avoids generating hashes in our package IDs,- -- which helps the test suite's expect tests.- , "--enable-deterministic"- -- These flags make the test suite run faster- -- Can't do this unless we LD_LIBRARY_PATH correctly- -- , "--enable-executable-dynamic"- -- , "--disable-optimization"- -- Specify where we want our installed packages to go- , "--prefix=" ++ testPrefixDir env- ] ++ packageDBParams (testPackageDBStack env)- ++ args- _ -> args- let rel_dist_dir = definitelyMakeRelative (testCurrentDir env) (testDistDir env)- full_args = cmd : [marked_verbose, "--distdir", rel_dist_dir] ++ args'- defaultRecordMode RecordMarked $ do- recordHeader ["Setup", cmd]- if testCabalInstallAsSetup env- then- -- `cabal` and `Setup` no longer have the same interface.- -- A bit of fettling is required to hide this fact.- let- legacyCmds =- [ "build"- , "configure"- , "repl"- , "freeze"- , "run"- , "test"- , "bench"- , "haddock"- , "exec"- , "update"- , "install"- , "clean"- , "register"- , "copy"- , "sdist"- , "reconfigure"- , "doctest"- ]- (a:as) = full_args- full_args' = if a `elem` legacyCmds then ("v1-" ++ a) : as else a:as- in runProgramM cabalProgram full_args'- else do- pdfile <- liftIO $ tryFindPackageDesc (testVerbosity env)- (testCurrentDir env </> prefix)- pdesc <- liftIO $ readGenericPackageDescription (testVerbosity env) pdfile- if buildType (packageDescription pdesc) == Simple- then runM (testSetupPath env) full_args- -- Run the Custom script!- else do- r <- liftIO $ runghc (testScriptEnv env)- (Just (testCurrentDir env))- (testEnvironment env)- (testCurrentDir env </> prefix </> "Setup.hs")- full_args- recordLog r- requireSuccess r- -- This code is very tempting (and in principle should be quick:- -- after all we are loading the built version of Cabal), but- -- actually it costs quite a bit in wallclock time (e.g. 54sec to- -- 68sec on AllowNewer, working with un-optimized Cabal.)- {-- r <- liftIO $ runghc (testScriptEnv env)- (Just (testCurrentDir env))- (testEnvironment env)- "Setup.hs"- (cmd : ["-v", "--distdir", testDistDir env] ++ args')- -- don't forget to check results...- -}--definitelyMakeRelative :: FilePath -> FilePath -> FilePath-definitelyMakeRelative base0 path0 =- let go [] path = joinPath path- go base [] = joinPath (replicate (length base) "..")- go (x:xs) (y:ys)- | x == y = go xs ys- | otherwise = go (x:xs) [] </> go [] (y:ys)- -- NB: It's important to normalize, as otherwise if- -- we see "foo/./bar" we'll incorrectly conclude that we need- -- to go "../../.." to get out of it.- in go (splitPath (normalise base0)) (splitPath (normalise path0))---- | This abstracts the common pattern of configuring and then building.-setup_build :: [String] -> TestM ()-setup_build args = do- setup "configure" args- setup "build" []- return ()---- | This abstracts the common pattern of "installing" a package.-setup_install :: [String] -> TestM ()-setup_install args = do- setup "configure" args- setup "build" []- setup "copy" []- setup "register" []- return ()---- | This abstracts the common pattern of "installing" a package,--- with haddock documentation.-setup_install_with_docs :: [String] -> TestM ()-setup_install_with_docs args = do- setup "configure" args- setup "build" []- setup "haddock" []- setup "copy" []- setup "register" []- return ()--packageDBParams :: PackageDBStack -> [String]-packageDBParams dbs = "--package-db=clear"- : map (("--package-db=" ++) . convert) dbs- where- convert :: PackageDB -> String- convert GlobalPackageDB = "global"- convert UserPackageDB = "user"- convert (SpecificPackageDB path) = path----------------------------------------------------------------------------- * Running cabal--cabal :: String -> [String] -> TestM ()-cabal "sandbox" _ =- error "Use cabal_sandbox instead"-cabal cmd args = void (cabal' cmd args)--cabal' :: String -> [String] -> TestM Result-cabal' = cabalG' []--cabalG :: [String] -> String -> [String] -> TestM ()-cabalG global_args cmd args = void (cabalG' global_args cmd args)--cabalG' :: [String] -> String -> [String] -> TestM Result-cabalG' _ "sandbox" _ =- -- NB: We don't just auto-pass this through, because it's- -- possible that the first argument isn't the sub-sub-command.- -- So make sure the user specifies it correctly.- error "Use cabal_sandbox' instead"-cabalG' global_args cmd args = do- env <- getTestEnv- -- Freeze writes out cabal.config to source directory, this is not- -- overwritable- when (cmd == "v1-freeze") requireHasSourceCopy- let extra_args- -- Sandboxes manage dist dir- | testHaveSandbox env- = install_args- | cmd `elem` ["v1-update", "outdated", "user-config", "manpage", "v1-freeze", "check"]- = [ ]- -- new-build commands are affected by testCabalProjectFile- | cmd == "v2-sdist" = [ "--project-file", testCabalProjectFile env ]- | "v2-" `isPrefixOf` cmd- = [ "--builddir", testDistDir env- , "--project-file", testCabalProjectFile env- , "-j1" ]- | otherwise- = [ "--builddir", testDistDir env ] ++- install_args- install_args- | cmd == "v1-install"- || cmd == "v1-build" = [ "-j1" ]- | otherwise = []- extra_global_args- | testHaveSandbox env- = [ "--sandbox-config-file", testSandboxConfigFile env ]- | otherwise- = []- cabal_args = extra_global_args- ++ global_args- ++ [ cmd, marked_verbose ]- ++ extra_args- ++ args- defaultRecordMode RecordMarked $ do- recordHeader ["cabal", cmd]- cabal_raw' cabal_args--cabal_sandbox :: String -> [String] -> TestM ()-cabal_sandbox cmd args = void $ cabal_sandbox' cmd args--cabal_sandbox' :: String -> [String] -> TestM Result-cabal_sandbox' cmd args = do- env <- getTestEnv- let cabal_args = [ "--sandbox-config-file", testSandboxConfigFile env- , "v1-sandbox", cmd- , marked_verbose ]- ++ args- defaultRecordMode RecordMarked $ do- recordHeader ["cabal", "v1-sandbox", cmd]- cabal_raw' cabal_args--cabal_raw' :: [String] -> TestM Result-cabal_raw' cabal_args = runProgramM cabalProgram cabal_args--withSandbox :: TestM a -> TestM a-withSandbox m = do- env0 <- getTestEnv- -- void $ cabal_raw' ["sandbox", "init", "--sandbox", testSandboxDir env0]- cabal_sandbox "init" ["--sandbox", testSandboxDir env0]- withReaderT (\env -> env { testHaveSandbox = True }) m--withProjectFile :: FilePath -> TestM a -> TestM a-withProjectFile fp m =- withReaderT (\env -> env { testCabalProjectFile = fp }) m---- | Assuming we've successfully configured a new-build project,--- read out the plan metadata so that we can use it to do other--- operations.-withPlan :: TestM a -> TestM a-withPlan m = do- env0 <- getTestEnv- let filepath = testDistDir env0 </> "cache" </> "plan.json"- mplan <- JSON.eitherDecode `fmap` liftIO (BSL.readFile filepath)- case mplan of- Left err -> fail $ "withPlan: cannot decode plan " ++ err- Right plan -> withReaderT (\env -> env { testPlan = Just plan }) m---- | Run an executable from a package. Requires 'withPlan' to have--- been run so that we can find the dist dir.-runPlanExe :: String {- package name -} -> String {- component name -}- -> [String] -> TestM ()-runPlanExe pkg_name cname args = void $ runPlanExe' pkg_name cname args---- | Run an executable from a package. Requires 'withPlan' to have--- been run so that we can find the dist dir. Also returns 'Result'.-runPlanExe' :: String {- package name -} -> String {- component name -}- -> [String] -> TestM Result-runPlanExe' pkg_name cname args = do- Just plan <- testPlan `fmap` getTestEnv- let dist_dir = planDistDir plan (mkPackageName pkg_name)- (CExeName (mkUnqualComponentName cname))- defaultRecordMode RecordAll $ do- recordHeader [pkg_name, cname]- runM (dist_dir </> "build" </> cname </> cname) args----------------------------------------------------------------------------- * Running ghc-pkg--withPackageDb :: TestM a -> TestM a-withPackageDb m = do- env <- getTestEnv- let db_path = testPackageDbDir env- if testHavePackageDb env- then m- else withReaderT (\nenv ->- nenv { testPackageDBStack- = testPackageDBStack env- ++ [SpecificPackageDB db_path]- , testHavePackageDb = True- } )- $ do ghcPkg "init" [db_path]- m--ghcPkg :: String -> [String] -> TestM ()-ghcPkg cmd args = void (ghcPkg' cmd args)--ghcPkg' :: String -> [String] -> TestM Result-ghcPkg' cmd args = do- env <- getTestEnv- unless (testHavePackageDb env) $- error "Must initialize package database using withPackageDb"- -- NB: testDBStack already has the local database- ghcConfProg <- requireProgramM ghcProgram- let db_stack = testPackageDBStack env- extraArgs = ghcPkgPackageDBParams- (fromMaybe- (error "ghc-pkg: cannot detect version")- (programVersion ghcConfProg))- db_stack- recordHeader ["ghc-pkg", cmd]- runProgramM ghcPkgProgram (cmd : extraArgs ++ args)--ghcPkgPackageDBParams :: Version -> PackageDBStack -> [String]-ghcPkgPackageDBParams version dbs = concatMap convert dbs where- convert :: PackageDB -> [String]- -- Ignoring global/user is dodgy but there's no way good- -- way to give ghc-pkg the correct flags in this case.- convert GlobalPackageDB = []- convert UserPackageDB = []- convert (SpecificPackageDB path)- | version >= mkVersion [7,6]- = ["--package-db=" ++ path]- | otherwise- = ["--package-conf=" ++ path]----------------------------------------------------------------------------- * Running other things---- | Run an executable that was produced by cabal. The @exe_name@--- is precisely the name of the executable section in the file.-runExe :: String -> [String] -> TestM ()-runExe exe_name args = void (runExe' exe_name args)--runExe' :: String -> [String] -> TestM Result-runExe' exe_name args = do- env <- getTestEnv- defaultRecordMode RecordAll $ do- recordHeader [exe_name]- runM (testDistDir env </> "build" </> exe_name </> exe_name) args---- | Run an executable that was installed by cabal. The @exe_name@--- is precisely the name of the executable.-runInstalledExe :: String -> [String] -> TestM ()-runInstalledExe exe_name args = void (runInstalledExe' exe_name args)---- | Run an executable that was installed by cabal. Use this--- instead of 'runInstalledExe' if you need to inspect the--- stdout/stderr output.-runInstalledExe' :: String -> [String] -> TestM Result-runInstalledExe' exe_name args = do- env <- getTestEnv- defaultRecordMode RecordAll $ do- recordHeader [exe_name]- runM (testPrefixDir env </> "bin" </> exe_name) args---- | Run a shell command in the current directory.-shell :: String -> [String] -> TestM Result-shell exe args = runM exe args----------------------------------------------------------------------------- * Repository manipulation---- Workflows we support:--- 1. Test comes with some packages (directories in repository) which--- should be in the repository and available for depsolving/installing--- into global store.------ Workflows we might want to support in the future--- * Regression tests may want to test on Hackage index. They will--- operate deterministically as they will be pinned to a timestamp.--- (But should we allow this? Have to download the tarballs in that--- case. Perhaps dep solver only!)--- * We might sdist a local package, and then upload it to the--- repository--- * Some of our tests involve old versions of Cabal. This might--- be one of the rare cases where we're willing to grab the entire--- tarball.------ Properties we want to hold:--- 1. Tests can be run offline. No dependence on hackage.haskell.org--- beyond what we needed to actually get the build of Cabal working--- itself--- 2. Tests are deterministic. Updates to Hackage should not cause--- tests to fail. (OTOH, it's good to run tests on most recent--- Hackage index; some sort of canary test which is run nightly.--- Point is it should NOT be tied to cabal source code.)------ Technical notes:--- * We depend on hackage-repo-tool binary. It would better if it was--- libified into hackage-security but this has not been done yet.-----hackageRepoTool :: String -> [String] -> TestM ()-hackageRepoTool cmd args = void $ hackageRepoTool' cmd args--hackageRepoTool' :: String -> [String] -> TestM Result-hackageRepoTool' cmd args = do- recordHeader ["hackage-repo-tool", cmd]- runProgramM hackageRepoToolProgram (cmd : args)--tar :: [String] -> TestM ()-tar args = void $ tar' args--tar' :: [String] -> TestM Result-tar' args = do- recordHeader ["tar"]- runProgramM tarProgram args---- | Creates a tarball of a directory, such that if you--- archive the directory "/foo/bar/baz" to "mine.tgz", @tar tf@ reports--- @baz/file1@, @baz/file2@, etc.-archiveTo :: FilePath -> FilePath -> TestM ()-src `archiveTo` dst = do- -- TODO: Consider using the @tar@ library?- let (src_parent, src_dir) = splitFileName src- -- TODO: --format ustar, like createArchive?- -- --force-local is necessary for handling colons in Windows paths.- tar $ ["-czf", dst]- ++ ["--force-local" | buildOS == Windows]- ++ ["-C", src_parent, src_dir]--infixr 4 `archiveTo`---- | Given a directory (relative to the 'testCurrentDir') containing--- a series of directories representing packages, generate an--- external repository corresponding to all of these packages-withRepo :: FilePath -> TestM a -> TestM a-withRepo repo_dir m = do- env <- getTestEnv-- -- Check if hackage-repo-tool is available, and skip if not- skipUnless =<< isAvailableProgram hackageRepoToolProgram-- -- 1. Generate keys- hackageRepoTool "create-keys" ["--keys", testKeysDir env]- -- 2. Initialize repo directory- let package_dir = testRepoDir env </> "package"- liftIO $ createDirectoryIfMissing True (testRepoDir env </> "index")- liftIO $ createDirectoryIfMissing True package_dir- -- 3. Create tarballs- pkgs <- liftIO $ getDirectoryContents (testCurrentDir env </> repo_dir)- forM_ pkgs $ \pkg -> do- case pkg of- '.':_ -> return ()- _ -> testCurrentDir env </> repo_dir </> pkg- `archiveTo`- package_dir </> pkg <.> "tar.gz"- -- 4. Initialize repository- hackageRepoTool "bootstrap" ["--keys", testKeysDir env, "--repo", testRepoDir env]- -- 5. Wire it up in .cabal/config- -- TODO: libify this- let package_cache = testCabalDir env </> "packages"- liftIO $ appendFile (testUserCabalConfigFile env)- $ unlines [ "repository test-local-repo"- , " url: " ++ repoUri env- , " secure: True"- -- TODO: Hypothetically, we could stick in the- -- correct key here- , " root-keys: "- , " key-threshold: 0"- , "remote-repo-cache: " ++ package_cache ]- -- 6. Create local directories (TODO: this is a bug #4136, once you- -- fix that this can be removed)- liftIO $ createDirectoryIfMissing True (package_cache </> "test-local-repo")- -- 7. Update our local index- cabal "v1-update" []- -- 8. Profit- withReaderT (\env' -> env' { testHaveRepo = True }) m- -- TODO: Arguably should undo everything when we're done...- where- -- Work around issue #5218 (incorrect conversions between Windows paths and- -- file URIs) by using a relative path on Windows.- repoUri env =- if buildOS == Windows- then let relPath = definitelyMakeRelative (testCurrentDir env)- (testRepoDir env)- convertSeparators = intercalate "/"- . map dropTrailingPathSeparator- . splitPath- in "file:" ++ convertSeparators relPath- else "file:" ++ testRepoDir env----------------------------------------------------------------------------- * Subprocess run results--requireSuccess :: Result -> TestM Result-requireSuccess r@Result { resultCommand = cmd- , resultExitCode = exitCode- , resultOutput = output } = withFrozenCallStack $ do- env <- getTestEnv- when (exitCode /= ExitSuccess && not (testShouldFail env)) $- assertFailure $ "Command " ++ cmd ++ " failed.\n" ++- "Output:\n" ++ output ++ "\n"- when (exitCode == ExitSuccess && testShouldFail env) $- assertFailure $ "Command " ++ cmd ++ " succeeded.\n" ++- "Output:\n" ++ output ++ "\n"- return r--initWorkDir :: TestM ()-initWorkDir = do- env <- getTestEnv- liftIO $ createDirectoryIfMissing True (testWorkDir env)---- | Record a header to help identify the output to the expect--- log. Unlike the 'recordLog', we don't record all arguments;--- just enough to give you an idea of what the command might have--- been. (This is because the arguments may not be deterministic,--- so we don't want to spew them to the log.)-recordHeader :: [String] -> TestM ()-recordHeader args = do- env <- getTestEnv- let mode = testRecordMode env- str_header = "# " ++ intercalate " " args ++ "\n"- header = C.pack (testRecordNormalizer env str_header)- case mode of- DoNotRecord -> return ()- _ -> do- initWorkDir- liftIO $ putStr str_header- liftIO $ C.appendFile (testWorkDir env </> "test.log") header- liftIO $ C.appendFile (testActualFile env) header--recordLog :: Result -> TestM ()-recordLog res = do- env <- getTestEnv- let mode = testRecordMode env- initWorkDir- liftIO $ C.appendFile (testWorkDir env </> "test.log")- (C.pack $ "+ " ++ resultCommand res ++ "\n"- ++ resultOutput res ++ "\n\n")- liftIO . C.appendFile (testActualFile env) . C.pack . testRecordNormalizer env $- case mode of- RecordAll -> unlines (lines (resultOutput res))- RecordMarked -> getMarkedOutput (resultOutput res)- DoNotRecord -> ""--getMarkedOutput :: String -> String -- trailing newline-getMarkedOutput out = unlines (go (lines out) False)- where- go [] _ = []- go (x:xs) True- | "-----END CABAL OUTPUT-----" `isPrefixOf` x- = go xs False- | otherwise = x : go xs True- go (x:xs) False- -- NB: Windows has extra goo at the end- | "-----BEGIN CABAL OUTPUT-----" `isPrefixOf` x- = go xs True- | otherwise = go xs False----------------------------------------------------------------------------- * Test helpers--assertFailure :: WithCallStack (String -> m ())-assertFailure msg = withFrozenCallStack $ error msg--assertExitCode :: MonadIO m => WithCallStack (ExitCode -> Result -> m ())-assertExitCode code result =- when (code /= resultExitCode result) $- assertFailure $ "Expected exit code: "- ++ show code- ++ "\nActual: "- ++ show (resultExitCode result)--assertEqual :: (Eq a, Show a, MonadIO m) => WithCallStack (String -> a -> a -> m ())-assertEqual s x y =- withFrozenCallStack $- when (x /= y) $- error (s ++ ":\nExpected: " ++ show x ++ "\nActual: " ++ show y)--assertNotEqual :: (Eq a, Show a, MonadIO m) => WithCallStack (String -> a -> a -> m ())-assertNotEqual s x y =- withFrozenCallStack $- when (x == y) $- error (s ++ ":\nGot both: " ++ show x)--assertBool :: MonadIO m => WithCallStack (String -> Bool -> m ())-assertBool s x =- withFrozenCallStack $- unless x $ error s--shouldExist :: MonadIO m => WithCallStack (FilePath -> m ())-shouldExist path =- withFrozenCallStack $- liftIO $ doesFileExist path >>= assertBool (path ++ " should exist")--shouldNotExist :: MonadIO m => WithCallStack (FilePath -> m ())-shouldNotExist path =- withFrozenCallStack $- liftIO $ doesFileExist path >>= assertBool (path ++ " should exist") . not--assertRegex :: MonadIO m => String -> String -> Result -> m ()-assertRegex msg regex r =- withFrozenCallStack $- let out = resultOutput r- in assertBool (msg ++ ",\nactual output:\n" ++ out)- (out =~ regex)--fails :: TestM a -> TestM a-fails = withReaderT (\env -> env { testShouldFail = not (testShouldFail env) })--defaultRecordMode :: RecordMode -> TestM a -> TestM a-defaultRecordMode mode = withReaderT (\env -> env {- testRecordDefaultMode = mode- })--recordMode :: RecordMode -> TestM a -> TestM a-recordMode mode = withReaderT (\env -> env {- testRecordUserMode = Just mode- })--recordNormalizer :: (String -> String) -> TestM a -> TestM a-recordNormalizer f =- withReaderT (\env -> env { testRecordNormalizer = testRecordNormalizer env . f })--assertOutputContains :: MonadIO m => WithCallStack (String -> Result -> m ())-assertOutputContains needle result =- withFrozenCallStack $- unless (needle `isInfixOf` (concatOutput output)) $- assertFailure $ " expected: " ++ needle- where output = resultOutput result--assertOutputDoesNotContain :: MonadIO m => WithCallStack (String -> Result -> m ())-assertOutputDoesNotContain needle result =- withFrozenCallStack $- when (needle `isInfixOf` (concatOutput output)) $- assertFailure $ "unexpected: " ++ needle- where output = resultOutput result--assertFindInFile :: MonadIO m => WithCallStack (String -> FilePath -> m ())-assertFindInFile needle path =- withFrozenCallStack $- liftIO $ withFileContents path- (\contents ->- unless (needle `isInfixOf` contents)- (assertFailure ("expected: " ++ needle ++ "\n" ++- " in file: " ++ path)))--assertFileDoesContain :: MonadIO m => WithCallStack (FilePath -> String -> m ())-assertFileDoesContain path needle =- withFrozenCallStack $- liftIO $ withFileContents path- (\contents ->- unless (needle `isInfixOf` contents)- (assertFailure ("expected: " ++ needle ++ "\n" ++- " in file: " ++ path)))--assertFileDoesNotContain :: MonadIO m => WithCallStack (FilePath -> String -> m ())-assertFileDoesNotContain path needle =- withFrozenCallStack $- liftIO $ withFileContents path- (\contents ->- when (needle `isInfixOf` contents)- (assertFailure ("expected: " ++ needle ++ "\n" ++- " in file: " ++ path)))---- | Replace line breaks with spaces, correctly handling "\r\n".-concatOutput :: String -> String-concatOutput = unwords . lines . filter ((/=) '\r')----------------------------------------------------------------------------- * Skipping tests--hasSharedLibraries :: TestM Bool-hasSharedLibraries = do- shared_libs_were_removed <- ghcVersionIs (>= mkVersion [7,8])- return (not (buildOS == Windows && shared_libs_were_removed))--hasProfiledLibraries :: TestM Bool-hasProfiledLibraries = do- env <- getTestEnv- ghc_path <- programPathM ghcProgram- let prof_test_hs = testWorkDir env </> "Prof.hs"- liftIO $ writeFile prof_test_hs "module Prof where"- r <- liftIO $ run (testVerbosity env) (Just (testCurrentDir env))- (testEnvironment env) ghc_path ["-prof", "-c", prof_test_hs]- return (resultExitCode r == ExitSuccess)---- | Check if the GHC that is used for compiling package tests has--- a shared library of the cabal library under test in its database.------ An example where this is needed is if you want to dynamically link--- detailed-0.9 test suites, since those depend on the Cabal library unde rtest.-hasCabalShared :: TestM Bool-hasCabalShared = do- env <- getTestEnv- return (testHaveCabalShared env)--ghcVersionIs :: WithCallStack ((Version -> Bool) -> TestM Bool)-ghcVersionIs f = do- ghc_program <- requireProgramM ghcProgram- case programVersion ghc_program of- Nothing -> error $ "ghcVersionIs: no ghc version for "- ++ show (programLocation ghc_program)- Just v -> return (f v)--isWindows :: TestM Bool-isWindows = return (buildOS == Windows)--isOSX :: TestM Bool-isOSX = return (buildOS == OSX)--isLinux :: TestM Bool-isLinux = return (buildOS == Linux)--getOpenFilesLimit :: TestM (Maybe Integer)-#ifdef mingw32_HOST_OS--- No MS-specified limit, was determined experimentally on Windows 10 Pro x64,--- matches other online reports from other versions of Windows.-getOpenFilesLimit = return (Just 2048)-#else-getOpenFilesLimit = liftIO $ do- ResourceLimits { softLimit } <- getResourceLimit ResourceOpenFiles- case softLimit of- ResourceLimit n | n >= 0 && n <= 4096 -> return (Just n)- _ -> return Nothing-#endif--hasCabalForGhc :: TestM Bool-hasCabalForGhc = do- env <- getTestEnv- ghc_program <- requireProgramM ghcProgram- (runner_ghc_program, _) <- liftIO $ requireProgram- (testVerbosity env)- ghcProgram- (runnerProgramDb (testScriptEnv env))- -- TODO: I guess, to be more robust what we should check for- -- specifically is that the Cabal library we want to use- -- will be picked up by the package db stack of ghc-program- return (programPath ghc_program == programPath runner_ghc_program)---- | If you want to use a Custom setup with new-build, it needs to--- be 1.20 or later. Ordinarily, Cabal can go off and build a--- sufficiently recent Cabal if necessary, but in our test suite,--- by default, we try to avoid doing so (since that involves a--- rather lengthy build process), instead using the boot Cabal if--- possible. But some GHCs don't have a recent enough boot Cabal!--- You'll want to exclude them in that case.----hasNewBuildCompatBootCabal :: TestM Bool-hasNewBuildCompatBootCabal = ghcVersionIs (>= mkVersion [7,9])----------------------------------------------------------------------------- * Broken tests--expectBroken :: Int -> TestM a -> TestM ()-expectBroken ticket m = do- env <- getTestEnv- liftIO . withAsync (runReaderT m env) $ \a -> do- r <- waitCatch a- case r of- Left e -> do- putStrLn $ "This test is known broken, see #" ++ show ticket ++ ":"- print e- runReaderT expectedBroken env- Right _ -> do- runReaderT unexpectedSuccess env--expectBrokenIf :: Bool -> Int -> TestM a -> TestM ()-expectBrokenIf False _ m = void $ m-expectBrokenIf True ticket m = expectBroken ticket m--expectBrokenUnless :: Bool -> Int -> TestM a -> TestM ()-expectBrokenUnless b = expectBrokenIf (not b)----------------------------------------------------------------------------- * Miscellaneous--git :: String -> [String] -> TestM ()-git cmd args = void $ git' cmd args--git' :: String -> [String] -> TestM Result-git' cmd args = do- recordHeader ["git", cmd]- runProgramM gitProgram (cmd : args)--gcc :: [String] -> TestM ()-gcc args = void $ gcc' args--gcc' :: [String] -> TestM Result-gcc' args = do- recordHeader ["gcc"]- runProgramM gccProgram args--ghc :: [String] -> TestM ()-ghc args = void $ ghc' args--ghc' :: [String] -> TestM Result-ghc' args = do- recordHeader ["ghc"]- runProgramM ghcProgram args---- | If a test needs to modify or write out source files, it's--- necessary to make a hermetic copy of the source files to operate--- on. This function arranges for this to be done.------ This requires the test repository to be a Git checkout, because--- we use the Git metadata to figure out what files to copy into the--- hermetic copy.------ Also see 'withSourceCopyDir'.-withSourceCopy :: TestM a -> TestM a-withSourceCopy m = do- env <- getTestEnv- let cwd = testCurrentDir env- dest = testSourceCopyDir env- r <- git' "ls-files" ["--cached", "--modified"]- forM_ (lines (resultOutput r)) $ \f -> do- unless (isTestFile f) $ do- liftIO $ createDirectoryIfMissing True (takeDirectory (dest </> f))- liftIO $ copyFile (cwd </> f) (dest </> f)- withReaderT (\nenv -> nenv { testHaveSourceCopy = True }) m---- | If a test needs to modify or write out source files, it's--- necessary to make a hermetic copy of the source files to operate--- on. This function arranges for this to be done in a subdirectory--- with a given name, so that tests that are sensitive to the path--- that they're running in (e.g., autoconf tests) can run.------ This requires the test repository to be a Git checkout, because--- we use the Git metadata to figure out what files to copy into the--- hermetic copy.------ Also see 'withSourceCopy'.-withSourceCopyDir :: FilePath -> TestM a -> TestM a-withSourceCopyDir dir =- withReaderT (\nenv -> nenv { testSourceCopyRelativeDir = dir }) . withSourceCopy---- | Look up the 'InstalledPackageId' of a package name.-getIPID :: String -> TestM String-getIPID pn = do- r <- ghcPkg' "field" ["--global", pn, "id"]- -- Don't choke on warnings from ghc-pkg- case mapMaybe (stripPrefix "id: ") (lines (resultOutput r)) of- -- ~/.cabal/store may contain multiple versions of single package- -- we pick first one. It should work- (x:_) -> return (takeWhile (not . Char.isSpace) x)- _ -> error $ "could not determine id of " ++ pn---- | Delay a sufficient period of time to permit file timestamp--- to be updated.-delay :: TestM ()-delay = do- env <- getTestEnv- is_old_ghc <- ghcVersionIs (< mkVersion [7,7])- -- For old versions of GHC, we only had second-level precision,- -- so we need to sleep a full second. Newer versions use- -- millisecond level precision, so we only have to wait- -- the granularity of the underlying filesystem.- -- TODO: cite commit when GHC got better precision; this- -- version bound was empirically generated.- liftIO . threadDelay $- if is_old_ghc- then 1000000- else fromMaybe- (error "Delay must be enclosed by withDelay")- (testMtimeChangeDelay env)---- | Calibrate file modification time delay, if not--- already determined.-withDelay :: TestM a -> TestM a-withDelay m = do- env <- getTestEnv- case testMtimeChangeDelay env of- Nothing -> do- -- Figure out how long we need to delay for recompilation tests- (_, mtimeChange) <- liftIO $ calibrateMtimeChangeDelay- withReaderT (\nenv -> nenv { testMtimeChangeDelay = Just mtimeChange }) m- Just _ -> m---- | Create a symlink for the duration of the provided action. If the symlink--- already exists, it is deleted. Does not work on Windows.-withSymlink :: FilePath -> FilePath -> TestM a -> TestM a-#ifdef mingw32_HOST_OS-withSymlink _oldpath _newpath _act =- error "PackageTests.PackageTester.withSymlink: does not work on Windows!"-#else-withSymlink oldpath newpath0 act = do- env <- getTestEnv- let newpath = testCurrentDir env </> newpath0- symlinkExists <- liftIO $ doesFileExist newpath- when symlinkExists $ liftIO $ removeFile newpath- bracket_ (liftIO $ createSymbolicLink oldpath newpath)- (liftIO $ removeFile newpath) act-#endif--writeSourceFile :: FilePath -> String -> TestM ()-writeSourceFile fp s = do- requireHasSourceCopy- cwd <- fmap testCurrentDir getTestEnv- liftIO $ writeFile (cwd </> fp) s--copySourceFileTo :: FilePath -> FilePath -> TestM ()-copySourceFileTo src dest = do- requireHasSourceCopy- cwd <- fmap testCurrentDir getTestEnv- liftIO $ copyFile (cwd </> src) (cwd </> dest)--requireHasSourceCopy :: TestM ()-requireHasSourceCopy = do- env <- getTestEnv- unless (testHaveSourceCopy env) $ do- error "This operation requires a source copy; use withSourceCopy and 'git add' all test files"---- NB: Keep this synchronized with partitionTests-isTestFile :: FilePath -> Bool-isTestFile f =- case takeExtensions f of- ".test.hs" -> True- ".multitest.hs" -> True- _ -> False---- | Work around issue #4515 (store paths exceeding the Windows path length--- limit) by creating a temporary directory for the new-build store. This--- function creates a directory immediately under the current drive on Windows.--- The directory must be passed to new- commands with --store-dir.-withShorterPathForNewBuildStore :: (FilePath -> IO a) -> IO a-withShorterPathForNewBuildStore test = do- tempDir <- if buildOS == Windows- then takeDrive `fmap` getCurrentDirectory- else getTemporaryDirectory- withTempDirectory normal tempDir "cabal-test-store" test
− cabal/cabal-testsuite/Test/Cabal/Run.hs
@@ -1,72 +0,0 @@-{-# LANGUAGE NondecreasingIndentation #-}--- | A module for running commands in a chatty way.-module Test.Cabal.Run (- run,- Result(..)-) where--import Distribution.Compat.CreatePipe (createPipe)-import Distribution.Simple.Program.Run-import Distribution.Verbosity--import Control.Concurrent.Async-import System.Process (runProcess, waitForProcess, showCommandForUser)-import System.IO-import System.Exit-import System.Directory-import System.FilePath---- | The result of invoking the command line.-data Result = Result- { resultExitCode :: ExitCode- , resultCommand :: String- , resultOutput :: String- } deriving Show---- | Run a command, streaming its output to stdout, and return a 'Result'--- with this information.-run :: Verbosity -> Maybe FilePath -> [(String, Maybe String)] -> FilePath -> [String] -> IO Result-run _verbosity mb_cwd env_overrides path0 args = do- -- In our test runner, we allow a path to be relative to the- -- current directory using the same heuristic as shells:- -- 'foo' refers to an executable in the PATH, but './foo'- -- and 'foo/bar' refer to relative files.- --- -- Unfortunately, we cannot just pass these relative paths directly:- -- 'runProcess' resolves an executable path not with respect to the- -- current working directory, but the working directory that the- -- subprocess will execute in. Thus, IF we have a relative- -- path which is not a bare executable name, we have to tack on- -- the CWD to make it resolve correctly- cwd <- getCurrentDirectory- let path | length (splitPath path0) /= 1 && isRelative path0- = cwd </> path0- | otherwise- = path0-- mb_env <- getEffectiveEnvironment env_overrides- putStrLn $ "+ " ++ showCommandForUser path args- (readh, writeh) <- createPipe- hSetBuffering readh LineBuffering- hSetBuffering writeh LineBuffering- let drain = do- r <- hGetContents readh- putStr r -- forces the output- hClose readh- return r- withAsync drain $ \sync -> do-- -- NB: do NOT extend this to take stdin; then we will- -- start deadlocking on AppVeyor. See https://github.com/haskell/process/issues/76- pid <- runProcess path args mb_cwd mb_env Nothing {- no stdin -}- (Just writeh) (Just writeh)-- -- wait for the program to terminate- exitcode <- waitForProcess pid- out <- wait sync-- return Result {- resultExitCode = exitcode,- resultCommand = showCommandForUser path args,- resultOutput = out- }
− cabal/cabal-testsuite/Test/Cabal/Script.hs
@@ -1,97 +0,0 @@--- | Functionality for invoking Haskell scripts with the correct--- package database setup.-module Test.Cabal.Script (- ScriptEnv(..),- mkScriptEnv,- runnerGhcArgs,- runnerCommand,- runghc,-) where--import Test.Cabal.Run-import Test.Cabal.ScriptEnv0--import Distribution.Backpack-import Distribution.Types.ModuleRenaming-import Distribution.Utils.NubList-import Distribution.Simple.Program.Db-import Distribution.Simple.Program.Builtin-import Distribution.Simple.Program.GHC-import Distribution.Simple.Program-import Distribution.Simple.Compiler-import Distribution.Verbosity-import Distribution.System-import Distribution.Simple.Setup (Flag(..))--import qualified Data.Monoid as M----- | The runner environment, which contains all of the important--- parameters for invoking GHC. Mostly subset of 'LocalBuildInfo'.-data ScriptEnv = ScriptEnv- { runnerProgramDb :: ProgramDb- , runnerPackageDbStack :: PackageDBStack- , runnerVerbosity :: Verbosity- , runnerPlatform :: Platform- , runnerCompiler :: Compiler- , runnerPackages :: [(OpenUnitId, ModuleRenaming)]- , runnerWithSharedLib :: Bool- }--{----- | Convert package database into absolute path, so that--- if we change working directories in a subprocess we get the correct database.-canonicalizePackageDB :: PackageDB -> IO PackageDB-canonicalizePackageDB (SpecificPackageDB path)- = SpecificPackageDB `fmap` canonicalizePath path-canonicalizePackageDB x = return x---}---- | Create a 'ScriptEnv' from a 'LocalBuildInfo' configured with--- the GHC that we want to use.-mkScriptEnv :: Verbosity -> IO ScriptEnv-mkScriptEnv verbosity =- return $ ScriptEnv- { runnerVerbosity = verbosity- , runnerProgramDb = lbiProgramDb- , runnerPackageDbStack = lbiPackageDbStack- , runnerPlatform = lbiPlatform- , runnerCompiler = lbiCompiler- -- NB: the set of packages available to test.hs scripts will COINCIDE- -- with the dependencies on the cabal-testsuite library- , runnerPackages = lbiPackages- , runnerWithSharedLib = lbiWithSharedLib- }---- | Run a script with 'runghc', under the 'ScriptEnv'.-runghc :: ScriptEnv -> Maybe FilePath -> [(String, Maybe String)]- -> FilePath -> [String] -> IO Result-runghc senv mb_cwd env_overrides script_path args = do- (real_path, real_args) <- runnerCommand senv mb_cwd env_overrides script_path args- run (runnerVerbosity senv) mb_cwd env_overrides real_path real_args---- | Compute the command line which should be used to run a Haskell--- script with 'runghc'.-runnerCommand :: ScriptEnv -> Maybe FilePath -> [(String, Maybe String)]- -> FilePath -> [String] -> IO (FilePath, [String])-runnerCommand senv _mb_cwd _env_overrides script_path args = do- (prog, _) <- requireProgram verbosity runghcProgram (runnerProgramDb senv)- return (programPath prog,- runghc_args ++ ["--"] ++ map ("--ghc-arg="++) ghc_args ++ [script_path] ++ args)- where- verbosity = runnerVerbosity senv- runghc_args = []- ghc_args = runnerGhcArgs senv---- | Compute the GHC flags to invoke 'runghc' with under a 'ScriptEnv'.-runnerGhcArgs :: ScriptEnv -> [String]-runnerGhcArgs senv =- renderGhcOptions (runnerCompiler senv) (runnerPlatform senv) ghc_options- where- ghc_options = M.mempty { ghcOptPackageDBs = runnerPackageDbStack senv- , ghcOptPackages = toNubListR (runnerPackages senv)- -- Avoid picking stray module files that look- -- like our imports- , ghcOptSourcePathClear = Flag True }
− cabal/cabal-testsuite/Test/Cabal/Server.hs
@@ -1,443 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE NondecreasingIndentation #-}--- | A GHC run-server, which supports running multiple GHC scripts--- without having to restart from scratch.-module Test.Cabal.Server (- Server,- serverProcessId,- ServerLogMsg(..),- ServerLogMsgType(..),- ServerResult(..),- withNewServer,- runOnServer,- runMain,-) where--import Test.Cabal.Script--import Prelude hiding (log)-import Control.Concurrent.MVar-import Control.Concurrent-import Control.Concurrent.Async-import System.Process-import System.IO-import System.Exit-import Data.List-import Distribution.Simple.Program.Db-import Distribution.Simple.Program-import Control.Exception-import qualified Control.Exception as E-import Control.Monad-import Data.IORef-import Data.Maybe--import Distribution.Verbosity--import System.Process.Internals-#if mingw32_HOST_OS-import qualified System.Win32.Process as Win32-#endif---- TODO: Compare this implementation with--- https://github.com/ndmitchell/ghcid/blob/master/src/Language/Haskell/Ghcid.hs--- which does something similar---- ----------------------------------------------------------------- ----- Public API--- ----------------------------------------------------------------- ------ | A GHCi server session, which we can ask to run scripts.--- It operates in a *fixed* runner environment as specified--- by 'serverScriptEnv'.-data Server = Server {- serverStdin :: Handle,- serverStdout :: Handle,- serverStderr :: Handle,- serverProcessHandle :: ProcessHandle,- serverProcessId :: ProcessId,- serverScriptEnv :: ScriptEnv,- -- | Accumulators which we use to keep tracking- -- of stdout/stderr we've incrementally read out. In the event- -- of an error we'll use this to give diagnostic information.- serverStdoutAccum :: MVar [String],- serverStderrAccum :: MVar [String],- serverLogChan :: Chan ServerLogMsg- }---- | Portable representation of process ID; just a string rendered--- number.-type ProcessId = String--data ServerLogMsg = ServerLogMsg ServerLogMsgType String- | ServerLogEnd-data ServerLogMsgType = ServerOut ProcessId- | ServerErr ProcessId- | ServerIn ProcessId- | ServerMeta ProcessId- | AllServers--data ServerResult = ServerResult { -- Result- serverResultExitCode :: ExitCode,- serverResultCommand :: String,- serverResultStdout :: String,- serverResultStderr :: String- }---- | With 'ScriptEnv', create a new GHCi 'Server' session.--- When @f@ returns, the server is terminated and no longer--- valid.-withNewServer :: Chan ServerLogMsg -> ScriptEnv -> (Server -> IO a) -> IO a-withNewServer chan senv f =- bracketWithInit (startServer chan senv) initServer stopServer f---- | Like 'bracket', but with an initialization function on the resource--- which will be called, unmasked, on the resource to transform it--- in some way. If the initialization function throws an exception, the cleanup--- handler will get invoked with the original resource; if it succeeds, the--- cleanup handler will get invoked with the transformed resource.--- The cleanup handler must be able to handle both cases.------ This can help avoid race conditions in certain situations: with--- normal use of 'bracket', the resource acquisition function--- MUST return immediately after the resource is acquired. If it--- performs any interruptible actions afterwards, it could be--- interrupted and the exception handler not called.-bracketWithInit :: IO a -> (a -> IO a) -> (a -> IO b) -> (a -> IO c) -> IO c-bracketWithInit before initialize after thing =- mask $ \restore -> do- a0 <- before- a <- restore (initialize a0) `onException` after a0- r <- restore (thing a) `onException` after a- _ <- after a- return r---- | Run an hs script on the GHCi server, returning the 'ServerResult' of--- executing the command.------ * The script MUST have an @hs@ or @lhs@ filename; GHCi--- will reject non-Haskell filenames.------ * If the script is not well-typed, the returned output--- will be of GHC's compile errors.------ * Inside your script, do not rely on 'getProgName' having--- a sensible value.------ * Current working directory and environment overrides--- are currently not implemented.----runOnServer :: Server -> Maybe FilePath -> [(String, Maybe String)]- -> FilePath -> [String] -> IO ServerResult-runOnServer s mb_cwd env_overrides script_path args = do- -- TODO: cwd not implemented- when (isJust mb_cwd) $ error "runOnServer change directory not implemented"- -- TODO: env_overrides not implemented- unless (null env_overrides) $ error "runOnServer set environment not implemented"-- -- Set arguments returned by System.getArgs- write s $ ":set args " ++ show args- -- Output start sigil (do it here so we pick up compilation- -- failures)- write s $ "System.IO.hPutStrLn System.IO.stdout " ++ show start_sigil- write s $ "System.IO.hPutStrLn System.IO.stderr " ++ show start_sigil- _ <- readUntilSigil s start_sigil IsOut- _ <- readUntilSigil s start_sigil IsErr- -- Drain the output produced by the script as we are running so that- -- we do not deadlock over a full pipe.- withAsync (readUntilEnd s IsOut) $ \a_exit_out -> do- withAsync (readUntilSigil s end_sigil IsErr) $ \a_err -> do- -- NB: No :set prog; don't rely on this value in test scripts,- -- we pass it in via the arguments- -- NB: load drops all bindings, which is GOOD. Avoid holding onto- -- garbage.- write s $ ":load " ++ script_path- -- Create a ref which will record the exit status of the command- -- NB: do this after :load so it doesn't get dropped- write s $ "ref <- Data.IORef.newIORef (System.Exit.ExitFailure 1)"- -- TODO: What if an async exception gets raised here? At the- -- moment, there is no way to recover until we get to the top-level- -- bracket; then stopServer which correctly handles this case.- -- If you do want to be able to abort this computation but KEEP- -- USING THE SERVER SESSION, you will need to have a lot more- -- sophisticated logic.- write s $ "Test.Cabal.Server.runMain ref Main.main"- -- Output end sigil.- -- NB: We're line-oriented, so we MUST add an extra newline- -- to ensure that we see the end sigil.- write s $ "System.IO.hPutStrLn System.IO.stdout " ++ show ""- write s $ "System.IO.hPutStrLn System.IO.stderr " ++ show ""- write s $ "Data.IORef.readIORef ref >>= \\e -> " ++- " System.IO.hPutStrLn System.IO.stdout (" ++ show end_sigil ++ " ++ \" \" ++ show e)"- write s $ "System.IO.hPutStrLn System.IO.stderr " ++ show end_sigil- (code, out) <- wait a_exit_out- err <- wait a_err-- -- Give the user some indication about how they could run the- -- command by hand.- (real_path, real_args) <- runnerCommand (serverScriptEnv s) mb_cwd env_overrides script_path args- return ServerResult {- serverResultExitCode = code,- serverResultCommand = showCommandForUser real_path real_args,- serverResultStdout = out,- serverResultStderr = err- }---- | Helper function which we use in the GHCi session to communicate--- the exit code of the process.-runMain :: IORef ExitCode -> IO () -> IO ()-runMain ref m = do- E.catch (m >> writeIORef ref ExitSuccess) serverHandler- where- serverHandler :: SomeException -> IO ()- serverHandler e = do- -- TODO: Probably a few more cases you could handle;- -- e.g., StackOverflow should return 2; also signals.- writeIORef ref $- case fromException e of- Just exit_code -> exit_code- -- Only rethrow for non ExitFailure exceptions- _ -> ExitFailure 1- case fromException e :: Maybe ExitCode of- Just _ -> return ()- _ -> throwIO e---- ----------------------------------------------------------------- ----- Initialize/tear down--- ----------------------------------------------------------------- ------ | Start a new GHCi session.-startServer :: Chan ServerLogMsg -> ScriptEnv -> IO Server-startServer chan senv = do- (prog, _) <- requireProgram verbosity ghcProgram (runnerProgramDb senv)- let ghc_args = runnerGhcArgs senv ++ ["--interactive", "-v0", "-ignore-dot-ghci"]- proc_spec = (proc (programPath prog) ghc_args) {- create_group = True,- -- Closing fds is VERY important to avoid- -- deadlock; we won't see the end of a- -- stream until everyone gives up.- close_fds = True,- std_in = CreatePipe,- std_out = CreatePipe,- std_err = CreatePipe- }- -- printRawCommandAndArgsAndEnv (runnerVerbosity senv) (programPath prog) ghc_args Nothing- when (verbosity >= verbose) $- writeChan chan (ServerLogMsg AllServers (showCommandForUser (programPath prog) ghc_args))- (Just hin, Just hout, Just herr, proch) <- createProcess proc_spec- out_acc <- newMVar []- err_acc <- newMVar []- tid <- myThreadId- return Server {- serverStdin = hin,- serverStdout = hout,- serverStderr = herr,- serverProcessHandle = proch,- serverProcessId = show tid,- serverLogChan = chan,- serverStdoutAccum = out_acc,- serverStderrAccum = err_acc,- serverScriptEnv = senv- }- where- verbosity = runnerVerbosity senv---- | Unmasked initialization for the server-initServer :: Server -> IO Server-initServer s0 = do- -- NB: withProcessHandle reads an MVar and is interruptible-#if mingw32_HOST_OS- pid <- withProcessHandle (serverProcessHandle s0) $ \ph ->- case ph of- OpenHandle x -> fmap show (Win32.getProcessId x)- ClosedHandle _ -> return (serverProcessId s0)-#else- pid <- withProcessHandle (serverProcessHandle s0) $ \ph ->- case ph of-#if MIN_VERSION_process(1,2,0)- OpenHandle x -> return (show x)- -- TODO: handle OpenExtHandle?- _ -> return (serverProcessId s0)-#else- OpenHandle x -> return (ph, show x)- -- TODO: handle OpenExtHandle?- _ -> return (ph, serverProcessId s0)-#endif-#endif- let s = s0 { serverProcessId = pid }- -- We will read/write a line at a time, including for- -- output; our demarcation tokens are an entire line.- forM_ [serverStdin, serverStdout, serverStderr] $ \f -> do- hSetBuffering (f s) LineBuffering- hSetEncoding (f s) utf8- write s ":set prompt \"\""- write s "System.IO.hSetBuffering System.IO.stdout System.IO.LineBuffering"- return s---- | Stop a GHCi session.-stopServer :: Server -> IO ()-stopServer s = do- -- This is quite a bit of funny business.- -- On Linux, terminateProcess will send a SIGINT, which- -- GHCi will swallow and actually only use to terminate- -- whatever computation is going on at that time. So we- -- have to follow up with an actual :quit command to- -- finish it up (if you delete it, the processes will- -- hang around). On Windows, this will just actually kill- -- the process so the rest should be unnecessary.- mb_exit <- getProcessExitCode (serverProcessHandle s)-- let hardKiller = do- threadDelay 2000000 -- 2sec- log ServerMeta s $ "Terminating..."- terminateProcess (serverProcessHandle s)- softKiller = do- -- Ask to quit. If we're in the middle of a computation,- -- this will buffer up (unless the program is intercepting- -- stdin, but that should NOT happen.)- ignore $ write s ":quit"-- -- NB: it's important that we used create_group. We- -- run this AFTER write s ":quit" because if we C^C- -- sufficiently early in GHCi startup process, GHCi- -- will actually die, and then hClose will fail because- -- the ":quit" command was buffered up but never got- -- flushed.- interruptProcessGroupOf (serverProcessHandle s)-- log ServerMeta s $ "Waiting..."- -- Close input BEFORE waiting, close output AFTER waiting.- -- If you get either order wrong, deadlock!- hClose (serverStdin s)- -- waitForProcess has race condition- -- https://github.com/haskell/process/issues/46- waitForProcess $ serverProcessHandle s-- let drain f = do- r <- hGetContents (f s)- _ <- evaluate (length r)- hClose (f s)- return r- withAsync (drain serverStdout) $ \a_out -> do- withAsync (drain serverStderr) $ \a_err -> do-- r <- case mb_exit of- Nothing -> do- log ServerMeta s $ "Terminating GHCi"- race hardKiller softKiller- Just exit -> do- log ServerMeta s $ "GHCi died unexpectedly"- return (Right exit)-- -- Drain the output buffers- rest_out <- wait a_out- rest_err <- wait a_err- if r /= Right ExitSuccess &&- r /= Right (ExitFailure (-2)) -- SIGINT; happens frequently for some reason- then do withMVar (serverStdoutAccum s) $ \acc ->- mapM_ (info ServerOut s) (reverse acc)- info ServerOut s rest_out- withMVar (serverStderrAccum s) $ \acc ->- mapM_ (info ServerErr s) (reverse acc)- info ServerErr s rest_err- info ServerMeta s $- (case r of- Left () -> "GHCi was forcibly terminated"- Right exit -> "GHCi exited with " ++ show exit) ++- if verbosity < verbose- then " (use -v for more information)"- else ""- else log ServerOut s rest_out-- log ServerMeta s $ "Done"- return ()- where- verbosity = runnerVerbosity (serverScriptEnv s)---- Using the procedure from--- https://www.schoolofhaskell.com/user/snoyberg/general-haskell/exceptions/catching-all-exceptions-ignore :: IO () -> IO ()-ignore m = withAsync m $ \a -> void (waitCatch a)---- ----------------------------------------------------------------- ----- Utility functions--- ----------------------------------------------------------------- ----log :: (ProcessId -> ServerLogMsgType) -> Server -> String -> IO ()-log ctor s msg =- when (verbosity >= verbose) $ info ctor s msg- where- verbosity = runnerVerbosity (serverScriptEnv s)--info :: (ProcessId -> ServerLogMsgType) -> Server -> String -> IO ()-info ctor s msg =- writeChan chan (ServerLogMsg (ctor (serverProcessId s)) msg)- where- chan = serverLogChan s---- | Write a string to the prompt of the GHCi server.-write :: Server -> String -> IO ()-write s msg = do- log ServerIn s $ msg- hPutStrLn (serverStdin s) msg- hFlush (serverStdin s) -- line buffering should get it, but just for good luck--accumulate :: MVar [String] -> String -> IO ()-accumulate acc msg =- modifyMVar_ acc (\msgs -> return (msg:msgs))--flush :: MVar [String] -> IO [String]-flush acc = modifyMVar acc (\msgs -> return ([], reverse msgs))--data OutOrErr = IsOut | IsErr--serverHandle :: Server -> OutOrErr -> Handle-serverHandle s IsOut = serverStdout s-serverHandle s IsErr = serverStderr s--serverAccum :: Server -> OutOrErr -> MVar [String]-serverAccum s IsOut = serverStdoutAccum s-serverAccum s IsErr = serverStderrAccum s--outOrErrMsgType :: OutOrErr -> (ProcessId -> ServerLogMsgType)-outOrErrMsgType IsOut = ServerOut-outOrErrMsgType IsErr = ServerErr---- | Consume output from the GHCi server until we hit a "start--- sigil" (indicating that the subsequent output is for the--- command we want.) Call this only immediately after you--- send a command to GHCi to emit the start sigil.-readUntilSigil :: Server -> String -> OutOrErr -> IO String-readUntilSigil s sigil outerr = do- l <- hGetLine (serverHandle s outerr)- log (outOrErrMsgType outerr) s l- if sigil `isPrefixOf` l -- NB: on Windows there might be extra goo at end- then intercalate "\n" `fmap` flush (serverAccum s outerr)- else do accumulate (serverAccum s outerr) l- readUntilSigil s sigil outerr---- | Consume output from the GHCi server until we hit the--- end sigil. Return the consumed output as well as the--- exit code (which is at the end of the sigil).-readUntilEnd :: Server -> OutOrErr -> IO (ExitCode, String)-readUntilEnd s outerr = go []- where- go rs = do- l <- hGetLine (serverHandle s outerr)- log (outOrErrMsgType outerr) s l- if end_sigil `isPrefixOf` l- -- NB: NOT unlines, we don't want the trailing newline!- then do exit <- evaluate (parseExit l)- _ <- flush (serverAccum s outerr) -- TODO: don't toss this out- return (exit, intercalate "\n" (reverse rs))- else do accumulate (serverAccum s outerr) l- go (l:rs)- parseExit l = read (drop (length end_sigil) l)---- | The start and end sigils. This should be chosen to be--- reasonably unique, so that test scripts don't accidentally--- generate them. If these get spuriously generated, we will--- probably deadlock.-start_sigil, end_sigil :: String-start_sigil = "BEGIN Test.Cabal.Server"-end_sigil = "END Test.Cabal.Server"
− cabal/cabal-testsuite/Test/Cabal/Workdir.hs
@@ -1,30 +0,0 @@-{-# LANGUAGE CPP #-}--- | Functions for interrogating the current working directory-module Test.Cabal.Workdir where--import Distribution.Simple.Setup-import Distribution.Simple.Configure--import System.Directory-import System.FilePath--#if MIN_VERSION_base(4,6,0)-import System.Environment ( getExecutablePath )-#endif---- | Guess what the dist directory of a running executable is,--- by using the conventional layout of built executables--- in relation to the top of a dist directory. Will not work--- if the executable has been installed somewhere else.-guessDistDir :: IO FilePath-guessDistDir = do-#if MIN_VERSION_base(4,6,0)- exe_path <- canonicalizePath =<< getExecutablePath- let dist0 = dropFileName exe_path </> ".." </> ".."- b <- doesFileExist (dist0 </> "setup-config")-#else- let dist0 = error "no path"- b = False-#endif- if b then canonicalizePath dist0- else findDistPrefOrDefault NoFlag >>= canonicalizePath
cabal/cabal-testsuite/cabal-testsuite.cabal view
@@ -1,7 +1,7 @@ cabal-version: 2.2 name: cabal-testsuite-version: 3.1.0.0-copyright: 2003-2019, Cabal Development Team (see AUTHORS file)+version: 3+copyright: 2003-2020, Cabal Development Team (see AUTHORS file) license: BSD-3-Clause license-file: LICENSE author: Cabal Development Team <cabal-devel@haskell.org>@@ -26,24 +26,27 @@ default-language: Haskell2010 build-depends:- , base >= 4.6 && <4.13+ , base >= 4.6 && <4.15 -- this needs to match the in-tree lib:Cabal version- , Cabal == 3.1.0.0+ , Cabal == 3.3.0.0 - ghc-options: -Wall -fwarn-tabs+ ghc-options: -Wall -fwarn-tabs -fwarn-incomplete-uni-patterns + library import: shared + hs-source-dirs: src exposed-modules:- Test.Cabal.Workdir- Test.Cabal.Script- Test.Cabal.Run+ Test.Cabal.CheckArMetadata+ Test.Cabal.Monad+ Test.Cabal.OutputNormalizer Test.Cabal.Plan Test.Cabal.Prelude+ Test.Cabal.Run+ Test.Cabal.Script Test.Cabal.Server- Test.Cabal.Monad- Test.Cabal.CheckArMetadata+ Test.Cabal.Workdir other-modules: Test.Cabal.ScriptEnv0@@ -51,7 +54,7 @@ Test.Cabal.ScriptEnv0 build-depends:- , aeson ^>= 1.4.2.0+ , aeson ^>= 1.4.2.0 || ^>=1.5.0.0 , async ^>= 2.2.1 , attoparsec ^>= 0.13.2.2 , base16-bytestring ^>= 0.1.1.6@@ -64,11 +67,14 @@ , optparse-applicative ^>= 0.14.3.0 || ^>=0.15.1.0 , process ^>= 1.1.0.2 || ^>= 1.2.0.0 || ^>= 1.4.2.0 || ^>= 1.6.1.0 , regex-compat-tdfa ^>= 0.95.1.4- , regex-tdfa ^>= 1.2.3.1 || ^>=1.3.0+ , regex-tdfa ^>= 1.2.3.1 || ^>=1.3.1.0 , temporary ^>= 1.3 , text ^>= 1.2.3.1 , transformers ^>= 0.3.0.0 || ^>= 0.4.2.0 || ^>= 0.5.2.0 + if !impl(ghc >= 8.0)+ build-depends: semigroups+ if !os(windows) build-depends: , unix ^>= 2.6.0.0 || ^>= 2.7.0.0@@ -102,5 +108,5 @@ custom-setup -- we only depend on even stable releases of lib:Cabal- setup-depends: Cabal == 2.2.* || == 2.4.* || == 3.0.* || ==3.1.*,+ setup-depends: Cabal == 2.2.* || == 2.4.* || == 3.0.* || ==3.2.*, base, filepath, directory
cabal/cabal-testsuite/main/cabal-tests.hs view
@@ -186,7 +186,7 @@ = "UNEXPECTED OK" | otherwise = "FAIL"- unless (mainArgHideSuccesses args && status /= "FAIL") $ do+ unless (mainArgHideSuccesses args && status == "OK") $ do logMeta $ path ++ replicate (margin - length path) ' ' ++ status ++ if time >= 0.01
+ cabal/cabal-testsuite/src/Test/Cabal/CheckArMetadata.hs view
@@ -0,0 +1,87 @@+----------------------------------------------------------------------------+-- |+-- Module : Test.Cabal.CheckArMetadata+-- Created : 8 July 2017+--+-- Check well-formedness of metadata of .a files that @ar@ command produces.+-- One of the crucial properties of .a files is that they must be+-- deterministic - i.e. they must not include creation date as their+-- contents to facilitate deterministic builds.+----------------------------------------------------------------------------++{-# LANGUAGE OverloadedStrings #-}++module Test.Cabal.CheckArMetadata (checkMetadata) where++import Test.Cabal.Prelude++import qualified Data.ByteString as BS+import qualified Data.ByteString.Char8 as BS8+import Data.Char (isSpace)+import System.IO++import Distribution.Compiler (CompilerFlavor(..), CompilerId(..))+import Distribution.Package (getHSLibraryName)+import Distribution.Simple.Compiler (compilerId)+import Distribution.Simple.LocalBuildInfo (LocalBuildInfo, compiler, localUnitId)++-- Almost a copypasta of Distribution.Simple.Program.Ar.wipeMetadata+checkMetadata :: LocalBuildInfo -> FilePath -> IO ()+checkMetadata lbi dir = withBinaryFile path ReadMode $ \ h ->+ hFileSize h >>= checkArchive h+ where+ path = dir </> "lib" ++ getHSLibraryName (localUnitId lbi) ++ ".a"++ _ghc_7_10 = case compilerId (compiler lbi) of+ CompilerId GHC version | version >= mkVersion [7, 10] -> True+ _ -> False++ checkError msg = assertFailure (+ "PackageTests.DeterministicAr.checkMetadata: " ++ msg +++ " in " ++ path) >> undefined+ archLF = "!<arch>\x0a" -- global magic, 8 bytes+ x60LF = "\x60\x0a" -- header magic, 2 bytes+ metadata = BS.concat+ [ "0 " -- mtime, 12 bytes+ , "0 " -- UID, 6 bytes+ , "0 " -- GID, 6 bytes+ , "0644 " -- mode, 8 bytes+ ]+ headerSize = 60++ -- http://en.wikipedia.org/wiki/Ar_(Unix)#File_format_details+ checkArchive :: Handle -> Integer -> IO ()+ checkArchive h archiveSize = do+ global <- BS.hGet h (BS.length archLF)+ unless (global == archLF) $ checkError "Bad global header"+ checkHeader (toInteger $ BS.length archLF)++ where+ checkHeader :: Integer -> IO ()+ checkHeader offset = case compare offset archiveSize of+ EQ -> return ()+ GT -> checkError (atOffset "Archive truncated")+ LT -> do+ header <- BS.hGet h headerSize+ unless (BS.length header == headerSize) $+ checkError (atOffset "Short header")+ let magic = BS.drop 58 header+ unless (magic == x60LF) . checkError . atOffset $+ "Bad magic " ++ show magic ++ " in header"++ unless (metadata == BS.take 32 (BS.drop 16 header))+ . checkError . atOffset $ "Metadata has changed"++ let size = BS.take 10 $ BS.drop 48 header+ objSize <- case reads (BS8.unpack size) of+ [(n, s)] | all isSpace s -> return n+ _ -> checkError (atOffset "Bad file size in header")++ let nextHeader = offset + toInteger headerSize ++ -- Odd objects are padded with an extra '\x0a'+ if odd objSize then objSize + 1 else objSize+ hSeek h AbsoluteSeek nextHeader+ checkHeader nextHeader++ where+ atOffset msg = msg ++ " at offset " ++ show offset
+ cabal/cabal-testsuite/src/Test/Cabal/Monad.hs view
@@ -0,0 +1,614 @@+{-# LANGUAGE ScopedTypeVariables #-}++-- | The test monad+module Test.Cabal.Monad (+ -- * High-level runners+ setupAndCabalTest,+ setupTest,+ cabalTest,+ -- * The monad+ TestM,+ runTestM,+ -- * Helper functions+ programPathM,+ requireProgramM,+ isAvailableProgram,+ hackageRepoToolProgram,+ gitProgram,+ cabalProgram,+ diffProgram,+ -- * The test environment+ TestEnv(..),+ getTestEnv,+ -- * Recording mode+ RecordMode(..),+ testRecordMode,+ -- * Derived values from 'TestEnv'+ testCurrentDir,+ testWorkDir,+ testPrefixDir,+ testDistDir,+ testPackageDbDir,+ testRepoDir,+ testKeysDir,+ testSourceCopyDir,+ testCabalDir,+ testUserCabalConfigFile,+ testActualFile,+ -- * Skipping tests+ skip,+ skipIf,+ skipUnless,+ skipExitCode,+ -- * Known broken tests+ expectedBroken,+ unexpectedSuccess,+ expectedBrokenExitCode,+ unexpectedSuccessExitCode,+ -- whenHasSharedLibraries,+ -- * Arguments (TODO: move me)+ CommonArgs(..),+ renderCommonArgs,+ commonArgParser,+) where++import Test.Cabal.Script+import Test.Cabal.Plan+import Test.Cabal.OutputNormalizer++import Distribution.Simple.Compiler+ ( PackageDBStack, PackageDB(..), compilerFlavor+ , Compiler, compilerVersion )+import Distribution.System+import Distribution.Simple.Program.Db+import Distribution.Simple.Program+import Distribution.Simple.Configure+ ( configCompilerEx )+import Distribution.Text++import Distribution.Verbosity++import Data.Monoid ((<>), mempty)+import qualified Control.Exception as E+import Control.Monad+import Control.Monad.Trans.Reader+import Control.Monad.IO.Class+import Data.Maybe+import Control.Applicative+import System.Directory+import System.Exit+import System.FilePath+import System.IO+import System.IO.Error (isDoesNotExistError)+import System.IO.Temp (withSystemTempDirectory)+import System.Process hiding (env)+import Options.Applicative++data CommonArgs = CommonArgs {+ argCabalInstallPath :: Maybe FilePath,+ argGhcPath :: Maybe FilePath,+ argHackageRepoToolPath :: Maybe FilePath,+ argHaddockPath :: Maybe FilePath,+ argAccept :: Bool,+ argSkipSetupTests :: Bool+ }++commonArgParser :: Parser CommonArgs+commonArgParser = CommonArgs+ <$> optional (option str+ ( help "Path to cabal-install executable to test"+ Data.Monoid.<> long "with-cabal"+ <> metavar "PATH"+ ))+ <*> optional (option str+ ( help "GHC to ask Cabal to use via --with-ghc flag"+ <> short 'w'+ <> long "with-ghc"+ <> metavar "PATH"+ ))+ <*> optional (option str+ ( help "Path to hackage-repo-tool to use for repository manipulation"+ <> long "with-hackage-repo-tool"+ <> metavar "PATH"+ ))+ <*> optional (option str+ ( help "Path to haddock to use for --with-haddock flag"+ <> long "with-haddock"+ <> metavar "PATH"+ ))+ <*> switch+ ( long "accept"+ <> help "Accept output"+ )+ <*> switch (long "skip-setup-tests" <> help "Skip setup tests")++renderCommonArgs :: CommonArgs -> [String]+renderCommonArgs args =+ maybe [] (\x -> ["--with-cabal", x]) (argCabalInstallPath args) +++ maybe [] (\x -> ["--with-ghc", x]) (argGhcPath args) +++ maybe [] (\x -> ["--with-haddock", x]) (argHaddockPath args) +++ maybe [] (\x -> ["--with-hackage-repo-tool", x]) (argHackageRepoToolPath args) +++ (if argAccept args then ["--accept"] else []) +++ (if argSkipSetupTests args then ["--skip-setup-tests"] else [])++data TestArgs = TestArgs {+ testArgDistDir :: FilePath,+ testArgScriptPath :: FilePath,+ testCommonArgs :: CommonArgs+ }++testArgParser :: Parser TestArgs+testArgParser = TestArgs+ <$> option str+ ( help "Build directory of cabal-testsuite"+ <> long "builddir"+ <> metavar "DIR")+ <*> argument str ( metavar "FILE")+ <*> commonArgParser++skip :: TestM ()+skip = liftIO $ do+ putStrLn "SKIP"+ exitWith (ExitFailure skipExitCode)++skipIf :: Bool -> TestM ()+skipIf b = when b skip++skipUnless :: Bool -> TestM ()+skipUnless b = unless b skip++expectedBroken :: TestM ()+expectedBroken = liftIO $ do+ putStrLn "EXPECTED FAIL"+ exitWith (ExitFailure expectedBrokenExitCode)++unexpectedSuccess :: TestM ()+unexpectedSuccess = liftIO $ do+ putStrLn "UNEXPECTED OK"+ exitWith (ExitFailure unexpectedSuccessExitCode)++skipExitCode :: Int+skipExitCode = 64++expectedBrokenExitCode :: Int+expectedBrokenExitCode = 65++unexpectedSuccessExitCode :: Int+unexpectedSuccessExitCode = 66++catchSkip :: IO a -> IO a -> IO a+catchSkip m r = m `E.catch` \e ->+ case e of+ ExitFailure c | c == skipExitCode+ -> r+ _ -> E.throwIO e++setupAndCabalTest :: TestM () -> IO ()+setupAndCabalTest m = do+ r1 <- (setupTest m >> return False) `catchSkip` return True+ r2 <- (cabalTest' "cabal" m >> return False) `catchSkip` return True+ when (r1 && r2) $ do+ putStrLn "SKIP"+ exitWith (ExitFailure skipExitCode)++setupTest :: TestM () -> IO ()+setupTest m = runTestM "" $ do+ env <- getTestEnv+ skipIf (testSkipSetupTests env)+ m++cabalTest :: TestM () -> IO ()+cabalTest = cabalTest' ""++cabalTest' :: String -> TestM () -> IO ()+cabalTest' mode m = runTestM mode $ do+ skipUnless =<< isAvailableProgram cabalProgram+ withReaderT (\nenv -> nenv { testCabalInstallAsSetup = True }) m++type TestM = ReaderT TestEnv IO++gitProgram :: Program+gitProgram = simpleProgram "git"++hackageRepoToolProgram :: Program+hackageRepoToolProgram = simpleProgram "hackage-repo-tool"++cabalProgram :: Program+cabalProgram = (simpleProgram "cabal") {+ -- Do NOT search for executable named cabal, it's probably+ -- not the one you were intending to test+ programFindLocation = \_ _ -> return Nothing+ }++diffProgram :: Program+diffProgram = simpleProgram "diff"++-- | Run a test in the test monad according to program's arguments.+runTestM :: String -> TestM a -> IO a+runTestM mode m = withSystemTempDirectory "cabal-testsuite" $ \tmp_dir -> do+ args <- execParser (info testArgParser Data.Monoid.mempty)+ let dist_dir = testArgDistDir args+ (script_dir0, script_filename) = splitFileName (testArgScriptPath args)+ script_base = dropExtensions script_filename+ -- Canonicalize this so that it is stable across working directory changes+ script_dir <- canonicalizePath script_dir0+ let verbosity = normal -- TODO: configurable+ senv <- mkScriptEnv verbosity+ -- Add test suite specific programs+ let program_db0 =+ addKnownPrograms+ ([gitProgram, hackageRepoToolProgram, cabalProgram, diffProgram] ++ builtinPrograms)+ (runnerProgramDb senv)+ -- Reconfigure according to user flags+ let cargs = testCommonArgs args++ -- Reconfigure GHC+ (comp, platform, program_db2) <- case argGhcPath cargs of+ Nothing -> return (runnerCompiler senv, runnerPlatform senv, program_db0)+ Just ghc_path -> do+ -- All the things that get updated paths from+ -- configCompilerEx. The point is to make sure+ -- we reconfigure these when we need them.+ let program_db1 = unconfigureProgram "ghc"+ . unconfigureProgram "ghc-pkg"+ . unconfigureProgram "hsc2hs"+ . unconfigureProgram "haddock"+ . unconfigureProgram "hpc"+ . unconfigureProgram "runghc"+ . unconfigureProgram "gcc"+ . unconfigureProgram "ld"+ . unconfigureProgram "ar"+ . unconfigureProgram "strip"+ $ program_db0+ -- TODO: this actually leaves a pile of things unconfigured.+ -- Optimal strategy for us is to lazily configure them, so+ -- we don't pay for things we don't need. A bit difficult+ -- to do in the current design.+ configCompilerEx+ (Just (compilerFlavor (runnerCompiler senv)))+ (Just ghc_path)+ Nothing+ program_db1+ verbosity++ program_db3 <-+ reconfigurePrograms verbosity+ ([("cabal", p) | p <- maybeToList (argCabalInstallPath cargs)] +++ [("hackage-repo-tool", p)+ | p <- maybeToList (argHackageRepoToolPath cargs)] +++ [("haddock", p) | p <- maybeToList (argHaddockPath cargs)])+ [] -- --prog-options not supported ATM+ program_db2+ -- configCompilerEx only marks some programs as known, so to pick+ -- them up we must configure them+ program_db <- configureAllKnownPrograms verbosity program_db3++ let ghcAndRunnedGhcAreTheSame :: Bool+ ghcAndRunnedGhcAreTheSame = fromMaybe False $ do+ ghc_program <- lookupProgram ghcProgram program_db+ runner_ghc_program <- lookupProgram ghcProgram (runnerProgramDb senv)+ return $ programPath ghc_program == programPath runner_ghc_program++ let db_stack =+ case argGhcPath (testCommonArgs args) of+ Nothing -> runnerPackageDbStack senv -- NB: canonicalized+ -- Can't use the build package db stack since they+ -- are all for the wrong versions! TODO: Make+ -- this configurable+ --+ -- Oleg: if runner ghc and provided ghc are the same,+ -- use runnerPackageDbStack. See 'hasCabalForGhc' check.+ Just _+ | ghcAndRunnedGhcAreTheSame -> runnerPackageDbStack senv+ | otherwise -> [GlobalPackageDB]+ env = TestEnv {+ testSourceDir = script_dir,+ testTmpDir = tmp_dir,+ testSubName = script_base,+ testMode = mode,+ testProgramDb = program_db,+ testPlatform = platform,+ testCompiler = comp,+ testPackageDBStack = db_stack,+ testVerbosity = verbosity,+ testMtimeChangeDelay = Nothing,+ testScriptEnv = senv,+ testSetupPath = dist_dir </> "build" </> "setup" </> "setup",+ testSkipSetupTests = argSkipSetupTests (testCommonArgs args),+ testHaveCabalShared = runnerWithSharedLib senv,+ testEnvironment =+ -- Try to avoid Unicode output+ [ ("LC_ALL", Just "C")+ -- Hermetic builds (knot-tied)+ , ("HOME", Just (testHomeDir env))+ -- Set CABAL_DIR in addition to HOME, since HOME has no+ -- effect on Windows.+ , ("CABAL_DIR", Just (testCabalDir env))+ , ("CABAL_CONFIG", Just $ testCabalDir env </> "config")+ ],+ testShouldFail = False,+ testRelativeCurrentDir = ".",+ testHavePackageDb = False,+ testHaveRepo = False,+ testHaveSourceCopy = False,+ testCabalInstallAsSetup = False,+ testCabalProjectFile = "cabal.project",+ testPlan = Nothing,+ testRecordDefaultMode = DoNotRecord,+ testRecordUserMode = Nothing,+ testRecordNormalizer = id,+ testSourceCopyRelativeDir = "source"+ }+ let go = do cleanup+ r <- m+ check_expect (argAccept (testCommonArgs args))+ return r+ runReaderT go env+ where+ cleanup = do+ env <- getTestEnv+ onlyIfExists . removeDirectoryRecursive $ testWorkDir env+ -- NB: it's important to initialize this ourselves, as+ -- the default configuration hardcodes Hackage, which we do+ -- NOT want to assume for these tests (no test should+ -- hit Hackage.)+ liftIO $ createDirectoryIfMissing True (testCabalDir env)+ ghc_path <- programPathM ghcProgram+ liftIO $ writeFile (testUserCabalConfigFile env)+ $ unlines [ "with-compiler: " ++ ghc_path ]++ check_expect accept = do+ env <- getTestEnv+ actual_raw <- liftIO $ readFileOrEmpty (testActualFile env)+ expect <- liftIO $ readFileOrEmpty (testExpectFile env)+ norm_env <- mkNormalizerEnv+ let actual = normalizeOutput norm_env actual_raw+ when (words actual /= words expect) $ do+ -- First try whitespace insensitive diff+ let actual_fp = testNormalizedActualFile env+ expect_fp = testNormalizedExpectFile env+ liftIO $ writeFile actual_fp actual+ liftIO $ writeFile expect_fp expect+ liftIO $ putStrLn "Actual output differs from expected:"+ b <- diff ["-uw"] expect_fp actual_fp+ unless b . void $ diff ["-u"] expect_fp actual_fp+ if accept+ then do liftIO $ putStrLn "Accepting new output."+ liftIO $ writeFileNoCR (testExpectFile env) actual+ else liftIO $ exitWith (ExitFailure 1)++readFileOrEmpty :: FilePath -> IO String+readFileOrEmpty f = readFile f `E.catch` \e ->+ if isDoesNotExistError e+ then return ""+ else E.throwIO e++-- | Runs 'diff' with some arguments on two files, outputting the+-- diff to stderr, and returning true if the two files differ+diff :: [String] -> FilePath -> FilePath -> TestM Bool+diff args path1 path2 = do+ diff_path <- programPathM diffProgram+ (_,_,_,h) <- liftIO $+ createProcess (proc diff_path (args ++ [path1, path2])) {+ std_out = UseHandle stderr+ }+ r <- liftIO $ waitForProcess h+ return (r /= ExitSuccess)++-- | Write a file with no CRs, always.+writeFileNoCR :: FilePath -> String -> IO ()+writeFileNoCR f s =+ withFile f WriteMode $ \h -> do+ hSetNewlineMode h noNewlineTranslation+ hPutStr h s++mkNormalizerEnv :: TestM NormalizerEnv+mkNormalizerEnv = do+ env <- getTestEnv+ ghc_pkg_program <- requireProgramM ghcPkgProgram+ -- Arguably we should use Cabal's APIs but I am too lazy+ -- to remember what it is+ list_out <- liftIO $ readProcess (programPath ghc_pkg_program)+ ["list", "--global", "--simple-output"] ""+ tmpDir <- liftIO $ getTemporaryDirectory+ return NormalizerEnv {+ normalizerRoot+ = addTrailingPathSeparator (testSourceDir env),+ normalizerTmpDir+ = addTrailingPathSeparator (testTmpDir env),+ normalizerGblTmpDir+ = addTrailingPathSeparator tmpDir,+ normalizerGhcVersion+ = compilerVersion (testCompiler env),+ normalizerKnownPackages+ = mapMaybe simpleParse (words list_out),+ normalizerPlatform+ = testPlatform env+ }++requireProgramM :: Program -> TestM ConfiguredProgram+requireProgramM program = do+ env <- getTestEnv+ (configured_program, _) <- liftIO $+ requireProgram (testVerbosity env) program (testProgramDb env)+ return configured_program++programPathM :: Program -> TestM FilePath+programPathM program = do+ fmap programPath (requireProgramM program)++isAvailableProgram :: Program -> TestM Bool+isAvailableProgram program = do+ env <- getTestEnv+ case lookupProgram program (testProgramDb env) of+ Just _ -> return True+ Nothing -> do+ -- It might not have been configured. Try to configure.+ progdb <- liftIO $ configureProgram (testVerbosity env) program (testProgramDb env)+ case lookupProgram program progdb of+ Just _ -> return True+ Nothing -> return False++-- | Run an IO action, and suppress a "does not exist" error.+onlyIfExists :: MonadIO m => IO () -> m ()+onlyIfExists m =+ liftIO $ E.catch m $ \(e :: IOError) ->+ unless (isDoesNotExistError e) $ E.throwIO e++data TestEnv = TestEnv+ -- UNCHANGING:++ {+ -- | Path to the test directory, as specified by path to test+ -- script.+ testSourceDir :: FilePath+ -- | Somewhere to stow temporary files needed by the test.+ , testTmpDir :: FilePath+ -- | Test sub-name, used to qualify dist/database directory to avoid+ -- conflicts.+ , testSubName :: String+ -- | Test mode, further qualifies multiple invocations of the+ -- same test source code.+ , testMode :: String+ -- | Program database to use when we want ghc, ghc-pkg, etc.+ , testProgramDb :: ProgramDb+ -- | Compiler we are running tests for+ , testCompiler :: Compiler+ -- | Platform we are running tests on+ , testPlatform :: Platform+ -- | Package database stack (actually this changes lol)+ , testPackageDBStack :: PackageDBStack+ -- | How verbose to be+ , testVerbosity :: Verbosity+ -- | How long we should 'threadDelay' to make sure the file timestamp is+ -- updated correctly for recompilation tests. Nothing if we haven't+ -- calibrated yet.+ , testMtimeChangeDelay :: Maybe Int+ -- | Script environment for runghc+ , testScriptEnv :: ScriptEnv+ -- | Setup script path+ , testSetupPath :: FilePath+ -- | Skip Setup tests?+ , testSkipSetupTests :: Bool+ -- | Do we have shared libraries for the Cabal-under-tests?+ -- This is used for example to determine whether we can build+ -- detailed-0.9 tests dynamically, since they link against Cabal-under-test.+ , testHaveCabalShared :: Bool++ -- CHANGING:++ -- | Environment override+ , testEnvironment :: [(String, Maybe String)]+ -- | When true, we invert the meaning of command execution failure+ , testShouldFail :: Bool+ -- | The current working directory, relative to 'testSourceDir'+ , testRelativeCurrentDir :: FilePath+ -- | Says if we've initialized the per-test package DB+ , testHavePackageDb :: Bool+ -- | Says if we've setup a repository+ , testHaveRepo :: Bool+ -- | Says if we've copied the source to a hermetic directory+ , testHaveSourceCopy :: Bool+ -- | Says if we're testing cabal-install as setup+ , testCabalInstallAsSetup :: Bool+ -- | Says what cabal.project file to use (probed)+ , testCabalProjectFile :: FilePath+ -- | Cached record of the plan metadata from a new-build+ -- invocation; controlled by 'withPlan'.+ , testPlan :: Maybe Plan+ -- | If user mode is not set, this is the record mode we default to.+ , testRecordDefaultMode :: RecordMode+ -- | User explicitly set record mode. Not implemented ATM.+ , testRecordUserMode :: Maybe RecordMode+ -- | Function to normalize recorded output+ , testRecordNormalizer :: String -> String+ -- | Name of the subdirectory we copied the test's sources to,+ -- relative to 'testSourceDir'+ , testSourceCopyRelativeDir :: FilePath+ }++testRecordMode :: TestEnv -> RecordMode+testRecordMode env = fromMaybe (testRecordDefaultMode env) (testRecordUserMode env)++data RecordMode = DoNotRecord | RecordMarked | RecordAll+ deriving (Show, Eq, Ord)++getTestEnv :: TestM TestEnv+getTestEnv = ask++------------------------------------------------------------------------+-- * Directories++-- | The absolute path to the root of the package directory; it's+-- where the Cabal file lives. This is what you want the CWD of cabal+-- calls to be.+testCurrentDir :: TestEnv -> FilePath+testCurrentDir env =+ (if testHaveSourceCopy env+ then testSourceCopyDir env+ else testSourceDir env) </> testRelativeCurrentDir env++testName :: TestEnv -> String+testName env = testSubName env <.> testMode env++-- | The absolute path to the directory containing all the+-- files for ALL tests associated with a test (respecting+-- subtests.) To clean, you ONLY need to delete this directory.+testWorkDir :: TestEnv -> FilePath+testWorkDir env =+ testSourceDir env </> (testName env <.> "dist")++-- | The absolute prefix where installs go.+testPrefixDir :: TestEnv -> FilePath+testPrefixDir env = testWorkDir env </> "usr"++-- | The absolute path to the build directory that should be used+-- for the current package in a test.+testDistDir :: TestEnv -> FilePath+testDistDir env = testWorkDir env </> "work" </> testRelativeCurrentDir env </> "dist"++-- | The absolute path to the shared package database that should+-- be used by all packages in this test.+testPackageDbDir :: TestEnv -> FilePath+testPackageDbDir env = testWorkDir env </> "packagedb"++-- | The absolute prefix where our simulated HOME directory is.+testHomeDir :: TestEnv -> FilePath+testHomeDir env = testWorkDir env </> "home"++-- | The absolute prefix of our local secure repository, which we+-- use to simulate "external" packages+testRepoDir :: TestEnv -> FilePath+testRepoDir env = testWorkDir env </> "repo"++-- | The absolute prefix of keys for the test.+testKeysDir :: TestEnv -> FilePath+testKeysDir env = testWorkDir env </> "keys"++-- | If 'withSourceCopy' is used, where the source files go.+testSourceCopyDir :: TestEnv -> FilePath+testSourceCopyDir env = testWorkDir env </> testSourceCopyRelativeDir env++-- | The user cabal directory+testCabalDir :: TestEnv -> FilePath+testCabalDir env = testHomeDir env </> ".cabal"++-- | The user cabal config file+testUserCabalConfigFile :: TestEnv -> FilePath+testUserCabalConfigFile env = testCabalDir env </> "config"++-- | The file where the expected output of the test lives+testExpectFile :: TestEnv -> FilePath+testExpectFile env = testSourceDir env </> testName env <.> "out"++-- | Where we store the actual output+testActualFile :: TestEnv -> FilePath+testActualFile env = testWorkDir env </> testName env <.> "comp.out"++-- | Where we will write the normalized actual file (for diffing)+testNormalizedActualFile :: TestEnv -> FilePath+testNormalizedActualFile env = testActualFile env <.> "normalized"++-- | Where we will write the normalized expected file (for diffing)+testNormalizedExpectFile :: TestEnv -> FilePath+testNormalizedExpectFile env = testWorkDir env </> testName env <.> "out.normalized"
+ cabal/cabal-testsuite/src/Test/Cabal/OutputNormalizer.hs view
@@ -0,0 +1,79 @@+module Test.Cabal.OutputNormalizer (+ NormalizerEnv (..),+ normalizeOutput,+ ) where++import Data.Monoid (Endo (..))++import Distribution.Version+import Distribution.Text+import Distribution.Pretty+import Distribution.Package+import Distribution.System++import qualified Data.Foldable as F++import Text.Regex++normalizeOutput :: NormalizerEnv -> String -> String+normalizeOutput nenv =+ -- Munge away .exe suffix on filenames (Windows)+ resub "([A-Za-z0-9.-]+)\\.exe" "\\1"+ -- Normalize backslashes to forward slashes to normalize+ -- file paths+ . map (\c -> if c == '\\' then '/' else c)+ -- Install path frequently has architecture specific elements, so+ -- nub it out+ . resub "Installing (.+) in .+" "Installing \\1 in <PATH>"+ -- Things that look like libraries+ . resub "libHS[A-Za-z0-9.-]+\\.(so|dll|a|dynlib)" "<LIBRARY>"+ -- This is dumb but I don't feel like pulling in another dep for+ -- string search-replace. Make sure we do this before backslash+ -- normalization!+ . resub (posixRegexEscape (normalizerGblTmpDir nenv) ++ "[a-z0-9.-]+") "<GBLTMPDIR>" -- note, after TMPDIR+ . resub (posixRegexEscape (normalizerRoot nenv)) "<ROOT>/"+ . resub (posixRegexEscape (normalizerTmpDir nenv)) "<TMPDIR>/"+ . appEndo (F.fold (map (Endo . packageIdRegex) (normalizerKnownPackages nenv)))+ -- Look for 0.1/installed-0d6uzW7Ubh1Fb4TB5oeQ3G+ -- These installed packages will vary depending on GHC version+ -- Apply this before packageIdRegex, otherwise this regex doesn't match.+ . resub "[0-9]+(\\.[0-9]+)*/installed-[A-Za-z0-9.+]+"+ "<VERSION>/installed-<HASH>"+ -- Normalize architecture+ . resub (posixRegexEscape (display (normalizerPlatform nenv))) "<ARCH>"+ -- Some GHC versions are chattier than others+ . resub "^ignoring \\(possibly broken\\) abi-depends field for packages" ""+ -- Normalize the current GHC version. Apply this BEFORE packageIdRegex,+ -- which will pick up the install ghc library (which doesn't have the+ -- date glob).+ . (if normalizerGhcVersion nenv /= nullVersion+ then resub (posixRegexEscape (display (normalizerGhcVersion nenv))+ -- Also glob the date, for nightly GHC builds+ ++ "(\\.[0-9]+)?")+ "<GHCVER>"+ else id)+ -- hackage-security locks occur non-deterministically+ . resub "(Released|Acquired|Waiting) .*hackage-security-lock\n" ""+ where+ packageIdRegex pid =+ resub (posixRegexEscape (display pid) ++ "(-[A-Za-z0-9.-]+)?")+ (prettyShow (packageName pid) ++ "-<VERSION>")++data NormalizerEnv = NormalizerEnv+ { normalizerRoot :: FilePath+ , normalizerTmpDir :: FilePath+ , normalizerGblTmpDir :: FilePath+ , normalizerGhcVersion :: Version+ , normalizerKnownPackages :: [PackageId]+ , normalizerPlatform :: Platform+ }++posixSpecialChars :: [Char]+posixSpecialChars = ".^$*+?()[{\\|"++posixRegexEscape :: String -> String+posixRegexEscape = concatMap (\c -> if c `elem` posixSpecialChars then ['\\', c] else [c])++resub :: String {- search -} -> String {- replace -} -> String {- input -} -> String+resub search replace s =+ subRegex (mkRegex search) s replace
+ cabal/cabal-testsuite/src/Test/Cabal/Plan.hs view
@@ -0,0 +1,88 @@+{-# LANGUAGE OverloadedStrings #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+-- | Utilities for understanding @plan.json@.+module Test.Cabal.Plan (+ Plan,+ planDistDir,+) where++import Distribution.Parsec (simpleParsec)+import Distribution.Pretty (prettyShow)+import Distribution.Types.ComponentName+import Distribution.Package+import qualified Data.Text as Text+import Data.Aeson+import Data.Aeson.Types+import Control.Monad++-- TODO: index this+data Plan = Plan { planInstallPlan :: [InstallItem] }++data InstallItem+ = APreExisting+ | AConfiguredGlobal+ | AConfiguredInplace ConfiguredInplace++-- local or inplace package+data ConfiguredInplace = ConfiguredInplace+ { configuredInplaceDistDir :: FilePath+ , configuredInplacePackageName :: PackageName+ , configuredInplaceComponentName :: Maybe ComponentName }++instance FromJSON Plan where+ parseJSON (Object v) = fmap Plan (v .: "install-plan")+ parseJSON invalid = typeMismatch "Plan" invalid++instance FromJSON InstallItem where+ parseJSON obj@(Object v) = do+ t <- v .: "type"+ case t :: String of+ "pre-existing" -> return APreExisting+ "configured" -> do+ s <- v .: "style"+ case s :: String of+ "global" -> return AConfiguredGlobal+ "inplace" -> AConfiguredInplace `fmap` parseJSON obj+ "local" -> AConfiguredInplace `fmap` parseJSON obj+ _ -> fail $ "unrecognized value of 'style' field: " ++ s+ _ -> fail "unrecognized value of 'type' field"+ parseJSON invalid = typeMismatch "InstallItem" invalid++instance FromJSON ConfiguredInplace where+ parseJSON (Object v) = do+ dist_dir <- v .: "dist-dir"+ pkg_name <- v .: "pkg-name"+ component_name <- v .:? "component-name"+ return (ConfiguredInplace dist_dir pkg_name component_name)+ parseJSON invalid = typeMismatch "ConfiguredInplace" invalid++instance FromJSON PackageName where+ parseJSON (String t) = return (mkPackageName (Text.unpack t))+ parseJSON invalid = typeMismatch "PackageName" invalid++instance FromJSON ComponentName where+ parseJSON (String t) =+ case simpleParsec s of+ Nothing -> fail ("could not parse component-name: " ++ s)+ Just r -> return r+ where s = Text.unpack t+ parseJSON invalid = typeMismatch "ComponentName" invalid++planDistDir :: Plan -> PackageName -> ComponentName -> FilePath+planDistDir plan pkg_name cname =+ case concatMap p (planInstallPlan plan) of+ [x] -> x+ [] -> error $ "planDistDir: component " ++ prettyShow cname+ ++ " of package " ++ prettyShow pkg_name ++ " either does not"+ ++ " exist in the install plan or does not have a dist-dir"+ _ -> error $ "planDistDir: found multiple copies of component " ++ prettyShow cname+ ++ " of package " ++ prettyShow pkg_name ++ " in install plan"+ where+ p APreExisting = []+ p AConfiguredGlobal = []+ p (AConfiguredInplace conf) = do+ guard (configuredInplacePackageName conf == pkg_name)+ guard $ case configuredInplaceComponentName conf of+ Nothing -> True+ Just cname' -> cname == cname'+ return (configuredInplaceDistDir conf)
+ cabal/cabal-testsuite/src/Test/Cabal/Prelude.hs view
@@ -0,0 +1,994 @@+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE NondecreasingIndentation #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE CPP #-}++-- | Generally useful definitions that we expect most test scripts+-- to use.+module Test.Cabal.Prelude (+ module Test.Cabal.Prelude,+ module Test.Cabal.Monad,+ module Test.Cabal.Run,+ module System.FilePath,+ module Control.Monad,+ module Control.Monad.IO.Class,+ module Distribution.Version,+ module Distribution.Simple.Program,+) where++import Test.Cabal.Script+import Test.Cabal.Run+import Test.Cabal.Monad+import Test.Cabal.Plan++import Distribution.Compat.Time (calibrateMtimeChangeDelay)+import Distribution.Simple.Compiler (PackageDBStack, PackageDB(..))+import Distribution.Simple.Program.Types+import Distribution.Simple.Program.Db+import Distribution.Simple.Program+import Distribution.System (OS(Windows,Linux,OSX), buildOS)+import Distribution.Simple.Utils+ ( withFileContents, withTempDirectory, tryFindPackageDesc )+import Distribution.Simple.Configure+ ( getPersistBuildConfig )+import Distribution.Version+import Distribution.Package+import Distribution.Types.UnqualComponentName+import Distribution.Types.LocalBuildInfo+import Distribution.PackageDescription+import Distribution.PackageDescription.Parsec+import Distribution.Verbosity (normal)++import Distribution.Compat.Stack++import Text.Regex.TDFA ((=~))++import Control.Concurrent.Async (waitCatch, withAsync)+import qualified Data.Aeson as JSON+import qualified Data.ByteString.Lazy as BSL+import Control.Monad (unless, when, void, forM_, liftM2, liftM4)+import Control.Monad.Trans.Reader (withReaderT, runReaderT)+import Control.Monad.IO.Class (MonadIO (..))+import qualified Data.ByteString.Char8 as C+import Data.List (isInfixOf, stripPrefix, isPrefixOf, intercalate)+import Data.List.NonEmpty (NonEmpty (..))+import qualified Data.List.NonEmpty as NE+import Data.Maybe (mapMaybe, fromMaybe)+import System.Exit (ExitCode (..))+import System.FilePath ((</>), takeExtensions, takeDrive, takeDirectory, normalise, splitPath, joinPath, splitFileName, (<.>), dropTrailingPathSeparator)+import Control.Concurrent (threadDelay)+import qualified Data.Char as Char+import System.Directory (getTemporaryDirectory, getCurrentDirectory, copyFile, removeFile, copyFile, doesFileExist, createDirectoryIfMissing, getDirectoryContents)++#ifndef mingw32_HOST_OS+import Control.Monad.Catch ( bracket_ )+import System.Posix.Files ( createSymbolicLink )+import System.Posix.Resource+#endif++------------------------------------------------------------------------+-- * Utilities++runM :: FilePath -> [String] -> Maybe String -> TestM Result+runM path args input = do+ env <- getTestEnv+ r <- liftIO $ run (testVerbosity env)+ (Just (testCurrentDir env))+ (testEnvironment env)+ path+ args+ input+ recordLog r+ requireSuccess r++runProgramM :: Program -> [String] -> Maybe String -> TestM Result+runProgramM prog args input = do+ configured_prog <- requireProgramM prog+ -- TODO: Consider also using other information from+ -- ConfiguredProgram, e.g., env and args+ runM (programPath configured_prog) args input++getLocalBuildInfoM :: TestM LocalBuildInfo+getLocalBuildInfoM = do+ env <- getTestEnv+ liftIO $ getPersistBuildConfig (testDistDir env)++------------------------------------------------------------------------+-- * Changing parameters++withDirectory :: FilePath -> TestM a -> TestM a+withDirectory f = withReaderT+ (\env -> env { testRelativeCurrentDir = testRelativeCurrentDir env </> f })++-- We append to the environment list, as per 'getEffectiveEnvironment'+-- which prefers the latest override.+withEnv :: [(String, Maybe String)] -> TestM a -> TestM a+withEnv e = withReaderT (\env -> env { testEnvironment = testEnvironment env ++ e })++-- HACK please don't use me+withEnvFilter :: (String -> Bool) -> TestM a -> TestM a+withEnvFilter p = withReaderT (\env -> env { testEnvironment = filter (p . fst) (testEnvironment env) })++------------------------------------------------------------------------+-- * Running Setup++marked_verbose :: String+marked_verbose = "-vverbose +markoutput +nowrap"++setup :: String -> [String] -> TestM ()+setup cmd args = void (setup' cmd args)++setup' :: String -> [String] -> TestM Result+setup' = setup'' "."++setup''+ :: FilePath+ -- ^ Subdirectory to find the @.cabal@ file in.+ -> String+ -- ^ Command name+ -> [String]+ -- ^ Arguments+ -> TestM Result+setup'' prefix cmd args = do+ env <- getTestEnv+ when ((cmd == "register" || cmd == "copy") && not (testHavePackageDb env)) $+ error "Cannot register/copy without using 'withPackageDb'"+ ghc_path <- programPathM ghcProgram+ haddock_path <- programPathM haddockProgram+ let args' = case cmd of+ "configure" ->+ -- If the package database is empty, setting --global+ -- here will make us error loudly if we try to install+ -- into a bad place.+ [ "--global"+ -- NB: technically unnecessary with Cabal, but+ -- definitely needed for Setup, which doesn't+ -- respect cabal.config+ , "--with-ghc", ghc_path+ , "--with-haddock", haddock_path+ -- This avoids generating hashes in our package IDs,+ -- which helps the test suite's expect tests.+ , "--enable-deterministic"+ -- These flags make the test suite run faster+ -- Can't do this unless we LD_LIBRARY_PATH correctly+ -- , "--enable-executable-dynamic"+ -- , "--disable-optimization"+ -- Specify where we want our installed packages to go+ , "--prefix=" ++ testPrefixDir env+ ] ++ packageDBParams (testPackageDBStack env)+ ++ args+ _ -> args+ let rel_dist_dir = definitelyMakeRelative (testCurrentDir env) (testDistDir env)+ full_args = cmd :| [marked_verbose, "--distdir", rel_dist_dir] ++ args'+ defaultRecordMode RecordMarked $ do+ recordHeader ["Setup", cmd]++ -- We test `cabal act-act-setup` when running cabal-tests.+ --+ -- `cabal` and `Setup.hs` do have different interface.+ --++ pdfile <- liftIO $ tryFindPackageDesc (testVerbosity env) (testCurrentDir env </> prefix)+ pdesc <- liftIO $ readGenericPackageDescription (testVerbosity env) pdfile+ if testCabalInstallAsSetup env+ then if buildType (packageDescription pdesc) == Simple+ then runProgramM cabalProgram ("act-as-setup" : "--" : NE.toList full_args) Nothing+ else fail "Using act-as-setup for not 'build-type: Simple' package"+ else do+ if buildType (packageDescription pdesc) == Simple+ then runM (testSetupPath env) (NE.toList full_args) Nothing+ -- Run the Custom script!+ else do+ r <- liftIO $ runghc (testScriptEnv env)+ (Just (testCurrentDir env))+ (testEnvironment env)+ (testCurrentDir env </> prefix </> "Setup.hs")+ (NE.toList full_args)+ recordLog r+ requireSuccess r++ -- This code is very tempting (and in principle should be quick:+ -- after all we are loading the built version of Cabal), but+ -- actually it costs quite a bit in wallclock time (e.g. 54sec to+ -- 68sec on AllowNewer, working with un-optimized Cabal.)+ {-+ r <- liftIO $ runghc (testScriptEnv env)+ (Just (testCurrentDir env))+ (testEnvironment env)+ "Setup.hs"+ (cmd : ["-v", "--distdir", testDistDir env] ++ args')+ -- don't forget to check results...+ -}++definitelyMakeRelative :: FilePath -> FilePath -> FilePath+definitelyMakeRelative base0 path0 =+ let go [] path = joinPath path+ go base [] = joinPath (replicate (length base) "..")+ go (x:xs) (y:ys)+ | x == y = go xs ys+ | otherwise = go (x:xs) [] </> go [] (y:ys)+ -- NB: It's important to normalize, as otherwise if+ -- we see "foo/./bar" we'll incorrectly conclude that we need+ -- to go "../../.." to get out of it.+ in go (splitPath (normalise base0)) (splitPath (normalise path0))++-- | This abstracts the common pattern of configuring and then building.+setup_build :: [String] -> TestM ()+setup_build args = do+ setup "configure" args+ setup "build" []+ return ()++-- | This abstracts the common pattern of "installing" a package.+setup_install :: [String] -> TestM ()+setup_install args = do+ setup "configure" args+ setup "build" []+ setup "copy" []+ setup "register" []+ return ()++-- | This abstracts the common pattern of "installing" a package,+-- with haddock documentation.+setup_install_with_docs :: [String] -> TestM ()+setup_install_with_docs args = do+ setup "configure" args+ setup "build" []+ setup "haddock" []+ setup "copy" []+ setup "register" []+ return ()++packageDBParams :: PackageDBStack -> [String]+packageDBParams dbs = "--package-db=clear"+ : map (("--package-db=" ++) . convert) dbs+ where+ convert :: PackageDB -> String+ convert GlobalPackageDB = "global"+ convert UserPackageDB = "user"+ convert (SpecificPackageDB path) = path++------------------------------------------------------------------------+-- * Running cabal++cabal :: String -> [String] -> TestM ()+cabal cmd args = void (cabal' cmd args)++cabal' :: String -> [String] -> TestM Result+cabal' = cabalG' []++cabalWithStdin :: String -> [String] -> String -> TestM Result+cabalWithStdin cmd args input = cabalGArgs [] cmd args (Just input)++cabalG :: [String] -> String -> [String] -> TestM ()+cabalG global_args cmd args = void (cabalG' global_args cmd args)++cabalG' :: [String] -> String -> [String] -> TestM Result+cabalG' global_args cmd args = cabalGArgs global_args cmd args Nothing++cabalGArgs :: [String] -> String -> [String] -> Maybe String -> TestM Result+cabalGArgs global_args cmd args input = do+ env <- getTestEnv+ -- Freeze writes out cabal.config to source directory, this is not+ -- overwritable+ when (cmd == "v1-freeze") requireHasSourceCopy+ let extra_args+ | cmd `elem` ["v1-update", "outdated", "user-config", "man", "v1-freeze", "check"]+ = [ ]++ -- new-build commands are affected by testCabalProjectFile+ | cmd == "v2-sdist"+ = [ "--project-file", testCabalProjectFile env ]++ | "v2-" `isPrefixOf` cmd+ = [ "--builddir", testDistDir env+ , "--project-file", testCabalProjectFile env+ , "-j1" ]++ | otherwise+ = [ "--builddir", testDistDir env ] +++ install_args++ install_args+ | cmd == "v1-install" || cmd == "v1-build" = [ "-j1" ]+ | otherwise = []++ cabal_args = global_args+ ++ [ cmd, marked_verbose ]+ ++ extra_args+ ++ args+ defaultRecordMode RecordMarked $ do+ recordHeader ["cabal", cmd]+ cabal_raw' cabal_args input++cabal_raw' :: [String] -> Maybe String -> TestM Result+cabal_raw' cabal_args input = runProgramM cabalProgram cabal_args input++withProjectFile :: FilePath -> TestM a -> TestM a+withProjectFile fp m =+ withReaderT (\env -> env { testCabalProjectFile = fp }) m++-- | Assuming we've successfully configured a new-build project,+-- read out the plan metadata so that we can use it to do other+-- operations.+withPlan :: TestM a -> TestM a+withPlan m = do+ env0 <- getTestEnv+ let filepath = testDistDir env0 </> "cache" </> "plan.json"+ mplan <- JSON.eitherDecode `fmap` liftIO (BSL.readFile filepath)+ case mplan of+ Left err -> fail $ "withPlan: cannot decode plan " ++ err+ Right plan -> withReaderT (\env -> env { testPlan = Just plan }) m++-- | Run an executable from a package. Requires 'withPlan' to have+-- been run so that we can find the dist dir.+runPlanExe :: String {- package name -} -> String {- component name -}+ -> [String] -> TestM ()+runPlanExe pkg_name cname args = void $ runPlanExe' pkg_name cname args++-- | Run an executable from a package. Requires 'withPlan' to have+-- been run so that we can find the dist dir. Also returns 'Result'.+runPlanExe' :: String {- package name -} -> String {- component name -}+ -> [String] -> TestM Result+runPlanExe' pkg_name cname args = do+ Just plan <- testPlan `fmap` getTestEnv+ let dist_dir = planDistDir plan (mkPackageName pkg_name)+ (CExeName (mkUnqualComponentName cname))+ defaultRecordMode RecordAll $ do+ recordHeader [pkg_name, cname]+ runM (dist_dir </> "build" </> cname </> cname) args Nothing++------------------------------------------------------------------------+-- * Running ghc-pkg++withPackageDb :: TestM a -> TestM a+withPackageDb m = do+ env <- getTestEnv+ let db_path = testPackageDbDir env+ if testHavePackageDb env+ then m+ else withReaderT (\nenv ->+ nenv { testPackageDBStack+ = testPackageDBStack env+ ++ [SpecificPackageDB db_path]+ , testHavePackageDb = True+ } )+ $ do ghcPkg "init" [db_path]+ m++ghcPkg :: String -> [String] -> TestM ()+ghcPkg cmd args = void (ghcPkg' cmd args)++ghcPkg' :: String -> [String] -> TestM Result+ghcPkg' cmd args = do+ env <- getTestEnv+ unless (testHavePackageDb env) $+ error "Must initialize package database using withPackageDb"+ -- NB: testDBStack already has the local database+ ghcConfProg <- requireProgramM ghcProgram+ let db_stack = testPackageDBStack env+ extraArgs = ghcPkgPackageDBParams+ (fromMaybe+ (error "ghc-pkg: cannot detect version")+ (programVersion ghcConfProg))+ db_stack+ recordHeader ["ghc-pkg", cmd]+ runProgramM ghcPkgProgram (cmd : extraArgs ++ args) Nothing++ghcPkgPackageDBParams :: Version -> PackageDBStack -> [String]+ghcPkgPackageDBParams version dbs = concatMap convert dbs where+ convert :: PackageDB -> [String]+ -- Ignoring global/user is dodgy but there's no way good+ -- way to give ghc-pkg the correct flags in this case.+ convert GlobalPackageDB = []+ convert UserPackageDB = []+ convert (SpecificPackageDB path)+ | version >= mkVersion [7,6]+ = ["--package-db=" ++ path]+ | otherwise+ = ["--package-conf=" ++ path]++------------------------------------------------------------------------+-- * Running other things++-- | Run an executable that was produced by cabal. The @exe_name@+-- is precisely the name of the executable section in the file.+runExe :: String -> [String] -> TestM ()+runExe exe_name args = void (runExe' exe_name args)++runExe' :: String -> [String] -> TestM Result+runExe' exe_name args = do+ env <- getTestEnv+ defaultRecordMode RecordAll $ do+ recordHeader [exe_name]+ runM (testDistDir env </> "build" </> exe_name </> exe_name) args Nothing++-- | Run an executable that was installed by cabal. The @exe_name@+-- is precisely the name of the executable.+runInstalledExe :: String -> [String] -> TestM ()+runInstalledExe exe_name args = void (runInstalledExe' exe_name args)++-- | Run an executable that was installed by cabal. Use this+-- instead of 'runInstalledExe' if you need to inspect the+-- stdout/stderr output.+runInstalledExe' :: String -> [String] -> TestM Result+runInstalledExe' exe_name args = do+ env <- getTestEnv+ defaultRecordMode RecordAll $ do+ recordHeader [exe_name]+ runM (testPrefixDir env </> "bin" </> exe_name) args Nothing++-- | Run a shell command in the current directory.+shell :: String -> [String] -> TestM Result+shell exe args = runM exe args Nothing++------------------------------------------------------------------------+-- * Repository manipulation++-- Workflows we support:+-- 1. Test comes with some packages (directories in repository) which+-- should be in the repository and available for depsolving/installing+-- into global store.+--+-- Workflows we might want to support in the future+-- * Regression tests may want to test on Hackage index. They will+-- operate deterministically as they will be pinned to a timestamp.+-- (But should we allow this? Have to download the tarballs in that+-- case. Perhaps dep solver only!)+-- * We might sdist a local package, and then upload it to the+-- repository+-- * Some of our tests involve old versions of Cabal. This might+-- be one of the rare cases where we're willing to grab the entire+-- tarball.+--+-- Properties we want to hold:+-- 1. Tests can be run offline. No dependence on hackage.haskell.org+-- beyond what we needed to actually get the build of Cabal working+-- itself+-- 2. Tests are deterministic. Updates to Hackage should not cause+-- tests to fail. (OTOH, it's good to run tests on most recent+-- Hackage index; some sort of canary test which is run nightly.+-- Point is it should NOT be tied to cabal source code.)+--+-- Technical notes:+-- * We depend on hackage-repo-tool binary. It would better if it was+-- libified into hackage-security but this has not been done yet.+--++hackageRepoTool :: String -> [String] -> TestM ()+hackageRepoTool cmd args = void $ hackageRepoTool' cmd args++hackageRepoTool' :: String -> [String] -> TestM Result+hackageRepoTool' cmd args = do+ recordHeader ["hackage-repo-tool", cmd]+ runProgramM hackageRepoToolProgram (cmd : args) Nothing++tar :: [String] -> TestM ()+tar args = void $ tar' args++tar' :: [String] -> TestM Result+tar' args = do+ recordHeader ["tar"]+ runProgramM tarProgram args Nothing++-- | Creates a tarball of a directory, such that if you+-- archive the directory "/foo/bar/baz" to "mine.tgz", @tar tf@ reports+-- @baz/file1@, @baz/file2@, etc.+archiveTo :: FilePath -> FilePath -> TestM ()+src `archiveTo` dst = do+ -- TODO: Consider using the @tar@ library?+ let (src_parent, src_dir) = splitFileName src+ -- TODO: --format ustar, like createArchive?+ -- --force-local is necessary for handling colons in Windows paths.+ tar $ ["-czf", dst]+ ++ ["--force-local" | buildOS == Windows]+ ++ ["-C", src_parent, src_dir]++infixr 4 `archiveTo`++-- | Given a directory (relative to the 'testCurrentDir') containing+-- a series of directories representing packages, generate an+-- external repository corresponding to all of these packages+withRepo :: FilePath -> TestM a -> TestM a+withRepo repo_dir m = do+ env <- getTestEnv++ -- Check if hackage-repo-tool is available, and skip if not+ skipUnless =<< isAvailableProgram hackageRepoToolProgram++ -- 1. Generate keys+ hackageRepoTool "create-keys" ["--keys", testKeysDir env]+ -- 2. Initialize repo directory+ let package_dir = testRepoDir env </> "package"+ liftIO $ createDirectoryIfMissing True (testRepoDir env </> "index")+ liftIO $ createDirectoryIfMissing True package_dir+ -- 3. Create tarballs+ pkgs <- liftIO $ getDirectoryContents (testCurrentDir env </> repo_dir)+ forM_ pkgs $ \pkg -> do+ case pkg of+ '.':_ -> return ()+ _ -> testCurrentDir env </> repo_dir </> pkg+ `archiveTo`+ package_dir </> pkg <.> "tar.gz"+ -- 4. Initialize repository+ hackageRepoTool "bootstrap" ["--keys", testKeysDir env, "--repo", testRepoDir env]+ -- 5. Wire it up in .cabal/config+ -- TODO: libify this+ let package_cache = testCabalDir env </> "packages"+ liftIO $ appendFile (testUserCabalConfigFile env)+ $ unlines [ "repository test-local-repo"+ , " url: " ++ repoUri env+ , " secure: True"+ -- TODO: Hypothetically, we could stick in the+ -- correct key here+ , " root-keys: "+ , " key-threshold: 0"+ , "remote-repo-cache: " ++ package_cache ]+ -- 6. Create local directories (TODO: this is a bug #4136, once you+ -- fix that this can be removed)+ liftIO $ createDirectoryIfMissing True (package_cache </> "test-local-repo")+ -- 7. Update our local index+ cabal "v1-update" []+ -- 8. Profit+ withReaderT (\env' -> env' { testHaveRepo = True }) m+ -- TODO: Arguably should undo everything when we're done...+ where+ -- Work around issue #5218 (incorrect conversions between Windows paths and+ -- file URIs) by using a relative path on Windows.+ repoUri env =+ if buildOS == Windows+ then let relPath = definitelyMakeRelative (testCurrentDir env)+ (testRepoDir env)+ convertSeparators = intercalate "/"+ . map dropTrailingPathSeparator+ . splitPath+ in "file:" ++ convertSeparators relPath+ else "file:" ++ testRepoDir env++------------------------------------------------------------------------+-- * Subprocess run results++requireSuccess :: Result -> TestM Result+requireSuccess r@Result { resultCommand = cmd+ , resultExitCode = exitCode+ , resultOutput = output } = withFrozenCallStack $ do+ env <- getTestEnv+ when (exitCode /= ExitSuccess && not (testShouldFail env)) $+ assertFailure $ "Command " ++ cmd ++ " failed.\n" +++ "Output:\n" ++ output ++ "\n"+ when (exitCode == ExitSuccess && testShouldFail env) $+ assertFailure $ "Command " ++ cmd ++ " succeeded.\n" +++ "Output:\n" ++ output ++ "\n"+ return r++initWorkDir :: TestM ()+initWorkDir = do+ env <- getTestEnv+ liftIO $ createDirectoryIfMissing True (testWorkDir env)++-- | Record a header to help identify the output to the expect+-- log. Unlike the 'recordLog', we don't record all arguments;+-- just enough to give you an idea of what the command might have+-- been. (This is because the arguments may not be deterministic,+-- so we don't want to spew them to the log.)+recordHeader :: [String] -> TestM ()+recordHeader args = do+ env <- getTestEnv+ let mode = testRecordMode env+ str_header = "# " ++ intercalate " " args ++ "\n"+ header = C.pack (testRecordNormalizer env str_header)+ case mode of+ DoNotRecord -> return ()+ _ -> do+ initWorkDir+ liftIO $ putStr str_header+ liftIO $ C.appendFile (testWorkDir env </> "test.log") header+ liftIO $ C.appendFile (testActualFile env) header++recordLog :: Result -> TestM ()+recordLog res = do+ env <- getTestEnv+ let mode = testRecordMode env+ initWorkDir+ liftIO $ C.appendFile (testWorkDir env </> "test.log")+ (C.pack $ "+ " ++ resultCommand res ++ "\n"+ ++ resultOutput res ++ "\n\n")+ liftIO . C.appendFile (testActualFile env) . C.pack . testRecordNormalizer env $+ case mode of+ RecordAll -> unlines (lines (resultOutput res))+ RecordMarked -> getMarkedOutput (resultOutput res)+ DoNotRecord -> ""++getMarkedOutput :: String -> String -- trailing newline+getMarkedOutput out = unlines (go (lines out) False)+ where+ go [] _ = []+ go (x:xs) True+ | "-----END CABAL OUTPUT-----" `isPrefixOf` x+ = go xs False+ | otherwise = x : go xs True+ go (x:xs) False+ -- NB: Windows has extra goo at the end+ | "-----BEGIN CABAL OUTPUT-----" `isPrefixOf` x+ = go xs True+ | otherwise = go xs False++------------------------------------------------------------------------+-- * Test helpers++assertFailure :: WithCallStack (String -> m ())+assertFailure msg = withFrozenCallStack $ error msg++assertExitCode :: MonadIO m => WithCallStack (ExitCode -> Result -> m ())+assertExitCode code result =+ when (code /= resultExitCode result) $+ assertFailure $ "Expected exit code: "+ ++ show code+ ++ "\nActual: "+ ++ show (resultExitCode result)++assertEqual :: (Eq a, Show a, MonadIO m) => WithCallStack (String -> a -> a -> m ())+assertEqual s x y =+ withFrozenCallStack $+ when (x /= y) $+ error (s ++ ":\nExpected: " ++ show x ++ "\nActual: " ++ show y)++assertNotEqual :: (Eq a, Show a, MonadIO m) => WithCallStack (String -> a -> a -> m ())+assertNotEqual s x y =+ withFrozenCallStack $+ when (x == y) $+ error (s ++ ":\nGot both: " ++ show x)++assertBool :: MonadIO m => WithCallStack (String -> Bool -> m ())+assertBool s x =+ withFrozenCallStack $+ unless x $ error s++shouldExist :: MonadIO m => WithCallStack (FilePath -> m ())+shouldExist path =+ withFrozenCallStack $+ liftIO $ doesFileExist path >>= assertBool (path ++ " should exist")++shouldNotExist :: MonadIO m => WithCallStack (FilePath -> m ())+shouldNotExist path =+ withFrozenCallStack $+ liftIO $ doesFileExist path >>= assertBool (path ++ " should exist") . not++assertRegex :: MonadIO m => String -> String -> Result -> m ()+assertRegex msg regex r =+ withFrozenCallStack $+ let out = resultOutput r+ in assertBool (msg ++ ",\nactual output:\n" ++ out)+ (out =~ regex)++fails :: TestM a -> TestM a+fails = withReaderT (\env -> env { testShouldFail = not (testShouldFail env) })++defaultRecordMode :: RecordMode -> TestM a -> TestM a+defaultRecordMode mode = withReaderT (\env -> env {+ testRecordDefaultMode = mode+ })++recordMode :: RecordMode -> TestM a -> TestM a+recordMode mode = withReaderT (\env -> env {+ testRecordUserMode = Just mode+ })++recordNormalizer :: (String -> String) -> TestM a -> TestM a+recordNormalizer f =+ withReaderT (\env -> env { testRecordNormalizer = testRecordNormalizer env . f })++assertOutputContains :: MonadIO m => WithCallStack (String -> Result -> m ())+assertOutputContains needle result =+ withFrozenCallStack $+ unless (needle `isInfixOf` (concatOutput output)) $+ assertFailure $ " expected: " ++ needle+ where output = resultOutput result++assertOutputDoesNotContain :: MonadIO m => WithCallStack (String -> Result -> m ())+assertOutputDoesNotContain needle result =+ withFrozenCallStack $+ when (needle `isInfixOf` (concatOutput output)) $+ assertFailure $ "unexpected: " ++ needle+ where output = resultOutput result++assertFindInFile :: MonadIO m => WithCallStack (String -> FilePath -> m ())+assertFindInFile needle path =+ withFrozenCallStack $+ liftIO $ withFileContents path+ (\contents ->+ unless (needle `isInfixOf` contents)+ (assertFailure ("expected: " ++ needle ++ "\n" +++ " in file: " ++ path)))++assertFileDoesContain :: MonadIO m => WithCallStack (FilePath -> String -> m ())+assertFileDoesContain path needle =+ withFrozenCallStack $+ liftIO $ withFileContents path+ (\contents ->+ unless (needle `isInfixOf` contents)+ (assertFailure ("expected: " ++ needle ++ "\n" +++ " in file: " ++ path)))++assertFileDoesNotContain :: MonadIO m => WithCallStack (FilePath -> String -> m ())+assertFileDoesNotContain path needle =+ withFrozenCallStack $+ liftIO $ withFileContents path+ (\contents ->+ when (needle `isInfixOf` contents)+ (assertFailure ("expected: " ++ needle ++ "\n" +++ " in file: " ++ path)))++-- | Replace line breaks with spaces, correctly handling "\r\n".+concatOutput :: String -> String+concatOutput = unwords . lines . filter ((/=) '\r')++------------------------------------------------------------------------+-- * Skipping tests++hasSharedLibraries :: TestM Bool+hasSharedLibraries = do+ shared_libs_were_removed <- ghcVersionIs (>= mkVersion [7,8])+ return (not (buildOS == Windows && shared_libs_were_removed))++hasProfiledLibraries :: TestM Bool+hasProfiledLibraries = do+ env <- getTestEnv+ ghc_path <- programPathM ghcProgram+ let prof_test_hs = testWorkDir env </> "Prof.hs"+ liftIO $ writeFile prof_test_hs "module Prof where"+ r <- liftIO $ run (testVerbosity env) (Just (testCurrentDir env))+ (testEnvironment env) ghc_path ["-prof", "-c", prof_test_hs]+ Nothing+ return (resultExitCode r == ExitSuccess)++-- | Check if the GHC that is used for compiling package tests has+-- a shared library of the cabal library under test in its database.+--+-- An example where this is needed is if you want to dynamically link+-- detailed-0.9 test suites, since those depend on the Cabal library unde rtest.+hasCabalShared :: TestM Bool+hasCabalShared = do+ env <- getTestEnv+ return (testHaveCabalShared env)++ghcVersionIs :: WithCallStack ((Version -> Bool) -> TestM Bool)+ghcVersionIs f = do+ ghc_program <- requireProgramM ghcProgram+ case programVersion ghc_program of+ Nothing -> error $ "ghcVersionIs: no ghc version for "+ ++ show (programLocation ghc_program)+ Just v -> return (f v)++isWindows :: TestM Bool+isWindows = return (buildOS == Windows)++isOSX :: TestM Bool+isOSX = return (buildOS == OSX)++isLinux :: TestM Bool+isLinux = return (buildOS == Linux)++getOpenFilesLimit :: TestM (Maybe Integer)+#ifdef mingw32_HOST_OS+-- No MS-specified limit, was determined experimentally on Windows 10 Pro x64,+-- matches other online reports from other versions of Windows.+getOpenFilesLimit = return (Just 2048)+#else+getOpenFilesLimit = liftIO $ do+ ResourceLimits { softLimit } <- getResourceLimit ResourceOpenFiles+ case softLimit of+ ResourceLimit n | n >= 0 && n <= 4096 -> return (Just n)+ _ -> return Nothing+#endif++hasCabalForGhc :: TestM Bool+hasCabalForGhc = do+ env <- getTestEnv+ ghc_program <- requireProgramM ghcProgram+ (runner_ghc_program, _) <- liftIO $ requireProgram+ (testVerbosity env)+ ghcProgram+ (runnerProgramDb (testScriptEnv env))++ -- TODO: I guess, to be more robust what we should check for+ -- specifically is that the Cabal library we want to use+ -- will be picked up by the package db stack of ghc-program++ -- liftIO $ putStrLn $ "ghc_program: " ++ show ghc_program+ -- liftIO $ putStrLn $ "runner_ghc_program: " ++ show runner_ghc_program++ return (programPath ghc_program == programPath runner_ghc_program)++-- | If you want to use a Custom setup with new-build, it needs to+-- be 1.20 or later. Ordinarily, Cabal can go off and build a+-- sufficiently recent Cabal if necessary, but in our test suite,+-- by default, we try to avoid doing so (since that involves a+-- rather lengthy build process), instead using the boot Cabal if+-- possible. But some GHCs don't have a recent enough boot Cabal!+-- You'll want to exclude them in that case.+--+hasNewBuildCompatBootCabal :: TestM Bool+hasNewBuildCompatBootCabal = ghcVersionIs (>= mkVersion [7,9])++------------------------------------------------------------------------+-- * Broken tests++expectBroken :: Int -> TestM a -> TestM ()+expectBroken ticket m = do+ env <- getTestEnv+ liftIO . withAsync (runReaderT m env) $ \a -> do+ r <- waitCatch a+ case r of+ Left e -> do+ putStrLn $ "This test is known broken, see #" ++ show ticket ++ ":"+ print e+ runReaderT expectedBroken env+ Right _ -> do+ runReaderT unexpectedSuccess env++expectBrokenIf :: Bool -> Int -> TestM a -> TestM ()+expectBrokenIf False _ m = void $ m+expectBrokenIf True ticket m = expectBroken ticket m++expectBrokenUnless :: Bool -> Int -> TestM a -> TestM ()+expectBrokenUnless b = expectBrokenIf (not b)++------------------------------------------------------------------------+-- * Miscellaneous++git :: String -> [String] -> TestM ()+git cmd args = void $ git' cmd args++git' :: String -> [String] -> TestM Result+git' cmd args = do+ recordHeader ["git", cmd]+ runProgramM gitProgram (cmd : args) Nothing++gcc :: [String] -> TestM ()+gcc args = void $ gcc' args++gcc' :: [String] -> TestM Result+gcc' args = do+ recordHeader ["gcc"]+ runProgramM gccProgram args Nothing++ghc :: [String] -> TestM ()+ghc args = void $ ghc' args++ghc' :: [String] -> TestM Result+ghc' args = do+ recordHeader ["ghc"]+ runProgramM ghcProgram args Nothing++-- | If a test needs to modify or write out source files, it's+-- necessary to make a hermetic copy of the source files to operate+-- on. This function arranges for this to be done.+--+-- This requires the test repository to be a Git checkout, because+-- we use the Git metadata to figure out what files to copy into the+-- hermetic copy.+--+-- Also see 'withSourceCopyDir'.+withSourceCopy :: TestM a -> TestM a+withSourceCopy m = do+ env <- getTestEnv+ let cwd = testCurrentDir env+ dest = testSourceCopyDir env+ r <- git' "ls-files" ["--cached", "--modified"]+ forM_ (lines (resultOutput r)) $ \f -> do+ unless (isTestFile f) $ do+ liftIO $ createDirectoryIfMissing True (takeDirectory (dest </> f))+ liftIO $ copyFile (cwd </> f) (dest </> f)+ withReaderT (\nenv -> nenv { testHaveSourceCopy = True }) m++-- | If a test needs to modify or write out source files, it's+-- necessary to make a hermetic copy of the source files to operate+-- on. This function arranges for this to be done in a subdirectory+-- with a given name, so that tests that are sensitive to the path+-- that they're running in (e.g., autoconf tests) can run.+--+-- This requires the test repository to be a Git checkout, because+-- we use the Git metadata to figure out what files to copy into the+-- hermetic copy.+--+-- Also see 'withSourceCopy'.+withSourceCopyDir :: FilePath -> TestM a -> TestM a+withSourceCopyDir dir =+ withReaderT (\nenv -> nenv { testSourceCopyRelativeDir = dir }) . withSourceCopy++-- | Look up the 'InstalledPackageId' of a package name.+getIPID :: String -> TestM String+getIPID pn = do+ r <- ghcPkg' "field" ["--global", pn, "id"]+ -- Don't choke on warnings from ghc-pkg+ case mapMaybe (stripPrefix "id: ") (lines (resultOutput r)) of+ -- ~/.cabal/store may contain multiple versions of single package+ -- we pick first one. It should work+ (x:_) -> return (takeWhile (not . Char.isSpace) x)+ _ -> error $ "could not determine id of " ++ pn++-- | Delay a sufficient period of time to permit file timestamp+-- to be updated.+delay :: TestM ()+delay = do+ env <- getTestEnv+ is_old_ghc <- ghcVersionIs (< mkVersion [7,7])+ -- For old versions of GHC, we only had second-level precision,+ -- so we need to sleep a full second. Newer versions use+ -- millisecond level precision, so we only have to wait+ -- the granularity of the underlying filesystem.+ -- TODO: cite commit when GHC got better precision; this+ -- version bound was empirically generated.+ liftIO . threadDelay $+ if is_old_ghc+ then 1000000+ else fromMaybe+ (error "Delay must be enclosed by withDelay")+ (testMtimeChangeDelay env)++-- | Calibrate file modification time delay, if not+-- already determined.+withDelay :: TestM a -> TestM a+withDelay m = do+ env <- getTestEnv+ case testMtimeChangeDelay env of+ Nothing -> do+ -- Figure out how long we need to delay for recompilation tests+ (_, mtimeChange) <- liftIO $ calibrateMtimeChangeDelay+ withReaderT (\nenv -> nenv { testMtimeChangeDelay = Just mtimeChange }) m+ Just _ -> m++-- | Create a symlink for the duration of the provided action. If the symlink+-- already exists, it is deleted. Does not work on Windows.+withSymlink :: FilePath -> FilePath -> TestM a -> TestM a+#ifdef mingw32_HOST_OS+withSymlink _oldpath _newpath _act =+ error "PackageTests.PackageTester.withSymlink: does not work on Windows!"+#else+withSymlink oldpath newpath0 act = do+ env <- getTestEnv+ let newpath = testCurrentDir env </> newpath0+ symlinkExists <- liftIO $ doesFileExist newpath+ when symlinkExists $ liftIO $ removeFile newpath+ bracket_ (liftIO $ createSymbolicLink oldpath newpath)+ (liftIO $ removeFile newpath) act+#endif++writeSourceFile :: FilePath -> String -> TestM ()+writeSourceFile fp s = do+ requireHasSourceCopy+ cwd <- fmap testCurrentDir getTestEnv+ liftIO $ writeFile (cwd </> fp) s++copySourceFileTo :: FilePath -> FilePath -> TestM ()+copySourceFileTo src dest = do+ requireHasSourceCopy+ cwd <- fmap testCurrentDir getTestEnv+ liftIO $ copyFile (cwd </> src) (cwd </> dest)++requireHasSourceCopy :: TestM ()+requireHasSourceCopy = do+ env <- getTestEnv+ unless (testHaveSourceCopy env) $ do+ error "This operation requires a source copy; use withSourceCopy and 'git add' all test files"++-- NB: Keep this synchronized with partitionTests+isTestFile :: FilePath -> Bool+isTestFile f =+ case takeExtensions f of+ ".test.hs" -> True+ ".multitest.hs" -> True+ _ -> False++-- | Work around issue #4515 (store paths exceeding the Windows path length+-- limit) by creating a temporary directory for the new-build store. This+-- function creates a directory immediately under the current drive on Windows.+-- The directory must be passed to new- commands with --store-dir.+withShorterPathForNewBuildStore :: (FilePath -> IO a) -> IO a+withShorterPathForNewBuildStore test = do+ tempDir <- if buildOS == Windows+ then takeDrive `fmap` getCurrentDirectory+ else getTemporaryDirectory+ withTempDirectory normal tempDir "cabal-test-store" test
+ cabal/cabal-testsuite/src/Test/Cabal/Run.hs view
@@ -0,0 +1,83 @@+{-# LANGUAGE NondecreasingIndentation #-}+-- | A module for running commands in a chatty way.+module Test.Cabal.Run (+ run,+ Result(..)+) where++import qualified Distribution.Compat.CreatePipe as Compat+import Distribution.Simple.Program.Run+import Distribution.Verbosity++import Control.Concurrent.Async+import System.Process+import System.IO+import System.Exit+import System.Directory+import System.FilePath++-- | The result of invoking the command line.+data Result = Result+ { resultExitCode :: ExitCode+ , resultCommand :: String+ , resultOutput :: String+ } deriving Show++-- | Run a command, streaming its output to stdout, and return a 'Result'+-- with this information.+run :: Verbosity -> Maybe FilePath -> [(String, Maybe String)] -> FilePath -> [String] -> Maybe String -> IO Result+run _verbosity mb_cwd env_overrides path0 args input = do+ -- In our test runner, we allow a path to be relative to the+ -- current directory using the same heuristic as shells:+ -- 'foo' refers to an executable in the PATH, but './foo'+ -- and 'foo/bar' refer to relative files.+ --+ -- Unfortunately, we cannot just pass these relative paths directly:+ -- 'runProcess' resolves an executable path not with respect to the+ -- current working directory, but the working directory that the+ -- subprocess will execute in. Thus, IF we have a relative+ -- path which is not a bare executable name, we have to tack on+ -- the CWD to make it resolve correctly+ cwdir <- getCurrentDirectory+ let path | length (splitPath path0) /= 1 && isRelative path0+ = cwdir </> path0+ | otherwise+ = path0++ mb_env <- getEffectiveEnvironment env_overrides+ putStrLn $ "+ " ++ showCommandForUser path args+ (readh, writeh) <- Compat.createPipe+ hSetBuffering readh LineBuffering+ hSetBuffering writeh LineBuffering+ let drain = do+ r <- hGetContents readh+ putStr r -- forces the output+ hClose readh+ return r+ withAsync drain $ \sync -> do++ let prc = (proc path args)+ { cwd = mb_cwd+ , env = mb_env+ , std_in = case input of { Just _ -> CreatePipe; Nothing -> Inherit }+ , std_out = UseHandle writeh+ , std_err = UseHandle writeh+ }+ (stdin_h, _, _, procHandle) <- createProcess prc++ case input of+ Just x ->+ case stdin_h of+ Just h -> hPutStr h x >> hClose h+ Nothing -> error "No stdin handle when input was specified!"+ Nothing -> return ()++ -- wait for the program to terminate+ exitcode <- waitForProcess procHandle+ out <- wait sync++ return Result {+ resultExitCode = exitcode,+ resultCommand = showCommandForUser path args,+ resultOutput = out+ }
+ cabal/cabal-testsuite/src/Test/Cabal/Script.hs view
@@ -0,0 +1,97 @@+-- | Functionality for invoking Haskell scripts with the correct+-- package database setup.+module Test.Cabal.Script (+ ScriptEnv(..),+ mkScriptEnv,+ runnerGhcArgs,+ runnerCommand,+ runghc,+) where++import Test.Cabal.Run+import Test.Cabal.ScriptEnv0++import Distribution.Backpack+import Distribution.Types.ModuleRenaming+import Distribution.Utils.NubList+import Distribution.Simple.Program.Db+import Distribution.Simple.Program.Builtin+import Distribution.Simple.Program.GHC+import Distribution.Simple.Program+import Distribution.Simple.Compiler+import Distribution.Verbosity+import Distribution.System+import Distribution.Simple.Setup (Flag(..))++import qualified Data.Monoid as M+++-- | The runner environment, which contains all of the important+-- parameters for invoking GHC. Mostly subset of 'LocalBuildInfo'.+data ScriptEnv = ScriptEnv+ { runnerProgramDb :: ProgramDb+ , runnerPackageDbStack :: PackageDBStack+ , runnerVerbosity :: Verbosity+ , runnerPlatform :: Platform+ , runnerCompiler :: Compiler+ , runnerPackages :: [(OpenUnitId, ModuleRenaming)]+ , runnerWithSharedLib :: Bool+ }++{-++-- | Convert package database into absolute path, so that+-- if we change working directories in a subprocess we get the correct database.+canonicalizePackageDB :: PackageDB -> IO PackageDB+canonicalizePackageDB (SpecificPackageDB path)+ = SpecificPackageDB `fmap` canonicalizePath path+canonicalizePackageDB x = return x++-}++-- | Create a 'ScriptEnv' from a 'LocalBuildInfo' configured with+-- the GHC that we want to use.+mkScriptEnv :: Verbosity -> IO ScriptEnv+mkScriptEnv verbosity =+ return $ ScriptEnv+ { runnerVerbosity = verbosity+ , runnerProgramDb = lbiProgramDb+ , runnerPackageDbStack = lbiPackageDbStack+ , runnerPlatform = lbiPlatform+ , runnerCompiler = lbiCompiler+ -- NB: the set of packages available to test.hs scripts will COINCIDE+ -- with the dependencies on the cabal-testsuite library+ , runnerPackages = lbiPackages+ , runnerWithSharedLib = lbiWithSharedLib+ }++-- | Run a script with 'runghc', under the 'ScriptEnv'.+runghc :: ScriptEnv -> Maybe FilePath -> [(String, Maybe String)]+ -> FilePath -> [String] -> IO Result+runghc senv mb_cwd env_overrides script_path args = do+ (real_path, real_args) <- runnerCommand senv mb_cwd env_overrides script_path args+ run (runnerVerbosity senv) mb_cwd env_overrides real_path real_args Nothing++-- | Compute the command line which should be used to run a Haskell+-- script with 'runghc'.+runnerCommand :: ScriptEnv -> Maybe FilePath -> [(String, Maybe String)]+ -> FilePath -> [String] -> IO (FilePath, [String])+runnerCommand senv _mb_cwd _env_overrides script_path args = do+ (prog, _) <- requireProgram verbosity runghcProgram (runnerProgramDb senv)+ return (programPath prog,+ runghc_args ++ ["--"] ++ map ("--ghc-arg="++) ghc_args ++ [script_path] ++ args)+ where+ verbosity = runnerVerbosity senv+ runghc_args = []+ ghc_args = runnerGhcArgs senv++-- | Compute the GHC flags to invoke 'runghc' with under a 'ScriptEnv'.+runnerGhcArgs :: ScriptEnv -> [String]+runnerGhcArgs senv =+ renderGhcOptions (runnerCompiler senv) (runnerPlatform senv) ghc_options+ where+ ghc_options = M.mempty { ghcOptPackageDBs = runnerPackageDbStack senv+ , ghcOptPackages = toNubListR (runnerPackages senv)+ -- Avoid picking stray module files that look+ -- like our imports+ , ghcOptSourcePathClear = Flag True }
+ cabal/cabal-testsuite/src/Test/Cabal/Server.hs view
@@ -0,0 +1,443 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE NondecreasingIndentation #-}+-- | A GHC run-server, which supports running multiple GHC scripts+-- without having to restart from scratch.+module Test.Cabal.Server (+ Server,+ serverProcessId,+ ServerLogMsg(..),+ ServerLogMsgType(..),+ ServerResult(..),+ withNewServer,+ runOnServer,+ runMain,+) where++import Test.Cabal.Script++import Prelude hiding (log)+import Control.Concurrent.MVar+import Control.Concurrent+import Control.Concurrent.Async+import System.Process+import System.IO+import System.Exit+import Data.List+import Distribution.Simple.Program.Db+import Distribution.Simple.Program+import Control.Exception+import qualified Control.Exception as E+import Control.Monad+import Data.IORef+import Data.Maybe++import Distribution.Verbosity++import System.Process.Internals+#if mingw32_HOST_OS+import qualified System.Win32.Process as Win32+#endif++-- TODO: Compare this implementation with+-- https://github.com/ndmitchell/ghcid/blob/master/src/Language/Haskell/Ghcid.hs+-- which does something similar++-- ----------------------------------------------------------------- --+-- Public API+-- ----------------------------------------------------------------- --++-- | A GHCi server session, which we can ask to run scripts.+-- It operates in a *fixed* runner environment as specified+-- by 'serverScriptEnv'.+data Server = Server {+ serverStdin :: Handle,+ serverStdout :: Handle,+ serverStderr :: Handle,+ serverProcessHandle :: ProcessHandle,+ serverProcessId :: ProcessId,+ serverScriptEnv :: ScriptEnv,+ -- | Accumulators which we use to keep tracking+ -- of stdout/stderr we've incrementally read out. In the event+ -- of an error we'll use this to give diagnostic information.+ serverStdoutAccum :: MVar [String],+ serverStderrAccum :: MVar [String],+ serverLogChan :: Chan ServerLogMsg+ }++-- | Portable representation of process ID; just a string rendered+-- number.+type ProcessId = String++data ServerLogMsg = ServerLogMsg ServerLogMsgType String+ | ServerLogEnd+data ServerLogMsgType = ServerOut ProcessId+ | ServerErr ProcessId+ | ServerIn ProcessId+ | ServerMeta ProcessId+ | AllServers++data ServerResult = ServerResult { -- Result+ serverResultExitCode :: ExitCode,+ serverResultCommand :: String,+ serverResultStdout :: String,+ serverResultStderr :: String+ }++-- | With 'ScriptEnv', create a new GHCi 'Server' session.+-- When @f@ returns, the server is terminated and no longer+-- valid.+withNewServer :: Chan ServerLogMsg -> ScriptEnv -> (Server -> IO a) -> IO a+withNewServer chan senv f =+ bracketWithInit (startServer chan senv) initServer stopServer f++-- | Like 'bracket', but with an initialization function on the resource+-- which will be called, unmasked, on the resource to transform it+-- in some way. If the initialization function throws an exception, the cleanup+-- handler will get invoked with the original resource; if it succeeds, the+-- cleanup handler will get invoked with the transformed resource.+-- The cleanup handler must be able to handle both cases.+--+-- This can help avoid race conditions in certain situations: with+-- normal use of 'bracket', the resource acquisition function+-- MUST return immediately after the resource is acquired. If it+-- performs any interruptible actions afterwards, it could be+-- interrupted and the exception handler not called.+bracketWithInit :: IO a -> (a -> IO a) -> (a -> IO b) -> (a -> IO c) -> IO c+bracketWithInit before initialize after thing =+ mask $ \restore -> do+ a0 <- before+ a <- restore (initialize a0) `onException` after a0+ r <- restore (thing a) `onException` after a+ _ <- after a+ return r++-- | Run an hs script on the GHCi server, returning the 'ServerResult' of+-- executing the command.+--+-- * The script MUST have an @hs@ or @lhs@ filename; GHCi+-- will reject non-Haskell filenames.+--+-- * If the script is not well-typed, the returned output+-- will be of GHC's compile errors.+--+-- * Inside your script, do not rely on 'getProgName' having+-- a sensible value.+--+-- * Current working directory and environment overrides+-- are currently not implemented.+--+runOnServer :: Server -> Maybe FilePath -> [(String, Maybe String)]+ -> FilePath -> [String] -> IO ServerResult+runOnServer s mb_cwd env_overrides script_path args = do+ -- TODO: cwd not implemented+ when (isJust mb_cwd) $ error "runOnServer change directory not implemented"+ -- TODO: env_overrides not implemented+ unless (null env_overrides) $ error "runOnServer set environment not implemented"++ -- Set arguments returned by System.getArgs+ write s $ ":set args " ++ show args+ -- Output start sigil (do it here so we pick up compilation+ -- failures)+ write s $ "System.IO.hPutStrLn System.IO.stdout " ++ show start_sigil+ write s $ "System.IO.hPutStrLn System.IO.stderr " ++ show start_sigil+ _ <- readUntilSigil s start_sigil IsOut+ _ <- readUntilSigil s start_sigil IsErr+ -- Drain the output produced by the script as we are running so that+ -- we do not deadlock over a full pipe.+ withAsync (readUntilEnd s IsOut) $ \a_exit_out -> do+ withAsync (readUntilSigil s end_sigil IsErr) $ \a_err -> do+ -- NB: No :set prog; don't rely on this value in test scripts,+ -- we pass it in via the arguments+ -- NB: load drops all bindings, which is GOOD. Avoid holding onto+ -- garbage.+ write s $ ":load " ++ script_path+ -- Create a ref which will record the exit status of the command+ -- NB: do this after :load so it doesn't get dropped+ write s $ "ref <- Data.IORef.newIORef (System.Exit.ExitFailure 1)"+ -- TODO: What if an async exception gets raised here? At the+ -- moment, there is no way to recover until we get to the top-level+ -- bracket; then stopServer which correctly handles this case.+ -- If you do want to be able to abort this computation but KEEP+ -- USING THE SERVER SESSION, you will need to have a lot more+ -- sophisticated logic.+ write s $ "Test.Cabal.Server.runMain ref Main.main"+ -- Output end sigil.+ -- NB: We're line-oriented, so we MUST add an extra newline+ -- to ensure that we see the end sigil.+ write s $ "System.IO.hPutStrLn System.IO.stdout " ++ show ""+ write s $ "System.IO.hPutStrLn System.IO.stderr " ++ show ""+ write s $ "Data.IORef.readIORef ref >>= \\e -> " +++ " System.IO.hPutStrLn System.IO.stdout (" ++ show end_sigil ++ " ++ \" \" ++ show e)"+ write s $ "System.IO.hPutStrLn System.IO.stderr " ++ show end_sigil+ (code, out) <- wait a_exit_out+ err <- wait a_err++ -- Give the user some indication about how they could run the+ -- command by hand.+ (real_path, real_args) <- runnerCommand (serverScriptEnv s) mb_cwd env_overrides script_path args+ return ServerResult {+ serverResultExitCode = code,+ serverResultCommand = showCommandForUser real_path real_args,+ serverResultStdout = out,+ serverResultStderr = err+ }++-- | Helper function which we use in the GHCi session to communicate+-- the exit code of the process.+runMain :: IORef ExitCode -> IO () -> IO ()+runMain ref m = do+ E.catch (m >> writeIORef ref ExitSuccess) serverHandler+ where+ serverHandler :: SomeException -> IO ()+ serverHandler e = do+ -- TODO: Probably a few more cases you could handle;+ -- e.g., StackOverflow should return 2; also signals.+ writeIORef ref $+ case fromException e of+ Just exit_code -> exit_code+ -- Only rethrow for non ExitFailure exceptions+ _ -> ExitFailure 1+ case fromException e :: Maybe ExitCode of+ Just _ -> return ()+ _ -> throwIO e++-- ----------------------------------------------------------------- --+-- Initialize/tear down+-- ----------------------------------------------------------------- --++-- | Start a new GHCi session.+startServer :: Chan ServerLogMsg -> ScriptEnv -> IO Server+startServer chan senv = do+ (prog, _) <- requireProgram verbosity ghcProgram (runnerProgramDb senv)+ let ghc_args = runnerGhcArgs senv ++ ["--interactive", "-v0", "-ignore-dot-ghci"]+ proc_spec = (proc (programPath prog) ghc_args) {+ create_group = True,+ -- Closing fds is VERY important to avoid+ -- deadlock; we won't see the end of a+ -- stream until everyone gives up.+ close_fds = True,+ std_in = CreatePipe,+ std_out = CreatePipe,+ std_err = CreatePipe+ }+ -- printRawCommandAndArgsAndEnv (runnerVerbosity senv) (programPath prog) ghc_args Nothing+ when (verbosity >= verbose) $+ writeChan chan (ServerLogMsg AllServers (showCommandForUser (programPath prog) ghc_args))+ (Just hin, Just hout, Just herr, proch) <- createProcess proc_spec+ out_acc <- newMVar []+ err_acc <- newMVar []+ tid <- myThreadId+ return Server {+ serverStdin = hin,+ serverStdout = hout,+ serverStderr = herr,+ serverProcessHandle = proch,+ serverProcessId = show tid,+ serverLogChan = chan,+ serverStdoutAccum = out_acc,+ serverStderrAccum = err_acc,+ serverScriptEnv = senv+ }+ where+ verbosity = runnerVerbosity senv++-- | Unmasked initialization for the server+initServer :: Server -> IO Server+initServer s0 = do+ -- NB: withProcessHandle reads an MVar and is interruptible+#if mingw32_HOST_OS+ pid <- withProcessHandle (serverProcessHandle s0) $ \ph ->+ case ph of+ OpenHandle x -> fmap show (Win32.getProcessId x)+ ClosedHandle _ -> return (serverProcessId s0)+#else+ pid <- withProcessHandle (serverProcessHandle s0) $ \ph ->+ case ph of+#if MIN_VERSION_process(1,2,0)+ OpenHandle x -> return (show x)+ -- TODO: handle OpenExtHandle?+ _ -> return (serverProcessId s0)+#else+ OpenHandle x -> return (ph, show x)+ -- TODO: handle OpenExtHandle?+ _ -> return (ph, serverProcessId s0)+#endif+#endif+ let s = s0 { serverProcessId = pid }+ -- We will read/write a line at a time, including for+ -- output; our demarcation tokens are an entire line.+ forM_ [serverStdin, serverStdout, serverStderr] $ \f -> do+ hSetBuffering (f s) LineBuffering+ hSetEncoding (f s) utf8+ write s ":set prompt \"\""+ write s "System.IO.hSetBuffering System.IO.stdout System.IO.LineBuffering"+ return s++-- | Stop a GHCi session.+stopServer :: Server -> IO ()+stopServer s = do+ -- This is quite a bit of funny business.+ -- On Linux, terminateProcess will send a SIGINT, which+ -- GHCi will swallow and actually only use to terminate+ -- whatever computation is going on at that time. So we+ -- have to follow up with an actual :quit command to+ -- finish it up (if you delete it, the processes will+ -- hang around). On Windows, this will just actually kill+ -- the process so the rest should be unnecessary.+ mb_exit <- getProcessExitCode (serverProcessHandle s)++ let hardKiller = do+ threadDelay 2000000 -- 2sec+ log ServerMeta s $ "Terminating..."+ terminateProcess (serverProcessHandle s)+ softKiller = do+ -- Ask to quit. If we're in the middle of a computation,+ -- this will buffer up (unless the program is intercepting+ -- stdin, but that should NOT happen.)+ ignore $ write s ":quit"++ -- NB: it's important that we used create_group. We+ -- run this AFTER write s ":quit" because if we C^C+ -- sufficiently early in GHCi startup process, GHCi+ -- will actually die, and then hClose will fail because+ -- the ":quit" command was buffered up but never got+ -- flushed.+ interruptProcessGroupOf (serverProcessHandle s)++ log ServerMeta s $ "Waiting..."+ -- Close input BEFORE waiting, close output AFTER waiting.+ -- If you get either order wrong, deadlock!+ hClose (serverStdin s)+ -- waitForProcess has race condition+ -- https://github.com/haskell/process/issues/46+ waitForProcess $ serverProcessHandle s++ let drain f = do+ r <- hGetContents (f s)+ _ <- evaluate (length r)+ hClose (f s)+ return r+ withAsync (drain serverStdout) $ \a_out -> do+ withAsync (drain serverStderr) $ \a_err -> do++ r <- case mb_exit of+ Nothing -> do+ log ServerMeta s $ "Terminating GHCi"+ race hardKiller softKiller+ Just exit -> do+ log ServerMeta s $ "GHCi died unexpectedly"+ return (Right exit)++ -- Drain the output buffers+ rest_out <- wait a_out+ rest_err <- wait a_err+ if r /= Right ExitSuccess &&+ r /= Right (ExitFailure (-2)) -- SIGINT; happens frequently for some reason+ then do withMVar (serverStdoutAccum s) $ \acc ->+ mapM_ (info ServerOut s) (reverse acc)+ info ServerOut s rest_out+ withMVar (serverStderrAccum s) $ \acc ->+ mapM_ (info ServerErr s) (reverse acc)+ info ServerErr s rest_err+ info ServerMeta s $+ (case r of+ Left () -> "GHCi was forcibly terminated"+ Right exit -> "GHCi exited with " ++ show exit) +++ if verbosity < verbose+ then " (use -v for more information)"+ else ""+ else log ServerOut s rest_out++ log ServerMeta s $ "Done"+ return ()+ where+ verbosity = runnerVerbosity (serverScriptEnv s)++-- Using the procedure from+-- https://www.schoolofhaskell.com/user/snoyberg/general-haskell/exceptions/catching-all-exceptions+ignore :: IO () -> IO ()+ignore m = withAsync m $ \a -> void (waitCatch a)++-- ----------------------------------------------------------------- --+-- Utility functions+-- ----------------------------------------------------------------- --++log :: (ProcessId -> ServerLogMsgType) -> Server -> String -> IO ()+log ctor s msg =+ when (verbosity >= verbose) $ info ctor s msg+ where+ verbosity = runnerVerbosity (serverScriptEnv s)++info :: (ProcessId -> ServerLogMsgType) -> Server -> String -> IO ()+info ctor s msg =+ writeChan chan (ServerLogMsg (ctor (serverProcessId s)) msg)+ where+ chan = serverLogChan s++-- | Write a string to the prompt of the GHCi server.+write :: Server -> String -> IO ()+write s msg = do+ log ServerIn s $ msg+ hPutStrLn (serverStdin s) msg+ hFlush (serverStdin s) -- line buffering should get it, but just for good luck++accumulate :: MVar [String] -> String -> IO ()+accumulate acc msg =+ modifyMVar_ acc (\msgs -> return (msg:msgs))++flush :: MVar [String] -> IO [String]+flush acc = modifyMVar acc (\msgs -> return ([], reverse msgs))++data OutOrErr = IsOut | IsErr++serverHandle :: Server -> OutOrErr -> Handle+serverHandle s IsOut = serverStdout s+serverHandle s IsErr = serverStderr s++serverAccum :: Server -> OutOrErr -> MVar [String]+serverAccum s IsOut = serverStdoutAccum s+serverAccum s IsErr = serverStderrAccum s++outOrErrMsgType :: OutOrErr -> (ProcessId -> ServerLogMsgType)+outOrErrMsgType IsOut = ServerOut+outOrErrMsgType IsErr = ServerErr++-- | Consume output from the GHCi server until we hit a "start+-- sigil" (indicating that the subsequent output is for the+-- command we want.) Call this only immediately after you+-- send a command to GHCi to emit the start sigil.+readUntilSigil :: Server -> String -> OutOrErr -> IO String+readUntilSigil s sigil outerr = do+ l <- hGetLine (serverHandle s outerr)+ log (outOrErrMsgType outerr) s l+ if sigil `isPrefixOf` l -- NB: on Windows there might be extra goo at end+ then intercalate "\n" `fmap` flush (serverAccum s outerr)+ else do accumulate (serverAccum s outerr) l+ readUntilSigil s sigil outerr++-- | Consume output from the GHCi server until we hit the+-- end sigil. Return the consumed output as well as the+-- exit code (which is at the end of the sigil).+readUntilEnd :: Server -> OutOrErr -> IO (ExitCode, String)+readUntilEnd s outerr = go []+ where+ go rs = do+ l <- hGetLine (serverHandle s outerr)+ log (outOrErrMsgType outerr) s l+ if end_sigil `isPrefixOf` l+ -- NB: NOT unlines, we don't want the trailing newline!+ then do exit <- evaluate (parseExit l)+ _ <- flush (serverAccum s outerr) -- TODO: don't toss this out+ return (exit, intercalate "\n" (reverse rs))+ else do accumulate (serverAccum s outerr) l+ go (l:rs)+ parseExit l = read (drop (length end_sigil) l)++-- | The start and end sigils. This should be chosen to be+-- reasonably unique, so that test scripts don't accidentally+-- generate them. If these get spuriously generated, we will+-- probably deadlock.+start_sigil, end_sigil :: String+start_sigil = "BEGIN Test.Cabal.Server"+end_sigil = "END Test.Cabal.Server"
+ cabal/cabal-testsuite/src/Test/Cabal/Workdir.hs view
@@ -0,0 +1,30 @@+{-# LANGUAGE CPP #-}+-- | Functions for interrogating the current working directory+module Test.Cabal.Workdir where++import Distribution.Simple.Setup+import Distribution.Simple.Configure++import System.Directory+import System.FilePath++#if MIN_VERSION_base(4,6,0)+import System.Environment ( getExecutablePath )+#endif++-- | Guess what the dist directory of a running executable is,+-- by using the conventional layout of built executables+-- in relation to the top of a dist directory. Will not work+-- if the executable has been installed somewhere else.+guessDistDir :: IO FilePath+guessDistDir = do+#if MIN_VERSION_base(4,6,0)+ exe_path <- canonicalizePath =<< getExecutablePath+ let dist0 = dropFileName exe_path </> ".." </> ".."+ b <- doesFileExist (dist0 </> "setup-config")+#else+ let dist0 = error "no path"+ b = False+#endif+ if b then canonicalizePath dist0+ else findDistPrefOrDefault NoFlag >>= canonicalizePath
cabal/cabal.project view
@@ -2,6 +2,11 @@ packages: cabal-install/ solver-benchmarks/ tests: True +packages: Cabal/Cabal-QuickCheck/+packages: Cabal/Cabal-tree-diff/+packages: Cabal/Cabal-described+packages: cabal-benchmarks/+ -- Uncomment to allow picking up extra local unpacked deps: --optional-packages: */
+ cabal/cabal.project.buildinfo view
@@ -0,0 +1,10 @@+packages: Cabal/+packages: Cabal/Cabal-described+packages: buildinfo-reference-generator/+tests: False+optimization: False+with-compiler: ghc-8.8.3++-- avoiding extra dependencies+constraints: rere -rere-cfg+constraints: these -assoc
+ cabal/cabal.project.release view
@@ -0,0 +1,11 @@+packages: Cabal/+packages: cabal-install/+tests: False+benchmarks: False+optimizations: True++package Cabal+ ghc-options: -fexpose-all-unfoldings -fspecialise-aggressively++package parsec+ ghc-options: -fexpose-all-unfoldings
cabal/cabal.project.validate view
@@ -1,4 +1,13 @@-packages: Cabal/ cabal-testsuite/ cabal-install/+packages: Cabal/ cabal-testsuite/ cabal-install/ solver-benchmarks/+tests: True++packages: Cabal/Cabal-QuickCheck/+packages: Cabal/Cabal-tree-diff+packages: Cabal/Cabal-described++-- avoiding extra dependencies+constraints: rere -rere-cfg+constraints: these -assoc write-ghc-environment-files: never
cabal/cabal.project.validate.libonly view
@@ -1,6 +1,11 @@ packages: Cabal/ cabal-testsuite/+tests: True write-ghc-environment-files: never++-- avoiding extra dependencies+constraints: rere -rere-cfg+constraints: these -assoc package Cabal ghc-options: -Werror -fno-ignore-asserts
+ cabal/cabal.project.weeder view
@@ -0,0 +1,14 @@+-- project file for weeder. Only Cabal and cabal install+-- install weeder with+--+-- cabal install -w ghc-8.8.3 weeder+--++packages: Cabal/+packages: cabal-install/+tests: False++with-compiler: ghc-8.8.3++package *+ ghc-options: -fwrite-ide-info
+ cabal/changelog.d/Cabal-QuickCheck view
@@ -0,0 +1,4 @@+synopsis: Cabal-QuickCheck package with `Arbirary` instances+prs: #6557 #6891+issues: #6882+packages: Cabal
+ cabal/changelog.d/Cabal-tree-diff view
@@ -0,0 +1,3 @@+synopsis: Create Cabal-tree-diff package with `ToExpr` instances+prs: #6789+packages: Cabal
+ cabal/changelog.d/PerCompilerFlavor-functor view
@@ -0,0 +1,3 @@+synopsis: `Cabal.Distribution.Compiler`: add `Traversable` instance for `PerCompilerFlavor`+prs: #6763+packages: Cabal
+ cabal/changelog.d/active-repositories view
@@ -0,0 +1,14 @@+synopsis: Add active-repositories configuration+packages: cabal-install+prs: #6724 #6868+issues: #6819+significance: significant++description: {++New `active-repositories` `cabal.project` fields allows+specifying an order and ways various package repositories are combined.++The active `active-repositories` is saved in `cabal.project.freeze`.++}
+ cabal/changelog.d/added-tests view
@@ -0,0 +1,11 @@+synopsis: Tests additions+prs: #6753 #6759 #6802 #6842 #6872+issues: #6409++description: {++- Add shrinker, so writing big non-generic product shrinkers is easier+- Add `hs-source-dirs: NL .` test-case+- Add public multilib test(s)++}
+ cabal/changelog.d/backported view
@@ -0,0 +1,43 @@+synopsis: Backported to 3.2+packages: Cabal-internal+prs:+ -- solver+ #5918 #6447+ -- buildinfo generator+ #6258+ -- bump version+ #6426+ -- cabal install -z+ #6428+ -- incomplete-uni-patterns+ #6433+ -- packages/optional packages empty+ #6436+ -- file+noindex+ #6448+ -- documentation+ #6450 #6464 #6473 #6546+ -- bounds+ #6455+ -- safe functions+ #6456+ -- Improve few internalErrors in InstallPlan+ #6439+ -- v2-run -z+ #6457+ -- test fixes+ #6463 #6499 #6518+ -- CI+ #6469+ -- show full abi hash+ #6498 #6496 #6476+ -- Create distTempDirectory in withTempEnvFile+ #6501+ -- cabal_macros.h zinza+ -- TODO: check whether it made to 3.2+ -- issue: #6533+ #6502 #6535+ -- disallow spaces around : in dependency+ #6538+ -- pkg-config+ #6540 #6541
+ cabal/changelog.d/build-reports view
@@ -0,0 +1,3 @@+synopsis: Change `BuildReports` parse/pretty to use FieldGrammar framework+prs: #6783+packages: cabal-install
+ cabal/changelog.d/cabal-init view
@@ -0,0 +1,19 @@+synopsis: Various `cabal init` improvements+packages: cabal-install+prs: #6619 #6661 #6641 #6650 #6603 #6632 #6607 #6678 #6690 #6705 #6723 #6676 #6677+issues: #6150 #6675+significance: significant++description: {++- Default to `cabal-version: 2.4`+- `cabal` doesn't force a default license choice anymore+- Licenses are always asked using SPDX expression+- Fix an infinite loop when invalid license was passed on command line+- `Setup.hs` is not written anymore+- Default to --source-dir=src and --application-dir=app+- Add `FileCreators.generateCabalFile` unit tests.+- Default cabal init application-dir to `app`, and source-dir to `src`.+- Default to SPDX.NONE license in cabal init interactive mode.++}
+ cabal/changelog.d/cabal-list view
@@ -0,0 +1,5 @@+synopsis: `cabal list` accepts regular expression+packages: cabal-install+prs: #6618 #6806+issues: #4267 #6683+significance: significant
+ cabal/changelog.d/cabal-project-local-tilde view
@@ -0,0 +1,3 @@+synopsis: Tell users about `cabal.project.local~` in `cabal v2-configure`+prs: #6877+packages: cabal-install
+ cabal/changelog.d/cabal-sdist view
@@ -0,0 +1,32 @@+synopsis: Rework `v2-sdist` command+packages: cabal-install+issues: #6635 #5813 #2940 #6611 #6514+prs: #6454 #6637 #6640 #6660 #6666 #6884 #6916+significance: significant++description: {++`v2-sdist` marks all files as readonly in resulting tarballs.++The #2940 "cabal sdist should touch preprocessed .hs files" issue+is fixed by virtue of not doing any preprocessing anymore.+It's responsibility of packager.++The #6611 "v2-sdist includes a file twice in the tarball " issue+is fixed as we don't consider only one file list,+not two separate executable and ordinary file lists.++The #6514 "unpack doesn't preserve (executable) permissions" issue+is partially resolved, as there shouldn't be executable permissions+in the tar files.++The rationale for above simplification is simple. The only file+Cabal machinery would run is `configure` script. These+are run with explicit `sh` program. For package internal scripts,+maintainers should also use interpreters explicitly as well.+Scripts with shebangs are not executable on Windows.++The `v1-sdist` command is removed, as its functionality is completely+superseded by `v2-sdist`.++}
+ cabal/changelog.d/cabal-spec-3.4 view
@@ -0,0 +1,9 @@+synopsis: Add cabal-version: 3.4+prs: #6663+significance: significant++description: {++See various changes in https://cabal.readthedocs.io/en/latest/file-format-changelog.html#cabal-version-3-4++}
+ cabal/changelog.d/cabal-testsuite view
@@ -0,0 +1,8 @@+synopsis: Improvements to cabal-testsuite framework+prs: #6643++desciption: {++- setupAndCabalTest uses cabal act-as-setup for cabal part++}
+ cabal/changelog.d/cabalInstallVersion view
@@ -0,0 +1,3 @@+synopsis: Refactor cabalInstallVersions, add make doctest-cli+packages: cabal-install+prs: #6720
+ cabal/changelog.d/changelog view
@@ -0,0 +1,3 @@+synopsis: Changelog entries+packages: Cabal-internal+prs: #6634 #6950
+ cabal/changelog.d/ci view
@@ -0,0 +1,24 @@+synopsis: CI tweaks+packages: Cabal-internal+prs:+ #6494+ #6518+ #6559+ #6564+ #6571+ #6577+ #6578+ #6579+ #6585+ #6617+ #6636+ #6709+ #6827+ #6831+ #6900+ #6902+ #6914+ #6946+issues:+ #6500+ #6945
+ cabal/changelog.d/code-organization view
@@ -0,0 +1,16 @@+synopsis: Code organization+prs: #6599 #6642 #6734 #6745 #6746 #6817 #6818 #6821 #6867++description: {++- Split `Distribution.Client.Types` module+- Move cabal-testsuite code into `src/`+- Add `ProjectFlags`+- Add `NixStyleOptions`+- Internal refactorings to install command.+- Make own modules for `InstallMethod` and `OverwritePolicy`+- Make cabal-install compilable with `NoImplicitPrelude`+- Refactor shared `TargetProblem` data types into their own module.+- Template `cabal-install.cabal` using zinza++}
+ cabal/changelog.d/config view
@@ -0,0 +1,2 @@+organization: haskell+repository: cabal
+ cabal/changelog.d/copyright view
@@ -0,0 +1,2 @@+synopsis: Update copyright years to 2020+prs: #6644
+ cabal/changelog.d/dependency view
@@ -0,0 +1,16 @@+synopsis: Dependency type refactorings+packages: Cabal+prs: #6798 #6768 #6895 #6896 #6897 #6898+issues: #5570 #6894+significance: significant++description: {++With additions of (public) sublibraries, `Dependency` type use for multiple needs become painful.+Therefore a new type `PackageVersionConstraint` was added to serve *constraint on package* use-case.+`Dependency` type is *dependency on a library component*, i.e. representing `build-depends` entry.++- Use PackageVersionConstraint more+- Add NonEmptySet and use it in Dependency++}
+ cabal/changelog.d/described view
@@ -0,0 +1,8 @@+synopsis: The grammar of most package description fields is formally documented+prs: #6591 #6593 #6704 #6766 #6778 #6780 #6781 #6791 #6800++description: {++See https://cabal.readthedocs.io/en/latest/buildinfo-fields-reference.html++}
+ cabal/changelog.d/documentation view
@@ -0,0 +1,4 @@+synopsis: Documentation updates and typo-fixes+prs:+ #6613 #6560 #6660 #6668 #6669 #6697 #6761 #6940+ #6504 #6550 #6686 #6928 #6954 #6953 #6951
+ cabal/changelog.d/expose-all-unfoldings view
@@ -0,0 +1,9 @@+synopsis: Add -fexpose-all-unfoldings to parsec and Cabal in release project+packages: cabal-install+prs: #6708++description: {++This makes parser faster with acceptable code-size increase.++}
+ cabal/changelog.d/flag-assignment view
@@ -0,0 +1,3 @@+synopsis: Flag assignment parsing refactorings+prs: #6854 #6858+issues: #6853
+ cabal/changelog.d/ghc-8.12 view
@@ -0,0 +1,18 @@+synopsis: Support GHC-8.12+prs:+ #6735 #6844 #6865 #6848 #6908 #6947+ #6552 #6553 #6563 #6545+issues: #6903 #6904 #6905+significance: significant++description: {++- Support for `-this-package-key` deprecation+- Use process `createPipe`+- Add support for WINIO to Cabal+- Adopt to simplfied subsumption changes++There are no magical `IO = WithCallStack Prelude.IO` alias in Cabal,+as it is hard to get working with GHC-8.12's simplified subsumption.++}
+ cabal/changelog.d/ghci-fix view
@@ -0,0 +1,8 @@+synopsis: Fix ghci being launched before other sources are built.+prs: #6923++description: {++Related to foreign calls to C-sources.++}
+ cabal/changelog.d/help-remove-new-aliases view
@@ -0,0 +1,3 @@+synopsis: Remove new- command from `--help` output (there are v2-)+prs: #6930+packages: cabal-install
+ cabal/changelog.d/index-state view
@@ -0,0 +1,5 @@+synopsis: More rich `index-state` syntax. `v2-freeze` saves `index-state`.+packages: cabal-install+prs: #6596 #6581 #6597 #6591 #6682 #6733+issues: #6728+significance: significant
+ cabal/changelog.d/install-prints-destination view
@@ -0,0 +1,3 @@+synopsis: Installing (copy or symlink) executable message prints destination.+prs: #6590 #6582+packages: cabal-install
+ cabal/changelog.d/install-sha256 view
@@ -0,0 +1,3 @@+synopsis: Check sha256 if `#sha256=...` fragments are given to URIs+packages: cabal-install+prs: #6576
+ cabal/changelog.d/issue-4746 view
@@ -0,0 +1,4 @@+synopsis: all extra-source-files are change-tracked+packages: cabal-install+issues: #4746+prs: #6889
+ cabal/changelog.d/issue-5224 view
@@ -0,0 +1,4 @@+synopsis: `upload --help` now includes `password-command` as a config file option (#5224)+packages: cabal-install+issues: #5224+prs: #6609 #6313 #6680
+ cabal/changelog.d/issue-5555 view
@@ -0,0 +1,4 @@+synopsis: Use PrettyField to format cabal file in `cabal init`+packages: cabal-install+prs: #6718+issues: #5555
+ cabal/changelog.d/issue-5586 view
@@ -0,0 +1,12 @@+synopsis: `source-repository-package` directories aren't local+packages: cabal-install+issues: #5586+prs: #6917 #6915+significance: significant++description: {++Concretely these means that compiled `source-repository-package` entries+used in different projects are stored in the global nix-style store.++}
+ cabal/changelog.d/issue-5973 view
@@ -0,0 +1,14 @@+synopsis: Use default install directory if not specified+packages: cabal-install+prs: #6624+issues: #5973++description: {++Cabal 3.0.0.0 added the --installdir option to specify the location that+binaries should be installed in. Running a cabal user-config update would+populate the config file with the default value, but the cabal install program+would error if it wasn't set. This change uses the default value that would be+written to the config if its unset, and outputs a warning.++}
+ cabal/changelog.d/issue-6083 view
@@ -0,0 +1,23 @@+synopsis: Treat `pkg:sublib` dependency syntax as is in `cabal-version: 3.4`+issues: #6083+prs: #6907 #6893+significance: significant++description: {++In `cabal-version: 3.4` cabal files the dependency definition++```cabal+build-depends: somesublib+```++is not using in-package sublibraries. You have to be explicit and write++```cabal+build-depends: thispkg:somesublib+```++This fixes an issue, where it was impossible to refer to extenral+library, if you had sublibrary of the same name.++}
+ cabal/changelog.d/issue-6210 view
@@ -0,0 +1,4 @@+synopsis: Default to 'NoReports' for remote build reporting+packages: cabal-install+issues: #6210+prs: #6625
+ cabal/changelog.d/issue-6281 view
@@ -0,0 +1,3 @@+synopsis: Add foo:bar syntax to mixins+issues: #6281+prs: #6912
+ cabal/changelog.d/issue-6288 view
@@ -0,0 +1,3 @@+synopsis: default-language field is optional in cabal-version: 3.4+prs: #6926 #6924+issues: #6288
+ cabal/changelog.d/issue-6369 view
@@ -0,0 +1,4 @@+synopsis: Allow cabal v2-install pkgname:exename+packages: cabal-install+prs: #6576+issues: #6369
+ cabal/changelog.d/issue-6393 view
@@ -0,0 +1,4 @@+synopsis: Allow cabal v2-install http://+packages: cabal-install+prs: #6576+issues: #6393
+ cabal/changelog.d/issue-6432 view
@@ -0,0 +1,4 @@+synopsis: Split `KnownRepoType` out of `RepoType`+packages: Cabal+issues: #6432+prs: #6612
+ cabal/changelog.d/issue-6485 view
@@ -0,0 +1,3 @@+synopsis: Include component name in unit-id+issues: #6485+prs: #6547
+ cabal/changelog.d/issue-6565 view
@@ -0,0 +1,13 @@+synopsis: Update GHC environment location+prs: #6822+issues: #6565+packages: cabal-install++description: {++cabal-install currently assumes that the GHC environment files are always located in `$HOME/.ghc/`.+However, GHC itself doesn't query the home directory directly.+Instead, it uses `getAppUserDataDirectory "ghc"` which happens to coincide with `$HOME/.ghc`/ on UNIX systems.+On Windows, however, GHC ends up looking in `%APPDATA%/ghc/`.++}
+ cabal/changelog.d/issue-6575 view
@@ -0,0 +1,4 @@+synopsis: cabal v2-install prints copy/symlink destination+packages: cabal-install+prs: #6582 #6890+issues: #6575
+ cabal/changelog.d/issue-6589 view
@@ -0,0 +1,6 @@+synopsis: Remove `-any` and `-none` syntax for version ranges in cabal-version: 3.4+issues: #6589+prs: #6786++description:+ Use `>=0` (or empty in dependencies) and `<0` respectively.
+ cabal/changelog.d/issue-6610 view
@@ -0,0 +1,11 @@+synopsis: Add pijul to known repository type+issues: #6610+prs: #6684++description: {++Pijul is now explicitly recognized version control system.+However `cabal-install` isn't yet able to use it in+`source-repository-package`.++}
+ cabal/changelog.d/issue-6622 view
@@ -0,0 +1,4 @@+synopsis: Prepend hs-source-dir to match-component, fixes `cabal repl file`+packages: cabal-install+prs: #6623 #6826 #6875+issues: #6622
+ cabal/changelog.d/issue-6691 view
@@ -0,0 +1,13 @@+synopsis: Remove upgrade, uninstall and win32selfupgrade commands+packages: cabal-install+issues: #6691+prs: #6707++description: {++This commands were not implemented or are special purpose.+The removal of `win32selfupgrade` might break self upgrade on windows,+when `cabal-install` tries to rewrite the binary of itself.+This shouldn't be a problem when symlinking is used.++}
+ cabal/changelog.d/issue-6710 view
@@ -0,0 +1,16 @@+synopsis: Rename Flag to CompilerFlag and PackageFlag+packages: Cabal+issues: #6710+prs: #6725++description: {++There was three Flag's. Now they are++- `Flag` (cli parsing)+- `PackageFlag`+- `CompilerFlag`++This allows wild-imports without `hiding (Flag)`.++}
+ cabal/changelog.d/issue-6729 view
@@ -0,0 +1,11 @@+synopsis: Remove local-repo+packages: cabal-install+issues: #6729+prs: #6730++description: {++This functionality was mainly used by removed sandboxes.+`file+noindex` repositories are better variant for local package repositories.++}
+ cabal/changelog.d/issue-6739 view
@@ -0,0 +1,3 @@+synopsis: Change 'optional-packages' default to empty, when cabal.project is mising.+issues: #6739 #4797+prs: #6740
+ cabal/changelog.d/issue-6804 view
@@ -0,0 +1,4 @@+synopsis: v2-update reports new index-state+packages: cabal-install+issues: #6804+prs: #6810
+ cabal/changelog.d/issue-6805 view
@@ -0,0 +1,3 @@+synopsis: Fix rpmvercmp (trailing non-digit characters)+issues: #6805+prs: #6808
+ cabal/changelog.d/issue-6807 view
@@ -0,0 +1,11 @@+synopsis: Add list-bin command+packages: cabal-install+issues: #6807+prs: #6931+significance: significant++description: {++`cabal list-bin executable-component` tells the path to the build artifact.++}
+ cabal/changelog.d/issue-6809 view
@@ -0,0 +1,4 @@+synopsis: Add `-z` / `--ignore-project` flag to `cabal v2-update`+packages: cabal-install+issues: #6809+prs: #6814
+ cabal/changelog.d/issue-6856 view
@@ -0,0 +1,4 @@+synopsis: Adjust message indicating `--lib` is likely desired+packages: cabal-install+issues: #6856+prs: #6857
+ cabal/changelog.d/issue-6869 view
@@ -0,0 +1,4 @@+synopsis: cxx-sources, asm-sources and cmm-sources are change-tracked+packages: cabal-install+issues: #6869+prs: #6870
+ cabal/changelog.d/linux-androideabi view
@@ -0,0 +1,9 @@+synopsis: Accept "linux-androideabi" as an alias for Android for determining buildOS+prs: #6949 #6301+packages: Cabal++description: {++`Cabal` will able to parse `linux-androideabi` from the value of `System.Info.os`.++}
+ cabal/changelog.d/man-command view
@@ -0,0 +1,3 @@+synopsis: Change manpage command to man+packages: cabal-install+prs: #6548
+ cabal/changelog.d/others view
@@ -0,0 +1,10 @@+synopsis: other changes+prs:+ -- Expand elem+ #6556++ -- Add forEachGPD to hackage-tests+ #6598++ -- Add Pretty Component instance+ #6910
+ cabal/changelog.d/parser-benchmark view
@@ -0,0 +1,2 @@+synopsis: Package description parser benchmark+prs: #6594
+ cabal/changelog.d/pr-6878 view
@@ -0,0 +1,3 @@+synopsis: Add `licenceIsFsfLibre`+packages: Cabal+prs: #6878
+ cabal/changelog.d/pr-6929 view
@@ -0,0 +1,2 @@+synopsis: Add `+stderr` modifier to `Verbosity`+prs: #6929
+ cabal/changelog.d/public-libs view
@@ -0,0 +1,2 @@+synopsis: Mark public-libs as experimental feature+prs: #6605
+ cabal/changelog.d/public-libs-solver view
@@ -0,0 +1,13 @@+synopsis: Add support for multiple public libraries to the solver+packages: cabal-install+issues: #6039+prs: #6836 #6812 #6047++description: {++cabal-install can now take into account the presence and visibility of+sublibraries when solving. This also means that, when using cabal-install,+multiple public libraries support is extended to GHCs older than 8.8.+The support is limited to source packages for now.++}
+ cabal/changelog.d/refactor-packagedescription-module view
@@ -0,0 +1,9 @@+synopsis: Refactor Distribution.PackageDescription module+prs: #6855+packages: Cabal++description: {++Now it re-exports a collection of modules, not individual symbols.++}
+ cabal/changelog.d/remove-sandbox view
@@ -0,0 +1,11 @@+synopsis: Remove sandboxes+packages: cabal-install+prs: #6747+issues: #6445+significance: significant++description: {++Sandbox functionality is remove in favour of now default nix-style builds.++}
+ cabal/changelog.d/remove-text view
@@ -0,0 +1,11 @@+synopsis: Remove text type-class+packages: cabal-install+prs: #6764 #6777 #6784 #6785 #6793 #6794++description: {++`Text` type-class was removed from `Cabal`, but it still lived in `cabal-install`.+Now it is finally removed.+`cabal-install` is still using `ReadP` parsers for various things though.++}
+ cabal/changelog.d/rewriteFileLBS view
@@ -0,0 +1,3 @@+synopsis: Add rewriteFileLBS and use it to write setup wrapper+packages: Cabal+prs: #6574
+ cabal/changelog.d/spdx view
@@ -0,0 +1,3 @@+synopsis: Add SPDX License List 3.9+prs: #6662 #6944+issues: #6879
+ cabal/changelog.d/specVersion-type view
@@ -0,0 +1,3 @@+synopsis: Change specVersion to have CabalSpecVersion type+packages: Cabal+prs: #6653
+ cabal/changelog.d/symlinking-windows view
@@ -0,0 +1,11 @@+synopsis: Windows install symlinks+packages: cabal-install+prs: #5684 #6506 #6519++description: {++`cabal-install` will try to infer whether symlinking is supported on Windows,+and make symlinks in `install`. Otherwise it will fallback to copying files.+Either way can be forced with `--install-method`.++}
+ cabal/changelog.d/use-process-jobs view
@@ -0,0 +1,23 @@+synopsis: Use process jobs when spawning subprocesses+prs: #6529 #6536++description: {++Many toolchain tools written for POSIX systems rely on the exec system+call. Unfortunately, it is not possible to implement exec in a+POSIX-compliant manner on Windows. In particular, the semantics of the+exec implementation provided by the widely-used msvcrt C runtime+will cause process's waiting on the exec'ing process to incorrectly+conclude that the process has successfully terminated when in fact it is+still running in another process.++For this reason, the process library exposes the use_process_jobs+flag to use a more strict (although still not POSIX-compliant) mechanism+for tracking process completion.+This is explained in [the Process.hs comment](https://github.com/haskell/process/blob/master/System/Process.hs#L399)++Unfortunately, job support in the process library is currently quite+broken and was only recently fixed. Consequently, we only enable job+object support for process releases >= 1.6.8.++}
+ cabal/changelog.d/utf8 view
@@ -0,0 +1,3 @@+synopsis: Better UTF8 handling, parsed `ShortText` is now valid.+packages: Cabal+prs: #6588
+ cabal/changelog.d/version-range-parser view
@@ -0,0 +1,2 @@+synopsis: More checks in version range parser+prs: #6586
+ cabal/changelog.d/version-type view
@@ -0,0 +1,10 @@+synopsis: Remove `AnyVersion` and `WildcardVersion` constructors from `Version`+packages: Cabal+prs: #6742++description: {++This changes makes `Version` type less "syntactic",+i.e. contains less constructors for semantically same version ranges.++}
+ cabal/changelog.d/versions-exact view
@@ -0,0 +1,2 @@+synopsis: Require cabal-versions `>=1.25` to be exact+prs: #6654
+ cabal/changelog.d/weeder view
@@ -0,0 +1,2 @@+synopsis: Add and use weeder+prs: #6779 #6790
cabal/generics-sop-lens.hs view
@@ -38,7 +38,7 @@ genericLenses p = case gdatatypeInfo p of Newtype _ _ _ -> "-- newtype deriving not implemented" ADT _ _ (Constructor _ :* Nil) -> "-- fieldnameless deriving not implemented"- ADT _ _ (Infix _ _ _ :* Nil) -> "-- infix consturctor deriving not implemented"+ ADT _ _ (Infix _ _ _ :* Nil) -> "-- infix constructor deriving not implemented" ADT _ dn (Record _ fis :* Nil) -> unlines $ concatMap replaceTypes $ hcollapse $ hcmap (Proxy :: Proxy Typeable) derive fis where@@ -57,7 +57,7 @@ genericClassyLenses p = case gdatatypeInfo p of Newtype _ _ _ -> "-- newtype deriving not implemented" ADT _ _ (Constructor _ :* Nil) -> "-- fieldnameless deriving not implemented"- ADT _ _ (Infix _ _ _ :* Nil) -> "-- infix consturctor deriving not implemented"+ ADT _ _ (Infix _ _ _ :* Nil) -> "-- infix constructor deriving not implemented" ADT _ dn (Record _ fis :* Nil) -> unlines $ concatMap replaceTypes $ [[ "class Has" ++ dn ++ " a where"
+ cabal/license-list-data/exceptions-3.9.json view
@@ -0,0 +1,466 @@+{+ "licenseListVersion": "3.9",+ "releaseDate": "2020-05-15",+ "exceptions": [+ {+ "reference": "./GCC-exception-2.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/GCC-exception-2.0.json",+ "referenceNumber": "1",+ "name": "GCC Runtime Library exception 2.0",+ "seeAlso": [+ "https://gcc.gnu.org/git/?p\u003dgcc.git;a\u003dblob;f\u003dgcc/libgcc1.c;h\u003d762f5143fc6eed57b6797c82710f3538aa52b40b;hb\u003dcb143a3ce4fb417c68f5fa2691a1b1b1053dfba9#l10"+ ],+ "licenseExceptionId": "GCC-exception-2.0"+ },+ {+ "reference": "./openvpn-openssl-exception.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/openvpn-openssl-exception.json",+ "referenceNumber": "2",+ "name": "OpenVPN OpenSSL Exception",+ "seeAlso": [+ "http://openvpn.net/index.php/license.html"+ ],+ "licenseExceptionId": "openvpn-openssl-exception"+ },+ {+ "reference": "./Nokia-Qt-exception-1.1.html",+ "isDeprecatedLicenseId": true,+ "detailsUrl": "http://spdx.org/licenses/Nokia-Qt-exception-1.1.json",+ "referenceNumber": "3",+ "name": "Nokia Qt LGPL exception 1.1",+ "seeAlso": [+ "https://www.keepassx.org/dev/projects/keepassx/repository/revisions/b8dfb9cc4d5133e0f09cd7533d15a4f1c19a40f2/entry/LICENSE.NOKIA-LGPL-EXCEPTION"+ ],+ "licenseExceptionId": "Nokia-Qt-exception-1.1"+ },+ {+ "reference": "./GPL-3.0-linking-exception.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/GPL-3.0-linking-exception.json",+ "referenceNumber": "4",+ "name": "GPL-3.0 Linking Exception",+ "seeAlso": [+ "https://www.gnu.org/licenses/gpl-faq.en.html#GPLIncompatibleLibs"+ ],+ "licenseExceptionId": "GPL-3.0-linking-exception"+ },+ {+ "reference": "./Fawkes-Runtime-exception.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Fawkes-Runtime-exception.json",+ "referenceNumber": "5",+ "name": "Fawkes Runtime Exception",+ "seeAlso": [+ "http://www.fawkesrobotics.org/about/license/"+ ],+ "licenseExceptionId": "Fawkes-Runtime-exception"+ },+ {+ "reference": "./u-boot-exception-2.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/u-boot-exception-2.0.json",+ "referenceNumber": "6",+ "name": "U-Boot exception 2.0",+ "seeAlso": [+ "http://git.denx.de/?p\u003du-boot.git;a\u003dblob;f\u003dLicenses/Exceptions"+ ],+ "licenseExceptionId": "u-boot-exception-2.0"+ },+ {+ "reference": "./PS-or-PDF-font-exception-20170817.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/PS-or-PDF-font-exception-20170817.json",+ "referenceNumber": "7",+ "name": "PS/PDF font exception (2017-08-17)",+ "seeAlso": [+ "https://github.com/ArtifexSoftware/urw-base35-fonts/blob/65962e27febc3883a17e651cdb23e783668c996f/LICENSE"+ ],+ "licenseExceptionId": "PS-or-PDF-font-exception-20170817"+ },+ {+ "reference": "./gnu-javamail-exception.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/gnu-javamail-exception.json",+ "referenceNumber": "8",+ "name": "GNU JavaMail exception",+ "seeAlso": [+ "http://www.gnu.org/software/classpathx/javamail/javamail.html"+ ],+ "licenseExceptionId": "gnu-javamail-exception"+ },+ {+ "reference": "./LGPL-3.0-linking-exception.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/LGPL-3.0-linking-exception.json",+ "referenceNumber": "9",+ "name": "LGPL-3.0 Linking Exception",+ "seeAlso": [+ "https://raw.githubusercontent.com/go-xmlpath/xmlpath/v2/LICENSE",+ "https://github.com/goamz/goamz/blob/master/LICENSE",+ "https://github.com/juju/errors/blob/master/LICENSE"+ ],+ "licenseExceptionId": "LGPL-3.0-linking-exception"+ },+ {+ "reference": "./DigiRule-FOSS-exception.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/DigiRule-FOSS-exception.json",+ "referenceNumber": "10",+ "name": "DigiRule FOSS License Exception",+ "seeAlso": [+ "http://www.digirulesolutions.com/drupal/foss"+ ],+ "licenseExceptionId": "DigiRule-FOSS-exception"+ },+ {+ "reference": "./LLVM-exception.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/LLVM-exception.json",+ "referenceNumber": "11",+ "name": "LLVM Exception",+ "seeAlso": [+ "http://llvm.org/foundation/relicensing/LICENSE.txt"+ ],+ "licenseExceptionId": "LLVM-exception"+ },+ {+ "reference": "./Linux-syscall-note.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Linux-syscall-note.json",+ "referenceNumber": "12",+ "name": "Linux Syscall Note",+ "seeAlso": [+ "https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/COPYING"+ ],+ "licenseExceptionId": "Linux-syscall-note"+ },+ {+ "reference": "./GPL-3.0-linking-source-exception.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/GPL-3.0-linking-source-exception.json",+ "referenceNumber": "13",+ "name": "GPL-3.0 Linking Exception (with Corresponding Source)",+ "seeAlso": [+ "https://www.gnu.org/licenses/gpl-faq.en.html#GPLIncompatibleLibs",+ "https://github.com/mirror/wget/blob/master/src/http.c#L20"+ ],+ "licenseExceptionId": "GPL-3.0-linking-source-exception"+ },+ {+ "reference": "./Qwt-exception-1.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Qwt-exception-1.0.json",+ "referenceNumber": "14",+ "name": "Qwt exception 1.0",+ "seeAlso": [+ "http://qwt.sourceforge.net/qwtlicense.html"+ ],+ "licenseExceptionId": "Qwt-exception-1.0"+ },+ {+ "reference": "./389-exception.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/389-exception.json",+ "referenceNumber": "15",+ "name": "389 Directory Server Exception",+ "seeAlso": [+ "http://directory.fedoraproject.org/wiki/GPL_Exception_License_Text"+ ],+ "licenseExceptionId": "389-exception"+ },+ {+ "reference": "./mif-exception.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/mif-exception.json",+ "referenceNumber": "16",+ "name": "Macros and Inline Functions Exception",+ "seeAlso": [+ "http://www.scs.stanford.edu/histar/src/lib/cppsup/exception",+ "http://dev.bertos.org/doxygen/",+ "https://www.threadingbuildingblocks.org/licensing"+ ],+ "licenseExceptionId": "mif-exception"+ },+ {+ "reference": "./eCos-exception-2.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/eCos-exception-2.0.json",+ "referenceNumber": "17",+ "name": "eCos exception 2.0",+ "seeAlso": [+ "http://ecos.sourceware.org/license-overview.html"+ ],+ "licenseExceptionId": "eCos-exception-2.0"+ },+ {+ "reference": "./CLISP-exception-2.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/CLISP-exception-2.0.json",+ "referenceNumber": "18",+ "name": "CLISP exception 2.0",+ "seeAlso": [+ "http://sourceforge.net/p/clisp/clisp/ci/default/tree/COPYRIGHT"+ ],+ "licenseExceptionId": "CLISP-exception-2.0"+ },+ {+ "reference": "./Bison-exception-2.2.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Bison-exception-2.2.json",+ "referenceNumber": "19",+ "name": "Bison exception 2.2",+ "seeAlso": [+ "http://git.savannah.gnu.org/cgit/bison.git/tree/data/yacc.c?id\u003d193d7c7054ba7197b0789e14965b739162319b5e#n141"+ ],+ "licenseExceptionId": "Bison-exception-2.2"+ },+ {+ "reference": "./Libtool-exception.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Libtool-exception.json",+ "referenceNumber": "20",+ "name": "Libtool Exception",+ "seeAlso": [+ "http://git.savannah.gnu.org/cgit/libtool.git/tree/m4/libtool.m4"+ ],+ "licenseExceptionId": "Libtool-exception"+ },+ {+ "reference": "./LZMA-exception.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/LZMA-exception.json",+ "referenceNumber": "21",+ "name": "LZMA exception",+ "seeAlso": [+ "http://nsis.sourceforge.net/Docs/AppendixI.html#I.6"+ ],+ "licenseExceptionId": "LZMA-exception"+ },+ {+ "reference": "./OpenJDK-assembly-exception-1.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/OpenJDK-assembly-exception-1.0.json",+ "referenceNumber": "22",+ "name": "OpenJDK Assembly exception 1.0",+ "seeAlso": [+ "http://openjdk.java.net/legal/assembly-exception.html"+ ],+ "licenseExceptionId": "OpenJDK-assembly-exception-1.0"+ },+ {+ "reference": "./Font-exception-2.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Font-exception-2.0.json",+ "referenceNumber": "23",+ "name": "Font exception 2.0",+ "seeAlso": [+ "http://www.gnu.org/licenses/gpl-faq.html#FontException"+ ],+ "licenseExceptionId": "Font-exception-2.0"+ },+ {+ "reference": "./OCaml-LGPL-linking-exception.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/OCaml-LGPL-linking-exception.json",+ "referenceNumber": "24",+ "name": "OCaml LGPL Linking Exception",+ "seeAlso": [+ "https://caml.inria.fr/ocaml/license.en.html"+ ],+ "licenseExceptionId": "OCaml-LGPL-linking-exception"+ },+ {+ "reference": "./GCC-exception-3.1.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/GCC-exception-3.1.json",+ "referenceNumber": "25",+ "name": "GCC Runtime Library exception 3.1",+ "seeAlso": [+ "http://www.gnu.org/licenses/gcc-exception-3.1.html"+ ],+ "licenseExceptionId": "GCC-exception-3.1"+ },+ {+ "reference": "./Bootloader-exception.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Bootloader-exception.json",+ "referenceNumber": "26",+ "name": "Bootloader Distribution Exception",+ "seeAlso": [+ "https://github.com/pyinstaller/pyinstaller/blob/develop/COPYING.txt"+ ],+ "licenseExceptionId": "Bootloader-exception"+ },+ {+ "reference": "./SHL-2.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/SHL-2.0.json",+ "referenceNumber": "27",+ "name": "Solderpad Hardware License v2.0",+ "seeAlso": [+ "https://solderpad.org/licenses/SHL-2.0/"+ ],+ "licenseExceptionId": "SHL-2.0"+ },+ {+ "reference": "./Classpath-exception-2.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Classpath-exception-2.0.json",+ "referenceNumber": "28",+ "name": "Classpath exception 2.0",+ "seeAlso": [+ "http://www.gnu.org/software/classpath/license.html",+ "https://fedoraproject.org/wiki/Licensing/GPL_Classpath_Exception"+ ],+ "licenseExceptionId": "Classpath-exception-2.0"+ },+ {+ "reference": "./Swift-exception.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Swift-exception.json",+ "referenceNumber": "29",+ "name": "Swift Exception",+ "seeAlso": [+ "https://swift.org/LICENSE.txt",+ "https://github.com/apple/swift-package-manager/blob/7ab2275f447a5eb37497ed63a9340f8a6d1e488b/LICENSE.txt#L205"+ ],+ "licenseExceptionId": "Swift-exception"+ },+ {+ "reference": "./Autoconf-exception-2.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Autoconf-exception-2.0.json",+ "referenceNumber": "30",+ "name": "Autoconf exception 2.0",+ "seeAlso": [+ "http://ac-archive.sourceforge.net/doc/copyright.html",+ "http://ftp.gnu.org/gnu/autoconf/autoconf-2.59.tar.gz"+ ],+ "licenseExceptionId": "Autoconf-exception-2.0"+ },+ {+ "reference": "./FLTK-exception.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/FLTK-exception.json",+ "referenceNumber": "31",+ "name": "FLTK exception",+ "seeAlso": [+ "http://www.fltk.org/COPYING.php"+ ],+ "licenseExceptionId": "FLTK-exception"+ },+ {+ "reference": "./freertos-exception-2.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/freertos-exception-2.0.json",+ "referenceNumber": "32",+ "name": "FreeRTOS Exception 2.0",+ "seeAlso": [+ "https://web.archive.org/web/20060809182744/http://www.freertos.org/a00114.html"+ ],+ "licenseExceptionId": "freertos-exception-2.0"+ },+ {+ "reference": "./Universal-FOSS-exception-1.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Universal-FOSS-exception-1.0.json",+ "referenceNumber": "33",+ "name": "Universal FOSS Exception, Version 1.0",+ "seeAlso": [+ "https://oss.oracle.com/licenses/universal-foss-exception/"+ ],+ "licenseExceptionId": "Universal-FOSS-exception-1.0"+ },+ {+ "reference": "./WxWindows-exception-3.1.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/WxWindows-exception-3.1.json",+ "referenceNumber": "34",+ "name": "WxWindows Library Exception 3.1",+ "seeAlso": [+ "http://www.opensource.org/licenses/WXwindows"+ ],+ "licenseExceptionId": "WxWindows-exception-3.1"+ },+ {+ "reference": "./OCCT-exception-1.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/OCCT-exception-1.0.json",+ "referenceNumber": "35",+ "name": "Open CASCADE Exception 1.0",+ "seeAlso": [+ "http://www.opencascade.com/content/licensing"+ ],+ "licenseExceptionId": "OCCT-exception-1.0"+ },+ {+ "reference": "./Autoconf-exception-3.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Autoconf-exception-3.0.json",+ "referenceNumber": "36",+ "name": "Autoconf exception 3.0",+ "seeAlso": [+ "http://www.gnu.org/licenses/autoconf-exception-3.0.html"+ ],+ "licenseExceptionId": "Autoconf-exception-3.0"+ },+ {+ "reference": "./i2p-gpl-java-exception.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/i2p-gpl-java-exception.json",+ "referenceNumber": "37",+ "name": "i2p GPL+Java Exception",+ "seeAlso": [+ "http://geti2p.net/en/get-involved/develop/licenses#java_exception"+ ],+ "licenseExceptionId": "i2p-gpl-java-exception"+ },+ {+ "reference": "./GPL-CC-1.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/GPL-CC-1.0.json",+ "referenceNumber": "38",+ "name": "GPL Cooperation Commitment 1.0",+ "seeAlso": [+ "https://github.com/gplcc/gplcc/blob/master/Project/COMMITMENT",+ "https://gplcc.github.io/gplcc/Project/README-PROJECT.html"+ ],+ "licenseExceptionId": "GPL-CC-1.0"+ },+ {+ "reference": "./Qt-LGPL-exception-1.1.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Qt-LGPL-exception-1.1.json",+ "referenceNumber": "39",+ "name": "Qt LGPL exception 1.1",+ "seeAlso": [+ "http://code.qt.io/cgit/qt/qtbase.git/tree/LGPL_EXCEPTION.txt"+ ],+ "licenseExceptionId": "Qt-LGPL-exception-1.1"+ },+ {+ "reference": "./SHL-2.1.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/SHL-2.1.json",+ "referenceNumber": "40",+ "name": "Solderpad Hardware License v2.1",+ "seeAlso": [+ "https://solderpad.org/licenses/SHL-2.1/"+ ],+ "licenseExceptionId": "SHL-2.1"+ },+ {+ "reference": "./Qt-GPL-exception-1.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Qt-GPL-exception-1.0.json",+ "referenceNumber": "41",+ "name": "Qt GPL exception 1.0",+ "seeAlso": [+ "http://code.qt.io/cgit/qt/qtbase.git/tree/LICENSE.GPL3-EXCEPT"+ ],+ "licenseExceptionId": "Qt-GPL-exception-1.0"+ }+ ]+}
+ cabal/license-list-data/licenses-3.9.json view
@@ -0,0 +1,5297 @@+{+ "licenseListVersion": "3.9",+ "licenses": [+ {+ "reference": "./0BSD.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/0BSD.json",+ "referenceNumber": "239",+ "name": "BSD Zero Clause License",+ "licenseId": "0BSD",+ "seeAlso": [+ "http://landley.net/toybox/license.html"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./AAL.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/AAL.json",+ "referenceNumber": "60",+ "name": "Attribution Assurance License",+ "licenseId": "AAL",+ "seeAlso": [+ "https://opensource.org/licenses/attribution"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./ADSL.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/ADSL.json",+ "referenceNumber": "217",+ "name": "Amazon Digital Services License",+ "licenseId": "ADSL",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing/AmazonDigitalServicesLicense"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./AFL-1.1.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/AFL-1.1.json",+ "referenceNumber": "28",+ "name": "Academic Free License v1.1",+ "licenseId": "AFL-1.1",+ "seeAlso": [+ "http://opensource.linux-mirror.org/licenses/afl-1.1.txt",+ "http://wayback.archive.org/web/20021004124254/http://www.opensource.org/licenses/academic.php"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./AFL-1.2.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/AFL-1.2.json",+ "referenceNumber": "222",+ "name": "Academic Free License v1.2",+ "licenseId": "AFL-1.2",+ "seeAlso": [+ "http://opensource.linux-mirror.org/licenses/afl-1.2.txt",+ "http://wayback.archive.org/web/20021204204652/http://www.opensource.org/licenses/academic.php"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./AFL-2.0.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/AFL-2.0.json",+ "referenceNumber": "341",+ "name": "Academic Free License v2.0",+ "licenseId": "AFL-2.0",+ "seeAlso": [+ "http://wayback.archive.org/web/20060924134533/http://www.opensource.org/licenses/afl-2.0.txt"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./AFL-2.1.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/AFL-2.1.json",+ "referenceNumber": "249",+ "name": "Academic Free License v2.1",+ "licenseId": "AFL-2.1",+ "seeAlso": [+ "http://opensource.linux-mirror.org/licenses/afl-2.1.txt"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./AFL-3.0.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/AFL-3.0.json",+ "referenceNumber": "361",+ "name": "Academic Free License v3.0",+ "licenseId": "AFL-3.0",+ "seeAlso": [+ "http://www.rosenlaw.com/AFL3.0.htm",+ "https://opensource.org/licenses/afl-3.0"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./AGPL-1.0.html",+ "isDeprecatedLicenseId": true,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/AGPL-1.0.json",+ "referenceNumber": "175",+ "name": "Affero General Public License v1.0",+ "licenseId": "AGPL-1.0",+ "seeAlso": [+ "http://www.affero.org/oagpl.html"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./AGPL-1.0-only.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/AGPL-1.0-only.json",+ "referenceNumber": "71",+ "name": "Affero General Public License v1.0 only",+ "licenseId": "AGPL-1.0-only",+ "seeAlso": [+ "http://www.affero.org/oagpl.html"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./AGPL-1.0-or-later.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/AGPL-1.0-or-later.json",+ "referenceNumber": "168",+ "name": "Affero General Public License v1.0 or later",+ "licenseId": "AGPL-1.0-or-later",+ "seeAlso": [+ "http://www.affero.org/oagpl.html"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./AGPL-3.0.html",+ "isDeprecatedLicenseId": true,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/AGPL-3.0.json",+ "referenceNumber": "148",+ "name": "GNU Affero General Public License v3.0",+ "licenseId": "AGPL-3.0",+ "seeAlso": [+ "https://www.gnu.org/licenses/agpl.txt",+ "https://opensource.org/licenses/AGPL-3.0"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./AGPL-3.0-only.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/AGPL-3.0-only.json",+ "referenceNumber": "298",+ "name": "GNU Affero General Public License v3.0 only",+ "licenseId": "AGPL-3.0-only",+ "seeAlso": [+ "https://www.gnu.org/licenses/agpl.txt",+ "https://opensource.org/licenses/AGPL-3.0"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./AGPL-3.0-or-later.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/AGPL-3.0-or-later.json",+ "referenceNumber": "160",+ "name": "GNU Affero General Public License v3.0 or later",+ "licenseId": "AGPL-3.0-or-later",+ "seeAlso": [+ "https://www.gnu.org/licenses/agpl.txt",+ "https://opensource.org/licenses/AGPL-3.0"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./AMDPLPA.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/AMDPLPA.json",+ "referenceNumber": "133",+ "name": "AMD\u0027s plpa_map.c License",+ "licenseId": "AMDPLPA",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing/AMD_plpa_map_License"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./AML.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/AML.json",+ "referenceNumber": "157",+ "name": "Apple MIT License",+ "licenseId": "AML",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing/Apple_MIT_License"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./AMPAS.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/AMPAS.json",+ "referenceNumber": "136",+ "name": "Academy of Motion Picture Arts and Sciences BSD",+ "licenseId": "AMPAS",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing/BSD#AMPASBSD"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./ANTLR-PD.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/ANTLR-PD.json",+ "referenceNumber": "44",+ "name": "ANTLR Software Rights Notice",+ "licenseId": "ANTLR-PD",+ "seeAlso": [+ "http://www.antlr2.org/license.html"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./APAFML.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/APAFML.json",+ "referenceNumber": "248",+ "name": "Adobe Postscript AFM License",+ "licenseId": "APAFML",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing/AdobePostscriptAFM"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./APL-1.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/APL-1.0.json",+ "referenceNumber": "278",+ "name": "Adaptive Public License 1.0",+ "licenseId": "APL-1.0",+ "seeAlso": [+ "https://opensource.org/licenses/APL-1.0"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./APSL-1.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/APSL-1.0.json",+ "referenceNumber": "387",+ "name": "Apple Public Source License 1.0",+ "licenseId": "APSL-1.0",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing/Apple_Public_Source_License_1.0"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./APSL-1.1.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/APSL-1.1.json",+ "referenceNumber": "338",+ "name": "Apple Public Source License 1.1",+ "licenseId": "APSL-1.1",+ "seeAlso": [+ "http://www.opensource.apple.com/source/IOSerialFamily/IOSerialFamily-7/APPLE_LICENSE"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./APSL-1.2.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/APSL-1.2.json",+ "referenceNumber": "201",+ "name": "Apple Public Source License 1.2",+ "licenseId": "APSL-1.2",+ "seeAlso": [+ "http://www.samurajdata.se/opensource/mirror/licenses/apsl.php"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./APSL-2.0.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/APSL-2.0.json",+ "referenceNumber": "141",+ "name": "Apple Public Source License 2.0",+ "licenseId": "APSL-2.0",+ "seeAlso": [+ "http://www.opensource.apple.com/license/apsl/"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./Abstyles.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Abstyles.json",+ "referenceNumber": "75",+ "name": "Abstyles License",+ "licenseId": "Abstyles",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing/Abstyles"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./Adobe-2006.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Adobe-2006.json",+ "referenceNumber": "310",+ "name": "Adobe Systems Incorporated Source Code License Agreement",+ "licenseId": "Adobe-2006",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing/AdobeLicense"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./Adobe-Glyph.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Adobe-Glyph.json",+ "referenceNumber": "343",+ "name": "Adobe Glyph List License",+ "licenseId": "Adobe-Glyph",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing/MIT#AdobeGlyph"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./Afmparse.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Afmparse.json",+ "referenceNumber": "332",+ "name": "Afmparse License",+ "licenseId": "Afmparse",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing/Afmparse"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./Aladdin.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Aladdin.json",+ "referenceNumber": "315",+ "name": "Aladdin Free Public License",+ "licenseId": "Aladdin",+ "seeAlso": [+ "http://pages.cs.wisc.edu/~ghost/doc/AFPL/6.01/Public.htm"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./Apache-1.0.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/Apache-1.0.json",+ "referenceNumber": "32",+ "name": "Apache License 1.0",+ "licenseId": "Apache-1.0",+ "seeAlso": [+ "http://www.apache.org/licenses/LICENSE-1.0"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./Apache-1.1.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/Apache-1.1.json",+ "referenceNumber": "274",+ "name": "Apache License 1.1",+ "licenseId": "Apache-1.1",+ "seeAlso": [+ "http://apache.org/licenses/LICENSE-1.1",+ "https://opensource.org/licenses/Apache-1.1"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./Apache-2.0.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/Apache-2.0.json",+ "referenceNumber": "366",+ "name": "Apache License 2.0",+ "licenseId": "Apache-2.0",+ "seeAlso": [+ "http://www.apache.org/licenses/LICENSE-2.0",+ "https://opensource.org/licenses/Apache-2.0"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./Artistic-1.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Artistic-1.0.json",+ "referenceNumber": "273",+ "name": "Artistic License 1.0",+ "licenseId": "Artistic-1.0",+ "seeAlso": [+ "https://opensource.org/licenses/Artistic-1.0"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./Artistic-1.0-Perl.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Artistic-1.0-Perl.json",+ "referenceNumber": "306",+ "name": "Artistic License 1.0 (Perl)",+ "licenseId": "Artistic-1.0-Perl",+ "seeAlso": [+ "http://dev.perl.org/licenses/artistic.html"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./Artistic-1.0-cl8.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Artistic-1.0-cl8.json",+ "referenceNumber": "229",+ "name": "Artistic License 1.0 w/clause 8",+ "licenseId": "Artistic-1.0-cl8",+ "seeAlso": [+ "https://opensource.org/licenses/Artistic-1.0"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./Artistic-2.0.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/Artistic-2.0.json",+ "referenceNumber": "78",+ "name": "Artistic License 2.0",+ "licenseId": "Artistic-2.0",+ "seeAlso": [+ "http://www.perlfoundation.org/artistic_license_2_0",+ "https://opensource.org/licenses/artistic-license-2.0"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./BSD-1-Clause.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/BSD-1-Clause.json",+ "referenceNumber": "389",+ "name": "BSD 1-Clause License",+ "licenseId": "BSD-1-Clause",+ "seeAlso": [+ "https://svnweb.freebsd.org/base/head/include/ifaddrs.h?revision\u003d326823"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./BSD-2-Clause.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/BSD-2-Clause.json",+ "referenceNumber": "307",+ "name": "BSD 2-Clause \"Simplified\" License",+ "licenseId": "BSD-2-Clause",+ "seeAlso": [+ "https://opensource.org/licenses/BSD-2-Clause"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./BSD-2-Clause-FreeBSD.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/BSD-2-Clause-FreeBSD.json",+ "referenceNumber": "281",+ "name": "BSD 2-Clause FreeBSD License",+ "licenseId": "BSD-2-Clause-FreeBSD",+ "seeAlso": [+ "http://www.freebsd.org/copyright/freebsd-license.html"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./BSD-2-Clause-NetBSD.html",+ "isDeprecatedLicenseId": true,+ "detailsUrl": "http://spdx.org/licenses/BSD-2-Clause-NetBSD.json",+ "referenceNumber": "186",+ "name": "BSD 2-Clause NetBSD License",+ "licenseId": "BSD-2-Clause-NetBSD",+ "seeAlso": [+ "http://www.netbsd.org/about/redistribution.html#default"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./BSD-2-Clause-Patent.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/BSD-2-Clause-Patent.json",+ "referenceNumber": "362",+ "name": "BSD-2-Clause Plus Patent License",+ "licenseId": "BSD-2-Clause-Patent",+ "seeAlso": [+ "https://opensource.org/licenses/BSDplusPatent"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./BSD-3-Clause.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/BSD-3-Clause.json",+ "referenceNumber": "202",+ "name": "BSD 3-Clause \"New\" or \"Revised\" License",+ "licenseId": "BSD-3-Clause",+ "seeAlso": [+ "https://opensource.org/licenses/BSD-3-Clause"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./BSD-3-Clause-Attribution.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/BSD-3-Clause-Attribution.json",+ "referenceNumber": "39",+ "name": "BSD with attribution",+ "licenseId": "BSD-3-Clause-Attribution",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing/BSD_with_Attribution"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./BSD-3-Clause-Clear.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/BSD-3-Clause-Clear.json",+ "referenceNumber": "88",+ "name": "BSD 3-Clause Clear License",+ "licenseId": "BSD-3-Clause-Clear",+ "seeAlso": [+ "http://labs.metacarta.com/license-explanation.html#license"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./BSD-3-Clause-LBNL.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/BSD-3-Clause-LBNL.json",+ "referenceNumber": "147",+ "name": "Lawrence Berkeley National Labs BSD variant license",+ "licenseId": "BSD-3-Clause-LBNL",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing/LBNLBSD"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./BSD-3-Clause-No-Nuclear-License.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/BSD-3-Clause-No-Nuclear-License.json",+ "referenceNumber": "62",+ "name": "BSD 3-Clause No Nuclear License",+ "licenseId": "BSD-3-Clause-No-Nuclear-License",+ "seeAlso": [+ "http://download.oracle.com/otn-pub/java/licenses/bsd.txt?AuthParam\u003d1467140197_43d516ce1776bd08a58235a7785be1cc"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./BSD-3-Clause-No-Nuclear-License-2014.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/BSD-3-Clause-No-Nuclear-License-2014.json",+ "referenceNumber": "342",+ "name": "BSD 3-Clause No Nuclear License 2014",+ "licenseId": "BSD-3-Clause-No-Nuclear-License-2014",+ "seeAlso": [+ "https://java.net/projects/javaeetutorial/pages/BerkeleyLicense"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./BSD-3-Clause-No-Nuclear-Warranty.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/BSD-3-Clause-No-Nuclear-Warranty.json",+ "referenceNumber": "117",+ "name": "BSD 3-Clause No Nuclear Warranty",+ "licenseId": "BSD-3-Clause-No-Nuclear-Warranty",+ "seeAlso": [+ "https://jogamp.org/git/?p\u003dgluegen.git;a\u003dblob_plain;f\u003dLICENSE.txt"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./BSD-3-Clause-Open-MPI.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/BSD-3-Clause-Open-MPI.json",+ "referenceNumber": "214",+ "name": "BSD 3-Clause Open MPI variant",+ "licenseId": "BSD-3-Clause-Open-MPI",+ "seeAlso": [+ "https://www.open-mpi.org/community/license.php",+ "http://www.netlib.org/lapack/LICENSE.txt"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./BSD-4-Clause.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/BSD-4-Clause.json",+ "referenceNumber": "69",+ "name": "BSD 4-Clause \"Original\" or \"Old\" License",+ "licenseId": "BSD-4-Clause",+ "seeAlso": [+ "http://directory.fsf.org/wiki/License:BSD_4Clause"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./BSD-4-Clause-UC.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/BSD-4-Clause-UC.json",+ "referenceNumber": "372",+ "name": "BSD-4-Clause (University of California-Specific)",+ "licenseId": "BSD-4-Clause-UC",+ "seeAlso": [+ "http://www.freebsd.org/copyright/license.html"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./BSD-Protection.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/BSD-Protection.json",+ "referenceNumber": "400",+ "name": "BSD Protection License",+ "licenseId": "BSD-Protection",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing/BSD_Protection_License"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./BSD-Source-Code.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/BSD-Source-Code.json",+ "referenceNumber": "169",+ "name": "BSD Source Code Attribution",+ "licenseId": "BSD-Source-Code",+ "seeAlso": [+ "https://github.com/robbiehanson/CocoaHTTPServer/blob/master/LICENSE.txt"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./BSL-1.0.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/BSL-1.0.json",+ "referenceNumber": "295",+ "name": "Boost Software License 1.0",+ "licenseId": "BSL-1.0",+ "seeAlso": [+ "http://www.boost.org/LICENSE_1_0.txt",+ "https://opensource.org/licenses/BSL-1.0"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./Bahyph.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Bahyph.json",+ "referenceNumber": "151",+ "name": "Bahyph License",+ "licenseId": "Bahyph",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing/Bahyph"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./Barr.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Barr.json",+ "referenceNumber": "128",+ "name": "Barr License",+ "licenseId": "Barr",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing/Barr"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./Beerware.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Beerware.json",+ "referenceNumber": "251",+ "name": "Beerware License",+ "licenseId": "Beerware",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing/Beerware",+ "https://people.freebsd.org/~phk/"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./BitTorrent-1.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/BitTorrent-1.0.json",+ "referenceNumber": "207",+ "name": "BitTorrent Open Source License v1.0",+ "licenseId": "BitTorrent-1.0",+ "seeAlso": [+ "http://sources.gentoo.org/cgi-bin/viewvc.cgi/gentoo-x86/licenses/BitTorrent?r1\u003d1.1\u0026r2\u003d1.1.1.1\u0026diff_format\u003ds"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./BitTorrent-1.1.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/BitTorrent-1.1.json",+ "referenceNumber": "188",+ "name": "BitTorrent Open Source License v1.1",+ "licenseId": "BitTorrent-1.1",+ "seeAlso": [+ "http://directory.fsf.org/wiki/License:BitTorrentOSL1.1"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./BlueOak-1.0.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/BlueOak-1.0.0.json",+ "referenceNumber": "211",+ "name": "Blue Oak Model License 1.0.0",+ "licenseId": "BlueOak-1.0.0",+ "seeAlso": [+ "https://blueoakcouncil.org/license/1.0.0"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./Borceux.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Borceux.json",+ "referenceNumber": "305",+ "name": "Borceux license",+ "licenseId": "Borceux",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing/Borceux"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./CAL-1.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/CAL-1.0.json",+ "referenceNumber": "59",+ "name": "Cryptographic Autonomy License 1.0",+ "licenseId": "CAL-1.0",+ "seeAlso": [+ "http://cryptographicautonomylicense.com/license-text.html",+ "https://opensource.org/licenses/CAL-1.0"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./CAL-1.0-Combined-Work-Exception.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/CAL-1.0-Combined-Work-Exception.json",+ "referenceNumber": "80",+ "name": "Cryptographic Autonomy License 1.0 (Combined Work Exception)",+ "licenseId": "CAL-1.0-Combined-Work-Exception",+ "seeAlso": [+ "http://cryptographicautonomylicense.com/license-text.html",+ "https://opensource.org/licenses/CAL-1.0"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./CATOSL-1.1.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/CATOSL-1.1.json",+ "referenceNumber": "234",+ "name": "Computer Associates Trusted Open Source License 1.1",+ "licenseId": "CATOSL-1.1",+ "seeAlso": [+ "https://opensource.org/licenses/CATOSL-1.1"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./CC-BY-1.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/CC-BY-1.0.json",+ "referenceNumber": "23",+ "name": "Creative Commons Attribution 1.0 Generic",+ "licenseId": "CC-BY-1.0",+ "seeAlso": [+ "https://creativecommons.org/licenses/by/1.0/legalcode"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./CC-BY-2.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/CC-BY-2.0.json",+ "referenceNumber": "61",+ "name": "Creative Commons Attribution 2.0 Generic",+ "licenseId": "CC-BY-2.0",+ "seeAlso": [+ "https://creativecommons.org/licenses/by/2.0/legalcode"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./CC-BY-2.5.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/CC-BY-2.5.json",+ "referenceNumber": "187",+ "name": "Creative Commons Attribution 2.5 Generic",+ "licenseId": "CC-BY-2.5",+ "seeAlso": [+ "https://creativecommons.org/licenses/by/2.5/legalcode"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./CC-BY-3.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/CC-BY-3.0.json",+ "referenceNumber": "344",+ "name": "Creative Commons Attribution 3.0 Unported",+ "licenseId": "CC-BY-3.0",+ "seeAlso": [+ "https://creativecommons.org/licenses/by/3.0/legalcode"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./CC-BY-4.0.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/CC-BY-4.0.json",+ "referenceNumber": "218",+ "name": "Creative Commons Attribution 4.0 International",+ "licenseId": "CC-BY-4.0",+ "seeAlso": [+ "https://creativecommons.org/licenses/by/4.0/legalcode"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./CC-BY-NC-1.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-1.0.json",+ "referenceNumber": "231",+ "name": "Creative Commons Attribution Non Commercial 1.0 Generic",+ "licenseId": "CC-BY-NC-1.0",+ "seeAlso": [+ "https://creativecommons.org/licenses/by-nc/1.0/legalcode"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./CC-BY-NC-2.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-2.0.json",+ "referenceNumber": "326",+ "name": "Creative Commons Attribution Non Commercial 2.0 Generic",+ "licenseId": "CC-BY-NC-2.0",+ "seeAlso": [+ "https://creativecommons.org/licenses/by-nc/2.0/legalcode"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./CC-BY-NC-2.5.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-2.5.json",+ "referenceNumber": "398",+ "name": "Creative Commons Attribution Non Commercial 2.5 Generic",+ "licenseId": "CC-BY-NC-2.5",+ "seeAlso": [+ "https://creativecommons.org/licenses/by-nc/2.5/legalcode"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./CC-BY-NC-3.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-3.0.json",+ "referenceNumber": "336",+ "name": "Creative Commons Attribution Non Commercial 3.0 Unported",+ "licenseId": "CC-BY-NC-3.0",+ "seeAlso": [+ "https://creativecommons.org/licenses/by-nc/3.0/legalcode"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./CC-BY-NC-4.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-4.0.json",+ "referenceNumber": "272",+ "name": "Creative Commons Attribution Non Commercial 4.0 International",+ "licenseId": "CC-BY-NC-4.0",+ "seeAlso": [+ "https://creativecommons.org/licenses/by-nc/4.0/legalcode"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./CC-BY-NC-ND-1.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-ND-1.0.json",+ "referenceNumber": "102",+ "name": "Creative Commons Attribution Non Commercial No Derivatives 1.0 Generic",+ "licenseId": "CC-BY-NC-ND-1.0",+ "seeAlso": [+ "https://creativecommons.org/licenses/by-nd-nc/1.0/legalcode"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./CC-BY-NC-ND-2.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-ND-2.0.json",+ "referenceNumber": "138",+ "name": "Creative Commons Attribution Non Commercial No Derivatives 2.0 Generic",+ "licenseId": "CC-BY-NC-ND-2.0",+ "seeAlso": [+ "https://creativecommons.org/licenses/by-nc-nd/2.0/legalcode"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./CC-BY-NC-ND-2.5.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-ND-2.5.json",+ "referenceNumber": "30",+ "name": "Creative Commons Attribution Non Commercial No Derivatives 2.5 Generic",+ "licenseId": "CC-BY-NC-ND-2.5",+ "seeAlso": [+ "https://creativecommons.org/licenses/by-nc-nd/2.5/legalcode"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./CC-BY-NC-ND-3.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-ND-3.0.json",+ "referenceNumber": "41",+ "name": "Creative Commons Attribution Non Commercial No Derivatives 3.0 Unported",+ "licenseId": "CC-BY-NC-ND-3.0",+ "seeAlso": [+ "https://creativecommons.org/licenses/by-nc-nd/3.0/legalcode"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./CC-BY-NC-ND-4.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-ND-4.0.json",+ "referenceNumber": "172",+ "name": "Creative Commons Attribution Non Commercial No Derivatives 4.0 International",+ "licenseId": "CC-BY-NC-ND-4.0",+ "seeAlso": [+ "https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./CC-BY-NC-SA-1.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-SA-1.0.json",+ "referenceNumber": "120",+ "name": "Creative Commons Attribution Non Commercial Share Alike 1.0 Generic",+ "licenseId": "CC-BY-NC-SA-1.0",+ "seeAlso": [+ "https://creativecommons.org/licenses/by-nc-sa/1.0/legalcode"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./CC-BY-NC-SA-2.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-SA-2.0.json",+ "referenceNumber": "411",+ "name": "Creative Commons Attribution Non Commercial Share Alike 2.0 Generic",+ "licenseId": "CC-BY-NC-SA-2.0",+ "seeAlso": [+ "https://creativecommons.org/licenses/by-nc-sa/2.0/legalcode"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./CC-BY-NC-SA-2.5.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-SA-2.5.json",+ "referenceNumber": "215",+ "name": "Creative Commons Attribution Non Commercial Share Alike 2.5 Generic",+ "licenseId": "CC-BY-NC-SA-2.5",+ "seeAlso": [+ "https://creativecommons.org/licenses/by-nc-sa/2.5/legalcode"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./CC-BY-NC-SA-3.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-SA-3.0.json",+ "referenceNumber": "360",+ "name": "Creative Commons Attribution Non Commercial Share Alike 3.0 Unported",+ "licenseId": "CC-BY-NC-SA-3.0",+ "seeAlso": [+ "https://creativecommons.org/licenses/by-nc-sa/3.0/legalcode"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./CC-BY-NC-SA-4.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-SA-4.0.json",+ "referenceNumber": "331",+ "name": "Creative Commons Attribution Non Commercial Share Alike 4.0 International",+ "licenseId": "CC-BY-NC-SA-4.0",+ "seeAlso": [+ "https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./CC-BY-ND-1.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/CC-BY-ND-1.0.json",+ "referenceNumber": "94",+ "name": "Creative Commons Attribution No Derivatives 1.0 Generic",+ "licenseId": "CC-BY-ND-1.0",+ "seeAlso": [+ "https://creativecommons.org/licenses/by-nd/1.0/legalcode"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./CC-BY-ND-2.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/CC-BY-ND-2.0.json",+ "referenceNumber": "46",+ "name": "Creative Commons Attribution No Derivatives 2.0 Generic",+ "licenseId": "CC-BY-ND-2.0",+ "seeAlso": [+ "https://creativecommons.org/licenses/by-nd/2.0/legalcode"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./CC-BY-ND-2.5.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/CC-BY-ND-2.5.json",+ "referenceNumber": "27",+ "name": "Creative Commons Attribution No Derivatives 2.5 Generic",+ "licenseId": "CC-BY-ND-2.5",+ "seeAlso": [+ "https://creativecommons.org/licenses/by-nd/2.5/legalcode"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./CC-BY-ND-3.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/CC-BY-ND-3.0.json",+ "referenceNumber": "284",+ "name": "Creative Commons Attribution No Derivatives 3.0 Unported",+ "licenseId": "CC-BY-ND-3.0",+ "seeAlso": [+ "https://creativecommons.org/licenses/by-nd/3.0/legalcode"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./CC-BY-ND-4.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/CC-BY-ND-4.0.json",+ "referenceNumber": "318",+ "name": "Creative Commons Attribution No Derivatives 4.0 International",+ "licenseId": "CC-BY-ND-4.0",+ "seeAlso": [+ "https://creativecommons.org/licenses/by-nd/4.0/legalcode"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./CC-BY-SA-1.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/CC-BY-SA-1.0.json",+ "referenceNumber": "403",+ "name": "Creative Commons Attribution Share Alike 1.0 Generic",+ "licenseId": "CC-BY-SA-1.0",+ "seeAlso": [+ "https://creativecommons.org/licenses/by-sa/1.0/legalcode"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./CC-BY-SA-2.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/CC-BY-SA-2.0.json",+ "referenceNumber": "367",+ "name": "Creative Commons Attribution Share Alike 2.0 Generic",+ "licenseId": "CC-BY-SA-2.0",+ "seeAlso": [+ "https://creativecommons.org/licenses/by-sa/2.0/legalcode"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./CC-BY-SA-2.5.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/CC-BY-SA-2.5.json",+ "referenceNumber": "203",+ "name": "Creative Commons Attribution Share Alike 2.5 Generic",+ "licenseId": "CC-BY-SA-2.5",+ "seeAlso": [+ "https://creativecommons.org/licenses/by-sa/2.5/legalcode"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./CC-BY-SA-3.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/CC-BY-SA-3.0.json",+ "referenceNumber": "233",+ "name": "Creative Commons Attribution Share Alike 3.0 Unported",+ "licenseId": "CC-BY-SA-3.0",+ "seeAlso": [+ "https://creativecommons.org/licenses/by-sa/3.0/legalcode"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./CC-BY-SA-4.0.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/CC-BY-SA-4.0.json",+ "referenceNumber": "297",+ "name": "Creative Commons Attribution Share Alike 4.0 International",+ "licenseId": "CC-BY-SA-4.0",+ "seeAlso": [+ "https://creativecommons.org/licenses/by-sa/4.0/legalcode"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./CC-PDDC.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/CC-PDDC.json",+ "referenceNumber": "92",+ "name": "Creative Commons Public Domain Dedication and Certification",+ "licenseId": "CC-PDDC",+ "seeAlso": [+ "https://creativecommons.org/licenses/publicdomain/"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./CC0-1.0.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/CC0-1.0.json",+ "referenceNumber": "66",+ "name": "Creative Commons Zero v1.0 Universal",+ "licenseId": "CC0-1.0",+ "seeAlso": [+ "https://creativecommons.org/publicdomain/zero/1.0/legalcode"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./CDDL-1.0.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/CDDL-1.0.json",+ "referenceNumber": "335",+ "name": "Common Development and Distribution License 1.0",+ "licenseId": "CDDL-1.0",+ "seeAlso": [+ "https://opensource.org/licenses/cddl1"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./CDDL-1.1.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/CDDL-1.1.json",+ "referenceNumber": "283",+ "name": "Common Development and Distribution License 1.1",+ "licenseId": "CDDL-1.1",+ "seeAlso": [+ "http://glassfish.java.net/public/CDDL+GPL_1_1.html",+ "https://javaee.github.io/glassfish/LICENSE"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./CDLA-Permissive-1.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/CDLA-Permissive-1.0.json",+ "referenceNumber": "108",+ "name": "Community Data License Agreement Permissive 1.0",+ "licenseId": "CDLA-Permissive-1.0",+ "seeAlso": [+ "https://cdla.io/permissive-1-0"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./CDLA-Sharing-1.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/CDLA-Sharing-1.0.json",+ "referenceNumber": "178",+ "name": "Community Data License Agreement Sharing 1.0",+ "licenseId": "CDLA-Sharing-1.0",+ "seeAlso": [+ "https://cdla.io/sharing-1-0"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./CECILL-1.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/CECILL-1.0.json",+ "referenceNumber": "10",+ "name": "CeCILL Free Software License Agreement v1.0",+ "licenseId": "CECILL-1.0",+ "seeAlso": [+ "http://www.cecill.info/licences/Licence_CeCILL_V1-fr.html"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./CECILL-1.1.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/CECILL-1.1.json",+ "referenceNumber": "135",+ "name": "CeCILL Free Software License Agreement v1.1",+ "licenseId": "CECILL-1.1",+ "seeAlso": [+ "http://www.cecill.info/licences/Licence_CeCILL_V1.1-US.html"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./CECILL-2.0.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/CECILL-2.0.json",+ "referenceNumber": "5",+ "name": "CeCILL Free Software License Agreement v2.0",+ "licenseId": "CECILL-2.0",+ "seeAlso": [+ "http://www.cecill.info/licences/Licence_CeCILL_V2-en.html"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./CECILL-2.1.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/CECILL-2.1.json",+ "referenceNumber": "145",+ "name": "CeCILL Free Software License Agreement v2.1",+ "licenseId": "CECILL-2.1",+ "seeAlso": [+ "http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.html"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./CECILL-B.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/CECILL-B.json",+ "referenceNumber": "93",+ "name": "CeCILL-B Free Software License Agreement",+ "licenseId": "CECILL-B",+ "seeAlso": [+ "http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./CECILL-C.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/CECILL-C.json",+ "referenceNumber": "240",+ "name": "CeCILL-C Free Software License Agreement",+ "licenseId": "CECILL-C",+ "seeAlso": [+ "http://www.cecill.info/licences/Licence_CeCILL-C_V1-en.html"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./CERN-OHL-1.1.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/CERN-OHL-1.1.json",+ "referenceNumber": "123",+ "name": "CERN Open Hardware Licence v1.1",+ "licenseId": "CERN-OHL-1.1",+ "seeAlso": [+ "https://www.ohwr.org/project/licenses/wikis/cern-ohl-v1.1"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./CERN-OHL-1.2.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/CERN-OHL-1.2.json",+ "referenceNumber": "167",+ "name": "CERN Open Hardware Licence v1.2",+ "licenseId": "CERN-OHL-1.2",+ "seeAlso": [+ "https://www.ohwr.org/project/licenses/wikis/cern-ohl-v1.2"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./CERN-OHL-P-2.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/CERN-OHL-P-2.0.json",+ "referenceNumber": "255",+ "name": "CERN Open Hardware Licence Version 2 - Permissive",+ "licenseId": "CERN-OHL-P-2.0",+ "seeAlso": [+ "https://www.ohwr.org/project/cernohl/wikis/Documents/CERN-OHL-version-2"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./CERN-OHL-S-2.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/CERN-OHL-S-2.0.json",+ "referenceNumber": "47",+ "name": "CERN Open Hardware Licence Version 2 - Strongly Reciprocal",+ "licenseId": "CERN-OHL-S-2.0",+ "seeAlso": [+ "https://www.ohwr.org/project/cernohl/wikis/Documents/CERN-OHL-version-2"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./CERN-OHL-W-2.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/CERN-OHL-W-2.0.json",+ "referenceNumber": "267",+ "name": "CERN Open Hardware Licence Version 2 - Weakly Reciprocal",+ "licenseId": "CERN-OHL-W-2.0",+ "seeAlso": [+ "https://www.ohwr.org/project/cernohl/wikis/Documents/CERN-OHL-version-2"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./CNRI-Jython.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/CNRI-Jython.json",+ "referenceNumber": "77",+ "name": "CNRI Jython License",+ "licenseId": "CNRI-Jython",+ "seeAlso": [+ "http://www.jython.org/license.html"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./CNRI-Python.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/CNRI-Python.json",+ "referenceNumber": "96",+ "name": "CNRI Python License",+ "licenseId": "CNRI-Python",+ "seeAlso": [+ "https://opensource.org/licenses/CNRI-Python"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./CNRI-Python-GPL-Compatible.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/CNRI-Python-GPL-Compatible.json",+ "referenceNumber": "348",+ "name": "CNRI Python Open Source GPL Compatible License Agreement",+ "licenseId": "CNRI-Python-GPL-Compatible",+ "seeAlso": [+ "http://www.python.org/download/releases/1.6.1/download_win/"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./CPAL-1.0.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/CPAL-1.0.json",+ "referenceNumber": "285",+ "name": "Common Public Attribution License 1.0",+ "licenseId": "CPAL-1.0",+ "seeAlso": [+ "https://opensource.org/licenses/CPAL-1.0"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./CPL-1.0.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/CPL-1.0.json",+ "referenceNumber": "236",+ "name": "Common Public License 1.0",+ "licenseId": "CPL-1.0",+ "seeAlso": [+ "https://opensource.org/licenses/CPL-1.0"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./CPOL-1.02.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/CPOL-1.02.json",+ "referenceNumber": "230",+ "name": "Code Project Open License 1.02",+ "licenseId": "CPOL-1.02",+ "seeAlso": [+ "http://www.codeproject.com/info/cpol10.aspx"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./CUA-OPL-1.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/CUA-OPL-1.0.json",+ "referenceNumber": "165",+ "name": "CUA Office Public License v1.0",+ "licenseId": "CUA-OPL-1.0",+ "seeAlso": [+ "https://opensource.org/licenses/CUA-OPL-1.0"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./Caldera.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Caldera.json",+ "referenceNumber": "250",+ "name": "Caldera License",+ "licenseId": "Caldera",+ "seeAlso": [+ "http://www.lemis.com/grog/UNIX/ancient-source-all.pdf"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./ClArtistic.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/ClArtistic.json",+ "referenceNumber": "245",+ "name": "Clarified Artistic License",+ "licenseId": "ClArtistic",+ "seeAlso": [+ "http://gianluca.dellavedova.org/2011/01/03/clarified-artistic-license/",+ "http://www.ncftp.com/ncftp/doc/LICENSE.txt"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./Condor-1.1.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/Condor-1.1.json",+ "referenceNumber": "150",+ "name": "Condor Public License v1.1",+ "licenseId": "Condor-1.1",+ "seeAlso": [+ "http://research.cs.wisc.edu/condor/license.html#condor",+ "http://web.archive.org/web/20111123062036/http://research.cs.wisc.edu/condor/license.html#condor"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./Crossword.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Crossword.json",+ "referenceNumber": "101",+ "name": "Crossword License",+ "licenseId": "Crossword",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing/Crossword"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./CrystalStacker.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/CrystalStacker.json",+ "referenceNumber": "38",+ "name": "CrystalStacker License",+ "licenseId": "CrystalStacker",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing:CrystalStacker?rd\u003dLicensing/CrystalStacker"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./Cube.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Cube.json",+ "referenceNumber": "391",+ "name": "Cube License",+ "licenseId": "Cube",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing/Cube"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./D-FSL-1.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/D-FSL-1.0.json",+ "referenceNumber": "358",+ "name": "Deutsche Freie Software Lizenz",+ "licenseId": "D-FSL-1.0",+ "seeAlso": [+ "http://www.dipp.nrw.de/d-fsl/lizenzen/",+ "http://www.dipp.nrw.de/d-fsl/index_html/lizenzen/de/D-FSL-1_0_de.txt",+ "http://www.dipp.nrw.de/d-fsl/index_html/lizenzen/en/D-FSL-1_0_en.txt",+ "https://www.hbz-nrw.de/produkte/open-access/lizenzen/dfsl",+ "https://www.hbz-nrw.de/produkte/open-access/lizenzen/dfsl/deutsche-freie-software-lizenz",+ "https://www.hbz-nrw.de/produkte/open-access/lizenzen/dfsl/german-free-software-license",+ "https://www.hbz-nrw.de/produkte/open-access/lizenzen/dfsl/D-FSL-1_0_de.txt/at_download/file",+ "https://www.hbz-nrw.de/produkte/open-access/lizenzen/dfsl/D-FSL-1_0_en.txt/at_download/file"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./DOC.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/DOC.json",+ "referenceNumber": "275",+ "name": "DOC License",+ "licenseId": "DOC",+ "seeAlso": [+ "http://www.cs.wustl.edu/~schmidt/ACE-copying.html"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./DSDP.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/DSDP.json",+ "referenceNumber": "266",+ "name": "DSDP License",+ "licenseId": "DSDP",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing/DSDP"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./Dotseqn.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Dotseqn.json",+ "referenceNumber": "33",+ "name": "Dotseqn License",+ "licenseId": "Dotseqn",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing/Dotseqn"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./ECL-1.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/ECL-1.0.json",+ "referenceNumber": "418",+ "name": "Educational Community License v1.0",+ "licenseId": "ECL-1.0",+ "seeAlso": [+ "https://opensource.org/licenses/ECL-1.0"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./ECL-2.0.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/ECL-2.0.json",+ "referenceNumber": "1",+ "name": "Educational Community License v2.0",+ "licenseId": "ECL-2.0",+ "seeAlso": [+ "https://opensource.org/licenses/ECL-2.0"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./EFL-1.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/EFL-1.0.json",+ "referenceNumber": "76",+ "name": "Eiffel Forum License v1.0",+ "licenseId": "EFL-1.0",+ "seeAlso": [+ "http://www.eiffel-nice.org/license/forum.txt",+ "https://opensource.org/licenses/EFL-1.0"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./EFL-2.0.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/EFL-2.0.json",+ "referenceNumber": "7",+ "name": "Eiffel Forum License v2.0",+ "licenseId": "EFL-2.0",+ "seeAlso": [+ "http://www.eiffel-nice.org/license/eiffel-forum-license-2.html",+ "https://opensource.org/licenses/EFL-2.0"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./EPL-1.0.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/EPL-1.0.json",+ "referenceNumber": "277",+ "name": "Eclipse Public License 1.0",+ "licenseId": "EPL-1.0",+ "seeAlso": [+ "http://www.eclipse.org/legal/epl-v10.html",+ "https://opensource.org/licenses/EPL-1.0"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./EPL-2.0.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/EPL-2.0.json",+ "referenceNumber": "416",+ "name": "Eclipse Public License 2.0",+ "licenseId": "EPL-2.0",+ "seeAlso": [+ "https://www.eclipse.org/legal/epl-2.0",+ "https://www.opensource.org/licenses/EPL-2.0"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./EUDatagrid.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/EUDatagrid.json",+ "referenceNumber": "263",+ "name": "EU DataGrid Software License",+ "licenseId": "EUDatagrid",+ "seeAlso": [+ "http://eu-datagrid.web.cern.ch/eu-datagrid/license.html",+ "https://opensource.org/licenses/EUDatagrid"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./EUPL-1.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/EUPL-1.0.json",+ "referenceNumber": "98",+ "name": "European Union Public License 1.0",+ "licenseId": "EUPL-1.0",+ "seeAlso": [+ "http://ec.europa.eu/idabc/en/document/7330.html",+ "http://ec.europa.eu/idabc/servlets/Doc027f.pdf?id\u003d31096"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./EUPL-1.1.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/EUPL-1.1.json",+ "referenceNumber": "409",+ "name": "European Union Public License 1.1",+ "licenseId": "EUPL-1.1",+ "seeAlso": [+ "https://joinup.ec.europa.eu/software/page/eupl/licence-eupl",+ "https://joinup.ec.europa.eu/sites/default/files/custom-page/attachment/eupl1.1.-licence-en_0.pdf",+ "https://opensource.org/licenses/EUPL-1.1"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./EUPL-1.2.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/EUPL-1.2.json",+ "referenceNumber": "271",+ "name": "European Union Public License 1.2",+ "licenseId": "EUPL-1.2",+ "seeAlso": [+ "https://joinup.ec.europa.eu/page/eupl-text-11-12",+ "https://joinup.ec.europa.eu/sites/default/files/custom-page/attachment/eupl_v1.2_en.pdf",+ "https://joinup.ec.europa.eu/sites/default/files/inline-files/EUPL%20v1_2%20EN(1).txt",+ "http://eur-lex.europa.eu/legal-content/EN/TXT/HTML/?uri\u003dCELEX:32017D0863",+ "https://opensource.org/licenses/EUPL-1.1"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./Entessa.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Entessa.json",+ "referenceNumber": "386",+ "name": "Entessa Public License v1.0",+ "licenseId": "Entessa",+ "seeAlso": [+ "https://opensource.org/licenses/Entessa"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./ErlPL-1.1.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/ErlPL-1.1.json",+ "referenceNumber": "408",+ "name": "Erlang Public License v1.1",+ "licenseId": "ErlPL-1.1",+ "seeAlso": [+ "http://www.erlang.org/EPLICENSE"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./Eurosym.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Eurosym.json",+ "referenceNumber": "171",+ "name": "Eurosym License",+ "licenseId": "Eurosym",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing/Eurosym"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./FSFAP.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/FSFAP.json",+ "referenceNumber": "394",+ "name": "FSF All Permissive License",+ "licenseId": "FSFAP",+ "seeAlso": [+ "https://www.gnu.org/prep/maintain/html_node/License-Notices-for-Other-Files.html"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./FSFUL.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/FSFUL.json",+ "referenceNumber": "2",+ "name": "FSF Unlimited License",+ "licenseId": "FSFUL",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing/FSF_Unlimited_License"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./FSFULLR.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/FSFULLR.json",+ "referenceNumber": "308",+ "name": "FSF Unlimited License (with License Retention)",+ "licenseId": "FSFULLR",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing/FSF_Unlimited_License#License_Retention_Variant"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./FTL.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/FTL.json",+ "referenceNumber": "374",+ "name": "Freetype Project License",+ "licenseId": "FTL",+ "seeAlso": [+ "http://freetype.fis.uniroma2.it/FTL.TXT",+ "http://git.savannah.gnu.org/cgit/freetype/freetype2.git/tree/docs/FTL.TXT"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./Fair.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Fair.json",+ "referenceNumber": "262",+ "name": "Fair License",+ "licenseId": "Fair",+ "seeAlso": [+ "http://fairlicense.org/",+ "https://opensource.org/licenses/Fair"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./Frameworx-1.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Frameworx-1.0.json",+ "referenceNumber": "373",+ "name": "Frameworx Open License 1.0",+ "licenseId": "Frameworx-1.0",+ "seeAlso": [+ "https://opensource.org/licenses/Frameworx-1.0"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./FreeImage.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/FreeImage.json",+ "referenceNumber": "370",+ "name": "FreeImage Public License v1.0",+ "licenseId": "FreeImage",+ "seeAlso": [+ "http://freeimage.sourceforge.net/freeimage-license.txt"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./GFDL-1.1.html",+ "isDeprecatedLicenseId": true,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/GFDL-1.1.json",+ "referenceNumber": "257",+ "name": "GNU Free Documentation License v1.1",+ "licenseId": "GFDL-1.1",+ "seeAlso": [+ "https://www.gnu.org/licenses/old-licenses/fdl-1.1.txt"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./GFDL-1.1-only.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/GFDL-1.1-only.json",+ "referenceNumber": "104",+ "name": "GNU Free Documentation License v1.1 only",+ "licenseId": "GFDL-1.1-only",+ "seeAlso": [+ "https://www.gnu.org/licenses/old-licenses/fdl-1.1.txt"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./GFDL-1.1-or-later.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/GFDL-1.1-or-later.json",+ "referenceNumber": "124",+ "name": "GNU Free Documentation License v1.1 or later",+ "licenseId": "GFDL-1.1-or-later",+ "seeAlso": [+ "https://www.gnu.org/licenses/old-licenses/fdl-1.1.txt"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./GFDL-1.2.html",+ "isDeprecatedLicenseId": true,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/GFDL-1.2.json",+ "referenceNumber": "197",+ "name": "GNU Free Documentation License v1.2",+ "licenseId": "GFDL-1.2",+ "seeAlso": [+ "https://www.gnu.org/licenses/old-licenses/fdl-1.2.txt"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./GFDL-1.2-only.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/GFDL-1.2-only.json",+ "referenceNumber": "90",+ "name": "GNU Free Documentation License v1.2 only",+ "licenseId": "GFDL-1.2-only",+ "seeAlso": [+ "https://www.gnu.org/licenses/old-licenses/fdl-1.2.txt"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./GFDL-1.2-or-later.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/GFDL-1.2-or-later.json",+ "referenceNumber": "132",+ "name": "GNU Free Documentation License v1.2 or later",+ "licenseId": "GFDL-1.2-or-later",+ "seeAlso": [+ "https://www.gnu.org/licenses/old-licenses/fdl-1.2.txt"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./GFDL-1.3.html",+ "isDeprecatedLicenseId": true,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/GFDL-1.3.json",+ "referenceNumber": "365",+ "name": "GNU Free Documentation License v1.3",+ "licenseId": "GFDL-1.3",+ "seeAlso": [+ "https://www.gnu.org/licenses/fdl-1.3.txt"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./GFDL-1.3-only.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/GFDL-1.3-only.json",+ "referenceNumber": "200",+ "name": "GNU Free Documentation License v1.3 only",+ "licenseId": "GFDL-1.3-only",+ "seeAlso": [+ "https://www.gnu.org/licenses/fdl-1.3.txt"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./GFDL-1.3-or-later.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/GFDL-1.3-or-later.json",+ "referenceNumber": "53",+ "name": "GNU Free Documentation License v1.3 or later",+ "licenseId": "GFDL-1.3-or-later",+ "seeAlso": [+ "https://www.gnu.org/licenses/fdl-1.3.txt"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./GL2PS.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/GL2PS.json",+ "referenceNumber": "314",+ "name": "GL2PS License",+ "licenseId": "GL2PS",+ "seeAlso": [+ "http://www.geuz.org/gl2ps/COPYING.GL2PS"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./GPL-1.0.html",+ "isDeprecatedLicenseId": true,+ "detailsUrl": "http://spdx.org/licenses/GPL-1.0.json",+ "referenceNumber": "330",+ "name": "GNU General Public License v1.0 only",+ "licenseId": "GPL-1.0",+ "seeAlso": [+ "https://www.gnu.org/licenses/old-licenses/gpl-1.0-standalone.html"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./GPL-1.0+.html",+ "isDeprecatedLicenseId": true,+ "detailsUrl": "http://spdx.org/licenses/GPL-1.0+.json",+ "referenceNumber": "205",+ "name": "GNU General Public License v1.0 or later",+ "licenseId": "GPL-1.0+",+ "seeAlso": [+ "https://www.gnu.org/licenses/old-licenses/gpl-1.0-standalone.html"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./GPL-1.0-only.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/GPL-1.0-only.json",+ "referenceNumber": "15",+ "name": "GNU General Public License v1.0 only",+ "licenseId": "GPL-1.0-only",+ "seeAlso": [+ "https://www.gnu.org/licenses/old-licenses/gpl-1.0-standalone.html"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./GPL-1.0-or-later.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/GPL-1.0-or-later.json",+ "referenceNumber": "134",+ "name": "GNU General Public License v1.0 or later",+ "licenseId": "GPL-1.0-or-later",+ "seeAlso": [+ "https://www.gnu.org/licenses/old-licenses/gpl-1.0-standalone.html"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./GPL-2.0.html",+ "isDeprecatedLicenseId": true,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/GPL-2.0.json",+ "referenceNumber": "356",+ "name": "GNU General Public License v2.0 only",+ "licenseId": "GPL-2.0",+ "seeAlso": [+ "https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html",+ "https://opensource.org/licenses/GPL-2.0"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./GPL-2.0+.html",+ "isDeprecatedLicenseId": true,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/GPL-2.0+.json",+ "referenceNumber": "401",+ "name": "GNU General Public License v2.0 or later",+ "licenseId": "GPL-2.0+",+ "seeAlso": [+ "https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html",+ "https://opensource.org/licenses/GPL-2.0"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./GPL-2.0-only.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/GPL-2.0-only.json",+ "referenceNumber": "235",+ "name": "GNU General Public License v2.0 only",+ "licenseId": "GPL-2.0-only",+ "seeAlso": [+ "https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html",+ "https://opensource.org/licenses/GPL-2.0"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./GPL-2.0-or-later.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/GPL-2.0-or-later.json",+ "referenceNumber": "258",+ "name": "GNU General Public License v2.0 or later",+ "licenseId": "GPL-2.0-or-later",+ "seeAlso": [+ "https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html",+ "https://opensource.org/licenses/GPL-2.0"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./GPL-2.0-with-GCC-exception.html",+ "isDeprecatedLicenseId": true,+ "detailsUrl": "http://spdx.org/licenses/GPL-2.0-with-GCC-exception.json",+ "referenceNumber": "340",+ "name": "GNU General Public License v2.0 w/GCC Runtime Library exception",+ "licenseId": "GPL-2.0-with-GCC-exception",+ "seeAlso": [+ "https://gcc.gnu.org/git/?p\u003dgcc.git;a\u003dblob;f\u003dgcc/libgcc1.c;h\u003d762f5143fc6eed57b6797c82710f3538aa52b40b;hb\u003dcb143a3ce4fb417c68f5fa2691a1b1b1053dfba9#l10"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./GPL-2.0-with-autoconf-exception.html",+ "isDeprecatedLicenseId": true,+ "detailsUrl": "http://spdx.org/licenses/GPL-2.0-with-autoconf-exception.json",+ "referenceNumber": "36",+ "name": "GNU General Public License v2.0 w/Autoconf exception",+ "licenseId": "GPL-2.0-with-autoconf-exception",+ "seeAlso": [+ "http://ac-archive.sourceforge.net/doc/copyright.html"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./GPL-2.0-with-bison-exception.html",+ "isDeprecatedLicenseId": true,+ "detailsUrl": "http://spdx.org/licenses/GPL-2.0-with-bison-exception.json",+ "referenceNumber": "371",+ "name": "GNU General Public License v2.0 w/Bison exception",+ "licenseId": "GPL-2.0-with-bison-exception",+ "seeAlso": [+ "http://git.savannah.gnu.org/cgit/bison.git/tree/data/yacc.c?id\u003d193d7c7054ba7197b0789e14965b739162319b5e#n141"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./GPL-2.0-with-classpath-exception.html",+ "isDeprecatedLicenseId": true,+ "detailsUrl": "http://spdx.org/licenses/GPL-2.0-with-classpath-exception.json",+ "referenceNumber": "227",+ "name": "GNU General Public License v2.0 w/Classpath exception",+ "licenseId": "GPL-2.0-with-classpath-exception",+ "seeAlso": [+ "https://www.gnu.org/software/classpath/license.html"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./GPL-2.0-with-font-exception.html",+ "isDeprecatedLicenseId": true,+ "detailsUrl": "http://spdx.org/licenses/GPL-2.0-with-font-exception.json",+ "referenceNumber": "24",+ "name": "GNU General Public License v2.0 w/Font exception",+ "licenseId": "GPL-2.0-with-font-exception",+ "seeAlso": [+ "https://www.gnu.org/licenses/gpl-faq.html#FontException"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./GPL-3.0.html",+ "isDeprecatedLicenseId": true,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/GPL-3.0.json",+ "referenceNumber": "414",+ "name": "GNU General Public License v3.0 only",+ "licenseId": "GPL-3.0",+ "seeAlso": [+ "https://www.gnu.org/licenses/gpl-3.0-standalone.html",+ "https://opensource.org/licenses/GPL-3.0"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./GPL-3.0+.html",+ "isDeprecatedLicenseId": true,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/GPL-3.0+.json",+ "referenceNumber": "152",+ "name": "GNU General Public License v3.0 or later",+ "licenseId": "GPL-3.0+",+ "seeAlso": [+ "https://www.gnu.org/licenses/gpl-3.0-standalone.html",+ "https://opensource.org/licenses/GPL-3.0"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./GPL-3.0-only.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/GPL-3.0-only.json",+ "referenceNumber": "127",+ "name": "GNU General Public License v3.0 only",+ "licenseId": "GPL-3.0-only",+ "seeAlso": [+ "https://www.gnu.org/licenses/gpl-3.0-standalone.html",+ "https://opensource.org/licenses/GPL-3.0"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./GPL-3.0-or-later.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/GPL-3.0-or-later.json",+ "referenceNumber": "399",+ "name": "GNU General Public License v3.0 or later",+ "licenseId": "GPL-3.0-or-later",+ "seeAlso": [+ "https://www.gnu.org/licenses/gpl-3.0-standalone.html",+ "https://opensource.org/licenses/GPL-3.0"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./GPL-3.0-with-GCC-exception.html",+ "isDeprecatedLicenseId": true,+ "detailsUrl": "http://spdx.org/licenses/GPL-3.0-with-GCC-exception.json",+ "referenceNumber": "6",+ "name": "GNU General Public License v3.0 w/GCC Runtime Library exception",+ "licenseId": "GPL-3.0-with-GCC-exception",+ "seeAlso": [+ "https://www.gnu.org/licenses/gcc-exception-3.1.html"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./GPL-3.0-with-autoconf-exception.html",+ "isDeprecatedLicenseId": true,+ "detailsUrl": "http://spdx.org/licenses/GPL-3.0-with-autoconf-exception.json",+ "referenceNumber": "8",+ "name": "GNU General Public License v3.0 w/Autoconf exception",+ "licenseId": "GPL-3.0-with-autoconf-exception",+ "seeAlso": [+ "https://www.gnu.org/licenses/autoconf-exception-3.0.html"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./Giftware.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Giftware.json",+ "referenceNumber": "379",+ "name": "Giftware License",+ "licenseId": "Giftware",+ "seeAlso": [+ "http://liballeg.org/license.html#allegro-4-the-giftware-license"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./Glide.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Glide.json",+ "referenceNumber": "121",+ "name": "3dfx Glide License",+ "licenseId": "Glide",+ "seeAlso": [+ "http://www.users.on.net/~triforce/glidexp/COPYING.txt"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./Glulxe.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Glulxe.json",+ "referenceNumber": "206",+ "name": "Glulxe License",+ "licenseId": "Glulxe",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing/Glulxe"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./HPND.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/HPND.json",+ "referenceNumber": "154",+ "name": "Historical Permission Notice and Disclaimer",+ "licenseId": "HPND",+ "seeAlso": [+ "https://opensource.org/licenses/HPND"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./HPND-sell-variant.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/HPND-sell-variant.json",+ "referenceNumber": "164",+ "name": "Historical Permission Notice and Disclaimer - sell variant",+ "licenseId": "HPND-sell-variant",+ "seeAlso": [+ "https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/sunrpc/auth_gss/gss_generic_token.c?h\u003dv4.19"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./HaskellReport.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/HaskellReport.json",+ "referenceNumber": "212",+ "name": "Haskell Language Report License",+ "licenseId": "HaskellReport",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing/Haskell_Language_Report_License"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./Hippocratic-2.1.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Hippocratic-2.1.json",+ "referenceNumber": "185",+ "name": "Hippocratic License 2.1",+ "licenseId": "Hippocratic-2.1",+ "seeAlso": [+ "https://firstdonoharm.dev/version/2/1/license.html",+ "https://github.com/EthicalSource/hippocratic-license/blob/58c0e646d64ff6fbee275bfe2b9492f914e3ab2a/LICENSE.txt"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./IBM-pibs.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/IBM-pibs.json",+ "referenceNumber": "241",+ "name": "IBM PowerPC Initialization and Boot Software",+ "licenseId": "IBM-pibs",+ "seeAlso": [+ "http://git.denx.de/?p\u003du-boot.git;a\u003dblob;f\u003darch/powerpc/cpu/ppc4xx/miiphy.c;h\u003d297155fdafa064b955e53e9832de93bfb0cfb85b;hb\u003d9fab4bf4cc077c21e43941866f3f2c196f28670d"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./ICU.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/ICU.json",+ "referenceNumber": "180",+ "name": "ICU License",+ "licenseId": "ICU",+ "seeAlso": [+ "http://source.icu-project.org/repos/icu/icu/trunk/license.html"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./IJG.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/IJG.json",+ "referenceNumber": "244",+ "name": "Independent JPEG Group License",+ "licenseId": "IJG",+ "seeAlso": [+ "http://dev.w3.org/cvsweb/Amaya/libjpeg/Attic/README?rev\u003d1.2"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./IPA.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/IPA.json",+ "referenceNumber": "321",+ "name": "IPA Font License",+ "licenseId": "IPA",+ "seeAlso": [+ "https://opensource.org/licenses/IPA"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./IPL-1.0.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/IPL-1.0.json",+ "referenceNumber": "320",+ "name": "IBM Public License v1.0",+ "licenseId": "IPL-1.0",+ "seeAlso": [+ "https://opensource.org/licenses/IPL-1.0"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./ISC.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/ISC.json",+ "referenceNumber": "364",+ "name": "ISC License",+ "licenseId": "ISC",+ "seeAlso": [+ "https://www.isc.org/downloads/software-support-policy/isc-license/",+ "https://opensource.org/licenses/ISC"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./ImageMagick.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/ImageMagick.json",+ "referenceNumber": "337",+ "name": "ImageMagick License",+ "licenseId": "ImageMagick",+ "seeAlso": [+ "http://www.imagemagick.org/script/license.php"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./Imlib2.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/Imlib2.json",+ "referenceNumber": "140",+ "name": "Imlib2 License",+ "licenseId": "Imlib2",+ "seeAlso": [+ "http://trac.enlightenment.org/e/browser/trunk/imlib2/COPYING",+ "https://git.enlightenment.org/legacy/imlib2.git/tree/COPYING"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./Info-ZIP.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Info-ZIP.json",+ "referenceNumber": "294",+ "name": "Info-ZIP License",+ "licenseId": "Info-ZIP",+ "seeAlso": [+ "http://www.info-zip.org/license.html"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./Intel.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/Intel.json",+ "referenceNumber": "29",+ "name": "Intel Open Source License",+ "licenseId": "Intel",+ "seeAlso": [+ "https://opensource.org/licenses/Intel"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./Intel-ACPI.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Intel-ACPI.json",+ "referenceNumber": "243",+ "name": "Intel ACPI Software License Agreement",+ "licenseId": "Intel-ACPI",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing/Intel_ACPI_Software_License_Agreement"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./Interbase-1.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Interbase-1.0.json",+ "referenceNumber": "334",+ "name": "Interbase Public License v1.0",+ "licenseId": "Interbase-1.0",+ "seeAlso": [+ "https://web.archive.org/web/20060319014854/http://info.borland.com/devsupport/interbase/opensource/IPL.html"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./JPNIC.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/JPNIC.json",+ "referenceNumber": "327",+ "name": "Japan Network Information Center License",+ "licenseId": "JPNIC",+ "seeAlso": [+ "https://gitlab.isc.org/isc-projects/bind9/blob/master/COPYRIGHT#L366"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./JSON.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/JSON.json",+ "referenceNumber": "204",+ "name": "JSON License",+ "licenseId": "JSON",+ "seeAlso": [+ "http://www.json.org/license.html"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./JasPer-2.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/JasPer-2.0.json",+ "referenceNumber": "81",+ "name": "JasPer License",+ "licenseId": "JasPer-2.0",+ "seeAlso": [+ "http://www.ece.uvic.ca/~mdadams/jasper/LICENSE"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./LAL-1.2.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/LAL-1.2.json",+ "referenceNumber": "159",+ "name": "Licence Art Libre 1.2",+ "licenseId": "LAL-1.2",+ "seeAlso": [+ "http://artlibre.org/licence/lal/licence-art-libre-12/"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./LAL-1.3.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/LAL-1.3.json",+ "referenceNumber": "368",+ "name": "Licence Art Libre 1.3",+ "licenseId": "LAL-1.3",+ "seeAlso": [+ "https://artlibre.org/"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./LGPL-2.0.html",+ "isDeprecatedLicenseId": true,+ "detailsUrl": "http://spdx.org/licenses/LGPL-2.0.json",+ "referenceNumber": "286",+ "name": "GNU Library General Public License v2 only",+ "licenseId": "LGPL-2.0",+ "seeAlso": [+ "https://www.gnu.org/licenses/old-licenses/lgpl-2.0-standalone.html"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./LGPL-2.0+.html",+ "isDeprecatedLicenseId": true,+ "detailsUrl": "http://spdx.org/licenses/LGPL-2.0+.json",+ "referenceNumber": "144",+ "name": "GNU Library General Public License v2 or later",+ "licenseId": "LGPL-2.0+",+ "seeAlso": [+ "https://www.gnu.org/licenses/old-licenses/lgpl-2.0-standalone.html"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./LGPL-2.0-only.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/LGPL-2.0-only.json",+ "referenceNumber": "339",+ "name": "GNU Library General Public License v2 only",+ "licenseId": "LGPL-2.0-only",+ "seeAlso": [+ "https://www.gnu.org/licenses/old-licenses/lgpl-2.0-standalone.html"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./LGPL-2.0-or-later.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/LGPL-2.0-or-later.json",+ "referenceNumber": "35",+ "name": "GNU Library General Public License v2 or later",+ "licenseId": "LGPL-2.0-or-later",+ "seeAlso": [+ "https://www.gnu.org/licenses/old-licenses/lgpl-2.0-standalone.html"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./LGPL-2.1.html",+ "isDeprecatedLicenseId": true,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/LGPL-2.1.json",+ "referenceNumber": "189",+ "name": "GNU Lesser General Public License v2.1 only",+ "licenseId": "LGPL-2.1",+ "seeAlso": [+ "https://www.gnu.org/licenses/old-licenses/lgpl-2.1-standalone.html",+ "https://opensource.org/licenses/LGPL-2.1"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./LGPL-2.1+.html",+ "isDeprecatedLicenseId": true,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/LGPL-2.1+.json",+ "referenceNumber": "209",+ "name": "GNU Library General Public License v2.1 or later",+ "licenseId": "LGPL-2.1+",+ "seeAlso": [+ "https://www.gnu.org/licenses/old-licenses/lgpl-2.1-standalone.html",+ "https://opensource.org/licenses/LGPL-2.1"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./LGPL-2.1-only.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/LGPL-2.1-only.json",+ "referenceNumber": "143",+ "name": "GNU Lesser General Public License v2.1 only",+ "licenseId": "LGPL-2.1-only",+ "seeAlso": [+ "https://www.gnu.org/licenses/old-licenses/lgpl-2.1-standalone.html",+ "https://opensource.org/licenses/LGPL-2.1"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./LGPL-2.1-or-later.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/LGPL-2.1-or-later.json",+ "referenceNumber": "279",+ "name": "GNU Lesser General Public License v2.1 or later",+ "licenseId": "LGPL-2.1-or-later",+ "seeAlso": [+ "https://www.gnu.org/licenses/old-licenses/lgpl-2.1-standalone.html",+ "https://opensource.org/licenses/LGPL-2.1"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./LGPL-3.0.html",+ "isDeprecatedLicenseId": true,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/LGPL-3.0.json",+ "referenceNumber": "216",+ "name": "GNU Lesser General Public License v3.0 only",+ "licenseId": "LGPL-3.0",+ "seeAlso": [+ "https://www.gnu.org/licenses/lgpl-3.0-standalone.html",+ "https://opensource.org/licenses/LGPL-3.0"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./LGPL-3.0+.html",+ "isDeprecatedLicenseId": true,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/LGPL-3.0+.json",+ "referenceNumber": "228",+ "name": "GNU Lesser General Public License v3.0 or later",+ "licenseId": "LGPL-3.0+",+ "seeAlso": [+ "https://www.gnu.org/licenses/lgpl-3.0-standalone.html",+ "https://opensource.org/licenses/LGPL-3.0"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./LGPL-3.0-only.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/LGPL-3.0-only.json",+ "referenceNumber": "49",+ "name": "GNU Lesser General Public License v3.0 only",+ "licenseId": "LGPL-3.0-only",+ "seeAlso": [+ "https://www.gnu.org/licenses/lgpl-3.0-standalone.html",+ "https://opensource.org/licenses/LGPL-3.0"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./LGPL-3.0-or-later.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/LGPL-3.0-or-later.json",+ "referenceNumber": "328",+ "name": "GNU Lesser General Public License v3.0 or later",+ "licenseId": "LGPL-3.0-or-later",+ "seeAlso": [+ "https://www.gnu.org/licenses/lgpl-3.0-standalone.html",+ "https://opensource.org/licenses/LGPL-3.0"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./LGPLLR.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/LGPLLR.json",+ "referenceNumber": "417",+ "name": "Lesser General Public License For Linguistic Resources",+ "licenseId": "LGPLLR",+ "seeAlso": [+ "http://www-igm.univ-mlv.fr/~unitex/lgpllr.html"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./LPL-1.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/LPL-1.0.json",+ "referenceNumber": "383",+ "name": "Lucent Public License Version 1.0",+ "licenseId": "LPL-1.0",+ "seeAlso": [+ "https://opensource.org/licenses/LPL-1.0"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./LPL-1.02.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/LPL-1.02.json",+ "referenceNumber": "125",+ "name": "Lucent Public License v1.02",+ "licenseId": "LPL-1.02",+ "seeAlso": [+ "http://plan9.bell-labs.com/plan9/license.html",+ "https://opensource.org/licenses/LPL-1.02"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./LPPL-1.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/LPPL-1.0.json",+ "referenceNumber": "86",+ "name": "LaTeX Project Public License v1.0",+ "licenseId": "LPPL-1.0",+ "seeAlso": [+ "http://www.latex-project.org/lppl/lppl-1-0.txt"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./LPPL-1.1.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/LPPL-1.1.json",+ "referenceNumber": "174",+ "name": "LaTeX Project Public License v1.1",+ "licenseId": "LPPL-1.1",+ "seeAlso": [+ "http://www.latex-project.org/lppl/lppl-1-1.txt"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./LPPL-1.2.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/LPPL-1.2.json",+ "referenceNumber": "166",+ "name": "LaTeX Project Public License v1.2",+ "licenseId": "LPPL-1.2",+ "seeAlso": [+ "http://www.latex-project.org/lppl/lppl-1-2.txt"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./LPPL-1.3a.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/LPPL-1.3a.json",+ "referenceNumber": "280",+ "name": "LaTeX Project Public License v1.3a",+ "licenseId": "LPPL-1.3a",+ "seeAlso": [+ "http://www.latex-project.org/lppl/lppl-1-3a.txt"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./LPPL-1.3c.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/LPPL-1.3c.json",+ "referenceNumber": "131",+ "name": "LaTeX Project Public License v1.3c",+ "licenseId": "LPPL-1.3c",+ "seeAlso": [+ "http://www.latex-project.org/lppl/lppl-1-3c.txt",+ "https://opensource.org/licenses/LPPL-1.3c"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./Latex2e.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Latex2e.json",+ "referenceNumber": "37",+ "name": "Latex2e License",+ "licenseId": "Latex2e",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing/Latex2e"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./Leptonica.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Leptonica.json",+ "referenceNumber": "311",+ "name": "Leptonica License",+ "licenseId": "Leptonica",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing/Leptonica"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./LiLiQ-P-1.1.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/LiLiQ-P-1.1.json",+ "referenceNumber": "83",+ "name": "Licence Libre du Québec – Permissive version 1.1",+ "licenseId": "LiLiQ-P-1.1",+ "seeAlso": [+ "https://forge.gouv.qc.ca/licence/fr/liliq-v1-1/",+ "http://opensource.org/licenses/LiLiQ-P-1.1"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./LiLiQ-R-1.1.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/LiLiQ-R-1.1.json",+ "referenceNumber": "301",+ "name": "Licence Libre du Québec – Réciprocité version 1.1",+ "licenseId": "LiLiQ-R-1.1",+ "seeAlso": [+ "https://www.forge.gouv.qc.ca/participez/licence-logicielle/licence-libre-du-quebec-liliq-en-francais/licence-libre-du-quebec-reciprocite-liliq-r-v1-1/",+ "http://opensource.org/licenses/LiLiQ-R-1.1"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./LiLiQ-Rplus-1.1.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/LiLiQ-Rplus-1.1.json",+ "referenceNumber": "346",+ "name": "Licence Libre du Québec – Réciprocité forte version 1.1",+ "licenseId": "LiLiQ-Rplus-1.1",+ "seeAlso": [+ "https://www.forge.gouv.qc.ca/participez/licence-logicielle/licence-libre-du-quebec-liliq-en-francais/licence-libre-du-quebec-reciprocite-forte-liliq-r-v1-1/",+ "http://opensource.org/licenses/LiLiQ-Rplus-1.1"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./Libpng.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Libpng.json",+ "referenceNumber": "388",+ "name": "libpng License",+ "licenseId": "Libpng",+ "seeAlso": [+ "http://www.libpng.org/pub/png/src/libpng-LICENSE.txt"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./Linux-OpenIB.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Linux-OpenIB.json",+ "referenceNumber": "224",+ "name": "Linux Kernel Variant of OpenIB.org license",+ "licenseId": "Linux-OpenIB",+ "seeAlso": [+ "https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/infiniband/core/sa.h"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./MIT.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/MIT.json",+ "referenceNumber": "265",+ "name": "MIT License",+ "licenseId": "MIT",+ "seeAlso": [+ "https://opensource.org/licenses/MIT"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./MIT-0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/MIT-0.json",+ "referenceNumber": "79",+ "name": "MIT No Attribution",+ "licenseId": "MIT-0",+ "seeAlso": [+ "https://github.com/aws/mit-0",+ "https://romanrm.net/mit-zero",+ "https://github.com/awsdocs/aws-cloud9-user-guide/blob/master/LICENSE-SAMPLECODE"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./MIT-CMU.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/MIT-CMU.json",+ "referenceNumber": "355",+ "name": "CMU License",+ "licenseId": "MIT-CMU",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing:MIT?rd\u003dLicensing/MIT#CMU_Style",+ "https://github.com/python-pillow/Pillow/blob/fffb426092c8db24a5f4b6df243a8a3c01fb63cd/LICENSE"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./MIT-advertising.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/MIT-advertising.json",+ "referenceNumber": "199",+ "name": "Enlightenment License (e16)",+ "licenseId": "MIT-advertising",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing/MIT_With_Advertising"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./MIT-enna.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/MIT-enna.json",+ "referenceNumber": "54",+ "name": "enna License",+ "licenseId": "MIT-enna",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing/MIT#enna"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./MIT-feh.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/MIT-feh.json",+ "referenceNumber": "376",+ "name": "feh License",+ "licenseId": "MIT-feh",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing/MIT#feh"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./MITNFA.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/MITNFA.json",+ "referenceNumber": "347",+ "name": "MIT +no-false-attribs license",+ "licenseId": "MITNFA",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing/MITNFA"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./MPL-1.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/MPL-1.0.json",+ "referenceNumber": "247",+ "name": "Mozilla Public License 1.0",+ "licenseId": "MPL-1.0",+ "seeAlso": [+ "http://www.mozilla.org/MPL/MPL-1.0.html",+ "https://opensource.org/licenses/MPL-1.0"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./MPL-1.1.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/MPL-1.1.json",+ "referenceNumber": "407",+ "name": "Mozilla Public License 1.1",+ "licenseId": "MPL-1.1",+ "seeAlso": [+ "http://www.mozilla.org/MPL/MPL-1.1.html",+ "https://opensource.org/licenses/MPL-1.1"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./MPL-2.0.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/MPL-2.0.json",+ "referenceNumber": "126",+ "name": "Mozilla Public License 2.0",+ "licenseId": "MPL-2.0",+ "seeAlso": [+ "http://www.mozilla.org/MPL/2.0/",+ "https://opensource.org/licenses/MPL-2.0"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./MPL-2.0-no-copyleft-exception.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/MPL-2.0-no-copyleft-exception.json",+ "referenceNumber": "190",+ "name": "Mozilla Public License 2.0 (no copyleft exception)",+ "licenseId": "MPL-2.0-no-copyleft-exception",+ "seeAlso": [+ "http://www.mozilla.org/MPL/2.0/",+ "https://opensource.org/licenses/MPL-2.0"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./MS-PL.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/MS-PL.json",+ "referenceNumber": "377",+ "name": "Microsoft Public License",+ "licenseId": "MS-PL",+ "seeAlso": [+ "http://www.microsoft.com/opensource/licenses.mspx",+ "https://opensource.org/licenses/MS-PL"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./MS-RL.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/MS-RL.json",+ "referenceNumber": "4",+ "name": "Microsoft Reciprocal License",+ "licenseId": "MS-RL",+ "seeAlso": [+ "http://www.microsoft.com/opensource/licenses.mspx",+ "https://opensource.org/licenses/MS-RL"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./MTLL.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/MTLL.json",+ "referenceNumber": "106",+ "name": "Matrix Template Library License",+ "licenseId": "MTLL",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing/Matrix_Template_Library_License"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./MakeIndex.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/MakeIndex.json",+ "referenceNumber": "354",+ "name": "MakeIndex License",+ "licenseId": "MakeIndex",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing/MakeIndex"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./MirOS.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/MirOS.json",+ "referenceNumber": "381",+ "name": "The MirOS Licence",+ "licenseId": "MirOS",+ "seeAlso": [+ "https://opensource.org/licenses/MirOS"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./Motosoto.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Motosoto.json",+ "referenceNumber": "12",+ "name": "Motosoto License",+ "licenseId": "Motosoto",+ "seeAlso": [+ "https://opensource.org/licenses/Motosoto"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./MulanPSL-1.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/MulanPSL-1.0.json",+ "referenceNumber": "208",+ "name": "Mulan Permissive Software License, Version 1",+ "licenseId": "MulanPSL-1.0",+ "seeAlso": [+ "https://license.coscl.org.cn/MulanPSL/",+ "https://github.com/yuwenlong/longphp/blob/25dfb70cc2a466dc4bb55ba30901cbce08d164b5/LICENSE"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./MulanPSL-2.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/MulanPSL-2.0.json",+ "referenceNumber": "153",+ "name": "Mulan Permissive Software License, Version 2",+ "licenseId": "MulanPSL-2.0",+ "seeAlso": [+ "https://license.coscl.org.cn/MulanPSL2/"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./Multics.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Multics.json",+ "referenceNumber": "170",+ "name": "Multics License",+ "licenseId": "Multics",+ "seeAlso": [+ "https://opensource.org/licenses/Multics"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./Mup.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Mup.json",+ "referenceNumber": "316",+ "name": "Mup License",+ "licenseId": "Mup",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing/Mup"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./NASA-1.3.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/NASA-1.3.json",+ "referenceNumber": "114",+ "name": "NASA Open Source Agreement 1.3",+ "licenseId": "NASA-1.3",+ "seeAlso": [+ "http://ti.arc.nasa.gov/opensource/nosa/",+ "https://opensource.org/licenses/NASA-1.3"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./NBPL-1.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/NBPL-1.0.json",+ "referenceNumber": "17",+ "name": "Net Boolean Public License v1",+ "licenseId": "NBPL-1.0",+ "seeAlso": [+ "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003d37b4b3f6cc4bf34e1d3dec61e69914b9819d8894"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./NCGL-UK-2.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/NCGL-UK-2.0.json",+ "referenceNumber": "225",+ "name": "Non-Commercial Government Licence",+ "licenseId": "NCGL-UK-2.0",+ "seeAlso": [+ "https://github.com/spdx/license-list-XML/blob/master/src/Apache-2.0.xml"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./NCSA.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/NCSA.json",+ "referenceNumber": "194",+ "name": "University of Illinois/NCSA Open Source License",+ "licenseId": "NCSA",+ "seeAlso": [+ "http://otm.illinois.edu/uiuc_openSource",+ "https://opensource.org/licenses/NCSA"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./NGPL.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/NGPL.json",+ "referenceNumber": "319",+ "name": "Nethack General Public License",+ "licenseId": "NGPL",+ "seeAlso": [+ "https://opensource.org/licenses/NGPL"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./NLOD-1.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/NLOD-1.0.json",+ "referenceNumber": "139",+ "name": "Norwegian Licence for Open Government Data",+ "licenseId": "NLOD-1.0",+ "seeAlso": [+ "http://data.norge.no/nlod/en/1.0"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./NLPL.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/NLPL.json",+ "referenceNumber": "317",+ "name": "No Limit Public License",+ "licenseId": "NLPL",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing/NLPL"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./NOSL.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/NOSL.json",+ "referenceNumber": "392",+ "name": "Netizen Open Source License",+ "licenseId": "NOSL",+ "seeAlso": [+ "http://bits.netizen.com.au/licenses/NOSL/nosl.txt"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./NPL-1.0.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/NPL-1.0.json",+ "referenceNumber": "253",+ "name": "Netscape Public License v1.0",+ "licenseId": "NPL-1.0",+ "seeAlso": [+ "http://www.mozilla.org/MPL/NPL/1.0/"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./NPL-1.1.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/NPL-1.1.json",+ "referenceNumber": "422",+ "name": "Netscape Public License v1.1",+ "licenseId": "NPL-1.1",+ "seeAlso": [+ "http://www.mozilla.org/MPL/NPL/1.1/"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./NPOSL-3.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/NPOSL-3.0.json",+ "referenceNumber": "156",+ "name": "Non-Profit Open Software License 3.0",+ "licenseId": "NPOSL-3.0",+ "seeAlso": [+ "https://opensource.org/licenses/NOSL3.0"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./NRL.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/NRL.json",+ "referenceNumber": "105",+ "name": "NRL License",+ "licenseId": "NRL",+ "seeAlso": [+ "http://web.mit.edu/network/isakmp/nrllicense.html"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./NTP.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/NTP.json",+ "referenceNumber": "268",+ "name": "NTP License",+ "licenseId": "NTP",+ "seeAlso": [+ "https://opensource.org/licenses/NTP"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./NTP-0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/NTP-0.json",+ "referenceNumber": "192",+ "name": "NTP No Attribution",+ "licenseId": "NTP-0",+ "seeAlso": [+ "https://github.com/tytso/e2fsprogs/blob/master/lib/et/et_name.c"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./Naumen.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Naumen.json",+ "referenceNumber": "293",+ "name": "Naumen Public License",+ "licenseId": "Naumen",+ "seeAlso": [+ "https://opensource.org/licenses/Naumen"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./Net-SNMP.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Net-SNMP.json",+ "referenceNumber": "288",+ "name": "Net-SNMP License",+ "licenseId": "Net-SNMP",+ "seeAlso": [+ "http://net-snmp.sourceforge.net/about/license.html"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./NetCDF.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/NetCDF.json",+ "referenceNumber": "219",+ "name": "NetCDF license",+ "licenseId": "NetCDF",+ "seeAlso": [+ "http://www.unidata.ucar.edu/software/netcdf/copyright.html"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./Newsletr.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Newsletr.json",+ "referenceNumber": "369",+ "name": "Newsletr License",+ "licenseId": "Newsletr",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing/Newsletr"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./Nokia.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/Nokia.json",+ "referenceNumber": "130",+ "name": "Nokia Open Source License",+ "licenseId": "Nokia",+ "seeAlso": [+ "https://opensource.org/licenses/nokia"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./Noweb.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Noweb.json",+ "referenceNumber": "73",+ "name": "Noweb License",+ "licenseId": "Noweb",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing/Noweb"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./Nunit.html",+ "isDeprecatedLicenseId": true,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/Nunit.json",+ "referenceNumber": "91",+ "name": "Nunit License",+ "licenseId": "Nunit",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing/Nunit"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./O-UDA-1.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/O-UDA-1.0.json",+ "referenceNumber": "48",+ "name": "Open Use of Data Agreement v1.0",+ "licenseId": "O-UDA-1.0",+ "seeAlso": [+ "https://github.com/microsoft/Open-Use-of-Data-Agreement/blob/v1.0/O-UDA-1.0.md"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./OCCT-PL.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/OCCT-PL.json",+ "referenceNumber": "68",+ "name": "Open CASCADE Technology Public License",+ "licenseId": "OCCT-PL",+ "seeAlso": [+ "http://www.opencascade.com/content/occt-public-license"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./OCLC-2.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/OCLC-2.0.json",+ "referenceNumber": "352",+ "name": "OCLC Research Public License 2.0",+ "licenseId": "OCLC-2.0",+ "seeAlso": [+ "http://www.oclc.org/research/activities/software/license/v2final.htm",+ "https://opensource.org/licenses/OCLC-2.0"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./ODC-By-1.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/ODC-By-1.0.json",+ "referenceNumber": "393",+ "name": "Open Data Commons Attribution License v1.0",+ "licenseId": "ODC-By-1.0",+ "seeAlso": [+ "https://opendatacommons.org/licenses/by/1.0/"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./ODbL-1.0.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/ODbL-1.0.json",+ "referenceNumber": "351",+ "name": "ODC Open Database License v1.0",+ "licenseId": "ODbL-1.0",+ "seeAlso": [+ "http://www.opendatacommons.org/licenses/odbl/1.0/"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./OFL-1.0.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/OFL-1.0.json",+ "referenceNumber": "84",+ "name": "SIL Open Font License 1.0",+ "licenseId": "OFL-1.0",+ "seeAlso": [+ "http://scripts.sil.org/cms/scripts/page.php?item_id\u003dOFL10_web"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./OFL-1.0-RFN.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/OFL-1.0-RFN.json",+ "referenceNumber": "309",+ "name": "SIL Open Font License 1.0 with Reserved Font Name",+ "licenseId": "OFL-1.0-RFN",+ "seeAlso": [+ "http://scripts.sil.org/cms/scripts/page.php?item_id\u003dOFL10_web"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./OFL-1.0-no-RFN.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/OFL-1.0-no-RFN.json",+ "referenceNumber": "74",+ "name": "SIL Open Font License 1.0 with no Reserved Font Name",+ "licenseId": "OFL-1.0-no-RFN",+ "seeAlso": [+ "http://scripts.sil.org/cms/scripts/page.php?item_id\u003dOFL10_web"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./OFL-1.1.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/OFL-1.1.json",+ "referenceNumber": "322",+ "name": "SIL Open Font License 1.1",+ "licenseId": "OFL-1.1",+ "seeAlso": [+ "http://scripts.sil.org/cms/scripts/page.php?item_id\u003dOFL_web",+ "https://opensource.org/licenses/OFL-1.1"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./OFL-1.1-RFN.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/OFL-1.1-RFN.json",+ "referenceNumber": "43",+ "name": "SIL Open Font License 1.1 with Reserved Font Name",+ "licenseId": "OFL-1.1-RFN",+ "seeAlso": [+ "http://scripts.sil.org/cms/scripts/page.php?item_id\u003dOFL_web",+ "https://opensource.org/licenses/OFL-1.1"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./OFL-1.1-no-RFN.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/OFL-1.1-no-RFN.json",+ "referenceNumber": "246",+ "name": "SIL Open Font License 1.1 with no Reserved Font Name",+ "licenseId": "OFL-1.1-no-RFN",+ "seeAlso": [+ "http://scripts.sil.org/cms/scripts/page.php?item_id\u003dOFL_web",+ "https://opensource.org/licenses/OFL-1.1"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./OGC-1.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/OGC-1.0.json",+ "referenceNumber": "378",+ "name": "OGC Software License, Version 1.0",+ "licenseId": "OGC-1.0",+ "seeAlso": [+ "https://www.ogc.org/ogc/software/1.0"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./OGL-Canada-2.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/OGL-Canada-2.0.json",+ "referenceNumber": "357",+ "name": "Open Government Licence - Canada",+ "licenseId": "OGL-Canada-2.0",+ "seeAlso": [+ "https://open.canada.ca/en/open-government-licence-canada"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./OGL-UK-1.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/OGL-UK-1.0.json",+ "referenceNumber": "359",+ "name": "Open Government Licence v1.0",+ "licenseId": "OGL-UK-1.0",+ "seeAlso": [+ "http://www.nationalarchives.gov.uk/doc/open-government-licence/version/1/"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./OGL-UK-2.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/OGL-UK-2.0.json",+ "referenceNumber": "13",+ "name": "Open Government Licence v2.0",+ "licenseId": "OGL-UK-2.0",+ "seeAlso": [+ "http://www.nationalarchives.gov.uk/doc/open-government-licence/version/2/"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./OGL-UK-3.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/OGL-UK-3.0.json",+ "referenceNumber": "21",+ "name": "Open Government Licence v3.0",+ "licenseId": "OGL-UK-3.0",+ "seeAlso": [+ "http://www.nationalarchives.gov.uk/doc/open-government-licence/version/3/"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./OGTSL.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/OGTSL.json",+ "referenceNumber": "26",+ "name": "Open Group Test Suite License",+ "licenseId": "OGTSL",+ "seeAlso": [+ "http://www.opengroup.org/testing/downloads/The_Open_Group_TSL.txt",+ "https://opensource.org/licenses/OGTSL"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./OLDAP-1.1.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/OLDAP-1.1.json",+ "referenceNumber": "57",+ "name": "Open LDAP Public License v1.1",+ "licenseId": "OLDAP-1.1",+ "seeAlso": [+ "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003d806557a5ad59804ef3a44d5abfbe91d706b0791f"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./OLDAP-1.2.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/OLDAP-1.2.json",+ "referenceNumber": "50",+ "name": "Open LDAP Public License v1.2",+ "licenseId": "OLDAP-1.2",+ "seeAlso": [+ "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003d42b0383c50c299977b5893ee695cf4e486fb0dc7"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./OLDAP-1.3.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/OLDAP-1.3.json",+ "referenceNumber": "42",+ "name": "Open LDAP Public License v1.3",+ "licenseId": "OLDAP-1.3",+ "seeAlso": [+ "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003de5f8117f0ce088d0bd7a8e18ddf37eaa40eb09b1"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./OLDAP-1.4.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/OLDAP-1.4.json",+ "referenceNumber": "52",+ "name": "Open LDAP Public License v1.4",+ "licenseId": "OLDAP-1.4",+ "seeAlso": [+ "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003dc9f95c2f3f2ffb5e0ae55fe7388af75547660941"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./OLDAP-2.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/OLDAP-2.0.json",+ "referenceNumber": "25",+ "name": "Open LDAP Public License v2.0 (or possibly 2.0A and 2.0B)",+ "licenseId": "OLDAP-2.0",+ "seeAlso": [+ "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003dcbf50f4e1185a21abd4c0a54d3f4341fe28f36ea"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./OLDAP-2.0.1.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/OLDAP-2.0.1.json",+ "referenceNumber": "290",+ "name": "Open LDAP Public License v2.0.1",+ "licenseId": "OLDAP-2.0.1",+ "seeAlso": [+ "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003db6d68acd14e51ca3aab4428bf26522aa74873f0e"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./OLDAP-2.1.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/OLDAP-2.1.json",+ "referenceNumber": "413",+ "name": "Open LDAP Public License v2.1",+ "licenseId": "OLDAP-2.1",+ "seeAlso": [+ "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003db0d176738e96a0d3b9f85cb51e140a86f21be715"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./OLDAP-2.2.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/OLDAP-2.2.json",+ "referenceNumber": "329",+ "name": "Open LDAP Public License v2.2",+ "licenseId": "OLDAP-2.2",+ "seeAlso": [+ "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003d470b0c18ec67621c85881b2733057fecf4a1acc3"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./OLDAP-2.2.1.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/OLDAP-2.2.1.json",+ "referenceNumber": "396",+ "name": "Open LDAP Public License v2.2.1",+ "licenseId": "OLDAP-2.2.1",+ "seeAlso": [+ "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003d4bc786f34b50aa301be6f5600f58a980070f481e"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./OLDAP-2.2.2.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/OLDAP-2.2.2.json",+ "referenceNumber": "176",+ "name": "Open LDAP Public License 2.2.2",+ "licenseId": "OLDAP-2.2.2",+ "seeAlso": [+ "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003ddf2cc1e21eb7c160695f5b7cffd6296c151ba188"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./OLDAP-2.3.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/OLDAP-2.3.json",+ "referenceNumber": "238",+ "name": "Open LDAP Public License v2.3",+ "licenseId": "OLDAP-2.3",+ "seeAlso": [+ "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003dd32cf54a32d581ab475d23c810b0a7fbaf8d63c3"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./OLDAP-2.4.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/OLDAP-2.4.json",+ "referenceNumber": "119",+ "name": "Open LDAP Public License v2.4",+ "licenseId": "OLDAP-2.4",+ "seeAlso": [+ "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003dcd1284c4a91a8a380d904eee68d1583f989ed386"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./OLDAP-2.5.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/OLDAP-2.5.json",+ "referenceNumber": "112",+ "name": "Open LDAP Public License v2.5",+ "licenseId": "OLDAP-2.5",+ "seeAlso": [+ "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003d6852b9d90022e8593c98205413380536b1b5a7cf"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./OLDAP-2.6.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/OLDAP-2.6.json",+ "referenceNumber": "113",+ "name": "Open LDAP Public License v2.6",+ "licenseId": "OLDAP-2.6",+ "seeAlso": [+ "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003d1cae062821881f41b73012ba816434897abf4205"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./OLDAP-2.7.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/OLDAP-2.7.json",+ "referenceNumber": "237",+ "name": "Open LDAP Public License v2.7",+ "licenseId": "OLDAP-2.7",+ "seeAlso": [+ "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003d47c2415c1df81556eeb39be6cad458ef87c534a2"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./OLDAP-2.8.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/OLDAP-2.8.json",+ "referenceNumber": "261",+ "name": "Open LDAP Public License v2.8",+ "licenseId": "OLDAP-2.8",+ "seeAlso": [+ "http://www.openldap.org/software/release/license.html"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./OML.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/OML.json",+ "referenceNumber": "177",+ "name": "Open Market License",+ "licenseId": "OML",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing/Open_Market_License"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./OPL-1.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/OPL-1.0.json",+ "referenceNumber": "349",+ "name": "Open Public License v1.0",+ "licenseId": "OPL-1.0",+ "seeAlso": [+ "http://old.koalateam.com/jackaroo/OPL_1_0.TXT",+ "https://fedoraproject.org/wiki/Licensing/Open_Public_License"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./OSET-PL-2.1.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/OSET-PL-2.1.json",+ "referenceNumber": "210",+ "name": "OSET Public License version 2.1",+ "licenseId": "OSET-PL-2.1",+ "seeAlso": [+ "http://www.osetfoundation.org/public-license",+ "https://opensource.org/licenses/OPL-2.1"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./OSL-1.0.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/OSL-1.0.json",+ "referenceNumber": "99",+ "name": "Open Software License 1.0",+ "licenseId": "OSL-1.0",+ "seeAlso": [+ "https://opensource.org/licenses/OSL-1.0"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./OSL-1.1.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/OSL-1.1.json",+ "referenceNumber": "184",+ "name": "Open Software License 1.1",+ "licenseId": "OSL-1.1",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing/OSL1.1"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./OSL-2.0.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/OSL-2.0.json",+ "referenceNumber": "375",+ "name": "Open Software License 2.0",+ "licenseId": "OSL-2.0",+ "seeAlso": [+ "http://web.archive.org/web/20041020171434/http://www.rosenlaw.com/osl2.0.html"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./OSL-2.1.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/OSL-2.1.json",+ "referenceNumber": "163",+ "name": "Open Software License 2.1",+ "licenseId": "OSL-2.1",+ "seeAlso": [+ "http://web.archive.org/web/20050212003940/http://www.rosenlaw.com/osl21.htm",+ "https://opensource.org/licenses/OSL-2.1"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./OSL-3.0.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/OSL-3.0.json",+ "referenceNumber": "155",+ "name": "Open Software License 3.0",+ "licenseId": "OSL-3.0",+ "seeAlso": [+ "https://web.archive.org/web/20120101081418/http://rosenlaw.com:80/OSL3.0.htm",+ "https://opensource.org/licenses/OSL-3.0"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./OpenSSL.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/OpenSSL.json",+ "referenceNumber": "87",+ "name": "OpenSSL License",+ "licenseId": "OpenSSL",+ "seeAlso": [+ "http://www.openssl.org/source/license.html"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./PDDL-1.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/PDDL-1.0.json",+ "referenceNumber": "137",+ "name": "ODC Public Domain Dedication \u0026 License 1.0",+ "licenseId": "PDDL-1.0",+ "seeAlso": [+ "http://opendatacommons.org/licenses/pddl/1.0/"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./PHP-3.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/PHP-3.0.json",+ "referenceNumber": "198",+ "name": "PHP License v3.0",+ "licenseId": "PHP-3.0",+ "seeAlso": [+ "http://www.php.net/license/3_0.txt",+ "https://opensource.org/licenses/PHP-3.0"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./PHP-3.01.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/PHP-3.01.json",+ "referenceNumber": "3",+ "name": "PHP License v3.01",+ "licenseId": "PHP-3.01",+ "seeAlso": [+ "http://www.php.net/license/3_01.txt"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./PSF-2.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/PSF-2.0.json",+ "referenceNumber": "95",+ "name": "Python Software Foundation License 2.0",+ "licenseId": "PSF-2.0",+ "seeAlso": [+ "https://opensource.org/licenses/Python-2.0"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./Parity-6.0.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Parity-6.0.0.json",+ "referenceNumber": "419",+ "name": "The Parity Public License 6.0.0",+ "licenseId": "Parity-6.0.0",+ "seeAlso": [+ "https://paritylicense.com/versions/6.0.0.html"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./Parity-7.0.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Parity-7.0.0.json",+ "referenceNumber": "404",+ "name": "The Parity Public License 7.0.0",+ "licenseId": "Parity-7.0.0",+ "seeAlso": [+ "https://paritylicense.com/versions/7.0.0.html"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./Plexus.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Plexus.json",+ "referenceNumber": "162",+ "name": "Plexus Classworlds License",+ "licenseId": "Plexus",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing/Plexus_Classworlds_License"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./PolyForm-Noncommercial-1.0.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/PolyForm-Noncommercial-1.0.0.json",+ "referenceNumber": "292",+ "name": "PolyForm Noncommercial License 1.0.0",+ "licenseId": "PolyForm-Noncommercial-1.0.0",+ "seeAlso": [+ "https://polyformproject.org/licenses/noncommercial/1.0.0"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./PolyForm-Small-Business-1.0.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/PolyForm-Small-Business-1.0.0.json",+ "referenceNumber": "122",+ "name": "PolyForm Small Business License 1.0.0",+ "licenseId": "PolyForm-Small-Business-1.0.0",+ "seeAlso": [+ "https://polyformproject.org/licenses/small-business/1.0.0"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./PostgreSQL.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/PostgreSQL.json",+ "referenceNumber": "11",+ "name": "PostgreSQL License",+ "licenseId": "PostgreSQL",+ "seeAlso": [+ "http://www.postgresql.org/about/licence",+ "https://opensource.org/licenses/PostgreSQL"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./Python-2.0.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/Python-2.0.json",+ "referenceNumber": "406",+ "name": "Python License 2.0",+ "licenseId": "Python-2.0",+ "seeAlso": [+ "https://opensource.org/licenses/Python-2.0"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./QPL-1.0.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/QPL-1.0.json",+ "referenceNumber": "300",+ "name": "Q Public License 1.0",+ "licenseId": "QPL-1.0",+ "seeAlso": [+ "http://doc.qt.nokia.com/3.3/license.html",+ "https://opensource.org/licenses/QPL-1.0"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./Qhull.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Qhull.json",+ "referenceNumber": "129",+ "name": "Qhull License",+ "licenseId": "Qhull",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing/Qhull"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./RHeCos-1.1.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/RHeCos-1.1.json",+ "referenceNumber": "64",+ "name": "Red Hat eCos Public License v1.1",+ "licenseId": "RHeCos-1.1",+ "seeAlso": [+ "http://ecos.sourceware.org/old-license.html"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./RPL-1.1.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/RPL-1.1.json",+ "referenceNumber": "223",+ "name": "Reciprocal Public License 1.1",+ "licenseId": "RPL-1.1",+ "seeAlso": [+ "https://opensource.org/licenses/RPL-1.1"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./RPL-1.5.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/RPL-1.5.json",+ "referenceNumber": "109",+ "name": "Reciprocal Public License 1.5",+ "licenseId": "RPL-1.5",+ "seeAlso": [+ "https://opensource.org/licenses/RPL-1.5"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./RPSL-1.0.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/RPSL-1.0.json",+ "referenceNumber": "55",+ "name": "RealNetworks Public Source License v1.0",+ "licenseId": "RPSL-1.0",+ "seeAlso": [+ "https://helixcommunity.org/content/rpsl",+ "https://opensource.org/licenses/RPSL-1.0"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./RSA-MD.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/RSA-MD.json",+ "referenceNumber": "289",+ "name": "RSA Message-Digest License ",+ "licenseId": "RSA-MD",+ "seeAlso": [+ "http://www.faqs.org/rfcs/rfc1321.html"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./RSCPL.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/RSCPL.json",+ "referenceNumber": "350",+ "name": "Ricoh Source Code Public License",+ "licenseId": "RSCPL",+ "seeAlso": [+ "http://wayback.archive.org/web/20060715140826/http://www.risource.org/RPL/RPL-1.0A.shtml",+ "https://opensource.org/licenses/RSCPL"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./Rdisc.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Rdisc.json",+ "referenceNumber": "333",+ "name": "Rdisc License",+ "licenseId": "Rdisc",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing/Rdisc_License"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./Ruby.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/Ruby.json",+ "referenceNumber": "14",+ "name": "Ruby License",+ "licenseId": "Ruby",+ "seeAlso": [+ "http://www.ruby-lang.org/en/LICENSE.txt"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./SAX-PD.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/SAX-PD.json",+ "referenceNumber": "158",+ "name": "Sax Public Domain Notice",+ "licenseId": "SAX-PD",+ "seeAlso": [+ "http://www.saxproject.org/copying.html"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./SCEA.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/SCEA.json",+ "referenceNumber": "142",+ "name": "SCEA Shared Source License",+ "licenseId": "SCEA",+ "seeAlso": [+ "http://research.scea.com/scea_shared_source_license.html"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./SGI-B-1.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/SGI-B-1.0.json",+ "referenceNumber": "196",+ "name": "SGI Free Software License B v1.0",+ "licenseId": "SGI-B-1.0",+ "seeAlso": [+ "http://oss.sgi.com/projects/FreeB/SGIFreeSWLicB.1.0.html"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./SGI-B-1.1.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/SGI-B-1.1.json",+ "referenceNumber": "299",+ "name": "SGI Free Software License B v1.1",+ "licenseId": "SGI-B-1.1",+ "seeAlso": [+ "http://oss.sgi.com/projects/FreeB/"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./SGI-B-2.0.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/SGI-B-2.0.json",+ "referenceNumber": "31",+ "name": "SGI Free Software License B v2.0",+ "licenseId": "SGI-B-2.0",+ "seeAlso": [+ "http://oss.sgi.com/projects/FreeB/SGIFreeSWLicB.2.0.pdf"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./SHL-0.5.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/SHL-0.5.json",+ "referenceNumber": "51",+ "name": "Solderpad Hardware License v0.5",+ "licenseId": "SHL-0.5",+ "seeAlso": [+ "https://solderpad.org/licenses/SHL-0.5/"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./SHL-0.51.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/SHL-0.51.json",+ "referenceNumber": "291",+ "name": "Solderpad Hardware License, Version 0.51",+ "licenseId": "SHL-0.51",+ "seeAlso": [+ "https://solderpad.org/licenses/SHL-0.51/"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./SISSL.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/SISSL.json",+ "referenceNumber": "82",+ "name": "Sun Industry Standards Source License v1.1",+ "licenseId": "SISSL",+ "seeAlso": [+ "http://www.openoffice.org/licenses/sissl_license.html",+ "https://opensource.org/licenses/SISSL"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./SISSL-1.2.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/SISSL-1.2.json",+ "referenceNumber": "65",+ "name": "Sun Industry Standards Source License v1.2",+ "licenseId": "SISSL-1.2",+ "seeAlso": [+ "http://gridscheduler.sourceforge.net/Gridengine_SISSL_license.html"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./SMLNJ.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/SMLNJ.json",+ "referenceNumber": "226",+ "name": "Standard ML of New Jersey License",+ "licenseId": "SMLNJ",+ "seeAlso": [+ "https://www.smlnj.org/license.html"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./SMPPL.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/SMPPL.json",+ "referenceNumber": "110",+ "name": "Secure Messaging Protocol Public License",+ "licenseId": "SMPPL",+ "seeAlso": [+ "https://github.com/dcblake/SMP/blob/master/Documentation/License.txt"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./SNIA.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/SNIA.json",+ "referenceNumber": "313",+ "name": "SNIA Public License 1.1",+ "licenseId": "SNIA",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing/SNIA_Public_License"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./SPL-1.0.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/SPL-1.0.json",+ "referenceNumber": "256",+ "name": "Sun Public License v1.0",+ "licenseId": "SPL-1.0",+ "seeAlso": [+ "https://opensource.org/licenses/SPL-1.0"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./SSH-OpenSSH.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/SSH-OpenSSH.json",+ "referenceNumber": "22",+ "name": "SSH OpenSSH license",+ "licenseId": "SSH-OpenSSH",+ "seeAlso": [+ "https://github.com/openssh/openssh-portable/blob/1b11ea7c58cd5c59838b5fa574cd456d6047b2d4/LICENCE#L10"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./SSH-short.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/SSH-short.json",+ "referenceNumber": "70",+ "name": "SSH short notice",+ "licenseId": "SSH-short",+ "seeAlso": [+ "https://github.com/openssh/openssh-portable/blob/1b11ea7c58cd5c59838b5fa574cd456d6047b2d4/pathnames.h",+ "http://web.mit.edu/kolya/.f/root/athena.mit.edu/sipb.mit.edu/project/openssh/OldFiles/src/openssh-2.9.9p2/ssh-add.1",+ "https://joinup.ec.europa.eu/svn/lesoll/trunk/italc/lib/src/dsa_key.cpp"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./SSPL-1.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/SSPL-1.0.json",+ "referenceNumber": "345",+ "name": "Server Side Public License, v 1",+ "licenseId": "SSPL-1.0",+ "seeAlso": [+ "https://www.mongodb.com/licensing/server-side-public-license"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./SWL.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/SWL.json",+ "referenceNumber": "97",+ "name": "Scheme Widget Library (SWL) Software License Agreement",+ "licenseId": "SWL",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing/SWL"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./Saxpath.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Saxpath.json",+ "referenceNumber": "34",+ "name": "Saxpath License",+ "licenseId": "Saxpath",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing/Saxpath_License"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./Sendmail.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Sendmail.json",+ "referenceNumber": "304",+ "name": "Sendmail License",+ "licenseId": "Sendmail",+ "seeAlso": [+ "http://www.sendmail.com/pdfs/open_source/sendmail_license.pdf",+ "https://web.archive.org/web/20160322142305/https://www.sendmail.com/pdfs/open_source/sendmail_license.pdf"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./Sendmail-8.23.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Sendmail-8.23.json",+ "referenceNumber": "182",+ "name": "Sendmail License 8.23",+ "licenseId": "Sendmail-8.23",+ "seeAlso": [+ "https://www.proofpoint.com/sites/default/files/sendmail-license.pdf",+ "https://web.archive.org/web/20181003101040/https://www.proofpoint.com/sites/default/files/sendmail-license.pdf"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./SimPL-2.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/SimPL-2.0.json",+ "referenceNumber": "259",+ "name": "Simple Public License 2.0",+ "licenseId": "SimPL-2.0",+ "seeAlso": [+ "https://opensource.org/licenses/SimPL-2.0"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./Sleepycat.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/Sleepycat.json",+ "referenceNumber": "58",+ "name": "Sleepycat License",+ "licenseId": "Sleepycat",+ "seeAlso": [+ "https://opensource.org/licenses/Sleepycat"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./Spencer-86.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Spencer-86.json",+ "referenceNumber": "191",+ "name": "Spencer License 86",+ "licenseId": "Spencer-86",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing/Henry_Spencer_Reg-Ex_Library_License"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./Spencer-94.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Spencer-94.json",+ "referenceNumber": "220",+ "name": "Spencer License 94",+ "licenseId": "Spencer-94",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing/Henry_Spencer_Reg-Ex_Library_License"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./Spencer-99.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Spencer-99.json",+ "referenceNumber": "67",+ "name": "Spencer License 99",+ "licenseId": "Spencer-99",+ "seeAlso": [+ "http://www.opensource.apple.com/source/tcl/tcl-5/tcl/generic/regfronts.c"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./StandardML-NJ.html",+ "isDeprecatedLicenseId": true,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/StandardML-NJ.json",+ "referenceNumber": "296",+ "name": "Standard ML of New Jersey License",+ "licenseId": "StandardML-NJ",+ "seeAlso": [+ "http://www.smlnj.org//license.html"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./SugarCRM-1.1.3.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/SugarCRM-1.1.3.json",+ "referenceNumber": "353",+ "name": "SugarCRM Public License v1.1.3",+ "licenseId": "SugarCRM-1.1.3",+ "seeAlso": [+ "http://www.sugarcrm.com/crm/SPL"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./TAPR-OHL-1.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/TAPR-OHL-1.0.json",+ "referenceNumber": "9",+ "name": "TAPR Open Hardware License v1.0",+ "licenseId": "TAPR-OHL-1.0",+ "seeAlso": [+ "https://www.tapr.org/OHL"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./TCL.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/TCL.json",+ "referenceNumber": "56",+ "name": "TCL/TK License",+ "licenseId": "TCL",+ "seeAlso": [+ "http://www.tcl.tk/software/tcltk/license.html",+ "https://fedoraproject.org/wiki/Licensing/TCL"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./TCP-wrappers.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/TCP-wrappers.json",+ "referenceNumber": "242",+ "name": "TCP Wrappers License",+ "licenseId": "TCP-wrappers",+ "seeAlso": [+ "http://rc.quest.com/topics/openssh/license.php#tcpwrappers"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./TMate.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/TMate.json",+ "referenceNumber": "415",+ "name": "TMate Open Source License",+ "licenseId": "TMate",+ "seeAlso": [+ "http://svnkit.com/license.html"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./TORQUE-1.1.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/TORQUE-1.1.json",+ "referenceNumber": "195",+ "name": "TORQUE v2.5+ Software License v1.1",+ "licenseId": "TORQUE-1.1",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing/TORQUEv1.1"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./TOSL.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/TOSL.json",+ "referenceNumber": "260",+ "name": "Trusster Open Source License",+ "licenseId": "TOSL",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing/TOSL"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./TU-Berlin-1.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/TU-Berlin-1.0.json",+ "referenceNumber": "384",+ "name": "Technische Universitaet Berlin License 1.0",+ "licenseId": "TU-Berlin-1.0",+ "seeAlso": [+ "https://github.com/swh/ladspa/blob/7bf6f3799fdba70fda297c2d8fd9f526803d9680/gsm/COPYRIGHT"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./TU-Berlin-2.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/TU-Berlin-2.0.json",+ "referenceNumber": "405",+ "name": "Technische Universitaet Berlin License 2.0",+ "licenseId": "TU-Berlin-2.0",+ "seeAlso": [+ "https://github.com/CorsixTH/deps/blob/fd339a9f526d1d9c9f01ccf39e438a015da50035/licences/libgsm.txt"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./UCL-1.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/UCL-1.0.json",+ "referenceNumber": "302",+ "name": "Upstream Compatibility License v1.0",+ "licenseId": "UCL-1.0",+ "seeAlso": [+ "https://opensource.org/licenses/UCL-1.0"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./UPL-1.0.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/UPL-1.0.json",+ "referenceNumber": "149",+ "name": "Universal Permissive License v1.0",+ "licenseId": "UPL-1.0",+ "seeAlso": [+ "https://opensource.org/licenses/UPL"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./Unicode-DFS-2015.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Unicode-DFS-2015.json",+ "referenceNumber": "270",+ "name": "Unicode License Agreement - Data Files and Software (2015)",+ "licenseId": "Unicode-DFS-2015",+ "seeAlso": [+ "https://web.archive.org/web/20151224134844/http://unicode.org/copyright.html"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./Unicode-DFS-2016.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Unicode-DFS-2016.json",+ "referenceNumber": "382",+ "name": "Unicode License Agreement - Data Files and Software (2016)",+ "licenseId": "Unicode-DFS-2016",+ "seeAlso": [+ "http://www.unicode.org/copyright.html"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./Unicode-TOU.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Unicode-TOU.json",+ "referenceNumber": "16",+ "name": "Unicode Terms of Use",+ "licenseId": "Unicode-TOU",+ "seeAlso": [+ "http://www.unicode.org/copyright.html"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./Unlicense.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/Unlicense.json",+ "referenceNumber": "179",+ "name": "The Unlicense",+ "licenseId": "Unlicense",+ "seeAlso": [+ "https://unlicense.org/"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./VOSTROM.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/VOSTROM.json",+ "referenceNumber": "363",+ "name": "VOSTROM Public License for Open Source",+ "licenseId": "VOSTROM",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing/VOSTROM"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./VSL-1.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/VSL-1.0.json",+ "referenceNumber": "402",+ "name": "Vovida Software License v1.0",+ "licenseId": "VSL-1.0",+ "seeAlso": [+ "https://opensource.org/licenses/VSL-1.0"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./Vim.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/Vim.json",+ "referenceNumber": "213",+ "name": "Vim License",+ "licenseId": "Vim",+ "seeAlso": [+ "http://vimdoc.sourceforge.net/htmldoc/uganda.html"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./W3C.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/W3C.json",+ "referenceNumber": "111",+ "name": "W3C Software Notice and License (2002-12-31)",+ "licenseId": "W3C",+ "seeAlso": [+ "http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231.html",+ "https://opensource.org/licenses/W3C"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./W3C-19980720.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/W3C-19980720.json",+ "referenceNumber": "276",+ "name": "W3C Software Notice and License (1998-07-20)",+ "licenseId": "W3C-19980720",+ "seeAlso": [+ "http://www.w3.org/Consortium/Legal/copyright-software-19980720.html"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./W3C-20150513.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/W3C-20150513.json",+ "referenceNumber": "115",+ "name": "W3C Software Notice and Document License (2015-05-13)",+ "licenseId": "W3C-20150513",+ "seeAlso": [+ "https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./WTFPL.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/WTFPL.json",+ "referenceNumber": "20",+ "name": "Do What The F*ck You Want To Public License",+ "licenseId": "WTFPL",+ "seeAlso": [+ "http://sam.zoy.org/wtfpl/COPYING"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./Watcom-1.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Watcom-1.0.json",+ "referenceNumber": "146",+ "name": "Sybase Open Watcom Public License 1.0",+ "licenseId": "Watcom-1.0",+ "seeAlso": [+ "https://opensource.org/licenses/Watcom-1.0"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./Wsuipa.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Wsuipa.json",+ "referenceNumber": "264",+ "name": "Wsuipa License",+ "licenseId": "Wsuipa",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing/Wsuipa"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./X11.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/X11.json",+ "referenceNumber": "103",+ "name": "X11 License",+ "licenseId": "X11",+ "seeAlso": [+ "http://www.xfree86.org/3.3.6/COPYRIGHT2.html#3"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./XFree86-1.1.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/XFree86-1.1.json",+ "referenceNumber": "161",+ "name": "XFree86 License 1.1",+ "licenseId": "XFree86-1.1",+ "seeAlso": [+ "http://www.xfree86.org/current/LICENSE4.html"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./XSkat.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/XSkat.json",+ "referenceNumber": "85",+ "name": "XSkat License",+ "licenseId": "XSkat",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing/XSkat_License"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./Xerox.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Xerox.json",+ "referenceNumber": "232",+ "name": "Xerox License",+ "licenseId": "Xerox",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing/Xerox"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./Xnet.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Xnet.json",+ "referenceNumber": "324",+ "name": "X.Net License",+ "licenseId": "Xnet",+ "seeAlso": [+ "https://opensource.org/licenses/Xnet"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./YPL-1.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/YPL-1.0.json",+ "referenceNumber": "303",+ "name": "Yahoo! Public License v1.0",+ "licenseId": "YPL-1.0",+ "seeAlso": [+ "http://www.zimbra.com/license/yahoo_public_license_1.0.html"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./YPL-1.1.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/YPL-1.1.json",+ "referenceNumber": "40",+ "name": "Yahoo! Public License v1.1",+ "licenseId": "YPL-1.1",+ "seeAlso": [+ "http://www.zimbra.com/license/yahoo_public_license_1.1.html"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./ZPL-1.1.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/ZPL-1.1.json",+ "referenceNumber": "89",+ "name": "Zope Public License 1.1",+ "licenseId": "ZPL-1.1",+ "seeAlso": [+ "http://old.zope.org/Resources/License/ZPL-1.1"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./ZPL-2.0.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/ZPL-2.0.json",+ "referenceNumber": "116",+ "name": "Zope Public License 2.0",+ "licenseId": "ZPL-2.0",+ "seeAlso": [+ "http://old.zope.org/Resources/License/ZPL-2.0",+ "https://opensource.org/licenses/ZPL-2.0"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./ZPL-2.1.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/ZPL-2.1.json",+ "referenceNumber": "380",+ "name": "Zope Public License 2.1",+ "licenseId": "ZPL-2.1",+ "seeAlso": [+ "http://old.zope.org/Resources/ZPL/"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./Zed.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Zed.json",+ "referenceNumber": "118",+ "name": "Zed License",+ "licenseId": "Zed",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing/Zed"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./Zend-2.0.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/Zend-2.0.json",+ "referenceNumber": "385",+ "name": "Zend License v2.0",+ "licenseId": "Zend-2.0",+ "seeAlso": [+ "https://web.archive.org/web/20130517195954/http://www.zend.com/license/2_00.txt"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./Zimbra-1.3.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/Zimbra-1.3.json",+ "referenceNumber": "181",+ "name": "Zimbra Public License v1.3",+ "licenseId": "Zimbra-1.3",+ "seeAlso": [+ "http://web.archive.org/web/20100302225219/http://www.zimbra.com/license/zimbra-public-license-1-3.html"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./Zimbra-1.4.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/Zimbra-1.4.json",+ "referenceNumber": "397",+ "name": "Zimbra Public License v1.4",+ "licenseId": "Zimbra-1.4",+ "seeAlso": [+ "http://www.zimbra.com/legal/zimbra-public-license-1-4"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./Zlib.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/Zlib.json",+ "referenceNumber": "45",+ "name": "zlib License",+ "licenseId": "Zlib",+ "seeAlso": [+ "http://www.zlib.net/zlib_license.html",+ "https://opensource.org/licenses/Zlib"+ ],+ "isOsiApproved": true+ },+ {+ "reference": "./blessing.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/blessing.json",+ "referenceNumber": "312",+ "name": "SQLite Blessing",+ "licenseId": "blessing",+ "seeAlso": [+ "https://www.sqlite.org/src/artifact/e33a4df7e32d742a?ln\u003d4-9",+ "https://sqlite.org/src/artifact/df5091916dbb40e6"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./bzip2-1.0.5.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/bzip2-1.0.5.json",+ "referenceNumber": "193",+ "name": "bzip2 and libbzip2 License v1.0.5",+ "licenseId": "bzip2-1.0.5",+ "seeAlso": [+ "https://sourceware.org/bzip2/1.0.5/bzip2-manual-1.0.5.html",+ "http://bzip.org/1.0.5/bzip2-manual-1.0.5.html"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./bzip2-1.0.6.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/bzip2-1.0.6.json",+ "referenceNumber": "72",+ "name": "bzip2 and libbzip2 License v1.0.6",+ "licenseId": "bzip2-1.0.6",+ "seeAlso": [+ "https://sourceware.org/git/?p\u003dbzip2.git;a\u003dblob;f\u003dLICENSE;hb\u003dbzip2-1.0.6",+ "http://bzip.org/1.0.5/bzip2-manual-1.0.5.html"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./copyleft-next-0.3.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/copyleft-next-0.3.0.json",+ "referenceNumber": "323",+ "name": "copyleft-next 0.3.0",+ "licenseId": "copyleft-next-0.3.0",+ "seeAlso": [+ "https://github.com/copyleft-next/copyleft-next/blob/master/Releases/copyleft-next-0.3.0"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./copyleft-next-0.3.1.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/copyleft-next-0.3.1.json",+ "referenceNumber": "390",+ "name": "copyleft-next 0.3.1",+ "licenseId": "copyleft-next-0.3.1",+ "seeAlso": [+ "https://github.com/copyleft-next/copyleft-next/blob/master/Releases/copyleft-next-0.3.1"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./curl.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/curl.json",+ "referenceNumber": "325",+ "name": "curl License",+ "licenseId": "curl",+ "seeAlso": [+ "https://github.com/bagder/curl/blob/master/COPYING"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./diffmark.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/diffmark.json",+ "referenceNumber": "410",+ "name": "diffmark license",+ "licenseId": "diffmark",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing/diffmark"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./dvipdfm.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/dvipdfm.json",+ "referenceNumber": "19",+ "name": "dvipdfm License",+ "licenseId": "dvipdfm",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing/dvipdfm"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./eCos-2.0.html",+ "isDeprecatedLicenseId": true,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/eCos-2.0.json",+ "referenceNumber": "282",+ "name": "eCos license version 2.0",+ "licenseId": "eCos-2.0",+ "seeAlso": [+ "https://www.gnu.org/licenses/ecos-license.html"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./eGenix.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/eGenix.json",+ "referenceNumber": "221",+ "name": "eGenix.com Public License 1.1.0",+ "licenseId": "eGenix",+ "seeAlso": [+ "http://www.egenix.com/products/eGenix.com-Public-License-1.1.0.pdf",+ "https://fedoraproject.org/wiki/Licensing/eGenix.com_Public_License_1.1.0"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./etalab-2.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/etalab-2.0.json",+ "referenceNumber": "269",+ "name": "Etalab Open License 2.0",+ "licenseId": "etalab-2.0",+ "seeAlso": [+ "https://github.com/DISIC/politique-de-contribution-open-source/blob/master/LICENSE.pdf",+ "https://raw.githubusercontent.com/DISIC/politique-de-contribution-open-source/master/LICENSE"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./gSOAP-1.3b.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/gSOAP-1.3b.json",+ "referenceNumber": "173",+ "name": "gSOAP Public License v1.3b",+ "licenseId": "gSOAP-1.3b",+ "seeAlso": [+ "http://www.cs.fsu.edu/~engelen/license.html"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./gnuplot.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/gnuplot.json",+ "referenceNumber": "395",+ "name": "gnuplot License",+ "licenseId": "gnuplot",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing/Gnuplot"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./iMatix.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/iMatix.json",+ "referenceNumber": "183",+ "name": "iMatix Standard Function Library Agreement",+ "licenseId": "iMatix",+ "seeAlso": [+ "http://legacy.imatix.com/html/sfl/sfl4.htm#license"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./libpng-2.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/libpng-2.0.json",+ "referenceNumber": "107",+ "name": "PNG Reference Library version 2",+ "licenseId": "libpng-2.0",+ "seeAlso": [+ "http://www.libpng.org/pub/png/src/libpng-LICENSE.txt"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./libselinux-1.0.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/libselinux-1.0.json",+ "referenceNumber": "18",+ "name": "libselinux public domain notice",+ "licenseId": "libselinux-1.0",+ "seeAlso": [+ "https://github.com/SELinuxProject/selinux/blob/master/libselinux/LICENSE"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./libtiff.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/libtiff.json",+ "referenceNumber": "420",+ "name": "libtiff License",+ "licenseId": "libtiff",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing/libtiff"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./mpich2.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/mpich2.json",+ "referenceNumber": "63",+ "name": "mpich2 License",+ "licenseId": "mpich2",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing/MIT"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./psfrag.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/psfrag.json",+ "referenceNumber": "421",+ "name": "psfrag License",+ "licenseId": "psfrag",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing/psfrag"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./psutils.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/psutils.json",+ "referenceNumber": "287",+ "name": "psutils License",+ "licenseId": "psutils",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing/psutils"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./wxWindows.html",+ "isDeprecatedLicenseId": true,+ "detailsUrl": "http://spdx.org/licenses/wxWindows.json",+ "referenceNumber": "252",+ "name": "wxWindows Library License",+ "licenseId": "wxWindows",+ "seeAlso": [+ "https://opensource.org/licenses/WXwindows"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./xinetd.html",+ "isDeprecatedLicenseId": false,+ "isFsfLibre": true,+ "detailsUrl": "http://spdx.org/licenses/xinetd.json",+ "referenceNumber": "412",+ "name": "xinetd License",+ "licenseId": "xinetd",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing/Xinetd_License"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./xpp.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/xpp.json",+ "referenceNumber": "100",+ "name": "XPP License",+ "licenseId": "xpp",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing/xpp"+ ],+ "isOsiApproved": false+ },+ {+ "reference": "./zlib-acknowledgement.html",+ "isDeprecatedLicenseId": false,+ "detailsUrl": "http://spdx.org/licenses/zlib-acknowledgement.json",+ "referenceNumber": "254",+ "name": "zlib/libpng License with Acknowledgement",+ "licenseId": "zlib-acknowledgement",+ "seeAlso": [+ "https://fedoraproject.org/wiki/Licensing/ZlibWithAcknowledgement"+ ],+ "isOsiApproved": false+ }+ ],+ "releaseDate": "2020-05-15"+}
cabal/release-checklist.md view
@@ -8,3 +8,4 @@ `supportedGHCVersions` (`Distribution.Simple.Program.GHC`) - Update `Language.Haskell.Extension` list, if there are new GHC extensions - Update `setupMinCabalVersionConstraint` (in `Distribution.Client.ProjectPlanning`)+- Update `Cabal.Distribution.Simple.GHC` to include new GHC version
+ cabal/release-notes/Cabal-3.4.0.0.md view
@@ -0,0 +1,147 @@+### Significant changes++- Add cabal-version: 3.4 [!6663](https://github.com/haskell/cabal/pull/6663)+ + See various changes in https://cabal.readthedocs.io/en/latest/file-format-changelog.html#cabal-version-3-4+ +- Support GHC-8.12 [#6903](https://github.com/haskell/cabal/issues/6903) [#6904](https://github.com/haskell/cabal/issues/6904) [#6905](https://github.com/haskell/cabal/issues/6905) [!6545](https://github.com/haskell/cabal/pull/6545) [!6552](https://github.com/haskell/cabal/pull/6552) [!6553](https://github.com/haskell/cabal/pull/6553) [!6563](https://github.com/haskell/cabal/pull/6563) [!6735](https://github.com/haskell/cabal/pull/6735) [!6844](https://github.com/haskell/cabal/pull/6844) [!6848](https://github.com/haskell/cabal/pull/6848) [!6865](https://github.com/haskell/cabal/pull/6865) [!6908](https://github.com/haskell/cabal/pull/6908) [!6947](https://github.com/haskell/cabal/pull/6947)+ + - Support for `-this-package-key` deprecation+ - Use process `createPipe`+ - Add support for WINIO to Cabal+ - Adopt to simplfied subsumption changes+ + There are no magical `IO = WithCallStack Prelude.IO` alias in Cabal,+ as it is hard to get working with GHC-8.12's simplified subsumption.+ +- Treat `pkg:sublib` dependency syntax as is in `cabal-version: 3.4` [#6083](https://github.com/haskell/cabal/issues/6083) [!6893](https://github.com/haskell/cabal/pull/6893) [!6907](https://github.com/haskell/cabal/pull/6907)+ + In `cabal-version: 3.4` cabal files the dependency definition+ + ```cabal+ build-depends: somesublib+ ```+ + is not using in-package sublibraries. You have to be explicit and write+ + ```cabal+ build-depends: thispkg:somesublib+ ```+ + This fixes an issue, where it was impossible to refer to extenral+ library, if you had sublibrary of the same name.+ +- Dependency type refactorings [#5570](https://github.com/haskell/cabal/issues/5570) [#6894](https://github.com/haskell/cabal/issues/6894) [!6768](https://github.com/haskell/cabal/pull/6768) [!6798](https://github.com/haskell/cabal/pull/6798) [!6895](https://github.com/haskell/cabal/pull/6895) [!6896](https://github.com/haskell/cabal/pull/6896) [!6897](https://github.com/haskell/cabal/pull/6897) [!6898](https://github.com/haskell/cabal/pull/6898)+ + With additions of (public) sublibraries, `Dependency` type use for multiple needs become painful.+ Therefore a new type `PackageVersionConstraint` was added to serve *constraint on package* use-case.+ `Dependency` type is *dependency on a library component*, i.e. representing `build-depends` entry.+ + - Use PackageVersionConstraint more+ - Add NonEmptySet and use it in Dependency+ +### Other changes++- Tests additions [#6409](https://github.com/haskell/cabal/issues/6409) [!6753](https://github.com/haskell/cabal/pull/6753) [!6759](https://github.com/haskell/cabal/pull/6759) [!6802](https://github.com/haskell/cabal/pull/6802) [!6842](https://github.com/haskell/cabal/pull/6842) [!6872](https://github.com/haskell/cabal/pull/6872)+ + - Add shrinker, so writing big non-generic product shrinkers is easier+ - Add `hs-source-dirs: NL .` test-case+ - Add public multilib test(s)+ +- Code organization [!6599](https://github.com/haskell/cabal/pull/6599) [!6642](https://github.com/haskell/cabal/pull/6642) [!6734](https://github.com/haskell/cabal/pull/6734) [!6745](https://github.com/haskell/cabal/pull/6745) [!6746](https://github.com/haskell/cabal/pull/6746) [!6817](https://github.com/haskell/cabal/pull/6817) [!6818](https://github.com/haskell/cabal/pull/6818) [!6821](https://github.com/haskell/cabal/pull/6821) [!6867](https://github.com/haskell/cabal/pull/6867)+ + - Split `Distribution.Client.Types` module+ - Move cabal-testsuite code into `src/`+ - Add `ProjectFlags`+ - Add `NixStyleOptions`+ - Internal refactorings to install command.+ - Make own modules for `InstallMethod` and `OverwritePolicy`+ - Make cabal-install compilable with `NoImplicitPrelude`+ - Refactor shared `TargetProblem` data types into their own module.+ - Template `cabal-install.cabal` using zinza+ +- The grammar of most package description fields is formally documented [!6591](https://github.com/haskell/cabal/pull/6591) [!6593](https://github.com/haskell/cabal/pull/6593) [!6704](https://github.com/haskell/cabal/pull/6704) [!6766](https://github.com/haskell/cabal/pull/6766) [!6778](https://github.com/haskell/cabal/pull/6778) [!6780](https://github.com/haskell/cabal/pull/6780) [!6781](https://github.com/haskell/cabal/pull/6781) [!6791](https://github.com/haskell/cabal/pull/6791) [!6800](https://github.com/haskell/cabal/pull/6800)+ + See https://cabal.readthedocs.io/en/latest/buildinfo-fields-reference.html+ +- Fix ghci being launched before other sources are built. [!6923](https://github.com/haskell/cabal/pull/6923)+ + Related to foreign calls to C-sources.+ +- Remove `-any` and `-none` syntax for version ranges in cabal-version: 3.4 [#6589](https://github.com/haskell/cabal/issues/6589) [!6786](https://github.com/haskell/cabal/pull/6786)+ + Use `>=0` (or empty in dependencies) and `<0` respectively.+ +- Add pijul to known repository type [#6610](https://github.com/haskell/cabal/issues/6610) [!6684](https://github.com/haskell/cabal/pull/6684)+ + Pijul is now explicitly recognized version control system.+ However `cabal-install` isn't yet able to use it in+ `source-repository-package`.+ +- Rename Flag to CompilerFlag and PackageFlag [#6710](https://github.com/haskell/cabal/issues/6710) [!6725](https://github.com/haskell/cabal/pull/6725)+ + There was three Flag's. Now they are+ + - `Flag` (cli parsing)+ - `PackageFlag`+ - `CompilerFlag`+ + This allows wild-imports without `hiding (Flag)`.+ +- Accept "linux-androideabi" as an alias for Android for determining buildOS [!6301](https://github.com/haskell/cabal/pull/6301) [!6949](https://github.com/haskell/cabal/pull/6949)+ + `Cabal` will able to parse `linux-androideabi` from the value of `System.Info.os`.+ +- Refactor Distribution.PackageDescription module [!6855](https://github.com/haskell/cabal/pull/6855)+ + Now it re-exports a collection of modules, not individual symbols.+ +- Use process jobs when spawning subprocesses [!6529](https://github.com/haskell/cabal/pull/6529) [!6536](https://github.com/haskell/cabal/pull/6536)+ + Many toolchain tools written for POSIX systems rely on the exec system+ call. Unfortunately, it is not possible to implement exec in a+ POSIX-compliant manner on Windows. In particular, the semantics of the+ exec implementation provided by the widely-used msvcrt C runtime+ will cause process's waiting on the exec'ing process to incorrectly+ conclude that the process has successfully terminated when in fact it is+ still running in another process.+ + For this reason, the process library exposes the use_process_jobs+ flag to use a more strict (although still not POSIX-compliant) mechanism+ for tracking process completion.+ This is explained in [the Process.hs comment](https://github.com/haskell/process/blob/master/System/Process.hs#L399)+ + Unfortunately, job support in the process library is currently quite+ broken and was only recently fixed. Consequently, we only enable job+ object support for process releases >= 1.6.8.+ +- Remove `AnyVersion` and `WildcardVersion` constructors from `Version` [!6742](https://github.com/haskell/cabal/pull/6742)+ + This changes makes `Version` type less "syntactic",+ i.e. contains less constructors for semantically same version ranges.+ +- Cabal-QuickCheck package with `Arbirary` instances [#6882](https://github.com/haskell/cabal/issues/6882) [!6557](https://github.com/haskell/cabal/pull/6557) [!6891](https://github.com/haskell/cabal/pull/6891)+- Create Cabal-tree-diff package with `ToExpr` instances [!6789](https://github.com/haskell/cabal/pull/6789)+- `Cabal.Distribution.Compiler`: add `Traversable` instance for `PerCompilerFlavor` [!6763](https://github.com/haskell/cabal/pull/6763)+- Improvements to cabal-testsuite framework [!6643](https://github.com/haskell/cabal/pull/6643)+- Update copyright years to 2020 [!6644](https://github.com/haskell/cabal/pull/6644)+- Documentation updates and typo-fixes [!6504](https://github.com/haskell/cabal/pull/6504) [!6550](https://github.com/haskell/cabal/pull/6550) [!6560](https://github.com/haskell/cabal/pull/6560) [!6613](https://github.com/haskell/cabal/pull/6613) [!6660](https://github.com/haskell/cabal/pull/6660) [!6668](https://github.com/haskell/cabal/pull/6668) [!6669](https://github.com/haskell/cabal/pull/6669) [!6686](https://github.com/haskell/cabal/pull/6686) [!6697](https://github.com/haskell/cabal/pull/6697) [!6761](https://github.com/haskell/cabal/pull/6761) [!6928](https://github.com/haskell/cabal/pull/6928) [!6940](https://github.com/haskell/cabal/pull/6940) [!6951](https://github.com/haskell/cabal/pull/6951) [!6953](https://github.com/haskell/cabal/pull/6953) [!6954](https://github.com/haskell/cabal/pull/6954)+- Flag assignment parsing refactorings [#6853](https://github.com/haskell/cabal/issues/6853) [!6854](https://github.com/haskell/cabal/pull/6854) [!6858](https://github.com/haskell/cabal/pull/6858)+- Add foo:bar syntax to mixins [#6281](https://github.com/haskell/cabal/issues/6281) [!6912](https://github.com/haskell/cabal/pull/6912)+- default-language field is optional in cabal-version: 3.4 [#6288](https://github.com/haskell/cabal/issues/6288) [!6924](https://github.com/haskell/cabal/pull/6924) [!6926](https://github.com/haskell/cabal/pull/6926)+- Split `KnownRepoType` out of `RepoType` [#6432](https://github.com/haskell/cabal/issues/6432) [!6612](https://github.com/haskell/cabal/pull/6612)+- Include component name in unit-id [#6485](https://github.com/haskell/cabal/issues/6485) [!6547](https://github.com/haskell/cabal/pull/6547)+- Change 'optional-packages' default to empty, when cabal.project is mising. [#4797](https://github.com/haskell/cabal/issues/4797) [#6739](https://github.com/haskell/cabal/issues/6739) [!6740](https://github.com/haskell/cabal/pull/6740)+- Fix rpmvercmp (trailing non-digit characters) [#6805](https://github.com/haskell/cabal/issues/6805) [!6808](https://github.com/haskell/cabal/pull/6808)+- other changes [!6556](https://github.com/haskell/cabal/pull/6556) [!6598](https://github.com/haskell/cabal/pull/6598) [!6910](https://github.com/haskell/cabal/pull/6910)+- Package description parser benchmark [!6594](https://github.com/haskell/cabal/pull/6594)+- Add `licenceIsFsfLibre` [!6878](https://github.com/haskell/cabal/pull/6878)+- Add `+stderr` modifier to `Verbosity` [!6929](https://github.com/haskell/cabal/pull/6929)+- Mark public-libs as experimental feature [!6605](https://github.com/haskell/cabal/pull/6605)+- Add rewriteFileLBS and use it to write setup wrapper [!6574](https://github.com/haskell/cabal/pull/6574)+- Add SPDX License List 3.9 [#6879](https://github.com/haskell/cabal/issues/6879) [!6662](https://github.com/haskell/cabal/pull/6662) [!6944](https://github.com/haskell/cabal/pull/6944)+- Change specVersion to have CabalSpecVersion type [!6653](https://github.com/haskell/cabal/pull/6653)+- Better UTF8 handling, parsed `ShortText` is now valid. [!6588](https://github.com/haskell/cabal/pull/6588)+- More checks in version range parser [!6586](https://github.com/haskell/cabal/pull/6586)+- Require cabal-versions `>=1.25` to be exact [!6654](https://github.com/haskell/cabal/pull/6654)+- Add and use weeder [!6779](https://github.com/haskell/cabal/pull/6779) [!6790](https://github.com/haskell/cabal/pull/6790)
+ cabal/release-notes/cabal-install-3.4.0.0.md view
@@ -0,0 +1,235 @@+### Significant changes++- Add cabal-version: 3.4 [!6663](https://github.com/haskell/cabal/pull/6663)+ + See various changes in https://cabal.readthedocs.io/en/latest/file-format-changelog.html#cabal-version-3-4+ +- Support GHC-8.12 [#6903](https://github.com/haskell/cabal/issues/6903) [#6904](https://github.com/haskell/cabal/issues/6904) [#6905](https://github.com/haskell/cabal/issues/6905) [!6545](https://github.com/haskell/cabal/pull/6545) [!6552](https://github.com/haskell/cabal/pull/6552) [!6553](https://github.com/haskell/cabal/pull/6553) [!6563](https://github.com/haskell/cabal/pull/6563) [!6735](https://github.com/haskell/cabal/pull/6735) [!6844](https://github.com/haskell/cabal/pull/6844) [!6848](https://github.com/haskell/cabal/pull/6848) [!6865](https://github.com/haskell/cabal/pull/6865) [!6908](https://github.com/haskell/cabal/pull/6908) [!6947](https://github.com/haskell/cabal/pull/6947)+ + - Support for `-this-package-key` deprecation+ - Use process `createPipe`+ - Add support for WINIO to Cabal+ - Adopt to simplfied subsumption changes+ + There are no magical `IO = WithCallStack Prelude.IO` alias in Cabal,+ as it is hard to get working with GHC-8.12's simplified subsumption.+ +- Treat `pkg:sublib` dependency syntax as is in `cabal-version: 3.4` [#6083](https://github.com/haskell/cabal/issues/6083) [!6893](https://github.com/haskell/cabal/pull/6893) [!6907](https://github.com/haskell/cabal/pull/6907)+ + In `cabal-version: 3.4` cabal files the dependency definition+ + ```cabal+ build-depends: somesublib+ ```+ + is not using in-package sublibraries. You have to be explicit and write+ + ```cabal+ build-depends: thispkg:somesublib+ ```+ + This fixes an issue, where it was impossible to refer to extenral+ library, if you had sublibrary of the same name.+ +- Add active-repositories configuration [#6819](https://github.com/haskell/cabal/issues/6819) [!6724](https://github.com/haskell/cabal/pull/6724) [!6868](https://github.com/haskell/cabal/pull/6868)+ + New `active-repositories` `cabal.project` fields allows+ specifying an order and ways various package repositories are combined.+ + The active `active-repositories` is saved in `cabal.project.freeze`.+ +- Various `cabal init` improvements [#6150](https://github.com/haskell/cabal/issues/6150) [#6675](https://github.com/haskell/cabal/issues/6675) [!6603](https://github.com/haskell/cabal/pull/6603) [!6607](https://github.com/haskell/cabal/pull/6607) [!6619](https://github.com/haskell/cabal/pull/6619) [!6632](https://github.com/haskell/cabal/pull/6632) [!6641](https://github.com/haskell/cabal/pull/6641) [!6650](https://github.com/haskell/cabal/pull/6650) [!6661](https://github.com/haskell/cabal/pull/6661) [!6676](https://github.com/haskell/cabal/pull/6676) [!6677](https://github.com/haskell/cabal/pull/6677) [!6678](https://github.com/haskell/cabal/pull/6678) [!6690](https://github.com/haskell/cabal/pull/6690) [!6705](https://github.com/haskell/cabal/pull/6705) [!6723](https://github.com/haskell/cabal/pull/6723)+ + - Default to `cabal-version: 2.4`+ - `cabal` doesn't force a default license choice anymore+ - Licenses are always asked using SPDX expression+ - Fix an infinite loop when invalid license was passed on command line+ - `Setup.hs` is not written anymore+ - Default to --source-dir=src and --application-dir=app+ - Add `FileCreators.generateCabalFile` unit tests.+ - Default cabal init application-dir to `app`, and source-dir to `src`.+ - Default to SPDX.NONE license in cabal init interactive mode.+ +- Rework `v2-sdist` command [#2940](https://github.com/haskell/cabal/issues/2940) [#5813](https://github.com/haskell/cabal/issues/5813) [#6514](https://github.com/haskell/cabal/issues/6514) [#6611](https://github.com/haskell/cabal/issues/6611) [#6635](https://github.com/haskell/cabal/issues/6635) [!6454](https://github.com/haskell/cabal/pull/6454) [!6637](https://github.com/haskell/cabal/pull/6637) [!6640](https://github.com/haskell/cabal/pull/6640) [!6660](https://github.com/haskell/cabal/pull/6660) [!6666](https://github.com/haskell/cabal/pull/6666) [!6884](https://github.com/haskell/cabal/pull/6884) [!6916](https://github.com/haskell/cabal/pull/6916)+ + `v2-sdist` marks all files as readonly in resulting tarballs.+ + The #2940 "cabal sdist should touch preprocessed .hs files" issue+ is fixed by virtue of not doing any preprocessing anymore.+ It's responsibility of packager.+ + The #6611 "v2-sdist includes a file twice in the tarball " issue+ is fixed as we don't consider only one file list,+ not two separate executable and ordinary file lists.+ + The #6514 "unpack doesn't preserve (executable) permissions" issue+ is partially resolved, as there shouldn't be executable permissions+ in the tar files.+ + The rationale for above simplification is simple. The only file+ Cabal machinery would run is `configure` script. These+ are run with explicit `sh` program. For package internal scripts,+ maintainers should also use interpreters explicitly as well.+ Scripts with shebangs are not executable on Windows.+ + The `v1-sdist` command is removed, as its functionality is completely+ superseded by `v2-sdist`.+ +- `source-repository-package` directories aren't local [#5586](https://github.com/haskell/cabal/issues/5586) [!6915](https://github.com/haskell/cabal/pull/6915) [!6917](https://github.com/haskell/cabal/pull/6917)+ + Concretely these means that compiled `source-repository-package` entries+ used in different projects are stored in the global nix-style store.+ +- Add list-bin command [#6807](https://github.com/haskell/cabal/issues/6807) [!6931](https://github.com/haskell/cabal/pull/6931)+ + `cabal list-bin executable-component` tells the path to the build artifact.+ +- Remove sandboxes [#6445](https://github.com/haskell/cabal/issues/6445) [!6747](https://github.com/haskell/cabal/pull/6747)+ + Sandbox functionality is remove in favour of now default nix-style builds.+ +- `cabal list` accepts regular expression [#4267](https://github.com/haskell/cabal/issues/4267) [#6683](https://github.com/haskell/cabal/issues/6683) [!6618](https://github.com/haskell/cabal/pull/6618) [!6806](https://github.com/haskell/cabal/pull/6806)+- More rich `index-state` syntax. `v2-freeze` saves `index-state`. [#6728](https://github.com/haskell/cabal/issues/6728) [!6581](https://github.com/haskell/cabal/pull/6581) [!6591](https://github.com/haskell/cabal/pull/6591) [!6596](https://github.com/haskell/cabal/pull/6596) [!6597](https://github.com/haskell/cabal/pull/6597) [!6682](https://github.com/haskell/cabal/pull/6682) [!6733](https://github.com/haskell/cabal/pull/6733)+### Other changes++- Tests additions [#6409](https://github.com/haskell/cabal/issues/6409) [!6753](https://github.com/haskell/cabal/pull/6753) [!6759](https://github.com/haskell/cabal/pull/6759) [!6802](https://github.com/haskell/cabal/pull/6802) [!6842](https://github.com/haskell/cabal/pull/6842) [!6872](https://github.com/haskell/cabal/pull/6872)+ + - Add shrinker, so writing big non-generic product shrinkers is easier+ - Add `hs-source-dirs: NL .` test-case+ - Add public multilib test(s)+ +- Code organization [!6599](https://github.com/haskell/cabal/pull/6599) [!6642](https://github.com/haskell/cabal/pull/6642) [!6734](https://github.com/haskell/cabal/pull/6734) [!6745](https://github.com/haskell/cabal/pull/6745) [!6746](https://github.com/haskell/cabal/pull/6746) [!6817](https://github.com/haskell/cabal/pull/6817) [!6818](https://github.com/haskell/cabal/pull/6818) [!6821](https://github.com/haskell/cabal/pull/6821) [!6867](https://github.com/haskell/cabal/pull/6867)+ + - Split `Distribution.Client.Types` module+ - Move cabal-testsuite code into `src/`+ - Add `ProjectFlags`+ - Add `NixStyleOptions`+ - Internal refactorings to install command.+ - Make own modules for `InstallMethod` and `OverwritePolicy`+ - Make cabal-install compilable with `NoImplicitPrelude`+ - Refactor shared `TargetProblem` data types into their own module.+ - Template `cabal-install.cabal` using zinza+ +- The grammar of most package description fields is formally documented [!6591](https://github.com/haskell/cabal/pull/6591) [!6593](https://github.com/haskell/cabal/pull/6593) [!6704](https://github.com/haskell/cabal/pull/6704) [!6766](https://github.com/haskell/cabal/pull/6766) [!6778](https://github.com/haskell/cabal/pull/6778) [!6780](https://github.com/haskell/cabal/pull/6780) [!6781](https://github.com/haskell/cabal/pull/6781) [!6791](https://github.com/haskell/cabal/pull/6791) [!6800](https://github.com/haskell/cabal/pull/6800)+ + See https://cabal.readthedocs.io/en/latest/buildinfo-fields-reference.html+ +- Add -fexpose-all-unfoldings to parsec and Cabal in release project [!6708](https://github.com/haskell/cabal/pull/6708)+ + This makes parser faster with acceptable code-size increase.+ +- Fix ghci being launched before other sources are built. [!6923](https://github.com/haskell/cabal/pull/6923)+ + Related to foreign calls to C-sources.+ +- Use default install directory if not specified [#5973](https://github.com/haskell/cabal/issues/5973) [!6624](https://github.com/haskell/cabal/pull/6624)+ + Cabal 3.0.0.0 added the --installdir option to specify the location that+ binaries should be installed in. Running a cabal user-config update would+ populate the config file with the default value, but the cabal install program+ would error if it wasn't set. This change uses the default value that would be+ written to the config if its unset, and outputs a warning.+ +- Update GHC environment location [#6565](https://github.com/haskell/cabal/issues/6565) [!6822](https://github.com/haskell/cabal/pull/6822)+ + cabal-install currently assumes that the GHC environment files are always located in `$HOME/.ghc/`.+ However, GHC itself doesn't query the home directory directly.+ Instead, it uses `getAppUserDataDirectory "ghc"` which happens to coincide with `$HOME/.ghc`/ on UNIX systems.+ On Windows, however, GHC ends up looking in `%APPDATA%/ghc/`.+ +- Remove `-any` and `-none` syntax for version ranges in cabal-version: 3.4 [#6589](https://github.com/haskell/cabal/issues/6589) [!6786](https://github.com/haskell/cabal/pull/6786)+ + Use `>=0` (or empty in dependencies) and `<0` respectively.+ +- Add pijul to known repository type [#6610](https://github.com/haskell/cabal/issues/6610) [!6684](https://github.com/haskell/cabal/pull/6684)+ + Pijul is now explicitly recognized version control system.+ However `cabal-install` isn't yet able to use it in+ `source-repository-package`.+ +- Remove upgrade, uninstall and win32selfupgrade commands [#6691](https://github.com/haskell/cabal/issues/6691) [!6707](https://github.com/haskell/cabal/pull/6707)+ + This commands were not implemented or are special purpose.+ The removal of `win32selfupgrade` might break self upgrade on windows,+ when `cabal-install` tries to rewrite the binary of itself.+ This shouldn't be a problem when symlinking is used.+ +- Remove local-repo [#6729](https://github.com/haskell/cabal/issues/6729) [!6730](https://github.com/haskell/cabal/pull/6730)+ + This functionality was mainly used by removed sandboxes.+ `file+noindex` repositories are better variant for local package repositories.+ +- Add support for multiple public libraries to the solver [#6039](https://github.com/haskell/cabal/issues/6039) [!6047](https://github.com/haskell/cabal/pull/6047) [!6812](https://github.com/haskell/cabal/pull/6812) [!6836](https://github.com/haskell/cabal/pull/6836)+ + cabal-install can now take into account the presence and visibility of+ sublibraries when solving. This also means that, when using cabal-install,+ multiple public libraries support is extended to GHCs older than 8.8.+ The support is limited to source packages for now.+ +- Remove text type-class [!6764](https://github.com/haskell/cabal/pull/6764) [!6777](https://github.com/haskell/cabal/pull/6777) [!6784](https://github.com/haskell/cabal/pull/6784) [!6785](https://github.com/haskell/cabal/pull/6785) [!6793](https://github.com/haskell/cabal/pull/6793) [!6794](https://github.com/haskell/cabal/pull/6794)+ + `Text` type-class was removed from `Cabal`, but it still lived in `cabal-install`.+ Now it is finally removed.+ `cabal-install` is still using `ReadP` parsers for various things though.+ +- Windows install symlinks [!5684](https://github.com/haskell/cabal/pull/5684) [!6506](https://github.com/haskell/cabal/pull/6506) [!6519](https://github.com/haskell/cabal/pull/6519)+ + `cabal-install` will try to infer whether symlinking is supported on Windows,+ and make symlinks in `install`. Otherwise it will fallback to copying files.+ Either way can be forced with `--install-method`.+ +- Use process jobs when spawning subprocesses [!6529](https://github.com/haskell/cabal/pull/6529) [!6536](https://github.com/haskell/cabal/pull/6536)+ + Many toolchain tools written for POSIX systems rely on the exec system+ call. Unfortunately, it is not possible to implement exec in a+ POSIX-compliant manner on Windows. In particular, the semantics of the+ exec implementation provided by the widely-used msvcrt C runtime+ will cause process's waiting on the exec'ing process to incorrectly+ conclude that the process has successfully terminated when in fact it is+ still running in another process.+ + For this reason, the process library exposes the use_process_jobs+ flag to use a more strict (although still not POSIX-compliant) mechanism+ for tracking process completion.+ This is explained in [the Process.hs comment](https://github.com/haskell/process/blob/master/System/Process.hs#L399)+ + Unfortunately, job support in the process library is currently quite+ broken and was only recently fixed. Consequently, we only enable job+ object support for process releases >= 1.6.8.+ +- Change `BuildReports` parse/pretty to use FieldGrammar framework [!6783](https://github.com/haskell/cabal/pull/6783)+- Tell users about `cabal.project.local~` in `cabal v2-configure` [!6877](https://github.com/haskell/cabal/pull/6877)+- Improvements to cabal-testsuite framework [!6643](https://github.com/haskell/cabal/pull/6643)+- Refactor cabalInstallVersions, add make doctest-cli [!6720](https://github.com/haskell/cabal/pull/6720)+- Update copyright years to 2020 [!6644](https://github.com/haskell/cabal/pull/6644)+- Documentation updates and typo-fixes [!6504](https://github.com/haskell/cabal/pull/6504) [!6550](https://github.com/haskell/cabal/pull/6550) [!6560](https://github.com/haskell/cabal/pull/6560) [!6613](https://github.com/haskell/cabal/pull/6613) [!6660](https://github.com/haskell/cabal/pull/6660) [!6668](https://github.com/haskell/cabal/pull/6668) [!6669](https://github.com/haskell/cabal/pull/6669) [!6686](https://github.com/haskell/cabal/pull/6686) [!6697](https://github.com/haskell/cabal/pull/6697) [!6761](https://github.com/haskell/cabal/pull/6761) [!6928](https://github.com/haskell/cabal/pull/6928) [!6940](https://github.com/haskell/cabal/pull/6940) [!6951](https://github.com/haskell/cabal/pull/6951) [!6953](https://github.com/haskell/cabal/pull/6953) [!6954](https://github.com/haskell/cabal/pull/6954)+- Flag assignment parsing refactorings [#6853](https://github.com/haskell/cabal/issues/6853) [!6854](https://github.com/haskell/cabal/pull/6854) [!6858](https://github.com/haskell/cabal/pull/6858)+- Remove new- command from `--help` output (there are v2-) [!6930](https://github.com/haskell/cabal/pull/6930)+- Installing (copy or symlink) executable message prints destination. [!6582](https://github.com/haskell/cabal/pull/6582) [!6590](https://github.com/haskell/cabal/pull/6590)+- Check sha256 if `#sha256=...` fragments are given to URIs [!6576](https://github.com/haskell/cabal/pull/6576)+- all extra-source-files are change-tracked [#4746](https://github.com/haskell/cabal/issues/4746) [!6889](https://github.com/haskell/cabal/pull/6889)+- `upload --help` now includes `password-command` as a config file option (#5224) [#5224](https://github.com/haskell/cabal/issues/5224) [!6313](https://github.com/haskell/cabal/pull/6313) [!6609](https://github.com/haskell/cabal/pull/6609) [!6680](https://github.com/haskell/cabal/pull/6680)+- Use PrettyField to format cabal file in `cabal init` [#5555](https://github.com/haskell/cabal/issues/5555) [!6718](https://github.com/haskell/cabal/pull/6718)+- Default to 'NoReports' for remote build reporting [#6210](https://github.com/haskell/cabal/issues/6210) [!6625](https://github.com/haskell/cabal/pull/6625)+- Add foo:bar syntax to mixins [#6281](https://github.com/haskell/cabal/issues/6281) [!6912](https://github.com/haskell/cabal/pull/6912)+- default-language field is optional in cabal-version: 3.4 [#6288](https://github.com/haskell/cabal/issues/6288) [!6924](https://github.com/haskell/cabal/pull/6924) [!6926](https://github.com/haskell/cabal/pull/6926)+- Allow cabal v2-install pkgname:exename [#6369](https://github.com/haskell/cabal/issues/6369) [!6576](https://github.com/haskell/cabal/pull/6576)+- Allow cabal v2-install http:// [#6393](https://github.com/haskell/cabal/issues/6393) [!6576](https://github.com/haskell/cabal/pull/6576)+- Include component name in unit-id [#6485](https://github.com/haskell/cabal/issues/6485) [!6547](https://github.com/haskell/cabal/pull/6547)+- cabal v2-install prints copy/symlink destination [#6575](https://github.com/haskell/cabal/issues/6575) [!6582](https://github.com/haskell/cabal/pull/6582) [!6890](https://github.com/haskell/cabal/pull/6890)+- Prepend hs-source-dir to match-component, fixes `cabal repl file` [#6622](https://github.com/haskell/cabal/issues/6622) [!6623](https://github.com/haskell/cabal/pull/6623) [!6826](https://github.com/haskell/cabal/pull/6826) [!6875](https://github.com/haskell/cabal/pull/6875)+- Change 'optional-packages' default to empty, when cabal.project is mising. [#4797](https://github.com/haskell/cabal/issues/4797) [#6739](https://github.com/haskell/cabal/issues/6739) [!6740](https://github.com/haskell/cabal/pull/6740)+- v2-update reports new index-state [#6804](https://github.com/haskell/cabal/issues/6804) [!6810](https://github.com/haskell/cabal/pull/6810)+- Fix rpmvercmp (trailing non-digit characters) [#6805](https://github.com/haskell/cabal/issues/6805) [!6808](https://github.com/haskell/cabal/pull/6808)+- Add `-z` / `--ignore-project` flag to `cabal v2-update` [#6809](https://github.com/haskell/cabal/issues/6809) [!6814](https://github.com/haskell/cabal/pull/6814)+- Adjust message indicating `--lib` is likely desired [#6856](https://github.com/haskell/cabal/issues/6856) [!6857](https://github.com/haskell/cabal/pull/6857)+- cxx-sources, asm-sources and cmm-sources are change-tracked [#6869](https://github.com/haskell/cabal/issues/6869) [!6870](https://github.com/haskell/cabal/pull/6870)+- Change manpage command to man [!6548](https://github.com/haskell/cabal/pull/6548)+- other changes [!6556](https://github.com/haskell/cabal/pull/6556) [!6598](https://github.com/haskell/cabal/pull/6598) [!6910](https://github.com/haskell/cabal/pull/6910)+- Package description parser benchmark [!6594](https://github.com/haskell/cabal/pull/6594)+- Add `+stderr` modifier to `Verbosity` [!6929](https://github.com/haskell/cabal/pull/6929)+- Mark public-libs as experimental feature [!6605](https://github.com/haskell/cabal/pull/6605)+- Add SPDX License List 3.9 [#6879](https://github.com/haskell/cabal/issues/6879) [!6662](https://github.com/haskell/cabal/pull/6662) [!6944](https://github.com/haskell/cabal/pull/6944)+- More checks in version range parser [!6586](https://github.com/haskell/cabal/pull/6586)+- Require cabal-versions `>=1.25` to be exact [!6654](https://github.com/haskell/cabal/pull/6654)+- Add and use weeder [!6779](https://github.com/haskell/cabal/pull/6779) [!6790](https://github.com/haskell/cabal/pull/6790)
cabal/solver-benchmarks/HackageBenchmark.hs view
@@ -27,7 +27,9 @@ , mannWhitneyUCriticalValue , mannWhitneyUtest) import Statistics.Types (PValue, mkPValue)+import System.Directory (getTemporaryDirectory) import System.Exit (ExitCode(..), exitFailure)+import System.FilePath ((</>)) import System.IO ( BufferMode(LineBuffering), hPutStrLn, hSetBuffering, stderr , stdout) import System.Process ( StdStream(CreatePipe), CreateProcess(..), callProcess@@ -56,6 +58,10 @@ = Solution | NoInstallPlan | BackjumpLimit+ | Unbuildable+ | UnbuildableDep+ | ComponentCycle+ | ModReexpIssue | PkgNotFound | Timeout | Unknown@@ -81,14 +87,14 @@ -- "trial" or "summary". when argPrintTrials $ putStr $ printf "%-16s " "trial/summary" putStrLn $- printf "%-*s %-13s %-13s %11s %11s %11s %11s %11s"+ printf "%-*s %-14s %-14s %11s %11s %11s %11s %11s" nameColumnWidth "package" "result1" "result2" "mean1" "mean2" "stddev1" "stddev2" "speedup" forM_ pkgs $ \pkg -> do let printTrial msgType result1 result2 time1 time2 = putStrLn $- printf "%-16s %-*s %-13s %-13s %10.3fs %10.3fs"+ printf "%-16s %-*s %-14s %-14s %10.3fs %10.3fs" msgType nameColumnWidth (unPackageName pkg) (show result1) (show result2) (diffTimeToDouble time1) (diffTimeToDouble time2)@@ -125,7 +131,7 @@ if isSignificantResult result1 result2 || isSignificantTimeDifference argPValue ts1 ts2 then putStrLn $- printf "%-*s %-13s %-13s %10.3fs %10.3fs %10.3fs %10.3fs %10.3f"+ printf "%-*s %-14s %-14s %10.3fs %10.3fs %10.3fs %10.3fs %10.3f" nameColumnWidth (unPackageName pkg) (show result1) (show result2) mean1 mean2 stddev1 stddev2 speedup else when (argPrintTrials || argPrintSkippedPackages) $@@ -169,10 +175,37 @@ runCabal :: Int -> FilePath -> [String] -> PackageName -> IO CabalTrial runCabal timeoutSeconds cabal flags pkg = do ((exitCode, err), time) <- timeEvent $ do+ tmpDir <- getTemporaryDirectory+ let timeout = "timeout --foreground -sINT " ++ show timeoutSeconds- cabalCmd =- unwords $- [cabal, "install", unPackageName pkg, "--dry-run", "-v0"] ++ flags+ cabalCmd = unwords $+ [ cabal++ -- A non-existent store directory prevents cabal from reading the+ -- store, which would cause the size of the store to affect run+ -- time.+ , "--store-dir=" ++ (tmpDir </> "non-existent-store-dir")++ , "v2-install"++ -- These flags prevent a Cabal project or package environment from+ -- affecting the install plan.+ , "--ignore-project"+ , "--package-env=non-existent-package-env"++ -- --lib allows solving for packages with libraries or+ -- executables.+ , "--lib"++ , unPackageName pkg++ , "--dry-run"++ -- The test doesn't currently handle stdout, so we suppress it+ -- with silent. nowrap simplifies parsing the errors messages.+ , "-vsilent+nowrap"]++ ++ flags cmd = (shell (timeout ++ " " ++ cabalCmd)) { std_err = CreatePipe } -- TODO: Read stdout and compare the install plans.@@ -182,12 +215,16 @@ let exhaustiveMsg = "After searching the rest of the dependency tree exhaustively" result- | exitCode == ExitSuccess = Solution- | exitCode == ExitFailure 124 = Timeout- | fromString exhaustiveMsg `B.isInfixOf` err = NoInstallPlan- | fromString "Backjump limit reached" `B.isInfixOf` err = BackjumpLimit- | fromString "There is no package named" `B.isInfixOf` err = PkgNotFound- | otherwise = Unknown+ | exitCode == ExitSuccess = Solution+ | exitCode == ExitFailure 124 = Timeout+ | fromString exhaustiveMsg `B.isInfixOf` err = NoInstallPlan+ | fromString "Backjump limit reached" `B.isInfixOf` err = BackjumpLimit+ | fromString "none of the components are available to build" `B.isInfixOf` err = Unbuildable+ | fromString "Dependency on unbuildable" `B.isInfixOf` err = UnbuildableDep+ | fromString "Dependency cycle between the following components" `B.isInfixOf` err = ComponentCycle+ | fromString "Problem with module re-exports" `B.isInfixOf` err = ModReexpIssue+ | fromString "There is no package named" `B.isInfixOf` err = PkgNotFound+ | otherwise = Unknown return (CabalTrial time result) isSampleLargeEnough :: PValue Double -> Int -> Bool@@ -224,12 +261,16 @@ -- Is this result expected in a benchmark run on all of Hackage? isExpectedResult :: CabalResult -> Bool-isExpectedResult Solution = True-isExpectedResult NoInstallPlan = True-isExpectedResult BackjumpLimit = True-isExpectedResult Timeout = True-isExpectedResult PkgNotFound = False-isExpectedResult Unknown = False+isExpectedResult Solution = True+isExpectedResult NoInstallPlan = True+isExpectedResult BackjumpLimit = True+isExpectedResult Timeout = True+isExpectedResult Unbuildable = True+isExpectedResult UnbuildableDep = True+isExpectedResult ComponentCycle = True+isExpectedResult ModReexpIssue = True+isExpectedResult PkgNotFound = False+isExpectedResult Unknown = False -- Combine CabalResults from multiple trials. Ignoring timeouts, all results -- should be the same. If they aren't the same, we returns Unknown.
cabal/solver-benchmarks/LICENSE view
@@ -1,5 +1,8 @@-Copyright (c) 2003-2017, Cabal Development Team.+Copyright (c) 2003-2020, Cabal Development Team. See the AUTHORS file for the full list of copyright holders.++See */LICENSE for the copyright holders of the subcomponents.+ All rights reserved. Redistribution and use in source and binary forms, with or without
cabal/solver-benchmarks/solver-benchmarks.cabal view
@@ -1,6 +1,6 @@ name: solver-benchmarks-version: 3.1.0.0-copyright: 2003-2017, Cabal Development Team (see AUTHORS file)+version: 3+copyright: 2003-2020, Cabal Development Team (see AUTHORS file) license: BSD3 license-file: LICENSE author: Cabal Development Team <cabal-devel@haskell.org>@@ -30,6 +30,8 @@ base, bytestring, Cabal >= 2.3,+ directory,+ filepath, optparse-applicative, process, time,
+ cabal/tests/UnitTests/Distribution/Client/Init/goldens/generateCabalFile/exe-only.cabal view
@@ -0,0 +1,16 @@+cabal-version: 2.4+name: foo+version: 3.2.1+synopsis: The foo package+homepage: https://github.com/foo/foo+license: NONE+author: me+maintainer: me@me.me+category: SomeCat+extra-source-files: CHANGELOG.md++executable foo+ main-is: Main.hs+ build-depends: base ^>=4.13.0.0, containers ^>=5.7.0.0, unordered-containers ^>=2.7.0.0+ hs-source-dirs: app+ default-language: Haskell2010
+ cabal/tests/UnitTests/Distribution/Client/Init/goldens/generateCabalFile/lib-exe-and-test.cabal view
@@ -0,0 +1,29 @@+cabal-version: 2.4+name: foo+version: 3.2.1+synopsis: The foo package+homepage: https://github.com/foo/foo+license: NONE+author: me+maintainer: me@me.me+category: SomeCat+extra-source-files: CHANGELOG.md++library+ exposed-modules: A, B+ build-depends: base ^>=4.13.0.0, containers ^>=5.7.0.0, unordered-containers ^>=2.7.0.0+ hs-source-dirs: src+ default-language: Haskell2010++executable foo+ main-is: Main.hs+ build-depends: base ^>=4.13.0.0, containers ^>=5.7.0.0, unordered-containers ^>=2.7.0.0+ hs-source-dirs: app+ default-language: Haskell2010++test-suite foo-test+ default-language: Haskell2010+ type: exitcode-stdio-1.0+ hs-source-dirs: tests+ main-is: MyLibTest.hs+ build-depends: base ^>=4.13.0.0, containers ^>=5.7.0.0, unordered-containers ^>=2.7.0.0
+ cabal/tests/fixtures/init/exe-only-golden.cabal view
@@ -0,0 +1,20 @@+cabal-version: 2.4+name: foo+version: 3.2.1+synopsis: The foo package+homepage: https://github.com/foo/foo+license: NONE+author: me+maintainer: me@me.me+category: SomeCat+extra-source-files: CHANGELOG.md++executable foo+ main-is: Main.hs+ build-depends:+ base ^>=4.13.0.0,+ containers ^>=5.7.0.0,+ unordered-containers ^>=2.7.0.0++ hs-source-dirs: app+ default-language: Haskell2010
+ cabal/tests/fixtures/init/lib-and-exe-golden.cabal view
@@ -0,0 +1,31 @@+cabal-version: 2.4+name: foo+version: 3.2.1+synopsis: The foo package+homepage: https://github.com/foo/foo+license: NONE+author: me+maintainer: me@me.me+category: SomeCat+extra-source-files: CHANGELOG.md++library+ exposed-modules: MyLib+ build-depends:+ base ^>=4.13.0.0,+ containers ^>=5.7.0.0,+ unordered-containers ^>=2.7.0.0++ hs-source-dirs: src+ default-language: Haskell2010++executable foo+ main-is: Main.hs+ build-depends:+ base ^>=4.13.0.0,+ containers ^>=5.7.0.0,+ unordered-containers ^>=2.7.0.0,+ foo++ hs-source-dirs: app+ default-language: Haskell2010
+ cabal/tests/fixtures/init/lib-exe-and-test-golden.cabal view
@@ -0,0 +1,43 @@+cabal-version: 2.4+name: foo+version: 3.2.1+synopsis: The foo package+homepage: https://github.com/foo/foo+license: NONE+author: me+maintainer: me@me.me+category: SomeCat+extra-source-files: CHANGELOG.md++library+ exposed-modules:+ A+ B++ build-depends:+ base ^>=4.13.0.0,+ containers ^>=5.7.0.0,+ unordered-containers ^>=2.7.0.0++ hs-source-dirs: src+ default-language: Haskell2010++executable foo+ main-is: Main.hs+ build-depends:+ base ^>=4.13.0.0,+ containers ^>=5.7.0.0,+ unordered-containers ^>=2.7.0.0++ hs-source-dirs: app+ default-language: Haskell2010++test-suite foo-test+ default-language: Haskell2010+ type: exitcode-stdio-1.0+ hs-source-dirs: tests+ main-is: MyLibTest.hs+ build-depends:+ base ^>=4.13.0.0,+ containers ^>=5.7.0.0,+ unordered-containers ^>=2.7.0.0
+ cabal/tests/fixtures/init/lib-exe-and-test-with-comments-golden.cabal view
@@ -0,0 +1,110 @@+cabal-version: 2.4++-- Initial package description 'lib-exe-and-test-with-comments-golden.cabal' generated by+-- 'cabal init'. For further documentation, see:+-- http://haskell.org/cabal/users-guide/+-- +-- The name of the package.+name: foo++-- The package version.+-- See the Haskell package versioning policy (PVP) for standards+-- guiding when and how versions should be incremented.+-- https://pvp.haskell.org+-- PVP summary: +-+------- breaking API changes+-- | | +----- non-breaking API additions+-- | | | +--- code changes with no API change+version: 3.2.1++-- A short (one-line) description of the package.+synopsis: The foo package++-- A longer description of the package.+-- description:++-- URL for the project homepage or repository.+homepage: https://github.com/foo/foo++-- A URL where users can report bugs.+-- bug-reports:++-- The license under which the package is released.+license: NONE++-- The package author(s).+author: me++-- An email address to which users can send suggestions, bug reports, and patches.+maintainer: me@me.me++-- A copyright notice.+-- copyright:+category: SomeCat++-- Extra files to be distributed with the package, such as examples or a README.+extra-source-files: CHANGELOG.md++library+ -- Modules exported by the library.+ exposed-modules:+ A+ B++ -- Modules included in this library but not exported.+ -- other-modules:++ -- LANGUAGE extensions used by modules in this package.+ -- other-extensions:++ -- Other library packages from which modules are imported.+ build-depends:+ base ^>=4.13.0.0,+ containers ^>=5.7.0.0,+ unordered-containers ^>=2.7.0.0++ -- Directories containing source files.+ hs-source-dirs: src++ -- Base language which the package is written in.+ default-language: Haskell2010++executable foo+ -- .hs or .lhs file containing the Main module.+ main-is: Main.hs++ -- Modules included in this executable, other than Main.+ -- other-modules:++ -- LANGUAGE extensions used by modules in this package.+ -- other-extensions:++ -- Other library packages from which modules are imported.+ build-depends:+ base ^>=4.13.0.0,+ containers ^>=5.7.0.0,+ unordered-containers ^>=2.7.0.0++ -- Directories containing source files.+ hs-source-dirs: app++ -- Base language which the package is written in.+ default-language: Haskell2010++test-suite foo-test+ -- Base language which the package is written in.+ default-language: Haskell2010++ -- The interface type and version of the test suite.+ type: exitcode-stdio-1.0++ -- Directories containing source files.+ hs-source-dirs: tests++ -- The entrypoint to the test suite.+ main-is: MyLibTest.hs++ -- Test dependencies.+ build-depends:+ base ^>=4.13.0.0,+ containers ^>=5.7.0.0,+ unordered-containers ^>=2.7.0.0
cabal/travis-common.sh view
@@ -1,7 +1,7 @@ set -e -CABAL_VERSION="3.1.0.0"-CABAL_INSTALL_VERSION="3.1.0.0"+CABAL_VERSION="3.3.0.0"+CABAL_INSTALL_VERSION="3.3.0.0" if [ "$TRAVIS_OS_NAME" = "linux" ]; then ARCH="x86_64-linux"@@ -12,9 +12,9 @@ CABAL_STORE_DB="${HOME}/.cabal/store/ghc-${GHCVER}/package.db" CABAL_LOCAL_DB="${TRAVIS_BUILD_DIR}/dist-newstyle/packagedb/ghc-${GHCVER}" CABAL_BDIR="${TRAVIS_BUILD_DIR}/dist-newstyle/build/$ARCH/ghc-$GHCVER/Cabal-${CABAL_VERSION}"-CABAL_TESTSUITE_BDIR="${TRAVIS_BUILD_DIR}/dist-newstyle/build/$ARCH/ghc-$GHCVER/cabal-testsuite-${CABAL_VERSION}"+CABAL_TESTSUITE_BDIR="${TRAVIS_BUILD_DIR}/dist-newstyle/build/$ARCH/ghc-$GHCVER/cabal-testsuite-3" CABAL_INSTALL_BDIR="${TRAVIS_BUILD_DIR}/dist-newstyle/build/$ARCH/ghc-$GHCVER/cabal-install-${CABAL_INSTALL_VERSION}"-SOLVER_BENCHMARKS_BDIR="${TRAVIS_BUILD_DIR}/dist-newstyle/build/$ARCH/ghc-$GHCVER/solver-benchmarks-${CABAL_VERSION}"+SOLVER_BENCHMARKS_BDIR="${TRAVIS_BUILD_DIR}/dist-newstyle/build/$ARCH/ghc-$GHCVER/solver-benchmarks-3" CABAL_INSTALL_EXE=${CABAL_INSTALL_BDIR}/x/cabal/build/cabal/cabal # ---------------------------------------------------------------------
cabal/travis-deploy.sh view
@@ -8,7 +8,7 @@ (cd cabal-website && git checkout --track -b gh-pages origin/gh-pages) rm -rf cabal-website/doc mkdir -p cabal-website/doc/html- mv dist-newstyle/build/`uname -m`-$TRAVIS_OS_NAME/ghc-$GHCVER/Cabal-3.1.0.0/doc/html/Cabal \+ mv dist-newstyle/build/`uname -m`-$TRAVIS_OS_NAME/ghc-$GHCVER/Cabal-3.3.0.0/doc/html/Cabal \ cabal-website/doc/html/Cabal (cd cabal-website && git add --all .) (cd cabal-website && \
cabal/travis-install.sh view
@@ -13,7 +13,7 @@ if [ "$TRAVIS_OS_NAME" = "linux" ]; then travis_retry sudo add-apt-repository -y ppa:hvr/ghc travis_retry sudo apt-get update- travis_retry sudo apt-get install --force-yes cabal-install-2.4 ghc-$GHCVER-prof ghc-$GHCVER-dyn+ travis_retry sudo apt-get install --force-yes cabal-install-3.0 ghc-$GHCVER-prof ghc-$GHCVER-dyn if [ "x$TEST_OTHER_VERSIONS" = "xYES" ]; then travis_retry sudo apt-get install --force-yes ghc-7.0.4-prof ghc-7.0.4-dyn ghc-7.2.2-prof ghc-7.2.2-dyn ghc-head-prof ghc-head-dyn; fi if [ "$SCRIPT" = "meta" ]; then@@ -67,7 +67,7 @@ cd ..; mkdir "${HOME}/bin"- travis_retry curl -L https://downloads.haskell.org/~cabal/cabal-install-2.4.0.0/cabal-install-2.4.0.0-x86_64-apple-darwin-sierra.tar.gz | tar xzO > "${HOME}/bin/cabal"+ travis_retry curl -L https://downloads.haskell.org/~cabal/cabal-install-3.0.0.0/cabal-install-3.0.0.0-x86_64-apple-darwin17.7.0.tar.xz | tar xzO > "${HOME}/bin/cabal" chmod a+x "${HOME}/bin/cabal" "${HOME}/bin/cabal" --version
cabal/travis-meta.sh view
@@ -6,6 +6,10 @@ # Check that auto-generated files/fields are up to date. # --------------------------------------------------------------------- +# For some reason status might now be clean after checkout+git reset --hard+git status+ # Regenerate the CONTRIBUTORS file. # Currently doesn't work because Travis uses --depth=50 when cloning. #./Cabal/misc/gen-authors.sh > AUTHORS
cabal/travis-script.sh view
@@ -73,7 +73,8 @@ # Install executables if necessary # --------------------------------------------------------------------- -timed cabal install $jobs happy+# TODO: we need v2-install -z+(cd /tmp && timed cabal v2-install $jobs happy --overwrite-policy=always) # --------------------------------------------------------------------- # Setup our local project@@ -159,7 +160,8 @@ # test suites are baked into the cabal binary timed cabal new-build $jobs $CABAL_INSTALL_FLAGS cabal-install:cabal -timed cabal new-install $jobs hackage-repo-tool --overwrite-policy=always+# TODO: we need v2-install -z+(cd /tmp && timed cabal new-install $jobs hackage-repo-tool --overwrite-policy=always) if [ "x$SKIP_TESTS" = "xYES" ]; then exit 1;
cabal/travis/binaries/.travis.yml view
@@ -1,5 +1,5 @@ language: c-dist: trusty+dist: xenial # This doesn't actually help because we always push a single # commit to the branch in question #git:@@ -12,7 +12,7 @@ - export PATH=$HOME/bin:$PATH - export PATH=$HOME/.cabal/bin:$PATH - export PATH=$HOME/.local/bin:$PATH- - export PATH=/opt/cabal/2.4/bin:$PATH+ - export PATH=/opt/cabal/3.0/bin:$PATH - export PATH=/opt/happy/1.19.5/bin:$PATH - export PATH=/opt/alex/3.1.7/bin:$PATH - ./travis-install.sh
− cabal/validate.dockerfile
@@ -1,48 +0,0 @@-FROM haskell:8.6.5--# We need prof GHC for some tests-RUN apt-get update-RUN apt-get install ghc-8.6.5-prof--# Install cabal-plan-RUN cabal v2-update-RUN cabal v2-install cabal-plan --constraint 'cabal-plan ^>=0.6'--# We install happy, so it's in the store; we (hopefully) don't use it directly.-RUN cabal v2-install happy --constraint 'happy ^>=1.19.12'--# Install some other dependencies-# Remove $HOME/.ghc so there aren't any environments-RUN cabal v2-install -w ghc-8.6.5 --lib \- aeson \- async \- base-compat \- base16-bytestring \- base64-bytestring \- cryptohash-sha256 \- Diff \- echo \- ed25519 \- edit-distance \- haskell-lexer \- HTTP \- network \- optparse-applicative \- pretty-show \- regex-compat-tdfa \- regex-tdfa \- resolv \- statistics \- tar \- tasty \- tasty-golden \- tasty-hunit \- tasty-quickcheck \- tree-diff \- zlib \- && rm -rf $HOME/.ghc--# Validate-WORKDIR /build-COPY . /build-RUN sh ./validate.sh -w ghc-8.6.5 -v
cabal/validate.sh view
@@ -8,13 +8,22 @@ CABAL=cabal CABALPLAN=cabal-plan JOBS=4-CABALTESTS=true-CABALINSTALLTESTS=true+LIBTESTS=true+CLITESTS=true CABALSUITETESTS=true-CABALONLY=false+LIBONLY=false DEPSONLY=false+DOCTEST=false+BENCHMARKS=false VERBOSE=false+HACKAGETESTSALL=false +TARGETS=""+STEPS=""+EXTRAHCS=""++LISTSTEPS=false+ # Help ####################################################################### @@ -22,22 +31,31 @@ cat <<EOF ./validate.sh - build & test -Usage: ./validate.sh [ -j JOBS | -l | -C | -c | -s | -w HC | -x CABAL | -y CABALPLAN | -d | -v ]+Usage: ./validate.sh [options] A script which runs all the tests. Available options:- -j JOBS cabal v2-build -j argument (default: $JOBS)- -l Test Cabal-the-library only (default: $CABALONLY)- -C Don't run Cabal tests (default: $CABALTESTS)- -c Don't run cabal-install tests (default: $CABALINSTALLTESTS)- -s Don't run cabal-testsuite tests (default: $CABALSUITETESTS)- -w HC With compiler- -x CABAL With cabal-install- -y CABALPLAN With cabal-plan- -d Build dependencies only- -v Verbose+ -j, --jobs JOBS cabal v2-build -j argument (default: $JOBS)+ --libonly Test onlt Cabal-the-library+ --cli Test both Cabal-the-library and cabal-install+ --(no-)run-lib-tests Run library tests+ --(no-)run-cli-tests Run client tests+ --(no-)run-lib-suite Run cabal-testsuite with library+ --(no-)run-cli-suite Run cabal-testsuite with client+ -w, --with-compiler HC With compiler+ --with-cabal CABAL With cabal-install+ --with-cabal-plan CABALPLAN With cabal-plan+ --extra-hc HC Extra compiler to run test-suite with+ --(no-)doctest Run doctest on library+ --(no-)solver-benchmarks Build and trial run solver-benchmarks+ --complete-hackage-tests Run hackage-tests on complete Hackage data+ --partial-hackage-tests Run hackage-tests on parts of Hackage data+ -v, --verbose Verbose output+ -q, --quiet Less output+ -s, --step STEP Run only specific step (can be specified mutliple times)+ --list-steps List steps and build-targets and exit+ --help Print this message and exit EOF-exit 0 } # "library"@@ -99,93 +117,187 @@ fi } -footer() {- JOB_END_TIME=$(date +%s)- tduration=$((JOB_END_TIME - JOB_START_TIME))+print_header() {+ TITLE=$1+ TITLEPAT="$(echo "$TITLE"|sed 's:.:=:g')"+ echo "$CYAN===X============================================================ $(date +%T) ===$RESET" \+ | sed "s#X$TITLEPAT=# $TITLE #" - echo "$CYAN=== END ============================================ $(date +%T) === $RESET"- echo "$CYAN!!! Validation took $tduration seconds. $RESET" } # getopt ####################################################################### -while getopts 'j:lCcsw:x:y:dv' flag; do- case $flag in- j) JOBS="$OPTARG"+while [ $# -gt 0 ]; do+ arg=$1+ case $arg in+ --help)+ show_usage+ exit ;;- l) CABALONLY=true+ -j|--jobs)+ JOBS="$2"+ shift+ shift ;;- C) CABALTESTS=false+ --lib-only)+ LIBONLY=true+ shift ;;- c) CABALINSTALLTESTS=false+ --cli)+ LIBONLY=false+ shift ;;- s) CABALSUITETESTS=false+ --run-lib-tests)+ LIBTESTS=true+ shift ;;- w) HC="$OPTARG"+ --no-run-lib-tests)+ LIBTESTS=false+ shift ;;- x) CABAL="$OPTARG"+ --run-cli-tests)+ CLITESTS=true+ shift ;;- y) CABALPLAN="$OPTARG"+ --no-run-cli-tests)+ CLITESTS=false+ shift ;;- d) DEPSONLY=true+ --run-lib-suite)+ LIBSUITE=true+ shift ;;- v) VERBOSE=true+ --no-run-lib-suite)+ LIBSUITE=false+ shift ;;- ?) show_usage+ --run-cli-suite)+ CLISUITE=true+ shift ;;+ --no-run-cli-suite)+ CLISUITE=false+ shift+ ;;+ -w|--with-compiler)+ HC=$2+ shift+ shift+ ;;+ --with-cabal)+ CABAL=$2+ shift+ shift+ ;;+ --with-cabal-plan)+ CABALPLAN=$2+ shift+ shift+ ;;+ --extra-hc)+ EXTRAHCS="$EXTRAHCS $2"+ shift+ shift+ ;;+ --doctest)+ DOCTEST=true+ shift+ ;;+ --no-doctest)+ DOCTEST=false+ shift+ ;;+ --solver-benchmarks)+ BENCHMARKS=true+ shift+ ;;+ --no-solver-benchmarks)+ BENCHMARKS=false+ shift+ ;;+ --complete-hackage-tests)+ HACKAGETESTSALL=true+ shift+ ;;+ --partial-hackage-tests)+ HACKAGETESTSALL=false+ shift+ ;;+ -v|--verbose)+ VERBOSE=true+ shift+ ;;+ -q|--quiet)+ VERBOSE=false+ shift+ ;;+ -s|--step)+ STEPS="$STEPS $2"+ shift+ shift+ ;;+ --list-steps)+ LISTSTEPS=true+ shift+ ;;+ *)+ echo "Unknown option $arg"+ exit 1 esac done -shift $((OPTIND - 1))--# header+# calculate steps and build targets ####################################################################### -if [ "xhelp" = "x$1" ]; then- show_usage;+# If there are no explicit steps given calculate them+if $LIBONLY; then+ CLITESTS=false+ CLISUITE=false+ BENCHMARKS=false fi -TESTSUITEJOBS="-j$JOBS"-JOBS="-j$JOBS"--# assume compiler is GHC-RUNHASKELL=$(echo $HC | sed -E 's/ghc(-[0-9.]*)$/runghc\1/')--echo "$CYAN=== validate.sh ======================================== $(date +%T) === $RESET"--cat <<EOF-compiler: $HC-runhaskell $RUNHASKELL-cabal-install: $CABAL-cabal-plan: $CABALPLAN-jobs: $JOBS-Cabal tests: $CABALTESTS-cabal-install tests: $CABALINSTALLTESTS-cabal-testsuite: $CABALSUITETESTS-library only: $CABALONLY-dependencies only: $DEPSONLY-verbose: $VERBOSE+if [ -z "$STEPS" ]; then+ STEPS="print-config print-tool-versions"+ if ! $LIBONLY; then STEPS="$STEPS make-cabal-install-dev"; fi+ STEPS="$STEPS build"+ if $DOCTEST; then STEPS="$STEPS doctest"; fi+ if $LIBTESTS; then STEPS="$STEPS lib-tests"; fi+ if $LIBSUITE; then STEPS="$STEPS lib-suite"; fi+ if $LIBSUITE && [ -n "$EXTRAHCS" ];+ then STEPS="$STEPS lib-suite-extras"; fi+ if $CLITESTS; then STEPS="$STEPS cli-tests"; fi+ if $CLISUITE; then STEPS="$STEPS cli-suite"; fi+ if $BENCHMARKS; then STEPS="$STEPS solver-benchmarks-tests solver-benchmarks-run"; fi+ STEPS="$STEPS time-summary"+fi -EOF+TARGETS="Cabal cabal-testsuite"+if ! $LIBONLY; then TARGETS="$TARGETS cabal-install"; fi+if $BENCHMARKS; then TARGETS="$TARGETS solver-benchmarks"; fi -timed $HC --version-timed $CABAL --version-timed $CABALPLAN --version+if $LISTSTEPS; then+ echo "Targets: $TARGETS"+ echo "Steps: $STEPS"+ exit+fi -# Basic setup+# Adjust runtime configuration ####################################################################### -# NOTE: This should match cabal-testsuite version-CABAL_VERSION="3.1.0.0"+TESTSUITEJOBS="-j$JOBS"+JOBS="-j$JOBS" +# assume compiler is GHC+RUNHASKELL=$(echo $HC | sed -E 's/ghc(-[0-9.]*)$/runghc\1/')+ if [ "$(uname)" = "Linux" ]; then ARCH="x86_64-linux" else ARCH="x86_64-osx" fi -if $CABALONLY; then+if $LIBONLY; then PROJECTFILE=cabal.project.validate.libonly else PROJECTFILE=cabal.project.validate@@ -193,59 +305,83 @@ BASEHC=ghc-$($HC --numeric-version) BUILDDIR=dist-newstyle-validate-$BASEHC-CABAL_TESTSUITE_BDIR="$(pwd)/$BUILDDIR/build/$ARCH/$BASEHC/cabal-testsuite-${CABAL_VERSION}"+CABAL_TESTSUITE_BDIR="$(pwd)/$BUILDDIR/build/$ARCH/$BASEHC/cabal-testsuite-3" CABALNEWBUILD="${CABAL} v2-build $JOBS -w $HC --builddir=$BUILDDIR --project-file=$PROJECTFILE" CABALPLANLISTBIN="${CABALPLAN} list-bin --builddir=$BUILDDIR" -# SCRIPT+# header ####################################################################### -if ! $CABALONLY; then+step_print_config() {+print_header print-config -echo "$CYAN=== make cabal-install-dev ============================= $(date +%T) === $RESET"+cat <<EOF+compiler: $HC+runhaskell $RUNHASKELL+cabal-install: $CABAL+cabal-plan: $CABALPLAN+jobs: $JOBS+Cabal tests: $LIBTESTS+cabal-install tests: $CLITESTS+cabal-testsuite: $CABALSUITETESTS+library only: $LIBONLY+dependencies only: $DEPSONLY+doctest: $DOCTEST+benchmarks: $BENCHMARKS+verbose: $VERBOSE+extra complers: $EXTRAHCS -# make cabal-install-dev-timed ${RUNHASKELL} cabal-dev-scripts/src/Preprocessor.hs -o cabal-install/cabal-install.cabal -f CABAL_FLAG_LIB cabal-install/cabal-install.cabal.pp+EOF+} -fi # CABALONLY+step_print_tool_versions() {+print_header print-tool-versions -# Dependencies+timed $HC --version+timed $CABAL --version+timed $CABALPLAN --version -if $DEPSONLY; then+for EXTRAHC in $EXTRAHCS; do+ timed $EXTRAHC --version+done+} -echo "$CYAN=== dependencies ====================================== $(date +%T) === $RESET"+step_time_summary() {+ print_header END -timed $CABALNEWBUILD Cabal:lib:Cabal --enable-tests --disable-benchmarks --dep --dry-run || exit 1-timed $CABALNEWBUILD Cabal:lib:Cabal --enable-tests --disable-benchmarks --dep || exit 1-if $CABALTESTS; then- timed $CABALNEWBUILD Cabal --enable-tests --disable-benchmarks --dep --dry-run || exit 1- timed $CABALNEWBUILD Cabal --enable-tests --disable-benchmarks --dep || exit 1-fi+ JOB_END_TIME=$(date +%s)+ tduration=$((JOB_END_TIME - JOB_START_TIME)) -# Unfortunately we can not install cabal-install or cabal-testsuite dependencies:-# that would build Cabal-lib!+ echo "$CYAN!!! Validation took $tduration seconds. $RESET"+} -footer-exit+# build+####################################################################### -fi # DEPSONLY+step_make_cabal_install_dev() {+print_header "make cabal-install-dev"+timed cp cabal-install/cabal-install.cabal.dev cabal-install/cabal-install.cabal+} +step_build() {+print_header "build"+timed $CABALNEWBUILD $TARGETS --dry-run || exit 1+timed $CABALNEWBUILD $TARGETS || exit 1+}+ # Cabal lib ####################################################################### -echo "$CYAN=== Cabal: build ======================================= $(date +%T) === $RESET"--timed $CABALNEWBUILD Cabal:lib:Cabal --enable-tests --disable-benchmarks --dry-run || exit 1-timed $CABALNEWBUILD Cabal:lib:Cabal --enable-tests --disable-benchmarks --dep || exit 1-timed $CABALNEWBUILD Cabal:lib:Cabal --enable-tests --disable-benchmarks || exit 1--if $CABALTESTS; then-echo "$CYAN=== Cabal: test ======================================== $(date +%T) === $RESET"+step_doctest() {+print_header "Cabal: doctest"+cabal-env --name doctest-Cabal --transitive QuickCheck+cabal-env --name doctest-Cabal array bytestring containers deepseq directory filepath pretty process time binary unix text parsec mtl+timed doctest -package-env=doctest-Cabal --fast Cabal/Distribution Cabal/Language+} -timed $CABALNEWBUILD Cabal:tests --enable-tests --disable-benchmarks --dry-run || exit 1-timed $CABALNEWBUILD Cabal:tests --enable-tests --disable-benchmarks --dep || exit 1-timed $CABALNEWBUILD Cabal:tests --enable-tests --disable-benchmarks || exit 1+step_lib_tests() {+print_header "Cabal: tests" CMD="$($CABALPLANLISTBIN Cabal:test:unit-tests) $TESTSUITEJOBS --hide-successes --with-ghc=$HC" (cd Cabal && timed $CMD) || exit 1@@ -258,46 +394,40 @@ CMD=$($CABALPLANLISTBIN Cabal:test:hackage-tests) (cd Cabal && timed $CMD read-fields) || exit 1-(cd Cabal && timed $CMD parsec d) || exit 1-(cd Cabal && timed $CMD roundtrip k) || exit 1 -fi # $CABALTESTS--if $CABALSUITETESTS; then--echo "$CYAN=== cabal-testsuite: build ============================= $(date +%T) === $RESET"+if $HACKAGETESTSALL; then+ (cd Cabal && timed $CMD parsec) || exit 1+ (cd Cabal && timed $CMD roundtrip) || exit 1+else+ (cd Cabal && timed $CMD parsec d) || exit 1+ (cd Cabal && timed $CMD roundtrip k) || exit 1+fi+} -timed $CABALNEWBUILD cabal-testsuite --enable-tests --disable-benchmarks --dry-run || exit 1-timed $CABALNEWBUILD cabal-testsuite --enable-tests --disable-benchmarks --dep || exit 1-timed $CABALNEWBUILD cabal-testsuite --enable-tests --disable-benchmarks || exit 1+# Cabal cabal-testsuite+####################################################################### -echo "$CYAN=== cabal-testsuite: Cabal test ======================== $(date +%T) === $RESET"+step_lib_suite() {+print_header "Cabal: cabal-testsuite" CMD="$($CABALPLANLISTBIN cabal-testsuite:exe:cabal-tests) --builddir=$CABAL_TESTSUITE_BDIR $TESTSUITEJOBS --with-ghc=$HC --hide-successes" (cd cabal-testsuite && timed $CMD) || exit 1+} -fi # CABALSUITETESTS (Cabal)+step_lib_suite_extras() {+for EXTRAHC in $EXTRAHCS; do -# If testing only library, stop here-if $CABALONLY; then- footer- exit-fi+CMD="$($CABALPLANLISTBIN cabal-testsuite:exe:cabal-tests) --builddir=$CABAL_TESTSUITE_BDIR $TESTSUITEJOBS --with-ghc=$EXTRAHC --hide-successes"+(cd cabal-testsuite && timed $CMD) || exit 1 +done+}+ # cabal-install ####################################################################### -echo "$CYAN=== cabal-install: build =============================== $(date +%T) === $RESET"--timed $CABALNEWBUILD cabal-install --enable-tests --disable-benchmarks --dry-run || exit 1--# For some reason this sometimes fails. So we try twice.-CMD="$CABALNEWBUILD cabal-install --enable-tests --disable-benchmarks"-(timed $CMD) || (timed $CMD) || exit 1---if $CABALINSTALLTESTS; then-echo "$CYAN=== cabal-install: test ================================ $(date +%T) === $RESET"+step_cli_tests() {+print_header "cabal-install: tests" # this are sorted in asc time used, quicker tests first. CMD="$($CABALPLANLISTBIN cabal-install:test:solver-quickcheck) $TESTSUITEJOBS --hide-successes"@@ -314,21 +444,59 @@ # This test-suite doesn't like concurrency CMD="$($CABALPLANLISTBIN cabal-install:test:integration-tests2) -j1 --hide-successes --with-ghc=$HC" (cd cabal-install && timed $CMD) || exit 1--fi # CABALINSTALLTESTS+} +# cabal-install cabal-testsuite+####################################################################### -if $CABALSUITETESTS; then-echo "$CYAN=== cabal-testsuite: cabal-install test ================ $(date +%T) === $RESET"+step_cli_suite() {+print_header "cabal-install: cabal-testsuite" CMD="$($CABALPLANLISTBIN cabal-testsuite:exe:cabal-tests) --builddir=$CABAL_TESTSUITE_BDIR --with-cabal=$($CABALPLANLISTBIN cabal-install:exe:cabal) $TESTSUITEJOBS --hide-successes" (cd cabal-testsuite && timed $CMD) || exit 1+} -fi # CABALSUITETESTS+# solver-benchmarks+####################################################################### -# END+step_solver_benchmarks_tests() {+print_header "solver-benchmarks: test"++CMD="$($CABALPLANLISTBIN solver-benchmarks:test:unit-tests)"+(cd Cabal && timed $CMD) || exit 1+}++step_solver_benchmarks_run() {+print_header "solver-benchmarks: run"++SOLVEPKG=Chart-diagrams+CMD="$($CABALPLANLISTBIN solver-benchmarks:exe:hackage-benchmark) --cabal1=$CABAL --cabal2=$($CABALPLANLISTBIN cabal-install:exe:cabal) --trials=5 --packages=$SOLVEPKG --print-trials"+(cd Cabal && timed $CMD) || exit 1+}++# Steps dispatcher ####################################################################### -footer+for step in $STEPS; do+ case $step in+ print-config) step_print_config ;;+ print-tool-versions) step_print_tool_versions ;;+ make-cabal-install-dev) step_make_cabal_install_dev ;;+ build) step_build ;;+ doctest) step_doctest ;;+ lib-tests) step_lib_tests ;;+ cli-tests) step_cli_tests ;;+ lib-suite) step_lib_suite ;;+ lib-suite-extras) step_lib_suite_extras ;;+ cli-suite) step_cli_suite ;;+ solver-benchmarks-tests) step_solver_benchmarks_tests ;;+ solver-benchmarks-run) step_solver_benchmarks_run ;;+ time-summary) step_time_summary ;;+ *) + echo "Invalid step $step"+ exit 1+ ;;+ esac+done #######################################################################
+ cabal/weeder.dhall view
@@ -0,0 +1,9 @@+{ roots =+ [ "^Main\\.main$"+ , "^Hackage\\.Security\\."+ , "^Text\\.JSON\\.Canonical\\."+ , "Paths_Cabal\\."+ , "Paths_cabal_install\\."+ ]+, type-class-roots = True+}
hackage-security/.travis.yml view
@@ -4,9 +4,11 @@ # # For more information, see https://github.com/haskell-CI/haskell-ci #-# version: 0.7.20191101+# version: 0.9.20200325 #+version: ~> 1.0 language: c+os: linux dist: xenial git: # whether to recursively clone submodules@@ -15,6 +17,7 @@ directories: - $HOME/.cabal/packages - $HOME/.cabal/store+ - $HOME/.hlint - $HOME/.ghc-install before_cache: - rm -fv $CABALHOME/packages/hackage.haskell.org/build-reports.log@@ -25,30 +28,43 @@ - rm -fv $CABALHOME/packages/hackage.haskell.org/01-index.tar - rm -fv $CABALHOME/packages/hackage.haskell.org/01-index.tar.idx - rm -rfv $CABALHOME/packages/head.hackage-matrix:+jobs: include:- - compiler: ghc-8.8.1- addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.8.1","cabal-install-3.0"]}}+ - compiler: ghc-8.10.1+ addons: {"apt":{"sources":[{"sourceline":"deb http://ppa.launchpad.net/hvr/ghc/ubuntu xenial main","key_url":"https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x063dab2bdc0b3f9fcebc378bff3aeacef6f88286"}],"packages":["ghc-8.10.1","cabal-install-3.2"]}}+ os: linux+ - compiler: ghc-8.8.3+ addons: {"apt":{"sources":[{"sourceline":"deb http://ppa.launchpad.net/hvr/ghc/ubuntu xenial main","key_url":"https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x063dab2bdc0b3f9fcebc378bff3aeacef6f88286"}],"packages":["ghc-8.8.3","cabal-install-3.0"]}}+ os: linux - compiler: ghc-8.6.5- addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.6.5","cabal-install-3.0"]}}+ addons: {"apt":{"sources":[{"sourceline":"deb http://ppa.launchpad.net/hvr/ghc/ubuntu xenial main","key_url":"https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x063dab2bdc0b3f9fcebc378bff3aeacef6f88286"}],"packages":["ghc-8.6.5","cabal-install-3.0"]}}+ os: linux - compiler: ghc-8.4.4- addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.4.4","cabal-install-3.0"]}}+ addons: {"apt":{"sources":[{"sourceline":"deb http://ppa.launchpad.net/hvr/ghc/ubuntu xenial main","key_url":"https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x063dab2bdc0b3f9fcebc378bff3aeacef6f88286"}],"packages":["ghc-8.4.4","cabal-install-3.0"]}}+ os: linux - compiler: ghc-8.2.2- addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.2.2","cabal-install-3.0"]}}+ addons: {"apt":{"sources":[{"sourceline":"deb http://ppa.launchpad.net/hvr/ghc/ubuntu xenial main","key_url":"https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x063dab2bdc0b3f9fcebc378bff3aeacef6f88286"}],"packages":["ghc-8.2.2","cabal-install-3.0"]}}+ os: linux - compiler: ghc-8.0.2- addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.0.2","cabal-install-3.0"]}}+ addons: {"apt":{"sources":[{"sourceline":"deb http://ppa.launchpad.net/hvr/ghc/ubuntu xenial main","key_url":"https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x063dab2bdc0b3f9fcebc378bff3aeacef6f88286"}],"packages":["ghc-8.0.2","cabal-install-3.0"]}}+ os: linux - compiler: ghc-7.10.3- addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-7.10.3","cabal-install-3.0"]}}+ addons: {"apt":{"sources":[{"sourceline":"deb http://ppa.launchpad.net/hvr/ghc/ubuntu xenial main","key_url":"https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x063dab2bdc0b3f9fcebc378bff3aeacef6f88286"}],"packages":["ghc-7.10.3","cabal-install-3.0"]}}+ os: linux - compiler: ghc-7.8.4- addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-7.8.4","cabal-install-3.0"]}}+ addons: {"apt":{"sources":[{"sourceline":"deb http://ppa.launchpad.net/hvr/ghc/ubuntu xenial main","key_url":"https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x063dab2bdc0b3f9fcebc378bff3aeacef6f88286"}],"packages":["ghc-7.8.4","cabal-install-3.0"]}}+ os: linux - compiler: ghc-7.6.3- addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-7.6.3","cabal-install-3.0"]}}+ addons: {"apt":{"sources":[{"sourceline":"deb http://ppa.launchpad.net/hvr/ghc/ubuntu xenial main","key_url":"https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x063dab2bdc0b3f9fcebc378bff3aeacef6f88286"}],"packages":["ghc-7.6.3","cabal-install-3.0"]}}+ os: linux - compiler: ghc-7.4.2- addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-7.4.2","cabal-install-3.0"]}}+ addons: {"apt":{"sources":[{"sourceline":"deb http://ppa.launchpad.net/hvr/ghc/ubuntu xenial main","key_url":"https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x063dab2bdc0b3f9fcebc378bff3aeacef6f88286"}],"packages":["ghc-7.4.2","cabal-install-3.0"]}}+ os: linux - compiler: ghc-head- addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-head","cabal-install-head"]}}+ addons: {"apt":{"sources":[{"sourceline":"deb http://ppa.launchpad.net/hvr/ghc/ubuntu xenial main","key_url":"https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x063dab2bdc0b3f9fcebc378bff3aeacef6f88286"}],"packages":["ghc-head","cabal-install-head"]}}+ os: linux - compiler: ghc-8.4.4- addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.4.4","cabal-install-3.0"]}}+ addons: {"apt":{"sources":[{"sourceline":"deb http://ppa.launchpad.net/hvr/ghc/ubuntu xenial main","key_url":"https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x063dab2bdc0b3f9fcebc378bff3aeacef6f88286"}],"packages":["ghc-8.4.4","cabal-install-3.0"]}} os: osx allow_failures: - compiler: ghc-head@@ -67,58 +83,29 @@ - if [ "$TRAVIS_OS_NAME" = "osx" ]; then HC=$HOME/.ghc-install/ghc/bin/$TRAVIS_COMPILER; WITHCOMPILER="-w $HC"; HCPKG=${HC/ghc/ghc-pkg}; CABAL=$HOME/.ghc-install/ghc/bin/cabal; fi - "HCNUMVER=$(${HC} --numeric-version|perl -ne '/^(\\d+)\\.(\\d+)\\.(\\d+)(\\.(\\d+))?$/; print(10000 * $1 + 100 * $2 + ($3 == 0 ? $5 != 1 : $3))')" - echo $HCNUMVER- - CABAL="$CABAL -vnormal+nowrap+markoutput"+ - CABAL="$CABAL -vnormal+nowrap" - set -o pipefail- - |- echo 'function blue(s) { printf "\033[0;34m" s "\033[0m " }' >> .colorful.awk- echo 'BEGIN { state = "output"; }' >> .colorful.awk- echo '/^-----BEGIN CABAL OUTPUT-----$/ { state = "cabal" }' >> .colorful.awk- echo '/^-----END CABAL OUTPUT-----$/ { state = "output" }' >> .colorful.awk- echo '!/^(-----BEGIN CABAL OUTPUT-----|-----END CABAL OUTPUT-----)/ {' >> .colorful.awk- echo ' if (state == "cabal") {' >> .colorful.awk- echo ' print blue($0)' >> .colorful.awk- echo ' } else {' >> .colorful.awk- echo ' print $0' >> .colorful.awk- echo ' }' >> .colorful.awk- echo '}' >> .colorful.awk- - cat .colorful.awk- - |- color_cabal_output () {- awk -f $TOP/.colorful.awk- }- - echo text | color_cabal_output-install:- - ${CABAL} --version- - echo "$(${HC} --version) [$(${HC} --print-project-git-commit-id 2> /dev/null || echo '?')]" - TEST=--enable-tests - BENCH=--enable-benchmarks - HEADHACKAGE=false- - if [ $HCNUMVER -gt 80801 ] ; then HEADHACKAGE=true ; fi+ - if [ $HCNUMVER -gt 81001 ] ; then HEADHACKAGE=true ; fi - rm -f $CABALHOME/config - |- echo "verbose: normal +nowrap +markoutput" >> $CABALHOME/config- echo "remote-build-reporting: anonymous" >> $CABALHOME/config- echo "write-ghc-environment-files: always" >> $CABALHOME/config- echo "remote-repo-cache: $CABALHOME/packages" >> $CABALHOME/config- echo "logs-dir: $CABALHOME/logs" >> $CABALHOME/config- echo "world-file: $CABALHOME/world" >> $CABALHOME/config- echo "extra-prog-path: $CABALHOME/bin" >> $CABALHOME/config- echo "symlink-bindir: $CABALHOME/bin" >> $CABALHOME/config- echo "installdir: $CABALHOME/bin" >> $CABALHOME/config- echo "build-summary: $CABALHOME/logs/build.log" >> $CABALHOME/config- echo "store-dir: $CABALHOME/store" >> $CABALHOME/config- echo "install-dirs user" >> $CABALHOME/config- echo " prefix: $CABALHOME" >> $CABALHOME/config- echo "repository hackage.haskell.org" >> $CABALHOME/config- echo " url: http://hackage.haskell.org/" >> $CABALHOME/config- echo " secure: True" >> $CABALHOME/config- echo " key-threshold: 3" >> $CABALHOME/config- echo " root-keys:" >> $CABALHOME/config- echo " fe331502606802feac15e514d9b9ea83fee8b6ffef71335479a2e68d84adc6b0" >> $CABALHOME/config- echo " 1ea9ba32c526d1cc91ab5e5bd364ec5e9e8cb67179a471872f6e26f0ae773d42" >> $CABALHOME/config- echo " 2c6c3627bd6c982990239487f1abd02e08a02e6cf16edb105a8012d444d870c3" >> $CABALHOME/config- echo " 0a5c7ea47cd1b15f01f5f51a33adda7e655bc0f0b0615baa8e271f4c3351e21d" >> $CABALHOME/config- echo " 51f0161b906011b52c6613376b1ae937670da69322113a246a09f807c62f6921" >> $CABALHOME/config+ echo "verbose: normal +nowrap +markoutput" >> $CABALHOME/config+ echo "remote-build-reporting: anonymous" >> $CABALHOME/config+ echo "write-ghc-environment-files: always" >> $CABALHOME/config+ echo "remote-repo-cache: $CABALHOME/packages" >> $CABALHOME/config+ echo "logs-dir: $CABALHOME/logs" >> $CABALHOME/config+ echo "world-file: $CABALHOME/world" >> $CABALHOME/config+ echo "extra-prog-path: $CABALHOME/bin" >> $CABALHOME/config+ echo "symlink-bindir: $CABALHOME/bin" >> $CABALHOME/config+ echo "installdir: $CABALHOME/bin" >> $CABALHOME/config+ echo "build-summary: $CABALHOME/logs/build.log" >> $CABALHOME/config+ echo "store-dir: $CABALHOME/store" >> $CABALHOME/config+ echo "install-dirs user" >> $CABALHOME/config+ echo " prefix: $CABALHOME" >> $CABALHOME/config+ echo "repository hackage.haskell.org" >> $CABALHOME/config+ echo " url: http://hackage.haskell.org/" >> $CABALHOME/config - | if $HEADHACKAGE; then echo "allow-newer: $($HCPKG list --simple-output | sed -E 's/([a-zA-Z-]+)-[0-9.]+/*:\1/g')" >> $CABALHOME/config@@ -130,6 +117,9 @@ echo " f76d08be13e9a61a377a85e2fb63f4c5435d40f8feb3e12eb05905edb8cdea89" >> $CABALHOME/config echo " key-threshold: 3" >> $CABALHOME/config fi+install:+ - ${CABAL} --version+ - echo "$(${HC} --version) [$(${HC} --print-project-git-commit-id 2> /dev/null || echo '?')]" - | echo "program-default-options" >> $CABALHOME/config echo " ghc-options: $GHCJOBS +RTS -M6G -RTS" >> $CABALHOME/config@@ -158,15 +148,15 @@ - if [ -f "hackage-root-tool/configure.ac" ]; then (cd "hackage-root-tool" && autoreconf -i); fi - if [ -f "hackage-repo-tool/configure.ac" ]; then (cd "hackage-repo-tool" && autoreconf -i); fi - if [ -f "hackage-security-HTTP/configure.ac" ]; then (cd "hackage-security-HTTP" && autoreconf -i); fi- - ${CABAL} v2-freeze $WITHCOMPILER ${TEST} ${BENCH} | color_cabal_output+ - ${CABAL} v2-freeze $WITHCOMPILER ${TEST} ${BENCH} - "cat cabal.project.freeze | sed -E 's/^(constraints: *| *)//' | sed 's/any.//'" - rm cabal.project.freeze- - ${CABAL} v2-build $WITHCOMPILER ${TEST} ${BENCH} --dep -j2 all | color_cabal_output- - ${CABAL} v2-build $WITHCOMPILER --disable-tests --disable-benchmarks --dep -j2 all | color_cabal_output+ - travis_wait 40 ${CABAL} v2-build $WITHCOMPILER ${TEST} ${BENCH} --dep -j2 all+ - travis_wait 40 ${CABAL} v2-build $WITHCOMPILER --disable-tests --disable-benchmarks --dep -j2 all script: - DISTDIR=$(mktemp -d /tmp/dist-test.XXXX) # Packaging...- - ${CABAL} v2-sdist all | color_cabal_output+ - ${CABAL} v2-sdist all # Unpacking... - mv dist-newstyle/sdist/*.tar.gz ${DISTDIR}/ - cd ${DISTDIR} || false@@ -196,12 +186,12 @@ - cat cabal.project.local || true # Building... # this builds all libraries and executables (without tests/benchmarks)- - ${CABAL} v2-build $WITHCOMPILER --disable-tests --disable-benchmarks all | color_cabal_output+ - ${CABAL} v2-build $WITHCOMPILER --disable-tests --disable-benchmarks all # Building with tests and benchmarks... # build & run tests, build benchmarks- - ${CABAL} v2-build $WITHCOMPILER ${TEST} ${BENCH} all | color_cabal_output+ - ${CABAL} v2-build $WITHCOMPILER ${TEST} ${BENCH} all # Testing...- - ${CABAL} v2-test $WITHCOMPILER ${TEST} ${BENCH} all | color_cabal_output+ - ${CABAL} v2-test $WITHCOMPILER ${TEST} ${BENCH} all # cabal check... - (cd ${PKGDIR_hackage_security} && ${CABAL} -vnormal check) - (cd ${PKGDIR_hackage_security_http_client} && ${CABAL} -vnormal check)@@ -211,10 +201,10 @@ - (cd ${PKGDIR_hackage_repo_tool} && ${CABAL} -vnormal check) - (cd ${PKGDIR_hackage_security_HTTP} && ${CABAL} -vnormal check) # haddock...- - ${CABAL} v2-haddock $WITHCOMPILER --with-haddock $HADDOCK ${TEST} ${BENCH} all | color_cabal_output+ - ${CABAL} v2-haddock $WITHCOMPILER --with-haddock $HADDOCK ${TEST} ${BENCH} all # Building without installed constraints for packages in global-db... - rm -f cabal.project.local- - ${CABAL} v2-build $WITHCOMPILER --disable-tests --disable-benchmarks all | color_cabal_output+ - ${CABAL} v2-build $WITHCOMPILER --disable-tests --disable-benchmarks all -# REGENDATA ("0.7.20191101",["--ghc-head","--osx=8.4.4","cabal.project"])+# REGENDATA ("0.9.20200325",["--ghc-head","--osx=8.4.4","cabal.project"]) # EOF
hackage-security/example-client/example-client.cabal view
@@ -10,7 +10,7 @@ category: Distribution build-type: Simple cabal-version: >=1.10-tested-with: GHC==8.8.1, GHC==8.6.5, GHC==8.4.4, GHC==8.2.2, GHC==8.0.2,+tested-with: GHC==8.10.1, GHC==8.8.3, GHC==8.6.5, GHC==8.4.4, GHC==8.2.2, GHC==8.0.2, GHC==7.10.3, GHC==7.8.4, GHC==7.6.3, GHC==7.4.2 flag use-network-uri@@ -21,7 +21,7 @@ main-is: Main.hs other-modules: Prelude ExampleClient.Options - build-depends: base >= 4.5 && < 4.14,+ build-depends: base >= 4.5 && < 4.15, bytestring >= 0.9, Cabal >= 1.12, directory >= 1.1,
hackage-security/hackage-repo-tool/ChangeLog.md view
@@ -1,3 +1,7 @@+0.1.1.2+-------+* Compat release for `hackage-security-0.6`+ 0.1.1.1 ------- * Make `hackage-repo-tool` buildable on Windows (#175)
+ hackage-security/hackage-repo-tool/README.md view
@@ -0,0 +1,98 @@+# `hackage-repo-tool`: Manage secure file-based package repositories++**Please refer to the [package description](https://hackage.haskell.org/package/hackage-repo-tool#description) for an overview of `hackage-repo-tool`, TUF and `hackage-security`.**++## Setting up a secure file-based repo++A file-based repository (as opposed to one running the actual [Hackage software](https://hackage.haskell.org/package/hackage-server)) is much easier to set up and will suffice for many purposes. Note that such a local file-based package repository can be turned into a remotely accessible secure package repository by any HTTP server supporting static file serving such as Nginx or Apache httpd.++1. Create a directory `~/my-secure-repo` containing a single+ subdirectory `~/my-secure-repo/package`. Put whatever packages you+ want to make available from your repo in this subdirectory. At this+ point your repository might look like++ ~/my-secure-repo/package/basic-sop-0.1.0.5.tar.gz+ ~/my-secure-repo/package/generics-sop-0.1.1.1.tar.gz+ ~/my-secure-repo/package/generics-sop-0.1.1.2.tar.gz+ ~/my-secure-repo/package/json-sop-0.1.0.4.tar.gz+ ~/my-secure-repo/package/lens-sop-0.1.0.2.tar.gz+ ~/my-secure-repo/package/pretty-sop-0.1.0.1.tar.gz+ ~/my-secure-repo/package/HsYAML-0.2.1.0.tar.gz++ *(Due to [#174](https://github.com/haskell/hackage-security/issues/174) this folder must contain at least one package tarball or `hackage-repo-tool` will fail in non-obvious ways)*++ Note the flat directory structure: different packages and+ different versions of those packages all live in the one+ directory.++2. Create public and private keys:++ # hackage-repo-tool create-keys \+ --keys ~/my-private-keys++ This will create a directory structure such as++ ~/my-private-keys/mirrors/id01.private+ ~/my-private-keys/mirrors/..+ ~/my-private-keys/root/id04.private+ ~/my-private-keys/root/..+ ~/my-private-keys/snapshot/id07.private+ ~/my-private-keys/target/id08.private+ ~/my-private-keys/target/..+ ~/my-private-keys/timestamp/id11.private++ containing keys for all the various TUF roles.++ Note that these keys are stored outside of the repository proper.++3. Create the initial TUF metadata and construct an index using++ # hackage-repo-tool bootstrap \+ --repo ~/my-secure-repo \+ --keys ~/my-private-keys++ This will create a directory `~/my-secure-repo/index` containing the+ `.cabal` files (extracted from the package tarballs) and TUF+ metadata for all packages++ ~/my-secure-repo/index/basic-sop/0.1.0.5/basic-sop.cabal+ ~/my-secure-repo/index/basic-sop/0.1.0.5/package.json+ ~/my-secure-repo/index/generics-sop/0.1.1.1/generics-sop.cabal+ ~/my-secure-repo/index/generics-sop/0.1.1.1/package.json+ ...++ and package the contents of that directory up as the index tarball+ `~/my-secure-repo/00-index.tar.gz`; it will also create the+ top-level metadata files++ ~/my-secure-repo/mirrors.json+ ~/my-secure-repo/root.json+ ~/my-secure-repo/snapshot.json+ ~/my-secure-repo/timestamp.json++4. The timestamp and snapshot are valid for three days, so you will+ need to resign these files regularly using++ # hackage-repo-tool update \+ --repo ~/my-secure-repo \+ --keys ~/my-private-keys++ You can use the same command whenever you add any additional+ packages to your repository.++5. If you now make this directory available (for instance, by pointing+ Apache httpd at it) you'll be able to use `cabal` to access it remotely by+ defining an appropriate [`repository` stanza](https://www.haskell.org/cabal/users-guide/installing-packages.html#using-secure-repositories):++ repository my-secure-repo+ url: http://packages.example.org/+ secure: True+ root-keys: 2ae741f4c4a5f70ed6e6c48762e0d7a493d8dd265e9cbc6c4037dfc7ceaec70e+ 32d3db5b4403935c0baf52a2bcb05031784a971ee2d43587288776f2e90609db+ eed36d2bb15f94628221cde558e99c4e1ad36fd243fe3748e1ee7ad00eb9d628+ key-threshold: 2++ Note that the keys in example above must be replaced: You need to+ copy the root key IDs from your generated `root.json` file (or you+ can set `key-threshold` to 0 if you're aware of the security+ implications)
hackage-security/hackage-repo-tool/hackage-repo-tool.cabal view
@@ -1,19 +1,17 @@ cabal-version: 1.12 name: hackage-repo-tool-version: 0.1.1.1+version: 0.1.1.2 +build-type: Simple synopsis: Manage secure file-based package repositories description: This utility can be used to manage secure file-based package- repositories (creating- [TUF](https://theupdateframework.github.io/)- metadata as well as a Hackage index tarball) which can be used- by clients such as- [cabal-install](http://hackage.haskell.org/package/cabal-install).- Currently it also provides various lower level utilities- for creating and signing TUF files.+ repositories (creating [TUF](https://theupdateframework.github.io/)+ metadata as well as a Hackage index tarball) which can be used by+ clients such as [cabal-install](http://hackage.haskell.org/package/cabal-install).+ Currently it also provides various lower level utilities for creating+ and signing TUF files. .- This is part of the- [Hackage Security](https://github.com/haskell/hackage-security#readme)+ This is part of the [Hackage Security](https://github.com/haskell/hackage-security#readme) infrastructure. license: BSD3 license-file: LICENSE@@ -23,12 +21,11 @@ category: Distribution homepage: https://github.com/haskell/hackage-security bug-reports: https://github.com/haskell/hackage-security/issues-build-type: Simple-tested-with: GHC==8.8.1, GHC==8.6.5, GHC==8.4.4, GHC==8.2.2, GHC==8.0.2,+tested-with: GHC==8.10.1, GHC==8.8.3, GHC==8.6.5, GHC==8.4.4, GHC==8.2.2, GHC==8.0.2, GHC==7.10.3, GHC==7.8.4, GHC==7.6.3, GHC==7.4.2 extra-source-files:- ChangeLog.md+ ChangeLog.md README.md source-repository head type: git@@ -52,17 +49,16 @@ Hackage.Security.RepoTool.Util.IO Prelude - build-depends: base >= 4.5 && < 5,- Cabal >= 1.14 && < 3.1,+ -- For boot libraries we try to accomodate the versions bundled with+ -- the respective GHC release+ build-depends: base >= 4.5 && < 4.15, bytestring >= 0.9 && < 0.11,+ Cabal >= 1.14 && < 1.26+ || >= 2.0 && < 2.6+ || >= 3.0 && < 3.4, directory >= 1.1 && < 1.4,- filepath >= 1.2 && < 1.5,- microlens >= 0.4.11.2 && < 0.5,- optparse-applicative >= 0.11 && < 0.16,- tar >= 0.4 && < 0.6,- time >= 1.2 && < 1.10,- zlib >= 0.5 && < 0.7,- hackage-security >= 0.5 && < 0.7+ filepath >= 1.3 && < 1.5,+ time >= 1.4 && < 1.10 if !os(windows) build-depends: unix >= 2.5 && < 2.8 @@ -72,12 +68,22 @@ else build-depends: directory >= 1.2 + -- For non-boot libraries we try to support single major versions+ -- to reduce the risk of semantic differences+ build-depends: microlens >= 0.4.11.2 && < 0.5,+ optparse-applicative >= 0.15.1 && < 0.16,+ tar >= 0.5 && < 0.6,+ zlib >= 0.6 && < 0.7,+ hackage-security >= 0.6 && < 0.7+ -- see comments in hackage-security.cabal if flag(use-network-uri) build-depends: network-uri >= 2.6 && < 2.7,- network >= 2.6 && < 3.2+ network >= 2.6 && < 2.9+ || >= 3.0 && < 3.2 else build-depends: network >= 2.5 && < 2.6+ default-language: Haskell2010 default-extensions: DeriveDataTypeable
hackage-security/hackage-root-tool/hackage-root-tool.cabal view
@@ -14,7 +14,7 @@ category: Distribution build-type: Simple cabal-version: >=1.10-tested-with: GHC==8.8.1, GHC==8.6.5, GHC==8.4.4, GHC==8.2.2, GHC==8.0.2,+tested-with: GHC==8.10.1, GHC==8.8.3, GHC==8.6.5, GHC==8.4.4, GHC==8.2.2, GHC==8.0.2, GHC==7.10.3, GHC==7.8.4, GHC==7.6.3, GHC==7.4.2 extra-source-files:
hackage-security/hackage-security-HTTP/hackage-security-HTTP.cabal view
@@ -15,7 +15,7 @@ bug-reports: https://github.com/haskell/hackage-security/issues build-type: Simple cabal-version: >=1.10-tested-with: GHC==8.8.1, GHC==8.6.5, GHC==8.4.4, GHC==8.2.2, GHC==8.0.2,+tested-with: GHC==8.10.1, GHC==8.8.3, GHC==8.6.5, GHC==8.4.4, GHC==8.2.2, GHC==8.0.2, GHC==7.10.3, GHC==7.8.4, GHC==7.6.3, GHC==7.4.2 extra-source-files:
hackage-security/hackage-security-curl/hackage-security-curl.cabal view
@@ -14,7 +14,7 @@ category: Distribution build-type: Simple cabal-version: >=1.10-tested-with: GHC==8.8.1, GHC==8.6.5, GHC==8.4.4, GHC==8.2.2, GHC==8.0.2,+tested-with: GHC==8.10.1, GHC==8.8.3, GHC==8.6.5, GHC==8.4.4, GHC==8.2.2, GHC==8.0.2, GHC==7.10.3, GHC==7.8.4, GHC==7.6.3, GHC==7.4.2 flag use-network-uri@@ -23,7 +23,7 @@ library exposed-modules: Hackage.Security.Client.Repository.HttpLib.Curl- build-depends: base >= 4.5 && < 4.14,+ build-depends: base >= 4.5 && < 4.15, bytestring >= 0.9, process >= 1.1, hackage-security
hackage-security/hackage-security-http-client/hackage-security-http-client.cabal view
@@ -13,7 +13,7 @@ category: Distribution build-type: Simple cabal-version: >=1.10-tested-with: GHC==8.8.1, GHC==8.6.5, GHC==8.4.4, GHC==8.2.2, GHC==8.0.2,+tested-with: GHC==8.10.1, GHC==8.8.3, GHC==8.6.5, GHC==8.4.4, GHC==8.2.2, GHC==8.0.2, GHC==7.10.3, GHC==7.8.4, GHC==7.6.3, GHC==7.4.2 flag use-network-uri@@ -22,7 +22,7 @@ library exposed-modules: Hackage.Security.Client.Repository.HttpLib.HttpClient- build-depends: base >= 4.5 && < 4.14,+ build-depends: base >= 4.5 && < 4.15, bytestring >= 0.9, data-default-class >= 0.0, http-client >= 0.4 && < 0.7,
hackage-security/hackage-security/ChangeLog.md view
@@ -1,5 +1,11 @@ See also http://pvp.haskell.org/faq +0.6.0.1+-------++* Fix bug in non-default `-lukko` build-configuration (#242)+* Add support for `template-haskell-2.16.0.0` (#240)+ 0.6.0.0 -------
hackage-security/hackage-security/hackage-security.cabal view
@@ -1,6 +1,6 @@ cabal-version: 1.12 name: hackage-security-version: 0.6.0.0+version: 0.6.0.1 synopsis: Hackage security library description: The hackage security library provides both server and@@ -29,7 +29,7 @@ homepage: https://github.com/haskell/hackage-security bug-reports: https://github.com/haskell/hackage-security/issues build-type: Simple-tested-with: GHC==8.8.1, GHC==8.6.5, GHC==8.4.4, GHC==8.2.2, GHC==8.0.2,+tested-with: GHC==8.10.1, GHC==8.8.3, GHC==8.6.5, GHC==8.4.4, GHC==8.2.2, GHC==8.0.2, GHC==7.10.3, GHC==7.8.4, GHC==7.6.3, GHC==7.4.2 @@ -110,13 +110,13 @@ Hackage.Security.Util.TypedEmbedded Prelude -- We support ghc 7.4 (bundled with Cabal 1.14) and up- build-depends: base >= 4.5 && < 4.14,+ build-depends: base >= 4.5 && < 4.15, base16-bytestring >= 0.1.1 && < 0.2,- base64-bytestring >= 1.0 && < 1.1,+ base64-bytestring >= 1.0 && < 1.2, bytestring >= 0.9 && < 0.11, Cabal >= 1.14 && < 1.26 || >= 2.0 && < 2.6- || >= 3.0 && < 3.2,+ || >= 3.0 && < 3.4, containers >= 0.4 && < 0.7, ed25519 >= 0.0 && < 0.1, filepath >= 1.2 && < 1.5,@@ -126,11 +126,11 @@ -- 0.4.2 introduces TarIndex, 0.4.4 introduces more -- functionality, 0.5.0 changes type of serialise tar >= 0.5 && < 0.6,+ template-haskell >= 2.7 && < 2.17, time >= 1.2 && < 1.10, transformers >= 0.3 && < 0.6, zlib >= 0.5 && < 0.7, -- whatever versions are bundled with ghc:- template-haskell, ghc-prim if flag(old-directory) build-depends: directory >= 1.1.0.2 && < 1.2,@@ -176,9 +176,9 @@ PackageImports UndecidableInstances - -- use the new stage1/cross-compile-friendly Quotes subset of TH for new GHCs+ -- use the new stage1/cross-compile-friendly DeriveLift extension for GHC 8.0+ if impl(ghc >= 8.0)- other-extensions: TemplateHaskellQuotes+ other-extensions: DeriveLift else other-extensions: TemplateHaskell
hackage-security/hackage-security/src/Hackage/Security/TUF/Patterns.hs view
@@ -4,7 +4,8 @@ -- It is currently unusued. {-# LANGUAGE CPP #-} #if __GLASGOW_HASKELL__ >= 800-{-# LANGUAGE TemplateHaskellQuotes #-}+{-# LANGUAGE DeriveLift #-}+{-# LANGUAGE StandaloneDeriving #-} #else {-# LANGUAGE TemplateHaskell #-} #endif@@ -272,6 +273,11 @@ Left err -> fail $ "Invalid delegation: " ++ err Right del -> TH.lift del +#if __GLASGOW_HASKELL__ >= 800+deriving instance TH.Lift (Pattern a)+deriving instance TH.Lift (Replacement a)+deriving instance TH.Lift Delegation+#else instance TH.Lift (Pattern a) where lift (PatFileConst fn) = [| PatFileConst fn |] lift (PatFileExt e) = [| PatFileExt e |]@@ -288,6 +294,7 @@ instance TH.Lift Delegation where lift (Delegation pat repl) = [| Delegation pat repl |]+#endif {------------------------------------------------------------------------------- JSON
hackage-security/hackage-security/src/Hackage/Security/Util/IO.hs view
@@ -141,10 +141,10 @@ (me++"cannot remove lock file before directory lock fallback") releaseLock (Just h) =- hClose h #if MIN_VERSION_base(4,11,0)- >> hUnlock h+ hUnlock h >> #endif+ hClose h releaseLock Nothing = removeDirectory lock #endif
hackport.cabal view
@@ -1,6 +1,6 @@ Name: hackport-Version: 0.6.5-License: GPL+Version: 0.6.6+License: GPL-3 License-file: LICENSE Author: Henning Günther, Duncan Coutts, Lennart Kolmodin Maintainer: Gentoo Haskell team <haskell@gentoo.org>@@ -28,7 +28,7 @@ hackage-security/hackage-security/src Build-Depends: array >= 0.4.0.1,- base >= 4.8 && < 5,+ base >= 4.9 && < 5, bytestring >= 0.10, containers >= 0.5, deepseq >= 1.3.0.1,@@ -111,6 +111,7 @@ HackPort.GlobalFlags Merge Merge.Dependencies+ Merge.Utils Overlays Paths_hackport Portage.Cabal@@ -134,7 +135,7 @@ Portage.Version Status Util- -- cabal modules+ -- cabal modules Distribution.Backpack Distribution.Backpack.ComponentsGraph Distribution.Backpack.Configure@@ -155,6 +156,7 @@ Distribution.Client.BuildReports.Types Distribution.Client.CmdInstall.ClientInstallFlags Distribution.Client.Compat.Directory+ Distribution.Client.Compat.Orphans Distribution.Client.Compat.Prelude Distribution.Client.Compat.Semaphore Distribution.Client.Config@@ -162,22 +164,39 @@ Distribution.Client.FetchUtils Distribution.Client.GZipUtils Distribution.Client.GlobalFlags+ Distribution.Client.HashValue Distribution.Client.HttpUtils Distribution.Client.IndexUtils+ Distribution.Client.IndexUtils.ActiveRepos+ Distribution.Client.IndexUtils.IndexState Distribution.Client.IndexUtils.Timestamp+ Distribution.Client.Init.Defaults Distribution.Client.Init.Types- Distribution.Client.InstallPlan- Distribution.Client.InstallSymlink Distribution.Client.JobControl+ Distribution.Client.ManpageFlags Distribution.Client.ParseUtils+ Distribution.Client.ProjectFlags Distribution.Client.Security.DNS Distribution.Client.Security.HTTP Distribution.Client.Setup- Distribution.Client.SolverInstallPlan- Distribution.Client.SourceRepo Distribution.Client.Tar Distribution.Client.Targets Distribution.Client.Types+ Distribution.Client.Types.AllowNewer+ Distribution.Client.Types.BuildResults+ Distribution.Client.Types.ConfiguredId+ Distribution.Client.Types.ConfiguredPackage+ Distribution.Client.Types.Credentials+ Distribution.Client.Types.InstallMethod+ Distribution.Client.Types.OverwritePolicy+ Distribution.Client.Types.PackageLocation+ Distribution.Client.Types.PackageSpecifier+ Distribution.Client.Types.ReadyPackage+ Distribution.Client.Types.Repo+ Distribution.Client.Types.RepoName+ Distribution.Client.Types.SourcePackageDb+ Distribution.Client.Types.SourceRepo+ Distribution.Client.Types.WriteGhcEnvironmentFilesPolicy Distribution.Client.Update Distribution.Client.Utils Distribution.Client.World@@ -194,23 +213,25 @@ Distribution.Compat.Graph Distribution.Compat.Internal.TempFile Distribution.Compat.Lens- Distribution.Compat.MD5 Distribution.Compat.MonadFail Distribution.Compat.Newtype+ Distribution.Compat.NonEmptySet Distribution.Compat.Parsing Distribution.Compat.Prelude Distribution.Compat.Prelude.Internal+ Distribution.Compat.Process Distribution.Compat.Semigroup Distribution.Compat.Stack Distribution.Compat.Time+ Distribution.Compat.Typeable Distribution.Compiler Distribution.Deprecated.ParseUtils Distribution.Deprecated.ReadP- Distribution.Deprecated.Text Distribution.Deprecated.ViewAsFieldDescr Distribution.FieldGrammar Distribution.FieldGrammar.Class Distribution.FieldGrammar.FieldDescrs+ Distribution.FieldGrammar.Newtypes Distribution.FieldGrammar.Parsec Distribution.FieldGrammar.Pretty Distribution.Fields@@ -238,7 +259,6 @@ Distribution.Parsec Distribution.Parsec.Error Distribution.Parsec.FieldLineStream- Distribution.Parsec.Newtypes Distribution.Parsec.Position Distribution.Parsec.Warning Distribution.Pretty@@ -295,17 +315,13 @@ Distribution.Solver.Compat.Prelude Distribution.Solver.Types.ComponentDeps Distribution.Solver.Types.ConstraintSource- Distribution.Solver.Types.InstSolverPackage Distribution.Solver.Types.LabeledPackageConstraint Distribution.Solver.Types.OptionalStanza Distribution.Solver.Types.PackageConstraint Distribution.Solver.Types.PackageFixedDeps Distribution.Solver.Types.PackageIndex Distribution.Solver.Types.PackagePath- Distribution.Solver.Types.ResolverPackage Distribution.Solver.Types.Settings- Distribution.Solver.Types.SolverId- Distribution.Solver.Types.SolverPackage Distribution.Solver.Types.SourcePackage Distribution.System Distribution.TestSuite@@ -392,11 +408,13 @@ Distribution.Utils.Generic Distribution.Utils.IOData Distribution.Utils.LogProgress+ Distribution.Utils.MD5 Distribution.Utils.MapAccum Distribution.Utils.NubList Distribution.Utils.Progress Distribution.Utils.ShortText Distribution.Utils.String+ Distribution.Utils.Structured Distribution.Utils.UnionFind Distribution.Verbosity Distribution.Verbosity.Internal@@ -448,6 +466,8 @@ Text.JSON.Canonical Test-Suite test-resolve-category+ -- requires a local Portage overlay, thus fails in a sandboxed test.+ buildable: False ghc-options: -Wall Type: exitcode-stdio-1.0 Default-Language: Haskell98@@ -478,6 +498,9 @@ DoAndIfThenElse Test-Suite test-print-deps+ -- This test-suite has been incorporated into the 'spec' test-suite,+ -- and may be removed in the future.+ buildable: False ghc-options: -Wall Type: exitcode-stdio-1.0 Default-Language: Haskell98@@ -507,6 +530,9 @@ DoAndIfThenElse Test-Suite test-normalize-deps+ -- This test-suite has been incorporated into the 'spec' test-suite,+ -- and may be removed in the future.+ buildable: False ghc-options: -Wall Type: exitcode-stdio-1.0 Default-Language: Haskell98@@ -531,6 +557,217 @@ unix, xml + default-extensions:+ -- cabal+ PatternGuards,+ DoAndIfThenElse++test-suite doctests+ type: exitcode-stdio-1.0+ ghc-options: -threaded+ default-language: Haskell98+ main-is: tests/doctests.hs+ build-depends: base,+ doctest >= 0.8,+ template-haskell,+ QuickCheck++test-suite spec+ ghc-options: -Wall+ Type: exitcode-stdio-1.0+ Default-Language: Haskell2010+ Main-Is: tests/Spec.hs+ Hs-Source-Dirs: ., cabal, cabal/Cabal, cabal/cabal-install, tests+ other-modules: Merge.UtilsSpec+ Portage.CabalSpec+ Portage.Dependency.PrintSpec+ Portage.EBuildSpec+ Portage.GHCCoreSpec+ Portage.MetadataSpec+ Portage.PackageIdSpec+ Portage.VersionSpec+ QuickCheck.Instances+ -- cabal:+ Distribution.Backpack+ Distribution.CabalSpecVersion+ Distribution.Compat.Async+ Distribution.Compat.Binary+ Distribution.Compat.CharParsing+ Distribution.Compat.CopyFile+ Distribution.Compat.DList+ Distribution.Compat.Exception+ Distribution.Compat.FilePath+ Distribution.Compat.Graph+ Distribution.Compat.Internal.TempFile+ Distribution.Compat.Lens+ Distribution.Compat.MonadFail+ Distribution.Compat.Newtype+ Distribution.Compat.NonEmptySet+ Distribution.Compat.Parsing+ Distribution.Compat.Prelude+ Distribution.Compat.Process+ Distribution.Compat.Semigroup+ Distribution.Compat.Stack+ Distribution.Compat.Typeable+ Distribution.Compiler+ Distribution.FieldGrammar+ Distribution.FieldGrammar.Class+ Distribution.FieldGrammar.FieldDescrs+ Distribution.FieldGrammar.Newtypes+ Distribution.FieldGrammar.Parsec+ Distribution.FieldGrammar.Pretty+ Distribution.Fields+ Distribution.Fields.Field+ Distribution.Fields.Lexer+ Distribution.Fields.LexerMonad+ Distribution.Fields.ParseResult+ Distribution.Fields.Parser+ Distribution.Fields.Pretty+ Distribution.InstalledPackageInfo+ Distribution.License+ Distribution.ModuleName+ Distribution.Package+ Distribution.PackageDescription+ Distribution.PackageDescription.Configuration+ Distribution.PackageDescription.Utils+ Distribution.Parsec+ Distribution.Parsec.Error+ Distribution.Parsec.FieldLineStream+ Distribution.Parsec.Position+ Distribution.Parsec.Warning+ Distribution.Pretty+ Distribution.ReadE+ Distribution.SPDX+ Distribution.SPDX.License+ Distribution.SPDX.LicenseExceptionId+ Distribution.SPDX.LicenseExpression+ Distribution.SPDX.LicenseId+ Distribution.SPDX.LicenseListVersion+ Distribution.SPDX.LicenseReference+ Distribution.Simple.PackageIndex+ Distribution.Simple.Utils+ Distribution.System+ Distribution.Types.AbiDependency+ Distribution.Types.AbiHash+ Distribution.Types.Benchmark+ Distribution.Types.Benchmark.Lens+ Distribution.Types.BenchmarkInterface+ Distribution.Types.BenchmarkType+ Distribution.Types.BuildInfo+ Distribution.Types.BuildInfo.Lens+ Distribution.Types.BuildType+ Distribution.Types.Component+ Distribution.Types.ComponentId+ Distribution.Types.ComponentName+ Distribution.Types.ComponentRequestedSpec+ Distribution.Types.CondTree+ Distribution.Types.Condition+ Distribution.Types.ConfVar+ Distribution.Types.Dependency+ Distribution.Types.DependencyMap+ Distribution.Types.ExeDependency+ Distribution.Types.Executable+ Distribution.Types.Executable.Lens+ Distribution.Types.ExecutableScope+ Distribution.Types.ExposedModule+ Distribution.Types.Flag+ Distribution.Types.ForeignLib+ Distribution.Types.ForeignLib.Lens+ Distribution.Types.ForeignLibOption+ Distribution.Types.ForeignLibType+ Distribution.Types.GenericPackageDescription+ Distribution.Types.GenericPackageDescription.Lens+ Distribution.Types.HookedBuildInfo+ Distribution.Types.IncludeRenaming+ Distribution.Types.InstalledPackageInfo+ Distribution.Types.InstalledPackageInfo.FieldGrammar+ Distribution.Types.InstalledPackageInfo.Lens+ Distribution.Types.LegacyExeDependency+ Distribution.Types.Library+ Distribution.Types.Library.Lens+ Distribution.Types.LibraryName+ Distribution.Types.LibraryVisibility+ Distribution.Types.Mixin+ Distribution.Types.Module+ Distribution.Types.ModuleReexport+ Distribution.Types.ModuleRenaming+ Distribution.Types.MungedPackageId+ Distribution.Types.MungedPackageName+ Distribution.Types.PackageDescription+ Distribution.Types.PackageDescription.Lens+ Distribution.Types.PackageId+ Distribution.Types.PackageId.Lens+ Distribution.Types.PackageName+ Distribution.Types.PackageVersionConstraint+ Distribution.Types.PkgconfigDependency+ Distribution.Types.PkgconfigName+ Distribution.Types.PkgconfigVersion+ Distribution.Types.PkgconfigVersionRange+ Distribution.Types.SetupBuildInfo+ Distribution.Types.SetupBuildInfo.Lens+ Distribution.Types.SourceRepo+ Distribution.Types.TestSuite+ Distribution.Types.TestSuite.Lens+ Distribution.Types.TestSuiteInterface+ Distribution.Types.TestType+ Distribution.Types.UnitId+ Distribution.Types.UnqualComponentName+ Distribution.Types.Version+ Distribution.Types.VersionInterval+ Distribution.Types.VersionRange+ Distribution.Types.VersionRange.Internal+ Distribution.Utils.Base62+ Distribution.Utils.Generic+ Distribution.Utils.IOData+ Distribution.Utils.MD5+ Distribution.Utils.ShortText+ Distribution.Utils.String+ Distribution.Utils.Structured+ Distribution.Verbosity+ Distribution.Verbosity.Internal+ Distribution.Version+ Language.Haskell.Extension+ -- hackport:+ AnsiColor+ Error+ Merge.Utils+ Paths_hackport+ Portage.Cabal+ Portage.Dependency+ Portage.Dependency.Builder+ Portage.Dependency.Normalize+ Portage.Dependency.Print+ Portage.Dependency.Types+ Portage.EBuild+ Portage.EBuild.CabalFeature+ Portage.EBuild.Render+ Portage.GHCCore+ Portage.Metadata+ Portage.PackageId+ Portage.Use+ Portage.Version+ build-tool-depends: hspec-discover:hspec-discover == 2.*+ Build-Depends: array,+ base,+ binary,+ deepseq,+ bytestring,+ containers,+ directory,+ extensible-exceptions,+ filepath,+ hspec >= 2.0,+ mtl,+ parsec,+ pretty,+ process,+ QuickCheck >= 2.0,+ split,+ text,+ time,+ transformers,+ unix,+ xml default-extensions: -- cabal PatternGuards,
+ tests/Merge/UtilsSpec.hs view
@@ -0,0 +1,120 @@+module Merge.UtilsSpec (spec) where++import Test.Hspec+import Test.Hspec.QuickCheck+import Test.QuickCheck+import QuickCheck.Instances++import Control.Applicative (liftA2)+import qualified Data.Map.Strict as Map+import qualified Data.List as L++import Error+import Merge.Utils+import Portage.PackageId++import qualified Distribution.Package as Cabal+import qualified Distribution.PackageDescription as Cabal+import Distribution.Pretty (prettyShow)++spec :: Spec+spec = do+ describe "readPackageString" $ do+ prop "returns a Right tuple containing the parsed information or a Left ArgumentError" $ do+ let cat = Category "dev-haskell"+ name = Cabal.mkPackageName "package-name1"+ in \(ComplexVersion version) ->+ readPackageString [prettyShow cat ++ "/" ++ prettyShow name +++ if (versionNumber version) == []+ then ""+ else "-" ++ prettyShow version]+ `shouldBe`+ if (versionChar version) /= Nothing ||+ (versionSuffix version) /= [] ||+ (versionRevision version) /= 0+ then Left (ArgumentError ("Could not parse [category/]package[-version]: "+ ++ prettyShow cat ++ "/" +++ prettyShow name +++ if (versionNumber version) == []+ then ""+ else "-" ++ prettyShow version))+ else Right ( Just cat+ , name+ , if (versionNumber version) == []+ then Nothing+ else Just version+ )+ it "returns a Left HackPortError if the package string is empty" $ do+ readPackageString []+ `shouldBe`+ Left (ArgumentError "Need an argument, [category/]package[-version]")+ prop "returns a Left HackPortError if fed too many arguments" $ do+ \(NonEmpty args) ->+ if length args > 1+ then readPackageString args `shouldBe`+ Left (ArgumentError ("Too many arguments: " ++ unwords args))+ else readPackageString args `shouldNotBe`+ Left (ArgumentError ("Too many arguments: " ++ unwords args))+ + describe "getPreviousPackageId" $ do+ context "when there is a previous version available" $ do+ it "returns the PackageId of the previous version" $ do+ let ebuildDir = [ "foo-bar2-3.0.0b_rc2-r1.ebuild"+ , "foo-bar2-3.0.0b_rc2-r2.ebuild"+ , "foo-bar2-3.0.1.ebuild"+ , "metadata.xml"+ , "Manifest"+ , "files"+ ]+ newPkgId = PackageId (PackageName (Category "dev-haskell")+ (Cabal.mkPackageName "foo-bar2"))+ (Version [3,0,2] Nothing [] 0 )+ in getPreviousPackageId ebuildDir newPkgId `shouldBe`+ Just (PackageId (PackageName (Category "dev-haskell")+ (Cabal.mkPackageName "foo-bar2"))+ (Version [3,0,1] Nothing [] 0))+ context "if there is no previous version available" $ do+ it "returns Nothing" $ do+ let ebuildDir = [ "foo-bar2-3.0.0b_rc2-r1.ebuild"+ , "foo-bar2-3.0.0b_rc2-r2.ebuild"+ , "foo-bar2-3.0.1.ebuild"+ , "metadata.xml"+ , "Manifest"+ , "files"+ ]+ newPkgId = PackageId (PackageName (Category "dev-haskell")+ (Cabal.mkPackageName "foo-bar2"))+ (Version [3,0,0] (Just 'a') [] 0 )+ in getPreviousPackageId ebuildDir newPkgId `shouldBe` Nothing++ describe "drop_prefix" $ do+ context "when an IUSE has a with/use prefix" $ do+ prop "drops the prefix" $ do+ let prefix = ["with","use"]+ sep = ["-","_"]+ prefixes = liftA2 (++) prefix sep+ \flag -> L.nub (drop_prefix <$> (liftA2 (++) prefixes [flag])) == [flag]+ context "when an IUSE has neither a with nor a use prefix" $ do+ prop "preserves the existing string" $ do+ \prefix flag -> L.nub (drop_prefix <$> (liftA2 (++) [prefix] ['-':flag])) ==+ if prefix == "with" || prefix == "use"+ then [flag]+ else [prefix ++ '-':flag]++ describe "mangle_iuse" $ do+ prop "converts underscores (_) into hyphens (-) and drops with/use prefixes" $ do+ \a -> mangle_iuse a == drop_prefix (map (\f -> if f == '_' then '-' else f) a)++ describe "to_unstable" $ do+ prop "creates an unstable keyword from a stable keyword, or preserves a mask" $ do+ \a -> to_unstable a ==+ case a of+ '~':_ -> a+ '-':_ -> a+ _ -> '~':a++ describe "metaFlags" $ do+ prop "converts a [Cabal.PackageFlag] into a Map.Map String String" $ do+ \name desc -> metaFlags [(Cabal.emptyFlag (Cabal.mkFlagName name))+ { Cabal.flagDescription = desc }] ==+ Map.fromList [(mangle_iuse name,desc)]
+ tests/Merge/UtilsSpec.hs~ view
@@ -0,0 +1,53 @@+module Merge.UtilsSpec (spec) where++import Test.Hspec++import Error+import Merge.Utils+import Portage.PackageId++import qualified Distribution.Package as Cabal++spec :: Spec+spec = do+ describe "(<.>)" $ do+ it "adds a dot (.) between two strings" $ do+ "foo" <.> "bar" `shouldBe` "foo.bar"++ describe "readPackageString" $ do+ context "when the package string is valid" $ do+ it "returns a Right tuple containing the parsed information" $ do+ readPackageString ["dev-haskell/packagename1-1.0.0"]+ `shouldBe` Right ( Just (Category "dev-haskell")+ , Cabal.mkPackageName "packagename1"+ , Just (Version [1,0,0] Nothing [] 0)+ )+ context "when the package string is empty" $ do+ it "returns a Left HackPortError" $ do+ readPackageString []+ `shouldBe`+ Left (ArgumentError "Need an argument, [category/]package[-version]")+ context "when the package string contains too many arguments" $ do+ it "returns a Left HackPortError" $ do+ let args = ["dev-haskell/packagename1-1.0.0", "dev-haskell/packagename2-1.0.0"]+ readPackageString args+ `shouldBe`+ Left (ArgumentError ("Too many arguments: " ++ unwords args))++ + + + -- describe "getPreviousPackageId" $ do+ -- it "returns the PackageId of the previous version" $ do+ -- let ebuildDir = [ "foo-bar2-3.0.0b_rc2-r1.ebuild"+ -- , "foo-bar2-3.0.0b_rc2-r2.ebuild"+ -- , "foo-bar2-3.0.1.ebuild"+ -- , "metadata.xml"+ -- , "Manifest"+ -- , "files"+ -- ]+ -- newPkgId = PackageId (PackageName (Category "dev-haskell")+ -- (Cabal.mkPackageName "foo-bar2"))+ -- Version + +
+ tests/Portage/CabalSpec.hs view
@@ -0,0 +1,69 @@+module Portage.CabalSpec (spec) where++import Test.Hspec++import qualified Distribution.SPDX as SPDX++import Portage.Cabal++spec :: Spec+spec = do+ describe "convertLicense" $ do+ it "converts AGPL_3_0_or_later into AGPL-3+" $ do+ convertLicense (SPDX.License $ SPDX.simpleLicenseExpression SPDX.AGPL_3_0_or_later)+ `shouldBe`+ Right "AGPL-3+"+ it "converts AGPL_3_0_only into AGPL-3" $ do+ convertLicense (SPDX.License $ SPDX.simpleLicenseExpression SPDX.AGPL_3_0_only)+ `shouldBe`+ Right "AGPL-3"+ it "converts GPL_2_0_or_later into GPL-2+" $ do+ convertLicense (SPDX.License $ SPDX.simpleLicenseExpression SPDX.GPL_2_0_or_later)+ `shouldBe`+ Right "GPL-2+"+ it "converts GPL_2_0_only into GPL-2" $ do+ convertLicense (SPDX.License $ SPDX.simpleLicenseExpression SPDX.GPL_2_0_only)+ `shouldBe`+ Right "GPL-2"+ it "converts GPL_3_0_or_later into GPL-3+" $ do+ convertLicense (SPDX.License $ SPDX.simpleLicenseExpression SPDX.GPL_3_0_or_later)+ `shouldBe`+ Right "GPL-3+"+ it "converts GPL_3_0_only into GPL-3" $ do+ convertLicense (SPDX.License $ SPDX.simpleLicenseExpression SPDX.GPL_3_0_only)+ `shouldBe`+ Right "GPL-3"+ -- Unfortunately, Cabal treats LGPL_2_0_only and LGPL_2_0_or_later as identical,+ -- just as it does with LGPL_2_1_only and LGPL_2_1_or_later. This means+ -- we cannot handle LGPL-2.0+ or LGPL-2,1+ without directly dealing with+ -- the SPDX licence, before it is converted into a Cabal-style licence.+ it "converts LGPL_2_0_or_later into LGPL-2, without a trailing plus (+)" $ do+ convertLicense (SPDX.License $ SPDX.simpleLicenseExpression SPDX.LGPL_2_0_or_later)+ `shouldBe`+ Right "LGPL-2"+ it "converts LGPL_2_0_only into LGPL-2" $ do+ convertLicense (SPDX.License $ SPDX.simpleLicenseExpression SPDX.LGPL_2_0_only)+ `shouldBe`+ Right "LGPL-2"+ it "converts LGPL_2_1_or_later into LGPL-2.1, without a trailing plus (+)" $ do+ convertLicense (SPDX.License $ SPDX.simpleLicenseExpression SPDX.LGPL_2_1_or_later)+ `shouldBe`+ Right "LGPL-2.1"+ it "converts LGPL_2_1_only into LGPL-2.1" $ do+ convertLicense (SPDX.License $ SPDX.simpleLicenseExpression SPDX.LGPL_2_1_only)+ `shouldBe`+ Right "LGPL-2.1"+ -- But these next two cases are correctly handled:+ it "converts LGPL_3_0_or_later into LGPL-3+" $ do+ convertLicense (SPDX.License $ SPDX.simpleLicenseExpression SPDX.LGPL_3_0_or_later)+ `shouldBe`+ Right "LGPL-3+"+ it "converts LGPL_3_0_only into LGPL-3" $ do+ convertLicense (SPDX.License $ SPDX.simpleLicenseExpression SPDX.LGPL_3_0_only)+ `shouldBe`+ Right "LGPL-3"+ context "when a licence string is invalid" $ do+ it "converts the unknown licence into an error string" $ do+ convertLicense (SPDX.License $ SPDX.simpleLicenseExpression SPDX.EUPL_1_1)+ `shouldBe`+ Left "license unknown to cabal. Please pick it manually."
+ tests/Portage/Dependency/PrintSpec.hs view
@@ -0,0 +1,327 @@+module Portage.Dependency.PrintSpec (spec) where++import Test.Hspec++import Control.Monad (forM_)+import Data.List (intercalate)++import qualified Portage.PackageId as P++import qualified Portage.Dependency.Builder as P+import qualified Portage.Dependency.Print as P+import qualified Portage.Dependency.Types as P+import qualified Portage.Dependency.Normalize as P++import qualified Portage.Use as P++spec :: Spec+spec = do+ describe "dep2str" $ do+ it "converts an empty Dependency into an empty string" $ do+ let d_all = P.DependAllOf+ d_any = P.DependAnyOf+ d_use u dep = P.mkUseDependency (True, P.Use u) dep+ deps = [ d_all []+ , d_any []+ , d_use "f" (d_all [])+ , P.DependAllOf [d_any []]+ , P.DependAnyOf [d_all []]+ -- Deep Useless Use Tree :]+ , d_use "f" $+ d_use "g" $+ d_all [d_any []+ , d_use "h" $+ d_all [ d_all []+ , d_any []+ ]+ , d_use "i" $+ d_all [ d_all []+ , d_any []+ ]+ ]+ ]+ forM_ deps $ \d ->+ P.dep2str 0 (P.normalize_depend d) `shouldBe` ""++ it "converts a Dependency into a normalized string" $ do+ let def_attr = P.DAttr P.AnySlot []+ p_v v = P.Version { P.versionNumber = v+ , P.versionChar = Nothing+ , P.versionSuffix = []+ , P.versionRevision = 0+ }+ d_all = P.DependAllOf+ d_any = P.DependAnyOf+ d_ge pn v = P.DependAtom $ P.Atom pn+ (P.DRange (P.NonstrictLB $ p_v v) P.InfinityB)+ def_attr+ d_lt pn v = P.DependAtom $ P.Atom pn+ (P.DRange P.ZeroB (P.StrictUB $ p_v v))+ def_attr+ -- for the deps_norm test, formerly normalize_deps+ pnm = P.mkPackageName "dev-haskell" "mtl"+ pnp = P.mkPackageName "dev-haskell" "parsec"+ pnq = P.mkPackageName "dev-haskell" "quickcheck"+ d_p pn = P.DependAtom $ P.Atom (P.mkPackageName "c" pn)+ (P.DRange P.ZeroB P.InfinityB)+ def_attr+ d_use u d = P.mkUseDependency (True, P.Use u) d+ d_nuse u d = P.mkUseDependency (False, P.Use u) d++ deps = [ -- from agda: "mtl ==2.0.* || >=2.1.1 && <2.2"+ ( d_all [ d_any [ d_all [ d_ge pnm [2, 0]+ , d_lt pnm [2, 1]+ ]+ , d_all [ d_ge pnm [2, 1, 1]+ , d_lt pnm [2, 2]+ ]+ ]+ ]+ , [ "|| ( ( >=dev-haskell/mtl-2.0 <dev-haskell/mtl-2.1 )"+ , " ( >=dev-haskell/mtl-2.1.1 <dev-haskell/mtl-2.2 ) )"+ ]+ )+ -- remove duplicate entries+ , ( let d = d_all [d_ge pnm [2, 0], d_lt pnm [2, 2]]+ in d_all [d, d]+ , [ ">=dev-haskell/mtl-2.0 <dev-haskell/mtl-2.2" ]+ )+ ]+ forM_ deps $ \(d,expected) ->+ P.dep2str 0 (P.normalize_depend d) `shouldBe` (intercalate "\n" expected)++ -- from normalize_deps.hs+ let deps_norm = [ ( d_all [ d_ge pnm [1,0]+ , d_use "foo" (d_all [ d_ge pnm [1,0] -- duplicate+ , d_ge pnp [2,1]+ ])+ ]+ , [ ">=dev-haskell/mtl-1.0"+ , "foo? ( >=dev-haskell/parsec-2.1 )"+ ]+ )+ , ( d_all [ d_ge pnm [1,0]+ , d_use "foo" (d_any [ d_ge pnm [1,0] -- already satisfied+ , d_ge pnp [2,1]+ ])+ ]+ , [ ">=dev-haskell/mtl-1.0" ]+ )+ , ( d_any [ d_all [ d_ge pnm [1,0] -- common subdep+ , d_ge pnq [1,2]+ ]+ , d_all [ d_ge pnm [1,0]+ , d_ge pnp [3,1]+ ]+ ]+ , [ ">=dev-haskell/mtl-1.0"+ , "|| ( >=dev-haskell/parsec-3.1"+ , " >=dev-haskell/quickcheck-1.2 )"+ ]+ )+ , ( d_all [ d_use "foo" $ d_use "bar" $ d_ge pnm [1,0]+ , d_use "bar" $ d_use "foo" $ d_ge pnm [1,0]+ ]+ , [ "bar? ( foo? ( >=dev-haskell/mtl-1.0 ) )" ]+ )+ , ( d_all [ d_use "foo" $ d_ge pnm [1,0]+ , d_use "foo" $ d_ge pnp [3,1]+ ]+ , [ "foo? ( >=dev-haskell/mtl-1.0"+ , " >=dev-haskell/parsec-3.1 )"+ ]+ )+ , ( d_all [ d_use "a" $ d_use "b" $ d_ge pnm [1,0]+ , d_nuse "a" $ d_use "b" $ d_ge pnm [1,0]+ ]+ , [ "b? ( >=dev-haskell/mtl-1.0 )"+ ]+ )+ -- 'test?' is special+ , ( d_use "a" $ d_use "test" $ d_ge pnm [1,0]+ , [ "test? ( a? ( >=dev-haskell/mtl-1.0 ) )"+ ]+ )+ , -- pop context for complementary depends, like+ -- a? ( x y a ) !a? ( x y na )+ -- leads to+ -- x y a? ( a ) !a? ( na )+ ( d_all [ d_use "a" $ d_all $ map d_p [ "x", "y", "a" ]+ , d_nuse "a" $ d_all $ map d_p [ "x", "y", "na" ]+ ]+ , [ "c/x"+ , "c/y"+ , "a? ( c/a )"+ , "!a? ( c/na )"+ ]+ )+ , -- push stricter context into less strict+ ( d_all [ d_ge pnm [2,0]+ , d_use "a" $ d_ge pnm [1,0]+ ]+ ,+ [ ">=dev-haskell/mtl-2.0" ]+ )+ , -- propagate use guarded depend into deeply nested one+ ( d_all [ d_use "a" $ d_all $ map d_p [ "x" ]+ , d_use "test" $ d_use "a" $ d_all $ map d_p [ "x", "t" ]+ ]+ , [ "test? ( a? ( c/t ) )"+ , "a? ( c/x )"+ ]+ )+ , -- lift nested use context for complementary depends+ -- a? ( b? ( y ) ) b? ( x )+ ( d_all [ d_use "a" $ d_use "b" $ d_all $ map d_p [ "x", "y" ]+ , d_nuse "a" $ d_use "b" $ d_p "x"+ ]+ , [ "a? ( b? ( c/y ) )"+ , "b? ( c/x )"+ ]+ )+ , -- more advanced lift of complementary deps+ -- a? ( b? ( x y ) )+ -- !a? ( b? ( y z ) )+ ( d_all [ d_use "a" $ d_use "b" $ d_all $ map d_p [ "x", "y" ]+ , d_nuse "a" $ d_use "b" $ d_all $ map d_p [ "y", "z" ]+ ]+ , [ "a? ( b? ( c/x ) )"+ , "!a? ( b? ( c/z ) )"+ , "b? ( c/y )"+ ]+ )+ , -- completely expanded set of USEs+ -- a? ( b? ( c? ( x y z ) )+ -- a? ( b? ( !c? ( x y ) )+ -- a? ( !b? ( c? ( x z ) )+ -- a? ( !b? ( !c? ( x ) )+ --+ -- !a? ( b? ( c? ( y z ) )+ -- !a? ( b? ( !c? ( y ) )+ -- !a? ( !b? ( c? ( z ) )+ -- !a? ( !b? ( !c? ( ) )+ ( d_all [ d_use "a" $ d_use "b" $ d_use "c" $ d_all $ map d_p [ "x", "y", "z" ]+ , d_use "a" $ d_use "b" $ d_nuse "c" $ d_all $ map d_p [ "x", "y" ]+ , d_use "a" $ d_nuse "b" $ d_use "c" $ d_all $ map d_p [ "x", "z" ]+ , d_use "a" $ d_nuse "b" $ d_nuse "c" $ d_all $ map d_p [ "x" ]+ , d_nuse "a" $ d_use "b" $ d_use "c" $ d_all $ map d_p [ "y", "z" ]+ , d_nuse "a" $ d_use "b" $ d_nuse "c" $ d_all $ map d_p [ "y" ]+ , d_nuse "a" $ d_nuse "b" $ d_use "c" $ d_all $ map d_p [ "z" ]+ , d_nuse "a" $ d_nuse "b" $ d_nuse "c" $ d_all $ map d_p [ ]+ ]+ , [ "a? ( c/x )"+ , "b? ( c/y )"+ , "c? ( c/z )"+ ]+ )+ , -- pop simple common subdepend+ -- a? ( b? ( d ) )+ -- !a? ( b? ( d ) )+ ( d_all [ d_use "a" $ d_use "b" $ d_p "d"+ , d_nuse "a" $ d_use "b" $ d_p "d"+ ]+ , [ "b? ( c/d )"+ ]+ )+ , -- pop '|| ( some thing )' depend+ ( let any_part = d_any $ map d_p ["a", "b"] in+ d_all [ d_use "u" $ d_all [ any_part , d_p "z"]+ , d_nuse "u" $ any_part+ ]+ , [ "|| ( c/a"+ , " c/b )"+ , "u? ( c/z )"+ ]+ )+ , -- simplify slightly more complex counterguard+ -- v? ( c/d )+ -- u? ( !v? ( c/d ) )+ -- to+ -- v? ( c/d )+ -- u? ( c/d )+ ( d_all [ d_use "v" $ d_p "d"+ , d_use "u" $ d_nuse "v" $ d_p "d"+ ]+ , [ "u? ( c/d )"+ , "v? ( c/d )"+ ]+ )+ + , -- ffi? ( c/d c/e )+ -- !ffi ( !gmp ( c/d c/e ) )+ -- gmp? ( c/d c/e )+ -- to+ -- ( c/d c/e )+ ( let de = d_all [ d_p "d" , d_p "e" ]+ in d_all [ d_use "ffi" de+ , d_nuse "ffi" $ d_nuse "gmp" $ de+ , d_use "gmp" $ de+ ]+ , [ "c/d"+ , "c/e"+ ]+ )+ + {- TODO: another popular case+ , -- simplify even more complex counterguard+ -- u? ( c/d )+ -- !u? ( v? ( c/d ) )+ -- to+ -- u? ( c/d )+ -- v? ( c/d )+ ( d_all [ d_use "u" $ d_p "d"+ , d_nuse "u" $ d_use "v" $ d_p "d"+ ]+ , [ "u? ( c/d )"+ , "v? ( c/d )"+ ]+ )+ -}+ ]+ forM_ deps_norm $ \(d, expected) ->+ (P.dep2str 0 $ P.normalize_depend d) `shouldBe` (intercalate "\n" expected)++ describe "dep2str_noindent" $ do+ it "converts a Dependency into a string" $ do+ let pn = P.mkPackageName "dev-haskell" "mtl"+ def_attr = P.DAttr P.AnySlot []+ p_v v = P.Version { P.versionNumber = v+ , P.versionChar = Nothing+ , P.versionSuffix = []+ , P.versionRevision = 0+ }+ d_all = P.DependAllOf+ d_any = P.DependAnyOf+ d_ge v = P.DependAtom $ P.Atom pn+ (P.DRange (P.NonstrictLB $ p_v v) P.InfinityB)+ def_attr+ d_lt v = P.DependAtom $ P.Atom pn+ (P.DRange P.ZeroB (P.StrictUB $ p_v v))+ def_attr+ deps = [ -- from agda: "mtl ==2.0.* || >=2.1.1 && <2.2"+ ( d_all [ d_any [ d_all [ d_ge [2, 0]+ , d_lt [2, 1]+ ]+ , d_all [ d_ge [2, 1, 1]+ , d_lt [2, 2]+ ]+ ]+ ]+ , [ "|| ( ( >=dev-haskell/mtl-2.0"+ , " <dev-haskell/mtl-2.1 )"+ , " ( >=dev-haskell/mtl-2.1.1"+ , " <dev-haskell/mtl-2.2 ) )"+ ]+ )+ -- remove duplicate entries+ , ( let d = d_all [d_ge [2, 0], d_lt [2, 2]]+ in d_all [d, d]+ , [ ">=dev-haskell/mtl-2.0"+ , "<dev-haskell/mtl-2.2"+ , ">=dev-haskell/mtl-2.0"+ , "<dev-haskell/mtl-2.2"+ ]+ )+ ]+ forM_ deps $ \(d, expected) ->+ P.dep2str_noindent d `shouldBe` intercalate "\n" expected
+ tests/Portage/EBuildSpec.hs view
@@ -0,0 +1,29 @@+module Portage.EBuildSpec (spec) where++import Test.Hspec++import Portage.EBuild++spec :: Spec+spec = do+ describe "src_uri" $ do+ it "returns the default SRC_URI for a lowercase package name" $ do+ src_uri ebuildTemplate+ `shouldBe` "https://hackage.haskell.org/package/${P}/${P}.tar.gz"+ it "returns the case-sensitive SRC_URI for a case-sensitive package name" $ do+ src_uri ebuildTemplate { my_pn = Just "Foo_Bar" }+ `shouldBe` "https://hackage.haskell.org/package/${MY_P}/${MY_P}.tar.gz"+ describe "sort_iuse" $ do+ it "sorts IUSE alphabetically despite pluses (+)" $ do+ sort_iuse ["+a","c","+b","d"] `shouldBe` ["+a","+b","c","d"]+ describe "drop_tdot" $ do+ it "drops trailing dots (.)" $ do+ drop_tdot "foo." `shouldBe` "foo"+ drop_tdot "foo..." `shouldBe` "foo"+ drop_tdot "foo" `shouldBe` "foo"+ describe "quote" $ do+ it "should correctly surround a string with special characters in quotes" $ do+ quote "Reading, writing and manipulating '.tar' archives." ""+ `shouldBe`+ "\"Reading, writing and manipulating \'.tar\' archives.\""+
+ tests/Portage/GHCCoreSpec.hs view
@@ -0,0 +1,23 @@+module Portage.GHCCoreSpec (spec) where++import Test.Hspec++import qualified Distribution.Version as Cabal+import qualified Distribution.Package as Cabal++import Portage.GHCCore++spec :: Spec+spec = do+ describe "cabalFromGHC" $ do+ it "returns the corresponding Cabal version for a valid GHC version" $ do+ cabalFromGHC [8,8,3] `shouldBe` Just (Cabal.mkVersion [3,0,1,0])+ it "returns Nothing for an invalid GHC version" $ do+ cabalFromGHC [9,9,9,9] `shouldBe` Nothing+ describe "packageIsCoreInAnyGHC" $ do+ it "returns True for the binary package" $ do+ packageIsCoreInAnyGHC (Cabal.mkPackageName "binary") `shouldBe` True+ it "returns False for the exceptions package (because it is upgradeable)" $ do+ packageIsCoreInAnyGHC (Cabal.mkPackageName "exceptions") `shouldBe` False+ it "returns False for the yesod package" $ do+ packageIsCoreInAnyGHC (Cabal.mkPackageName "yesod") `shouldBe` False
+ tests/Portage/MetadataSpec.hs view
@@ -0,0 +1,80 @@+module Portage.MetadataSpec (spec) where++import Test.Hspec+import Test.Hspec.QuickCheck++import qualified Data.Text as T+import qualified Data.Map.Strict as Map++import Portage.Metadata++spec :: Spec+spec = do+ describe "pureMetadataFromFile" $ do+ it "returns Nothing from an empty Text" $ do+ pureMetadataFromFile T.empty `shouldBe` Nothing+ prop "equals makeMinimalMetadata with no USE flags, no matter the description" $ do+ \desc -> pureMetadataFromFile (makeDefaultMetadata desc Map.empty) ==+ Just makeMinimalMetadata+ prop "equals makeMinimalMetadata plus the supplied USE flags, no matter the description" $+ do let flags = Map.singleton "name" "description"+ in \desc -> pureMetadataFromFile (makeDefaultMetadata desc flags)+ == Just (makeMinimalMetadata { metadataUseFlags = flags } )++ describe "prettyPrintFlags" $ do+ prop "should correctly format a single USE flag name with its description" $ do+ \name description -> prettyPrintFlags (Map.singleton name description) ==+ ["\t\t<flag name=\"" ++ name +++ "\">" ++ description ++ "</flag>"]+ prop "should have a length equal to the number of USE flags" $ do+ \flags -> length (prettyPrintFlags flags) == Map.size flags+ + describe "makeDefaultMetadata" $ do+ context "when writing a minimal metadata.xml" $ do+ it "should have a certain number of lines" $ do+ -- This is the number of lines in a skeleton metadata.xml.+ -- If it does not equal this number, the formatting may be wrong.+ length (T.lines (makeDefaultMetadata "" Map.empty)) `shouldBe` 13+ it "should have a certain format" $ do+ let desc = "foo"+ correctMetadata = T.pack $ unlines+ [ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"+ , "<!DOCTYPE pkgmetadata SYSTEM \"http://www.gentoo.org/dtd/metadata.dtd\">"+ , "<pkgmetadata>"+ , "\t<maintainer type=\"project\">"+ , "\t\t<email>haskell@gentoo.org</email>"+ , "\t\t<name>Gentoo Haskell</name>"+ , "\t</maintainer>"+ , "\t<use>"+ , "\t</use>"+ , "\t<longdescription>"+ , "\t\t" ++ desc+ , "\t</longdescription>"+ , "</pkgmetadata>"+ ]+ in makeDefaultMetadata desc Map.empty `shouldBe` correctMetadata+ context "when writing a metadata.xml with USE flags" $ do+ it "should have a certain number of lines relative to the number of USE flags" $ do+ let flags = Map.singleton "name" "description"+ in length (T.lines (makeDefaultMetadata "" flags))+ `shouldBe` 13 + (Map.size flags)+ it "should have a certain format" $ do+ let desc = "foo"+ flags = Map.singleton "name" "description"+ correctMetadata = T.pack $ unlines+ [ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"+ , "<!DOCTYPE pkgmetadata SYSTEM \"http://www.gentoo.org/dtd/metadata.dtd\">"+ , "<pkgmetadata>"+ , "\t<maintainer type=\"project\">"+ , "\t\t<email>haskell@gentoo.org</email>"+ , "\t\t<name>Gentoo Haskell</name>"+ , "\t</maintainer>"+ , "\t<use>"+ , "\t\t<flag name=\"name\">description</flag>"+ , "\t</use>"+ , "\t<longdescription>"+ , "\t\t" ++ desc+ , "\t</longdescription>"+ , "</pkgmetadata>"+ ]+ in makeDefaultMetadata desc flags `shouldBe` correctMetadata
+ tests/Portage/PackageIdSpec.hs view
@@ -0,0 +1,69 @@+module Portage.PackageIdSpec (spec) where++import Test.Hspec+import Test.Hspec.QuickCheck+import Test.QuickCheck+import QuickCheck.Instances++import qualified Data.Char as Char+import qualified Distribution.Package as Cabal+import Distribution.Pretty (prettyShow)++import Portage.PackageId++spec :: Spec+spec = do+ describe "packageIdToFilePath" $ do+ prop "transforms a PackageId into a FilePath" $ do+ let cat = Category "dev-haskell"+ name = Cabal.mkPackageName "foo-bar2+"+ in \(ComplexVersion version) ->+ packageIdToFilePath (PackageId (PackageName cat name) version)+ `shouldBe`+ "dev-haskell/" ++ prettyShow name ++ "/" ++ prettyShow name ++ "-" +++ prettyShow version ++ ".ebuild"++ describe "filePathToPackageId" $ do+ prop "returns a Just PackageId from a valid FilePath" $ do+ let cat = Category "dev-haskell"+ name = Cabal.mkPackageName "foo-bar2+"+ in \(ComplexVersion version) ->+ filePathToPackageId cat+ (prettyShow name ++ "-" ++ prettyShow version)+ `shouldBe`+ Just (PackageId (PackageName cat name) version)+ prop "returns Nothing on a malformed FilePath" $ do+ let cat = Category "dev-haskell"+ name = Cabal.mkPackageName "foo-bar-2+"+ in \(ComplexVersion version) ->+ filePathToPackageId cat (prettyShow name ++ "-" ++ prettyShow version)+ `shouldBe`+ Nothing++ describe "normalizeCabalPackageName" $ do+ prop "converts a Cabal.PackageName into lowercase" $ do+ \(PrintableString s) -> normalizeCabalPackageName (Cabal.mkPackageName s)+ `shouldBe` Cabal.mkPackageName (Char.toLower <$> s)++ describe "parseFriendlyPackage" $ do+ prop "parses a package string as [category/]name[-version]" $ do+ let cat = Category "dev-haskell"+ name = Cabal.mkPackageName "package-name1+"+ in \(ComplexVersion version) ->+ parseFriendlyPackage (prettyShow cat ++ "/" ++ prettyShow name+ ++ "-" ++ prettyShow version)+ `shouldBe`+ Right (Just cat, name, Just version)+ prop "returns an error string if parsing a malformed package string" $ do+ let cat = Category "dev-haskell"+ name = Cabal.mkPackageName "package-name-1+"+ in \(ComplexVersion version) ->+ parseFriendlyPackage (prettyShow cat ++ "/" ++ prettyShow name+ ++ "-" ++ prettyShow version)+ `shouldNotBe`+ Right (Just cat, name, Just version)++ describe "cabal_pn_to_PN" $ do+ prop "pretty-prints a Cabal PackageName as a lowercase String" $ do+ \(PrintableString s) -> cabal_pn_to_PN (Cabal.mkPackageName s)+ `shouldBe` Char.toLower <$> s
+ tests/Portage/VersionSpec.hs view
@@ -0,0 +1,27 @@+module Portage.VersionSpec (spec) where++import Test.Hspec+import Test.Hspec.QuickCheck++import QuickCheck.Instances+import qualified Distribution.Version as Cabal++import Portage.Version++spec :: Spec+spec = do+ describe "is_live" $ do+ prop "determines if a Portage version is live" $ do+ \(ComplexVersion v) -> is_live v ==+ if length (versionNumber v) >= 1 && last (versionNumber v) >= 9999+ then True else False+ + describe "fromCabalVersion" $ do+ prop "converts from a Cabal version to a Portage version" $ do+ \verNum -> fromCabalVersion (Cabal.mkVersion verNum) == Version verNum Nothing [] 0+ + describe "toCabalVersion" $ do+ prop "converts from a Portage version to a Cabal version" $ do+ \(ComplexVersion v) -> toCabalVersion v `shouldBe`+ if versionChar v == Nothing && versionSuffix v == []+ then Just (Cabal.mkVersion (versionNumber v)) else Nothing
+ tests/QuickCheck/Instances.hs view
@@ -0,0 +1,44 @@+module QuickCheck.Instances (ComplexVersion(..)) where++import Test.QuickCheck++import Portage.Version (Suffix(..), Version(..))++--------------------------------------------------------------------------------+-- Types+--------------------------------------------------------------------------------+-- | Wrapper for 'Suffix', intended for use in an 'Arbitrary' instance+-- to return a single, valid 'Suffix'.+newtype ValidSuffix = ValidSuffix { getSuffix :: Suffix }+ deriving (Eq,Ord,Show)++-- | Wrapper For 'Version', intended for use in an 'Arbitrary' instance+-- where we want to generate the most complex 'Version' possible.+newtype ComplexVersion = ComplexVersion { getVersion :: Version }+ deriving (Eq,Ord,Show)++--------------------------------------------------------------------------------+-- Instances+--------------------------------------------------------------------------------+-- | Return a single, valid 'ValidSuffix'.+instance Arbitrary ValidSuffix where+ arbitrary = oneof [ ValidSuffix . Alpha . getNonNegative <$> arbitrary+ , ValidSuffix . Beta . getNonNegative <$> arbitrary+ , ValidSuffix . Pre . getNonNegative <$> arbitrary+ , ValidSuffix . RC . getNonNegative <$> arbitrary+ , ValidSuffix . P . getNonNegative <$> arbitrary+ ]+ +-- | Return a valid 'ComplexVersion' with a non-empty 'versionNumber',+-- an optional 'versionChar' if valid, a ['Suffix'] which may be empty,+-- and a 'NonNegative' 'versionRevision' which may be zero.+--+-- This is used to generate a 'Version' of high complexity to+-- stress-test our parsers for a range of valid inputs.+instance Arbitrary ComplexVersion where+ arbitrary = do+ v <- listOf1 $ getNonNegative <$> arbitrary+ c <- Just <$> choose ('a','z')+ s <- listOf $ getSuffix <$> arbitrary+ (NonNegative r) <- arbitrary+ return $ ComplexVersion $ Version v (if length v == 1 then Nothing else c) s r
+ tests/Spec.hs view
@@ -0,0 +1,1 @@+{-# OPTIONS_GHC -F -pgmF hspec-discover #-}
+ tests/doctests.hs view
@@ -0,0 +1,12 @@+module Main where++import Test.DocTest+-- Some modules fail to find module Paths_hackport, which is generated during building.+-- There is a way to make this work properly, but for now just test modules which+-- don't import Paths_hackport.+main = doctest [ "Portage/Cabal.hs"+ , "Portage/GHCCore.hs"+ , "Portage/PackageId.hs"+ , "Portage/Version.hs"+ , "Portage/Metadata.hs"+ ]