stack2cabal 1.0.11 → 1.0.12
raw patch · 6 files changed
+176/−38 lines, 6 filesdep ~Cabaldep ~basedep ~hpackPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependency ranges changed: Cabal, base, hpack
API changes (from Hackage documentation)
- StackageToHackage.Stackage.Types: instance GHC.Base.Semigroup StackageToHackage.Stackage.Types.Resolver
+ StackageToHackage.Stackage: mergeResolvers :: Resolver -> Resolver -> Resolver
+ StackageToHackage.Stackage.Types: instance GHC.Base.Monoid StackageToHackage.Stackage.Types.Flags
+ StackageToHackage.Stackage.Types: instance GHC.Classes.Eq StackageToHackage.Stackage.Types.Git
+ StackageToHackage.Stackage.Types: instance GHC.Classes.Ord StackageToHackage.Stackage.Types.Git
Files
- CHANGELOG.md +35/−0
- README.md +56/−0
- lib/StackageToHackage/Hackage.hs +10/−9
- lib/StackageToHackage/Stackage.hs +46/−0
- lib/StackageToHackage/Stackage/Types.hs +2/−6
- stack2cabal.cabal +27/−23
+ CHANGELOG.md view
@@ -0,0 +1,35 @@+# Revision history for stack2cabal++## 1.0.12 -- 2020-10-23++- Use multiple subdirs per source-repository wrt #29+- Merge git repos properly, wrt #30++## 1.0.11 -- 2020-10-05++- Fix bug in `cabal.project.freeze` when git-package in extra-deps doesn't have a subdir+- Run hpack for git deps as well+- Fix `--output-file` option to use it as full filepath (instead of base directory)++## 1.0.10 -- 2020-10-04++- Allow to pin hackage state wrt #20+- Fix missing flags in cabal.project.freeze wrt #24+- fix bug in ghc-options conversion++## 1.0.9 -- 2020-10-04++- Inspect remote repository package names and exclude them from freeze file (fixes #1), disable with `--no-inspect-remotes`+- Add `--no-pin-ghc` option+- Add `--no-run-hpack` option+- Add `--output-file` option+- Also parse ghc-options wrt #9+- Fix path separators on windows wrt #5++## 1.0.8 -- 2020-09-25++- fix not parsing local deps [by d86leader](https://gitlab.com/d86leader/stack2cabal/-/commit/bd2370c8a453d2dec5546ab936604b2d7d9f6be2)+- add cli argument parses for specifying stack file+- Make stack2cabal comaptible with HsYAML>=2.0 [by Roman Melnikov](https://gitlab.com/serokell/morley/stack2cabal/-/commit/9c352382788c6f0c1917d877f6b7abdf3f96484a)+- Relax upper bound on Cabal+- Allow resolver to point to remote url
+ README.md view
@@ -0,0 +1,56 @@+[](https://gitter.im/hasufell/stack2cabal?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)+[](https://github.com/hasufell/stack2cabal/actions)+[](https://github.com/hasufell/stack2cabal/actions)+[](https://hackage.haskell.org/package/stack2cabal)+[](LICENSE)++# stack2cabal++This is forked of [tseenshe/stack2cabal](https://gitlab.com/tseenshe/stack2cabal) and+the current [hackage package](https://hackage.haskell.org/package/stack2cabal).++## Installation++Clone the repo and build with either cabal or stack or see the [release page](https://github.com/hasufell/stack2cabal/releases)+for binaries.++### Docker++[](https://hub.docker.com/repository/docker/hasufell/stack2cabal)+[](https://hub.docker.com/repository/docker/hasufell/stack2cabal)+[](https://hub.docker.com/repository/docker/hasufell/stack2cabal)++```sh+docker pull hasufell/stack2cabal:latest+```++## Usage++To convert a `stack.yaml` to `cabal.project` simply cd to the project directory and run:++```sh+stack2cabal+```++This will also create a `cabal.project.freeze` based on the stack resolver.++Also see `stack2cabal --help` for further options.++### Docker++```sh+docker run --rm \+ -v /etc/passwd:/etc/passwd:ro \+ -u `id -u`:`id -g` \+ -v `pwd`:`pwd` \+ -w `pwd` \+ --tmpfs "$HOME/.cache" \+ hasufell/stack2cabal:latest+```++## Notes++- Hackage packages that are specified as git repositories in e.g. `extra-deps` might+have a different version than the stack resolver. Therefore `stack2cabal` will download+all repos and ignore their package names when generating `cabal.project.freeze`.+This can take some time depending on your project. Pass `--no-inspect-remotes` to skip this.
lib/StackageToHackage/Hackage.hs view
@@ -13,7 +13,7 @@ ) where -import StackageToHackage.Stackage ( localDirs, unroll )+import StackageToHackage.Stackage ( localDirs, unroll, mergeResolvers ) import StackageToHackage.Stackage.Types ( Resolver(Resolver, compiler, deps, flags) , PkgId(unPkgId)@@ -34,11 +34,10 @@ import Control.Monad (forM, when, void) import Control.Monad.Catch (handleIOError) import Data.Hourglass (timePrint, ISO8601_DateAndTime(..), Elapsed)-import Data.List (nub, sort)-import Data.List.Extra (nubOrdOn)+import Data.List (nub, sort, sortOn)+import Data.List.Extra (nubOrd, nubOrdOn) import Data.List.NonEmpty (NonEmpty((:|))) import Data.Maybe (fromMaybe, mapMaybe, catMaybes)-import Data.Semigroup ( Semigroup(sconcat) ) import Data.Text (Text) import Distribution.PackageDescription.Parsec (readGenericPackageDescription) import Distribution.Pretty (prettyShow)@@ -72,7 +71,7 @@ -> IO (Project, Freeze) stackToCabal inspectRemotes runHpack dir stack = do resolvers <- unroll dir stack- let resolver = sconcat resolvers+ let resolver = foldr1 mergeResolvers resolvers project = genProject stack resolver localPkgs <- fmap catMaybes@@ -142,9 +141,11 @@ [ "source-repository-package\n ", "type: git\n ", "location: " , repo, "\n ", "tag: ", commit, "\n" ]- in if null subdirs- then [base]- else (\d -> T.concat [base, " subdir: ", d, "\n"]) <$> subdirs+ in case sort subdirs of+ [] -> [base]+ (x:xs) -> [T.concat $ [base, " subdir: ", x]+ ++ (("\n " <>) <$> xs)+ ++ ["\n"]] -- Get the ghc options. This requires IO, because we have to figure out -- the local package names.@@ -182,7 +183,7 @@ genProject stack Resolver { compiler, deps } = Project (fromMaybe (Ghc "ghc") compiler) (localDirs stack `appendList` localDeps deps)- (nubOrdOn repo $ mapMaybe pickGit deps)+ (sortOn repo $ nubOrd $ mapMaybe pickGit deps) (ghcOptions stack) where pickGit :: Dep -> Maybe Git
lib/StackageToHackage/Stackage.hs view
@@ -13,6 +13,7 @@ import Control.Applicative ((<|>)) import Control.Monad.Extra (loopM, unlessM) import Data.ByteString.Lazy (toStrict)+import Data.List (nub, foldl', find, (\\)) import Data.List.NonEmpty (NonEmpty(..), head, nonEmpty, reverse, (<|)) import Data.Maybe (fromMaybe, listToMaybe, mapMaybe) import Data.Semigroup@@ -127,6 +128,51 @@ (new2old' <$> packages) flags where new2old' (NewDep pkg) = Hackage pkg+++-- | Merging two resolvers is straight-forward, except for+-- handling Git deps. These need to be merged carefully, because+-- stack.yaml may add subdirs to the repo of a resolver.+-- Also see: https://github.com/hasufell/stack2cabal/issues/30+mergeResolvers :: Resolver -> Resolver -> Resolver+mergeResolvers (Resolver r c p f) (Resolver r' c' p' f') =+ Resolver (r <|> r') (c <|> c') (mergeDeps p p') (f <> f')+ where+ mergeDeps :: [Dep] -> [Dep] -> [Dep]+ mergeDeps lhs rhs =+ let nonGits = filter (not . isGitDep) lhs <> filter (not . isGitDep) rhs+ gitsLhs = (\(SourceDep dep) -> dep) <$> filter isGitDep lhs+ gitsRhs = (\(SourceDep dep) -> dep) <$> filter isGitDep rhs+ gitMerged = foldl' (\m key -> update key m) gitsRhs gitsLhs+ in (SourceDep <$> gitMerged) <> nonGits++ -- this is somewhat inefficient due to lists, but they're all fairly small+ update :: Git -> [Git] -> [Git]+ update git xs =+ -- find same repos+ case find (\g -> git { subdirs = [], commit = "" }+ == g { subdirs = [], commit = "" })+ xs of+ Just g+ -- on same commit, just append subdirs+ | commit g == commit git+ -> git { subdirs = nub (subdirs git <> subdirs g) }+ : delete g xs+ -- on different commit need to delete subdirs from lower resolver+ | otherwise+ -> git+ -- > [0, 0, 0] \\ [0, 0]+ -- [0]+ : g { subdirs = nub (subdirs g) \\ nub (subdirs git) }+ : delete g xs+ Nothing -> git : xs++ isGitDep :: Dep -> Bool+ isGitDep (SourceDep _) = True+ isGitDep _ = False++ delete :: Eq a => a -> [a] -> [a]+ delete deleted xs = [ x | x <- xs, x /= deleted ] -------------------------------------------------------------------------------- -- YAML
lib/StackageToHackage/Stackage/Types.hs view
@@ -4,7 +4,6 @@ module StackageToHackage.Stackage.Types where -import Control.Applicative ((<|>)) import Data.List.NonEmpty (NonEmpty(..)) import Data.Map.Strict (Map) import Data.Semigroup@@ -36,7 +35,7 @@ { repo :: Repo , commit :: Commit , subdirs :: [Subdir]- } deriving (Show)+ } deriving (Show, Eq, Ord) type Repo = Text@@ -55,7 +54,7 @@ newtype Flags = Flags (Map PkgName (Map FlagName Bool)) deriving (Show)- deriving newtype (Semigroup)+ deriving newtype (Semigroup, Monoid) newtype PackageGhcOpts = PackageGhcOpts (Map PkgId GhcFlags)@@ -102,9 +101,6 @@ , flags :: Flags } deriving (Show) -instance Semigroup Resolver where- (Resolver r c p f) <> (Resolver r' c' p' f') =- Resolver (r <|> r') (c <|> c') (p <> p') (f <> f') -- TODO: remote ResolverRefs data ResolverRef = Canned Text
stack2cabal.cabal view
@@ -1,20 +1,24 @@-cabal-version: 2.2-name: stack2cabal-version: 1.0.11+cabal-version: 2.2+name: stack2cabal+version: 1.0.12 synopsis: Convert stack projects to cabal.project + cabal.project.freeze -license: GPL-3.0-only-license-file: LICENSE-author: Tseen She-maintainer: Julian Ospald-copyright: 2018 Tseen She, 2020 Julian Ospald-bug-reports: https://github.com/hasufell/stack2cabal/issues-tested-with: GHC ^>=8.6.5 || ^>=8.8.4 || ^>=8.10.2-category: Building+license: GPL-3.0-only+license-file: LICENSE+author: Tseen She+maintainer: Julian Ospald+copyright: 2018 Tseen She, 2020 Julian Ospald+bug-reports: https://github.com/hasufell/stack2cabal/issues+tested-with: GHC ^>=8.6.5 || ^>=8.8.4 || ^>=8.10.2+category: Building description: Convert @stack.yaml@ \/ @package.yaml@ to @cabal.project@ \/ @cabal.project.freeze@\/ @*.cabal@. +extra-source-files:+ README.md+ CHANGELOG.md+ source-repository head type: git location: https://github.com/hasufell/stack2cabal.git@@ -28,25 +32,25 @@ common deps build-depends:- , base >=4.10 && <5.0+ , base >=4.10 && <5.0 , bytestring- , Cabal >=3.0 && <3.4+ , Cabal >=3.0 && <3.4 , containers , directory- , exceptions- , extra >=1.6.13+ , exceptions ^>=0.10.4+ , extra ^>=1.7.8 , filepath- , filepattern >=0.1.2- , fuzzy-dates >=0.1.1.2- , hourglass+ , filepattern ^>=0.1.2+ , fuzzy-dates ^>=0.1.1.2+ , hourglass ^>=0.2.12 , hpack ==0.34.2 , HsYAML ^>=0.2- , http-client >=0.5.14- , http-client-tls >=0.3.5.3- , optparse-applicative >=0.15+ , http-client ^>=0.6.4.1+ , http-client-tls ^>=0.3.5.3+ , optparse-applicative ^>=0.15.1.0 , process >=1.6.9.0- , safe >=0.3- , temporary >=1.3+ , safe ^>=0.3.19+ , temporary ^>=1.3 , text >=1.2.3.1 if flag(ghcflags)