Merge pull request #233 from DanielG/dev-pkgs

Make package dependencies consistent with Cabal
This commit is contained in:
Kazu Yamamoto 2014-05-08 10:24:23 +09:00
commit 89bd2ca08b
17 changed files with 218 additions and 66 deletions

3
.gitignore vendored
View File

@ -1,7 +1,8 @@
dist/ dist/
elisp/*.elc elisp/*.elc
*~ *~
.cabal-sandbox/ /.cabal-sandbox/
package.cache
cabal.sandbox.config cabal.sandbox.config
# Mac OS generates # Mac OS generates
# .DS_Store # .DS_Store

View File

@ -8,26 +8,26 @@ before_install:
- sudo add-apt-repository -y ppa:hvr/ghc - sudo add-apt-repository -y ppa:hvr/ghc
- sudo apt-get update - sudo apt-get update
- sudo apt-get install cabal-install-1.18 ghc-$GHCVER - sudo apt-get install cabal-install-1.18 ghc-$GHCVER
- export PATH=/opt/ghc/$GHCVER/bin:$PATH - export PATH=/opt/ghc/$GHCVER/bin:/opt/cabal/1.18/bin:$PATH
install: install:
- cabal-1.18 update - cabal update
- cabal-1.18 install happy - cabal install happy
- export PATH=$HOME/.cabal/bin:$PATH - export PATH=$HOME/.cabal/bin:$PATH
- happy --version - happy --version
- cabal-1.18 install --only-dependencies --enable-tests - cabal install --only-dependencies --enable-tests
script: script:
- cabal-1.18 configure --enable-tests - cabal configure --enable-tests
- cabal-1.18 build - cabal build
- cabal-1.18 test - cabal test
- cabal-1.18 check - cabal check
- cabal-1.18 sdist - cabal sdist
# The following scriptlet checks that the resulting source distribution can be built & installed # The following scriptlet checks that the resulting source distribution can be built & installed
- export SRC_TGZ=$(cabal-1.18 info . | awk '{print $2 ".tar.gz";exit}'); - export SRC_TGZ=$(cabal info . | awk '{print $2 ".tar.gz";exit}');
cd dist/; cd dist/;
if [ -f "$SRC_TGZ" ]; then if [ -f "$SRC_TGZ" ]; then
cabal-1.18 install --enable-tests "$SRC_TGZ"; cabal install --enable-tests "$SRC_TGZ";
else else
echo "expected '$SRC_TGZ' not found"; echo "expected '$SRC_TGZ' not found";
exit 1; exit 1;

View File

@ -7,20 +7,26 @@ module Language.Haskell.GhcMod.CabalApi (
, cabalDependPackages , cabalDependPackages
, cabalSourceDirs , cabalSourceDirs
, cabalAllTargets , cabalAllTargets
, cabalGetConfig
, cabalConfigPath
, cabalConfigDependencies
) where ) where
import Language.Haskell.GhcMod.Types import Language.Haskell.GhcMod.Types
import Language.Haskell.GhcMod.GhcPkg import Language.Haskell.GhcMod.GhcPkg
import Language.Haskell.GhcMod.Utils
import Control.Applicative ((<$>)) import Control.Applicative ((<$>))
import Control.Exception (throwIO) import Control.Exception (throwIO,catch,SomeException)
import Control.Monad (filterM) import Control.Monad (filterM)
import CoreMonad (liftIO) import CoreMonad (liftIO)
import Data.Maybe (maybeToList, catMaybes) import Data.Maybe (maybeToList)
import Data.Set (fromList, toList) import Data.Set (fromList, toList)
import Data.List (find,tails,isPrefixOf)
import Distribution.ModuleName (ModuleName,toFilePath) import Distribution.ModuleName (ModuleName,toFilePath)
import Distribution.Package (Dependency(Dependency) import Distribution.Package (Dependency(Dependency)
, PackageName(PackageName)) , PackageName(PackageName)
, InstalledPackageId(..))
import qualified Distribution.Package as C import qualified Distribution.Package as C
import Distribution.PackageDescription (PackageDescription, BuildInfo, TestSuite, TestSuiteInterface(..), Executable) import Distribution.PackageDescription (PackageDescription, BuildInfo, TestSuite, TestSuiteInterface(..), Executable)
import qualified Distribution.PackageDescription as P import qualified Distribution.PackageDescription as P
@ -29,12 +35,15 @@ import Distribution.PackageDescription.Parse (readPackageDescription)
import Distribution.Simple.Compiler (CompilerId(..), CompilerFlavor(..)) import Distribution.Simple.Compiler (CompilerId(..), CompilerFlavor(..))
import Distribution.Simple.Program (ghcProgram) import Distribution.Simple.Program (ghcProgram)
import Distribution.Simple.Program.Types (programName, programFindVersion) import Distribution.Simple.Program.Types (programName, programFindVersion)
import Distribution.Simple.BuildPaths (defaultDistPref)
import Distribution.Simple.Configure (localBuildInfoFile)
import Distribution.Simple.LocalBuildInfo (ComponentName(..),ComponentLocalBuildInfo(..))
import Distribution.System (buildPlatform) import Distribution.System (buildPlatform)
import Distribution.Text (display) import Distribution.Text (display)
import Distribution.Verbosity (silent) import Distribution.Verbosity (silent)
import Distribution.Version (Version) import Distribution.Version (Version)
import System.Directory (doesFileExist) import System.Directory (doesFileExist)
import System.FilePath (dropExtension, takeFileName, (</>)) import System.FilePath ((</>))
---------------------------------------------------------------- ----------------------------------------------------------------
@ -45,38 +54,13 @@ getCompilerOptions :: [GHCOption]
-> IO CompilerOptions -> IO CompilerOptions
getCompilerOptions ghcopts cradle pkgDesc = do getCompilerOptions ghcopts cradle pkgDesc = do
gopts <- getGHCOptions ghcopts cradle rdir $ head buildInfos gopts <- getGHCOptions ghcopts cradle rdir $ head buildInfos
dbPkgs <- ghcPkgListEx (cradlePkgDbStack cradle) depPkgs <- cabalConfigDependencies <$> cabalGetConfig cradle
return $ CompilerOptions gopts idirs (depPkgs dbPkgs) return $ CompilerOptions gopts idirs depPkgs
where where
wdir = cradleCurrentDir cradle wdir = cradleCurrentDir cradle
rdir = cradleRootDir cradle rdir = cradleRootDir cradle
Just cfile = cradleCabalFile cradle
thisPkg = dropExtension $ takeFileName cfile
buildInfos = cabalAllBuildInfo pkgDesc buildInfos = cabalAllBuildInfo pkgDesc
idirs = includeDirectories rdir wdir $ cabalSourceDirs buildInfos idirs = includeDirectories rdir wdir $ cabalSourceDirs buildInfos
depPkgs ps = attachPackageIds ps
$ removeThem (problematicPackages ++ [thisPkg])
$ cabalDependPackages buildInfos
----------------------------------------------------------------
-- Dependent packages
removeThem :: [PackageBaseName] -> [PackageBaseName] -> [PackageBaseName]
removeThem badpkgs = filter (`notElem` badpkgs)
problematicPackages :: [PackageBaseName]
problematicPackages = [
"base-compat" -- providing "Prelude"
]
attachPackageIds :: [Package] -> [PackageBaseName] -> [Package]
attachPackageIds pkgs = catMaybes . fmap (`lookup3` pkgs)
lookup3 :: Eq a => a -> [(a,b,c)] -> Maybe (a,b,c)
lookup3 _ [] = Nothing
lookup3 k (t@(a,_,_):ls)
| k == a = Just t
| otherwise = lookup3 k ls
---------------------------------------------------------------- ----------------------------------------------------------------
-- Include directories for modules -- Include directories for modules
@ -220,3 +204,54 @@ cabalAllTargets pd = do
getExecutableTarget exe = do getExecutableTarget exe = do
let maybeExes = [p </> e | p <- P.hsSourceDirs $ P.buildInfo exe, e <- [P.modulePath exe]] let maybeExes = [p </> e | p <- P.hsSourceDirs $ P.buildInfo exe, e <- [P.modulePath exe]]
liftIO $ filterM doesFileExist maybeExes liftIO $ filterM doesFileExist maybeExes
----------------------------------------------------------------
type CabalConfig = String
-- | Get file containing 'LocalBuildInfo' data. If it doesn't exist run @cabal
-- configure@ i.e. configure with default options like @cabal build@ would do.
cabalGetConfig :: Cradle -> IO CabalConfig
cabalGetConfig cradle =
readFile path `catch'` (\_ -> configure >> readFile path)
where
catch' = catch :: IO a -> (SomeException -> IO a) -> IO a
prjDir = cradleRootDir cradle
path = prjDir </> cabalConfigPath
configure =
withDirectory_ prjDir $ readProcess' "cabal" ["configure"]
-- | Path to 'LocalBuildInfo' file, usually @dist/setup-config@
cabalConfigPath :: FilePath
cabalConfigPath = localBuildInfoFile defaultDistPref
cabalConfigDependencies :: CabalConfig -> [Package]
cabalConfigDependencies config = cfgDepends
where
lbi :: (ComponentName, ComponentLocalBuildInfo, [ComponentName])
-> ComponentLocalBuildInfo
lbi (_,i,_) = i
components = case extractCabalSetupConfig "componentsConfigs" config of
Just comps -> lbi <$> comps
Nothing -> error $
"cabalConfigDependencies: Extracting field `componentsConfigs' from"
++ " setup-config failed"
pids :: [InstalledPackageId]
pids = fst <$> componentPackageDeps `concatMap` components
cfgDepends = filter (("inplace" /=) . pkgId)
$ fromInstalledPackageId <$> pids
-- | Extract part of cabal's @setup-config@, this is done with a mix of manual
-- string processing and use of 'read'. This way we can extract a field from
-- 'LocalBuildInfo' without having to parse the whole thing which would mean
-- depending on the exact version of Cabal used to configure the project as it
-- is rather likley that some part of 'LocalBuildInfo' changed.
--
-- Right now 'extractCabalSetupConfig' can only deal with Lists and Tuples in
-- the field!
extractCabalSetupConfig :: (Read r) => String -> CabalConfig -> Maybe r
extractCabalSetupConfig field config = do
read <$> extractParens <$> find (field `isPrefixOf`) (tails config)

View File

@ -6,6 +6,8 @@ module Language.Haskell.GhcMod.GhcPkg (
, ghcPkgDbStackOpts , ghcPkgDbStackOpts
, ghcDbStackOpts , ghcDbStackOpts
, ghcDbOpt , ghcDbOpt
, fromInstalledPackageId
, fromInstalledPackageId'
, getSandboxDb , getSandboxDb
, getPackageDbStack , getPackageDbStack
) where ) where
@ -16,13 +18,12 @@ import Control.Exception (SomeException(..))
import qualified Control.Exception as E import qualified Control.Exception as E
import Data.Char (isSpace,isAlphaNum) import Data.Char (isSpace,isAlphaNum)
import Data.List (isPrefixOf, intercalate) import Data.List (isPrefixOf, intercalate)
import Data.List.Split (splitOn)
import Data.Maybe (listToMaybe, maybeToList) import Data.Maybe (listToMaybe, maybeToList)
import Distribution.Package (InstalledPackageId(..))
import Language.Haskell.GhcMod.Types import Language.Haskell.GhcMod.Types
import Language.Haskell.GhcMod.Utils import Language.Haskell.GhcMod.Utils
import System.Exit (ExitCode(..))
import System.FilePath ((</>)) import System.FilePath ((</>))
import System.IO (hPutStrLn,stderr)
import System.Process (readProcessWithExitCode)
import Text.ParserCombinators.ReadP (ReadP, char, between, sepBy1, many1, string, choice, eof) import Text.ParserCombinators.ReadP (ReadP, char, between, sepBy1, many1, string, choice, eof)
import qualified Text.ParserCombinators.ReadP as P import qualified Text.ParserCombinators.ReadP as P
@ -58,7 +59,6 @@ getPackageDbStack cdir =
(getSandboxDb cdir >>= \db -> return [GlobalDb, PackageDb db]) (getSandboxDb cdir >>= \db -> return [GlobalDb, PackageDb db])
`E.catch` \(_ :: SomeException) -> return [GlobalDb, UserDb] `E.catch` \(_ :: SomeException) -> return [GlobalDb, UserDb]
-- | List packages in one or more ghc package store -- | List packages in one or more ghc package store
ghcPkgList :: [GhcPkgDb] -> IO [PackageBaseName] ghcPkgList :: [GhcPkgDb] -> IO [PackageBaseName]
ghcPkgList dbs = map fst3 <$> ghcPkgListEx dbs ghcPkgList dbs = map fst3 <$> ghcPkgListEx dbs
@ -66,14 +66,7 @@ ghcPkgList dbs = map fst3 <$> ghcPkgListEx dbs
ghcPkgListEx :: [GhcPkgDb] -> IO [Package] ghcPkgListEx :: [GhcPkgDb] -> IO [Package]
ghcPkgListEx dbs = do ghcPkgListEx dbs = do
(rv,output,err) <- readProcessWithExitCode "ghc-pkg" opts "" parseGhcPkgOutput .lines <$> readProcess' "ghc-pkg" opts
case rv of
ExitFailure val -> do
hPutStrLn stderr err
fail $ "ghc-pkg " ++ unwords opts ++ " (exit " ++ show val ++ ")"
ExitSuccess -> return ()
return $ parseGhcPkgOutput $ lines output
where where
opts = ["list", "-v"] ++ ghcPkgDbStackOpts dbs opts = ["list", "-v"] ++ ghcPkgDbStackOpts dbs
@ -92,6 +85,20 @@ packageLine l =
Just ((Hidden,p),_) -> Just p Just ((Hidden,p),_) -> Just p
_ -> Nothing _ -> Nothing
fromInstalledPackageId' :: InstalledPackageId -> Maybe Package
fromInstalledPackageId' pid = let
InstalledPackageId pkg = pid
in case reverse $ splitOn "-" pkg of
i:v:rest -> Just (intercalate "-" (reverse rest), v, i)
_ -> Nothing
fromInstalledPackageId :: InstalledPackageId -> Package
fromInstalledPackageId pid =
case fromInstalledPackageId' pid of
Just p -> p
Nothing -> error $
"fromInstalledPackageId: `"++show pid++"' is not a valid package-id"
data PackageState = Normal | Hidden | Broken deriving (Eq,Show) data PackageState = Normal | Hidden | Broken deriving (Eq,Show)
packageLineP :: ReadP (PackageState, Package) packageLineP :: ReadP (PackageState, Package)

View File

@ -1,5 +1,38 @@
module Language.Haskell.GhcMod.Utils where module Language.Haskell.GhcMod.Utils where
import Control.Exception (bracket)
import System.Directory (getCurrentDirectory, setCurrentDirectory)
import System.Process (readProcessWithExitCode)
import System.Exit (ExitCode(..))
import System.IO (hPutStrLn, stderr)
-- dropWhileEnd is not provided prior to base 4.5.0.0. -- dropWhileEnd is not provided prior to base 4.5.0.0.
dropWhileEnd :: (a -> Bool) -> [a] -> [a] dropWhileEnd :: (a -> Bool) -> [a] -> [a]
dropWhileEnd p = foldr (\x xs -> if p x && null xs then [] else x : xs) [] dropWhileEnd p = foldr (\x xs -> if p x && null xs then [] else x : xs) []
extractParens :: String -> String
extractParens str = extractParens' str 0
where
extractParens' :: String -> Int -> String
extractParens' [] _ = []
extractParens' (s:ss) level
| s `elem` "([{" = s : extractParens' ss (level+1)
| level == 0 = extractParens' ss 0
| s `elem` "}])" && level == 1 = s:[]
| s `elem` "}])" = s : extractParens' ss (level-1)
| otherwise = s : extractParens' ss level
readProcess' :: String -> [String] -> IO String
readProcess' cmd opts = do
(rv,output,err) <- readProcessWithExitCode cmd opts ""
case rv of
ExitFailure val -> do
hPutStrLn stderr err
fail $ cmd ++ " " ++ unwords opts ++ " (exit " ++ show val ++ ")"
ExitSuccess ->
return output
withDirectory_ :: FilePath -> IO a -> IO a
withDirectory_ dir action =
bracket getCurrentDirectory setCurrentDirectory
(\_ -> setCurrentDirectory dir >> action)

View File

@ -37,6 +37,11 @@ Extra-Source-Files: ChangeLog
test/data/check-test-subdir/test/Bar/*.hs test/data/check-test-subdir/test/Bar/*.hs
test/data/check-packageid/cabal.sandbox.config.in test/data/check-packageid/cabal.sandbox.config.in
test/data/check-packageid/.cabal-sandbox/i386-osx-ghc-7.6.3-packages.conf.d/template-haskell-2.8.0.0-32d4f24abdbb6bf41272b183b2e23e9c.conf test/data/check-packageid/.cabal-sandbox/i386-osx-ghc-7.6.3-packages.conf.d/template-haskell-2.8.0.0-32d4f24abdbb6bf41272b183b2e23e9c.conf
test/data/duplicate-pkgver/cabal.sandbox.config.in
test/data/duplicate-pkgver/duplicate-pkgver.cabal
test/data/duplicate-pkgver/.cabal-sandbox/i386-osx-ghc-7.6.3-packages.conf.d/template-haskell-1.0-7c59d13f32294d1ef6dc6233c24df961.conf
test/data/duplicate-pkgver/.cabal-sandbox/i386-osx-ghc-7.6.3-packages.conf.d/template-haskell-2.8.0.0-14e543bdae2da4d2aeff5386892c9112.conf
test/data/duplicate-pkgver/.cabal-sandbox/i386-osx-ghc-7.6.3-packages.conf.d/template-haskell-2.8.0.0-32d4f24abdbb6bf41272b183b2e23e9c.conf
test/data/ghc-mod-check/*.cabal test/data/ghc-mod-check/*.cabal
test/data/ghc-mod-check/*.hs test/data/ghc-mod-check/*.hs
test/data/ghc-mod-check/Data/*.hs test/data/ghc-mod-check/Data/*.hs
@ -83,6 +88,7 @@ Library
, syb , syb
, time , time
, transformers , transformers
, split
if impl(ghc < 7.7) if impl(ghc < 7.7)
Build-Depends: convertible Build-Depends: convertible
, Cabal >= 1.10 && < 1.17 , Cabal >= 1.10 && < 1.17
@ -154,6 +160,7 @@ Test-Suite spec
, time , time
, transformers , transformers
, hspec >= 1.8.2 , hspec >= 1.8.2
, split
if impl(ghc < 7.7) if impl(ghc < 7.7)
Build-Depends: convertible Build-Depends: convertible
, Cabal >= 1.10 && < 1.17 , Cabal >= 1.10 && < 1.17

View File

@ -19,7 +19,6 @@ import Config (cProjectVersionInt) -- ghc version
ghcVersion :: Int ghcVersion :: Int
ghcVersion = read cProjectVersionInt ghcVersion = read cProjectVersionInt
spec :: Spec spec :: Spec
spec = do spec = do
describe "parseCabalFile" $ do describe "parseCabalFile" $ do
@ -39,9 +38,9 @@ spec = do
} }
if ghcVersion < 706 if ghcVersion < 706
then ghcOptions res' `shouldBe` ["-global-package-conf", "-no-user-package-conf","-package-conf",cwd </> "test/data/.cabal-sandbox/i386-osx-ghc-7.6.3-packages.conf.d","-XHaskell98"] then ghcOptions res' `shouldBe` ["-global-package-conf", "-no-user-package-conf","-package-conf",cwd </> "test/data/.cabal-sandbox/i386-osx-ghc-7.6.3-packages.conf.d","-XHaskell98"]
else ghcOptions res' `shouldBe` ["-global-package-db", "-no-user-package-db","-package-db",cwd </> "test/data/.cabal-sandbox/i386-osx-ghc-7.6.3-packages.conf.d","-XHaskell98"] else ghcOptions res' `shouldBe` ["-global-package-db", "-no-user-package-db","-package-db",cwd </> "test/data/.cabal-sandbox/i386-osx-ghc-7.6.3-packages.conf.d","-XHaskell98","-optP-include","-optP" ++ cwd </> "test/data/dist/build/autogen/cabal_macros.h"]
includeDirs res' `shouldBe` ["test/data","test/data/dist/build","test/data/dist/build/autogen","test/data/subdir1/subdir2","test/data/test"] includeDirs res' `shouldBe` ["test/data","test/data/dist/build","test/data/dist/build/autogen","test/data/subdir1/subdir2","test/data/test"]
depPackages res' `shouldSatisfy` (("Cabal", "1.18.1.3", "2b161c6bf77657aa17e1681d83cb051b")`elem`) (pkgName `map` depPackages res') `shouldContain` ["Cabal"]
describe "cabalDependPackages" $ do describe "cabalDependPackages" $ do
@ -61,3 +60,10 @@ spec = do
it "extracts build info" $ do it "extracts build info" $ do
info <- cabalAllBuildInfo <$> parseCabalFile "test/data/cabalapi.cabal" info <- cabalAllBuildInfo <$> parseCabalFile "test/data/cabalapi.cabal"
show info `shouldBe` "[BuildInfo {buildable = True, buildTools = [], cppOptions = [], ccOptions = [], ldOptions = [], pkgconfigDepends = [], frameworks = [], cSources = [], hsSourceDirs = [\".\"], otherModules = [ModuleName [\"Browse\"],ModuleName [\"CabalApi\"],ModuleName [\"Cabal\"],ModuleName [\"CabalDev\"],ModuleName [\"Check\"],ModuleName [\"ErrMsg\"],ModuleName [\"Flag\"],ModuleName [\"GHCApi\"],ModuleName [\"GHCChoice\"],ModuleName [\"Gap\"],ModuleName [\"Info\"],ModuleName [\"Lang\"],ModuleName [\"Lint\"],ModuleName [\"List\"],ModuleName [\"Paths_ghc_mod\"],ModuleName [\"Types\"]], defaultLanguage = Nothing, otherLanguages = [], defaultExtensions = [], otherExtensions = [], oldExtensions = [], extraLibs = [], extraLibDirs = [], includeDirs = [], includes = [], installIncludes = [], options = [(GHC,[\"-Wall\"])], ghcProfOptions = [], ghcSharedOptions = [], customFieldsBI = [], targetBuildDepends = [Dependency (PackageName \"Cabal\") (UnionVersionRanges (ThisVersion (Version {versionBranch = [1,10], versionTags = []})) (LaterVersion (Version {versionBranch = [1,10], versionTags = []}))),Dependency (PackageName \"base\") (IntersectVersionRanges (UnionVersionRanges (ThisVersion (Version {versionBranch = [4,0], versionTags = []})) (LaterVersion (Version {versionBranch = [4,0], versionTags = []}))) (EarlierVersion (Version {versionBranch = [5], versionTags = []}))),Dependency (PackageName \"template-haskell\") AnyVersion]},BuildInfo {buildable = True, buildTools = [], cppOptions = [], ccOptions = [], ldOptions = [], pkgconfigDepends = [], frameworks = [], cSources = [], hsSourceDirs = [\"test\",\".\"], otherModules = [ModuleName [\"Expectation\"],ModuleName [\"BrowseSpec\"],ModuleName [\"CabalApiSpec\"],ModuleName [\"FlagSpec\"],ModuleName [\"LangSpec\"],ModuleName [\"LintSpec\"],ModuleName [\"ListSpec\"]], defaultLanguage = Nothing, otherLanguages = [], defaultExtensions = [], otherExtensions = [], oldExtensions = [], extraLibs = [], extraLibDirs = [], includeDirs = [], includes = [], installIncludes = [], options = [], ghcProfOptions = [], ghcSharedOptions = [], customFieldsBI = [], targetBuildDepends = [Dependency (PackageName \"Cabal\") (UnionVersionRanges (ThisVersion (Version {versionBranch = [1,10], versionTags = []})) (LaterVersion (Version {versionBranch = [1,10], versionTags = []}))),Dependency (PackageName \"base\") (IntersectVersionRanges (UnionVersionRanges (ThisVersion (Version {versionBranch = [4,0], versionTags = []})) (LaterVersion (Version {versionBranch = [4,0], versionTags = []}))) (EarlierVersion (Version {versionBranch = [5], versionTags = []})))]}]" show info `shouldBe` "[BuildInfo {buildable = True, buildTools = [], cppOptions = [], ccOptions = [], ldOptions = [], pkgconfigDepends = [], frameworks = [], cSources = [], hsSourceDirs = [\".\"], otherModules = [ModuleName [\"Browse\"],ModuleName [\"CabalApi\"],ModuleName [\"Cabal\"],ModuleName [\"CabalDev\"],ModuleName [\"Check\"],ModuleName [\"ErrMsg\"],ModuleName [\"Flag\"],ModuleName [\"GHCApi\"],ModuleName [\"GHCChoice\"],ModuleName [\"Gap\"],ModuleName [\"Info\"],ModuleName [\"Lang\"],ModuleName [\"Lint\"],ModuleName [\"List\"],ModuleName [\"Paths_ghc_mod\"],ModuleName [\"Types\"]], defaultLanguage = Nothing, otherLanguages = [], defaultExtensions = [], otherExtensions = [], oldExtensions = [], extraLibs = [], extraLibDirs = [], includeDirs = [], includes = [], installIncludes = [], options = [(GHC,[\"-Wall\"])], ghcProfOptions = [], ghcSharedOptions = [], customFieldsBI = [], targetBuildDepends = [Dependency (PackageName \"Cabal\") (UnionVersionRanges (ThisVersion (Version {versionBranch = [1,10], versionTags = []})) (LaterVersion (Version {versionBranch = [1,10], versionTags = []}))),Dependency (PackageName \"base\") (IntersectVersionRanges (UnionVersionRanges (ThisVersion (Version {versionBranch = [4,0], versionTags = []})) (LaterVersion (Version {versionBranch = [4,0], versionTags = []}))) (EarlierVersion (Version {versionBranch = [5], versionTags = []}))),Dependency (PackageName \"template-haskell\") AnyVersion]},BuildInfo {buildable = True, buildTools = [], cppOptions = [], ccOptions = [], ldOptions = [], pkgconfigDepends = [], frameworks = [], cSources = [], hsSourceDirs = [\"test\",\".\"], otherModules = [ModuleName [\"Expectation\"],ModuleName [\"BrowseSpec\"],ModuleName [\"CabalApiSpec\"],ModuleName [\"FlagSpec\"],ModuleName [\"LangSpec\"],ModuleName [\"LintSpec\"],ModuleName [\"ListSpec\"]], defaultLanguage = Nothing, otherLanguages = [], defaultExtensions = [], otherExtensions = [], oldExtensions = [], extraLibs = [], extraLibDirs = [], includeDirs = [], includes = [], installIncludes = [], options = [], ghcProfOptions = [], ghcSharedOptions = [], customFieldsBI = [], targetBuildDepends = [Dependency (PackageName \"Cabal\") (UnionVersionRanges (ThisVersion (Version {versionBranch = [1,10], versionTags = []})) (LaterVersion (Version {versionBranch = [1,10], versionTags = []}))),Dependency (PackageName \"base\") (IntersectVersionRanges (UnionVersionRanges (ThisVersion (Version {versionBranch = [4,0], versionTags = []})) (LaterVersion (Version {versionBranch = [4,0], versionTags = []}))) (EarlierVersion (Version {versionBranch = [5], versionTags = []})))]}]"
describe "cabalGetConfig" $ do
it "can reconfigure a cabal package" $ do
withDirectory_ "test/data/check-test-subdir" $ do
cradle <- findCradle
cfg <- cabalGetConfig cradle
cfg `shouldSatisfy` not . null

View File

@ -5,8 +5,16 @@ import Test.Hspec
import System.Process import System.Process
main = do main = do
let sandboxes = [ "test/data", "test/data/check-packageid" ] let sandboxes = [ "test/data", "test/data/check-packageid"
, "test/data/duplicate-pkgver/" ]
genSandboxCfg dir = withDirectory dir $ \cwd -> do genSandboxCfg dir = withDirectory dir $ \cwd -> do
system ("sed 's|@CWD@|" ++ cwd ++ "|g' cabal.sandbox.config.in > cabal.sandbox.config") system ("sed 's|@CWD@|" ++ cwd ++ "|g' cabal.sandbox.config.in > cabal.sandbox.config")
genSandboxCfg `mapM` sandboxes pkgDirs =
[ "test/data/.cabal-sandbox/i386-osx-ghc-7.6.3-packages.conf.d"
, "test/data/check-packageid/.cabal-sandbox/i386-osx-ghc-7.6.3-packages.conf.d"
, "test/data/duplicate-pkgver/.cabal-sandbox/i386-osx-ghc-7.6.3-packages.conf.d"]
genGhcPkgCache dir = system $ "ghc-pkg recache --force -f" ++ dir
genSandboxCfg `mapM_` sandboxes
genGhcPkgCache `mapM_` pkgDirs
system "find test -name setup-config -exec rm {} \\;"
hspec spec hspec spec

11
test/UtilsSpec.hs Normal file
View File

@ -0,0 +1,11 @@
module UtilsSpec where
import Language.Haskell.GhcMod.Utils
import Test.Hspec
spec :: Spec
spec = do
describe "extractParens" $ do
it "extracts the part of a string surrounded by parentheses" $ do
extractParens "asdasdasd ( hello [ world ] )()() kljlkjlkjlk" `shouldBe` "( hello [ world ] )"
extractParens "[(PackageName \"template-haskell\",InstalledPackageId \"template-haskell-2.9.0.0-8e2a49468f3b663b671c437d8579cd28\"),(PackageName \"base\",InstalledPackageId \"base-4.7.0.0-e4567cc9a8ef85f78696b03f3547b6d5\"),(PackageName \"Cabal\",InstalledPackageId \"Cabal-1.18.1.3-b9a44a5b15a8bce47d40128ac326e369\")][][]" `shouldBe` "[(PackageName \"template-haskell\",InstalledPackageId \"template-haskell-2.9.0.0-8e2a49468f3b663b671c437d8579cd28\"),(PackageName \"base\",InstalledPackageId \"base-4.7.0.0-e4567cc9a8ef85f78696b03f3547b6d5\"),(PackageName \"Cabal\",InstalledPackageId \"Cabal-1.18.1.3-b9a44a5b15a8bce47d40128ac326e369\")]"

Binary file not shown.

View File

@ -4,15 +4,15 @@
-- if you want to change the default settings for this sandbox. -- if you want to change the default settings for this sandbox.
local-repo: @CWD@/test/data/.cabal-sandbox/packages local-repo: @CWD@/test/data/check-packageid/.cabal-sandbox/packages
logs-dir: @CWD@/test/data/.cabal-sandbox/logs logs-dir: @CWD@/test/data/check-packageid/.cabal-sandbox/logs
world-file: @CWD@/test/data/.cabal-sandbox/world world-file: @CWD@/test/data/check-packageid/.cabal-sandbox/world
user-install: False user-install: False
package-db: test/data/check-packageid/.cabal-sandbox/i386-osx-ghc-7.6.3-packages.conf.d package-db: @CWD@/test/data/check-packageid/.cabal-sandbox/i386-osx-ghc-7.6.3-packages.conf.d
build-summary: @CWD@/test/data/.cabal-sandbox/logs/build.log build-summary: @CWD@/test/data/check-packageid/.cabal-sandbox/logs/build.log
install-dirs install-dirs
prefix: @CWD@/test/data/.cabal-sandbox prefix: @CWD@/test/data/check-packageid/.cabal-sandbox
bindir: $prefix/bin bindir: $prefix/bin
libdir: $prefix/lib libdir: $prefix/lib
libsubdir: $arch-$os-$compiler/$pkgid libsubdir: $arch-$os-$compiler/$pkgid

View File

@ -0,0 +1,4 @@
name: template-haskell
version: 1.0
id: template-haskell-1.0-7c59d13f32294d1ef6dc6233c24df961
exposed: True

View File

@ -0,0 +1,4 @@
name: template-haskell
version: 2.8.0.0
id: template-haskell-2.8.0.0-14e543bdae2da4d2aeff5386892c9112
exposed: True

View File

@ -0,0 +1,4 @@
name: template-haskell
version: 2.8.0.0
id: template-haskell-2.8.0.0-32d4f24abdbb6bf41272b183b2e23e9c
exposed: True

View File

@ -0,0 +1,25 @@
-- 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.
local-repo: @CWD@/test/data/duplicate-pkgver/.cabal-sandbox/packages
logs-dir: @CWD@/test/data/duplicate-pkgver/.cabal-sandbox/logs
world-file: @CWD@/test/data/duplicate-pkgver/.cabal-sandbox/world
user-install: False
package-db: @CWD@/test/data/duplicate-pkgver/.cabal-sandbox/i386-osx-ghc-7.6.3-packages.conf.d
build-summary: @CWD@/test/data/duplicate-pkgver/.cabal-sandbox/logs/build.log
install-dirs
prefix: @CWD@/test/data/duplicate-pkgver/.cabal-sandbox
bindir: $prefix/bin
libdir: $prefix/lib
libsubdir: $arch-$os-$compiler/$pkgid
libexecdir: $prefix/libexec
datadir: $prefix/share
datasubdir: $arch-$os-$compiler/$pkgid
docdir: $datadir/doc/$arch-$os-$compiler/$pkgid
htmldir: $docdir/html
haddockdir: $htmldir
sysconfdir: $prefix/etc

View File

@ -0,0 +1,7 @@
name: duplicate-pkgver
version: 0.1.0
build-type: Simple
cabal-version: >= 1.8
library
build-depends: base == 4.*