diff --git a/Cabal/src/Distribution/Compat/Prelude.hs b/Cabal/src/Distribution/Compat/Prelude.hs index edc7eb3386e..4eb6528e002 100644 --- a/Cabal/src/Distribution/Compat/Prelude.hs +++ b/Cabal/src/Distribution/Compat/Prelude.hs @@ -71,7 +71,7 @@ module Distribution.Compat.Prelude ( partition, -- * Data.List.NonEmpty - NonEmpty((:|)), foldl1, foldr1, + NonEmpty((:|)), nonEmpty, foldl1, foldr1, head, tail, last, init, -- * Data.Foldable @@ -187,7 +187,7 @@ 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.List.NonEmpty (NonEmpty ((:|)), nonEmpty, head, init, last, tail) import Data.Map (Map) import Data.Maybe (catMaybes, fromMaybe, isJust, isNothing, listToMaybe, mapMaybe, maybeToList) import Data.Ord (comparing) diff --git a/Cabal/src/Distribution/Simple/Configure.hs b/Cabal/src/Distribution/Simple/Configure.hs index e52c5b0d534..28e65a687ae 100644 --- a/Cabal/src/Distribution/Simple/Configure.hs +++ b/Cabal/src/Distribution/Simple/Configure.hs @@ -103,7 +103,6 @@ import qualified Distribution.Simple.HaskellSuite as HaskellSuite import Control.Exception ( try ) -import Data.List.NonEmpty ( nonEmpty ) import Distribution.Utils.Structured ( structuredDecodeOrFailIO, structuredEncode ) import Distribution.Compat.Directory ( listDirectory ) import Data.ByteString.Lazy ( ByteString ) diff --git a/Cabal/src/Distribution/Simple/SrcDist.hs b/Cabal/src/Distribution/Simple/SrcDist.hs index 10a9c8727f0..36ba5bd2488 100644 --- a/Cabal/src/Distribution/Simple/SrcDist.hs +++ b/Cabal/src/Distribution/Simple/SrcDist.hs @@ -450,7 +450,7 @@ allSourcesBuildInfo verbosity rip cwd bi pps modules = do -- file may show up in multiple paths due to a conditional; -- we need to package all of them. See #367. in findAllFilesCwdWithExtension cwd suffixes searchDirs file - >>= nonEmpty (notFound module_) return + >>= nonEmpty' (notFound module_) return | module_ <- modules ++ otherModules bi ] bootFiles <- sequenceA [ let file = ModuleName.toFilePath module_ @@ -462,8 +462,10 @@ allSourcesBuildInfo verbosity rip cwd bi pps modules = do cmmSources bi ++ asmSources bi ++ jsSources bi where - nonEmpty x _ [] = x - nonEmpty _ f xs = f xs + nonEmpty' :: b -> ([a] -> b) -> [a] -> b + nonEmpty' x _ [] = x + nonEmpty' _ f xs = f xs + suffixes = ppSuffixes pps ++ ["hs", "lhs", "hsig", "lhsig"] notFound :: ModuleName -> IO [FilePath] diff --git a/Cabal/src/Distribution/Types/VersionInterval.hs b/Cabal/src/Distribution/Types/VersionInterval.hs index 05354105d24..d07a47f3fd0 100644 --- a/Cabal/src/Distribution/Types/VersionInterval.hs +++ b/Cabal/src/Distribution/Types/VersionInterval.hs @@ -142,7 +142,7 @@ insertInterval :: VersionInterval -> VersionIntervals -> VersionIntervals insertInterval i is = unionVersionIntervals (VersionIntervals [i]) is validInterval :: (LowerBound, UpperBound) -> Bool -validInterval i@(l, u) = validLower l && validUpper u && nonEmpty i +validInterval i@(l, u) = validLower l && validUpper u && nonEmptyVI i where validLower (LowerBound v _) = validVersion v validUpper NoUpperBound = True @@ -150,9 +150,9 @@ validInterval i@(l, u) = validLower l && validUpper u && nonEmpty i -- Check an interval is non-empty -- -nonEmpty :: VersionInterval -> Bool -nonEmpty (_, NoUpperBound ) = True -nonEmpty (LowerBound l lb, UpperBound u ub) = +nonEmptyVI :: VersionInterval -> Bool +nonEmptyVI (_, NoUpperBound ) = True +nonEmptyVI (LowerBound l lb, UpperBound u ub) = (l < u) || (l == u && lb == InclusiveBound && ub == InclusiveBound) -- Check an upper bound does not intersect, or even touch a lower bound: diff --git a/cabal-install/src/Distribution/Client/List.hs b/cabal-install/src/Distribution/Client/List.hs index fd792b6845d..97fdb51aaf8 100644 --- a/cabal-install/src/Distribution/Client/List.hs +++ b/cabal-install/src/Distribution/Client/List.hs @@ -67,7 +67,7 @@ import Distribution.Client.FetchUtils import Data.Bits ((.|.)) import Data.List ( maximumBy ) -import Data.List.NonEmpty (groupBy, nonEmpty) +import Data.List.NonEmpty (groupBy) import qualified Data.List as L import Data.Maybe ( fromJust ) diff --git a/cabal-install/src/Distribution/Client/ProjectConfig.hs b/cabal-install/src/Distribution/Client/ProjectConfig.hs index 5c8cf444ca7..5a42729a841 100644 --- a/cabal-install/src/Distribution/Client/ProjectConfig.hs +++ b/cabal-install/src/Distribution/Client/ProjectConfig.hs @@ -116,7 +116,7 @@ import Distribution.Simple.InstallDirs ( PathTemplate, fromPathTemplate , toPathTemplate, substPathTemplate, initialPathTemplateEnv ) import Distribution.Simple.Utils - ( die', warn, notice, info, createDirectoryIfMissingVerbose ) + ( die', warn, notice, info, createDirectoryIfMissingVerbose, rawSystemIOWithEnv ) import Distribution.Client.Utils ( determineNumJobs ) import Distribution.Utils.NubList @@ -1172,7 +1172,12 @@ syncAndReadSourcePackagesRemoteRepos verbosity syncSourceRepos verbosity vcs [ (repo, repoPath) | (repo, _, repoPath) <- repoGroupWithPaths ] - -- TODO phadej 2020-06-18 add post-sync script + + -- Run post-checkout-command if it is specified + for_ repoGroupWithPaths $ \(repo, _, repoPath) -> + for_ (nonEmpty (srpCommand repo)) $ \(cmd :| args) -> liftIO $ do + exitCode <- rawSystemIOWithEnv verbosity cmd args (Just repoPath) Nothing Nothing Nothing Nothing + unless (exitCode /= ExitSuccess) $ exitWith exitCode -- But for reading we go through each 'SourceRepo' including its subdir -- value and have to know which path each one ended up in. diff --git a/cabal-install/src/Distribution/Client/ProjectConfig/Legacy.hs b/cabal-install/src/Distribution/Client/ProjectConfig/Legacy.hs index 39a0342aa08..c7622c092e0 100644 --- a/cabal-install/src/Distribution/Client/ProjectConfig/Legacy.hs +++ b/cabal-install/src/Distribution/Client/ProjectConfig/Legacy.hs @@ -1224,7 +1224,9 @@ legacyPackageConfigFieldDescrs = legacyPackageConfigFGSectionDescrs :: ( FieldGrammar c g, Applicative (g SourceRepoList) - , c (Identity RepoType), c (List NoCommaFSep FilePathNT String) + , c (Identity RepoType) + , c (List NoCommaFSep FilePathNT String) + , c (NonEmpty' NoCommaFSep Token String) ) => [FGSectionDescr g LegacyProjectConfig] legacyPackageConfigFGSectionDescrs = @@ -1253,7 +1255,9 @@ legacyPackageConfigSectionDescrs = packageRepoSectionDescr :: ( FieldGrammar c g, Applicative (g SourceRepoList) - , c (Identity RepoType), c (List NoCommaFSep FilePathNT String) + , c (Identity RepoType) + , c (List NoCommaFSep FilePathNT String) + , c (NonEmpty' NoCommaFSep Token String) ) => FGSectionDescr g LegacyProjectConfig packageRepoSectionDescr = FGSectionDescr diff --git a/cabal-install/src/Distribution/Client/Types/SourceRepo.hs b/cabal-install/src/Distribution/Client/Types/SourceRepo.hs index 0cc44ff7472..751c6c97266 100644 --- a/cabal-install/src/Distribution/Client/Types/SourceRepo.hs +++ b/cabal-install/src/Distribution/Client/Types/SourceRepo.hs @@ -32,6 +32,7 @@ data SourceRepositoryPackage f = SourceRepositoryPackage , srpTag :: !(Maybe String) , srpBranch :: !(Maybe String) , srpSubdir :: !(f FilePath) + , srpCommand :: ![String] } deriving (Generic) @@ -88,6 +89,10 @@ srpSubdirLens :: Lens (SourceRepositoryPackage f) (SourceRepositoryPackage g) (f srpSubdirLens f s = fmap (\x -> s { srpSubdir = x }) (f (srpSubdir s)) {-# INLINE srpSubdirLens #-} +srpCommandLensNE :: Lens' (SourceRepositoryPackage f) (Maybe (NonEmpty String)) +srpCommandLensNE f s = fmap (\x -> s { srpCommand = maybe [] toList x }) (f (nonEmpty (srpCommand s))) +{-# INLINE srpCommandLensNE #-} + ------------------------------------------------------------------------------- -- Parser & PPrinter ------------------------------------------------------------------------------- @@ -96,6 +101,7 @@ sourceRepositoryPackageGrammar :: ( FieldGrammar c g, Applicative (g SourceRepoList) , c (Identity RepoType) , c (List NoCommaFSep FilePathNT String) + , c (NonEmpty' NoCommaFSep Token String) ) => g SourceRepoList SourceRepoList sourceRepositoryPackageGrammar = SourceRepositoryPackage @@ -104,5 +110,8 @@ sourceRepositoryPackageGrammar = SourceRepositoryPackage <*> optionalFieldAla "tag" Token srpTagLens <*> optionalFieldAla "branch" Token srpBranchLens <*> monoidalFieldAla "subdir" (alaList' NoCommaFSep FilePathNT) srpSubdirLens -- note: NoCommaFSep is somewhat important for roundtrip, as "." is there... + <*> fmap (maybe [] toList) pcc + where + pcc = optionalFieldAla "post-checkout-command" (alaNonEmpty' NoCommaFSep Token) srpCommandLensNE {-# SPECIALIZE sourceRepositoryPackageGrammar :: ParsecFieldGrammar' SourceRepoList #-} {-# SPECIALIZE sourceRepositoryPackageGrammar :: PrettyFieldGrammar' SourceRepoList #-} diff --git a/cabal-install/src/Distribution/Client/VCS.hs b/cabal-install/src/Distribution/Client/VCS.hs index 49addef110c..2f2fd9fa41c 100644 --- a/cabal-install/src/Distribution/Client/VCS.hs +++ b/cabal-install/src/Distribution/Client/VCS.hs @@ -127,6 +127,7 @@ validatePDSourceRepo repo = do , srpTag = PD.repoTag repo , srpBranch = PD.repoBranch repo , srpSubdir = PD.repoSubdir repo + , srpCommand = mempty } where a ?! e = maybe (Left e) Right a diff --git a/cabal-install/tests/UnitTests/Distribution/Client/Get.hs b/cabal-install/tests/UnitTests/Distribution/Client/Get.hs index aa4378ede7e..313eccc6955 100644 --- a/cabal-install/tests/UnitTests/Distribution/Client/Get.hs +++ b/cabal-install/tests/UnitTests/Distribution/Client/Get.hs @@ -106,6 +106,7 @@ testUnsupportedRepoType = do , srpTag = Nothing , srpBranch = Nothing , srpSubdir = Proxy + , srpCommand = [] } repotype = OtherRepoType "baz" @@ -184,6 +185,7 @@ testGitFetchFailed = , srpTag = Nothing , srpBranch = Nothing , srpSubdir = Proxy + , srpCommand = [] } pkgrepos = [(pkgidfoo, [repo])] e1 <- assertException $ diff --git a/cabal-install/tests/UnitTests/Distribution/Client/ProjectConfig.hs b/cabal-install/tests/UnitTests/Distribution/Client/ProjectConfig.hs index 7be686771e8..132aa4090d8 100644 --- a/cabal-install/tests/UnitTests/Distribution/Client/ProjectConfig.hs +++ b/cabal-install/tests/UnitTests/Distribution/Client/ProjectConfig.hs @@ -735,17 +735,15 @@ instance f ~ [] => Arbitrary (SourceRepositoryPackage f) where <*> (fmap getShortToken <$> arbitrary) <*> (fmap getShortToken <$> arbitrary) <*> (fmap getShortToken <$> shortListOf 3 arbitrary) + <*> (fmap getShortToken <$> shortListOf 3 arbitrary) - shrink (SourceRepositoryPackage x1 x2 x3 x4 x5) = - [ SourceRepositoryPackage - x1' - (getShortToken x2') - (fmap getShortToken x3') - (fmap getShortToken x4') - (fmap getShortToken x5') - | (x1', x2', x3', x4', x5') <- shrink - (x1, ShortToken x2, fmap ShortToken x3, fmap ShortToken x4, fmap ShortToken x5) - ] + shrink SourceRepositoryPackage {..} = runShrinker $ pure SourceRepositoryPackage + <*> shrinker srpType + <*> shrinkerAla ShortToken srpLocation + <*> shrinkerAla (fmap ShortToken) srpTag + <*> shrinkerAla (fmap ShortToken) srpBranch + <*> shrinkerAla (fmap ShortToken) srpSubdir + <*> shrinkerAla (fmap ShortToken) srpCommand instance Arbitrary RemoteRepo where arbitrary = diff --git a/cabal-install/tests/UnitTests/Distribution/Client/VCS.hs b/cabal-install/tests/UnitTests/Distribution/Client/VCS.hs index 2cf222b0a75..e4d68b0f5ac 100644 --- a/cabal-install/tests/UnitTests/Distribution/Client/VCS.hs +++ b/cabal-install/tests/UnitTests/Distribution/Client/VCS.hs @@ -215,6 +215,7 @@ prop_cloneRepo vcs mkVCSTestDriver repoRecipe = , srpTag = Just tagname , srpBranch = Nothing , srpSubdir = [] + , srpCommand = [] } verbosity = silent @@ -315,6 +316,7 @@ pickSyncTargetSets repoType repoState srcRepoPath dstReposPath = , srpTag = Just tag , srpBranch = Nothing , srpSubdir = Proxy + , srpCommand = [] } (tag, workingState) = Map.elemAt tagIdx (allTags repoState) (tagIdx, prng') = randomR (0, Map.size (allTags repoState) - 1) prng diff --git a/changelog.d/documentation b/changelog.d/documentation index b6541b309b9..4eda812ed60 100644 --- a/changelog.d/documentation +++ b/changelog.d/documentation @@ -1,5 +1,6 @@ synopsis: Documentation improvements -prs: #6971 +prs: #6971 #7047 +issues: #6813 description: { diff --git a/changelog.d/issue-6664-pre-sdist-command b/changelog.d/issue-6664-pre-sdist-command new file mode 100644 index 00000000000..2b513d1374a --- /dev/null +++ b/changelog.d/issue-6664-pre-sdist-command @@ -0,0 +1,3 @@ +synopsis: Add post-checkout-command to source-package-repository +issues: #6664 +prs: #7047 diff --git a/doc/cabal-project.rst b/doc/cabal-project.rst index c3e1430c539..aea61583477 100644 --- a/doc/cabal-project.rst +++ b/doc/cabal-project.rst @@ -147,14 +147,7 @@ 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: +version control. .. code-block:: cabal @@ -171,6 +164,29 @@ A simple example is shown below: tag: 3d274c14ca3077c3a081ba7ad57c5182da65c8c1 subdir: cborg + source-repository-package + type: git + location: https://github.com/haskell/network.git + tag: e76fdc753e660dfa615af6c8b6a2ad9ddf6afe70 + post-checkout-command: autoreconf -i + +cabal-install 3.4 sdists the ``source-repository-package`` repositories and uses resulting tarballs as project packages. +This allows sharing of packages across different projects. + +.. cfg-field:: type: VCS kind + +.. cfg-field:: location: VCS location (usually URL) + +.. cfg-field:: type: VCS tag + +.. cfg-field:: subdir: subdirectory list + + Use one or more subdirectories of the repository. + +.. cfg-field:: post-checkout-command: command + + Run command in the checked out repository, prior sdisting. + Global configuration options ----------------------------