Commit 4b0f4b7d authored by Michael Hanus's avatar Michael Hanus
Browse files

CPM updated

parent 63794b9e
......@@ -267,9 +267,11 @@ of this default path).
To use the dependencies of a package, the Curry compiler needs to be
started via CPM so that the compiler will know where to search for the
modules provided. You can use the \code{cpm curry} command to start the current
Curry compiler (the \code{curry} command that is on the path). Any
parameters given to \code{cpm curry} will be passed along verbatim to
modules provided. You can use the \code{cpm curry} command to start the
Curry compiler (which is either the compiler used to install CPM
or specified with the configuration option \code{curry_bin},
see Section~\ref{sec:config}).
Any parameters given to \code{cpm curry} will be passed along verbatim to
the Curry compiler, for example the following will start the Curry
compiler, print the result of evaluating the expression \code{39+3}
and then quit.
......@@ -505,6 +507,12 @@ Default value: \code{\$HOME/.cpm/bin}
The path to the package cache where packages are checked out if only
their binaries are installed (see Section~\ref{sec:installbin}).
Default value: \code{\$HOME/.cpm/bin_packages}.
\item[\fbox{\code{curry_bin}}]
The name of the executable of the Curry system used
to compile and test packages.
The default value is the binary of the Curry system which has been used
to compile CPM.
\end{description}
%
Note that one can override the values of these configuration options
......@@ -679,8 +687,8 @@ For example, it can be used to execute \ccode{curry check}
or \ccode{curry analyze} with correct dependencies available.
\item[\fbox{\code{curry $args$}}] Executes the Curry compiler with the
dependencies of the current package available. Any arguments are passed verbatim
to the compiler.
dependencies of the current package available.
Any arguments are passed verbatim to the compiler.
\item[\fbox{\code{link $source$}}] Can be used to replace a dependency of the
current package using a local copy, see Section~\ref{sec:cpm-link} for details.
......@@ -696,6 +704,7 @@ after installing the application.
\item[\fbox{\code{new}}] Asks a few questions and creates a new package.
\end{description}
\section{Package Specification Reference}
\label{sec:reference}
......@@ -768,6 +777,13 @@ in all versions.
package described in the specification can be obtained. See
Section~\ref{sec:publishing-a-package} for details.
\item[\fbox{\code{sourceDirs}}] A list of directories inside this
package where the source code is located.
When the package is compiled, these directories are put at the front
of the Curry load path.
If this field is not specified, \code{src} is used as the single
source directory.
\item[\fbox{\code{exportedModules}}] A list of modules intended for use by
consumers of the package.
These are the modules compared by the \code{cpm diff}
......@@ -840,6 +856,8 @@ All these modules are tested with CurryCheck
by the command \code{cpm test}.
If no test suite is defined, all (exported) modules are tested
in the directory \code{src}.
A test suite can also contain a field \code{options}
which defines a string of options passed to the call to CurryCheck.
One can also specify test suites for more than one directory.
In this case, the \code{testsuite} value is an array
......@@ -855,6 +873,7 @@ directories \code{test} and \code{examples} could be as follows:
"modules": [ "testDataConversion", "testIO" ]
},
{ "src-dir": "examples",
"options": "-m80",
"modules": [ "Nats", "Ints" ]
}
]
......
......@@ -6,15 +6,15 @@
module CPM.AbstractCurry
( loadPathForPackage
, readAbstractCurryFromPath
, readAbstractCurryFromPackagePath
, readAbstractCurryFromDeps
, transformAbstractCurryInDeps
, applyModuleRenames
) where
import Distribution (FrontendTarget (..), FrontendParams (..), defaultParams
, callFrontendWithParams, setQuiet, setFullPath, sysLibPath
, curryCompiler, installDir, inCurrySubdir, modNameToPath
, callFrontendWithParams, setQuiet, setFullPath
, sysLibPath, inCurrySubdir, modNameToPath
, inCurrySubdirModule, lookupModuleSource)
import List (intercalate, nub)
import FilePath ((</>), (<.>), takeFileName, replaceExtension)
......@@ -25,42 +25,50 @@ import AbstractCurry.Transform
import AbstractCurry.Types (CurryProg)
import System
import CPM.ErrorLogger
import qualified CPM.PackageCache.Runtime as RuntimeCache
import CPM.Package (Package)
import CPM.Package (Package, loadPackageSpec, sourceDirsOf)
--- Returns the load path for a package stored in some directory
--- w.r.t. the dependent packages
--- w.r.t. the dependent packages.
---
--- @param - pkgDir - the package's directory
--- @param - pkg - the package
--- @param - pkgDir - the directory containing this package
--- @param - deps - the resolved dependencies of the package
--- @return the full load path for modules in the package or dependent packages
loadPathForPackage :: String -> [Package] -> [String]
loadPathForPackage pkgDir deps =
[pkgDir </> "src"] ++ RuntimeCache.dependencyPathsSeparate deps pkgDir
loadPathForPackage :: Package -> String -> [Package] -> [String]
loadPathForPackage pkg pkgDir deps =
(map (pkgDir </>) (sourceDirsOf pkg) ++
RuntimeCache.dependencyPathsSeparate deps pkgDir)
--- Returns the full load path for a package stored in some directory.
---
--- @param - pkgDir - the package's directory
--- @param - pkg - the package
--- @param - pkgDir - the directory containing this package
--- @param - deps - the resolved dependencies of the package
--- @return the full load path for modules in the package or dependent packages
fullLoadPathForPackage :: String -> [Package] -> [String]
fullLoadPathForPackage pkgDir deps =
sysLibPath ++ loadPathForPackage pkgDir deps
fullLoadPathForPackage :: Package -> String -> [Package] -> [String]
fullLoadPathForPackage pkg pkgDir deps =
loadPathForPackage pkg pkgDir deps ++ sysLibPath
-- here we assume that the system libs are identical for each Curry system
--- Reads an AbstractCurry module from a package.
---
--- @param - dir the package's directory
--- @param - deps the resolved dependencies of the package
--- @param - mod the module to read
readAbstractCurryFromPath :: String -> [Package] -> String -> IO CurryProg
readAbstractCurryFromPath pkgDir deps modname = do
let loadPath = fullLoadPathForPackage pkgDir deps
readAbstractCurryFromPackagePath :: Package -> String -> [Package] -> String
-> IO CurryProg
readAbstractCurryFromPackagePath pkg pkgDir deps modname = do
let loadPath = fullLoadPathForPackage pkg pkgDir deps
params <- return $ setQuiet True (setFullPath loadPath defaultParams)
callFrontendWithParams ACY params modname
src <- lookupModuleSource loadPath modname
acyName <- return $ case src of
Nothing -> error $ "Module not found: " ++ modname
Just (_, file) -> replaceExtension (inCurrySubdirModule modname file) ".acy"
readAbstractCurryFile acyName
where
acyName = inCurrySubdir (pkgDir </> "src" </> modname) ++ ".acy"
--- Reads an AbstractCurry module from a package or one of its dependencies.
---
--- @param dir - the package's directory
......@@ -68,7 +76,8 @@ readAbstractCurryFromPath pkgDir deps modname = do
--- @param mod - the module to read
readAbstractCurryFromDeps :: String -> [Package] -> String -> IO CurryProg
readAbstractCurryFromDeps pkgDir deps modname = do
let loadPath = fullLoadPathForPackage pkgDir deps
pkg <- fromErrorLogger (loadPackageSpec pkgDir)
let loadPath = fullLoadPathForPackage pkg pkgDir deps
params <- return $ setQuiet True (setFullPath loadPath defaultParams)
src <- lookupModuleSource loadPath modname
sourceFile <- return $ case src of
......@@ -88,7 +97,8 @@ readAbstractCurryFromDeps pkgDir deps modname = do
transformAbstractCurryInDeps :: String -> [Package] -> (CurryProg -> CurryProg)
-> String -> String -> IO ()
transformAbstractCurryInDeps pkgDir deps transform modname destFile = do
let loadPath = fullLoadPathForPackage pkgDir deps
pkg <- fromErrorLogger (loadPackageSpec pkgDir)
let loadPath = fullLoadPathForPackage pkg pkgDir deps
params <- return $ setQuiet True (setFullPath loadPath defaultParams)
src <- lookupModuleSource loadPath modname
sourceFile <- return $ case src of
......
--------------------------------------------------------------------------------
------------------------------------------------------------------------------
--- This module defines the data type for CPM's configuration options, the
--- default values for all options, and functions for reading the user's .cpmrc
--- file and merging its contents into the default options.
--------------------------------------------------------------------------------
------------------------------------------------------------------------------
module CPM.Config
( Config ( Config, packageInstallDir, binInstallDir, repositoryDir
, binPackageDir, packageIndexRepository )
, binPackageDir, packageIndexRepository, curryExec )
, readConfiguration, readConfigurationWithDefault, defaultConfig ) where
import Char (isSpace)
import Char (isSpace, toLower)
import Directory (getHomeDirectory, createDirectoryIfMissing)
import Distribution (installDir, curryCompiler)
import FilePath ((</>))
import Function ((***))
import List (splitOn, intersperse)
......@@ -39,6 +40,8 @@ data Config = Config {
, binPackageDir :: String
--- URL to the package index repository
, packageIndexRepository :: String
--- The executable of the Curry system used to compile and check packages
, curryExec :: String
}
--- CPM's default configuration values. These are used if no .cpmrc file is found
......@@ -49,7 +52,8 @@ defaultConfig = Config
, binInstallDir = "$HOME/.cpm/bin"
, repositoryDir = "$HOME/.cpm/index"
, binPackageDir = "$HOME/.cpm/bin_packages"
, packageIndexRepository = packageIndexURI }
, packageIndexRepository = packageIndexURI
, curryExec = installDir </> "bin" </> curryCompiler }
--- Reads the .cpmrc file from the user's home directory (if present) and merges
--- its contents into the default configuration. Resolves the $HOME variable
......@@ -111,11 +115,12 @@ mergeConfigSettings cfg props = applyEither setters cfg
unlines (map fst keySetters)
Just s -> \c -> Right $ s v c
--- Removes leading and trailing whitespace from option keys and values.
--- Removes leading and trailing whitespace from option keys and values
--- and transforms option keys to lowercase.
---
--- @param opts - the options
stripProps :: [(String, String)] -> [(String, String)]
stripProps = map (strip *** strip)
stripProps = map ((map toLower . strip) *** strip)
where
strip s = reverse $ dropWhile isSpace $ reverse $ dropWhile isSpace s
......@@ -127,6 +132,7 @@ keySetters =
, ("package_install_path", \v c -> c { packageInstallDir = v})
, ("bin_install_path" , \v c -> c { binInstallDir = v})
, ("bin_package_path" , \v c -> c { binPackageDir = v})
, ("curry_bin" , \v c -> c { curryExec = v})
]
--- Sequentially applies a list of functions that transform a value to a value
......@@ -141,3 +147,5 @@ applyEither [] z = Right z
applyEither (f:fs) z = case f z of
Left err -> Left err
Right z' -> applyEither fs z'
------------------------------------------------------------------------------
......@@ -26,7 +26,7 @@ import List (nub)
import Maybe (listToMaybe, catMaybes)
import Pretty (pPrint, text, (<+>), vcat, empty, red, ($$))
import CPM.AbstractCurry (readAbstractCurryFromPath)
import CPM.AbstractCurry (readAbstractCurryFromPackagePath)
import CPM.Config (Config)
import CPM.ErrorLogger
import CPM.FileUtil (copyDirectory, recreateDirectory)
......@@ -121,15 +121,18 @@ compareModulesInDirs cfg repo gc dirA dirB onlyMods = loadPackageSpec dirA |>=
compareApiModule :: Package -> String -> [Package] -> Package -> String
-> [Package] -> String -> IO (ErrorLogger Differences)
compareApiModule pkgA dirA depsA pkgB dirB depsB mod =
if mod `elem` (exportedModules pkgA)
then if mod `elem` (exportedModules pkgB)
then readAbstractCurryFromPath dirA depsA mod >>= succeedIO |>=
\prog1 -> readAbstractCurryFromPath dirB depsB mod >>= succeedIO |>=
\prog2 -> let
funcDiffs = diffFuncsFiltered funcIsPublic prog1 prog2
typeDiffs = diffTypesFiltered typeIsPublic prog1 prog2
opDiffs = diffOpsFiltered (\_ _ -> True) prog1 prog2 in
succeedIO $ (Nothing, funcDiffs, typeDiffs, opDiffs)
if mod `elem` exportedModules pkgA
then
if mod `elem` exportedModules pkgB
then
readAbstractCurryFromPackagePath pkgA dirA depsA mod >>= succeedIO
|>= \prog1 ->
readAbstractCurryFromPackagePath pkgB dirB depsB mod >>= succeedIO
|>= \prog2 ->
let funcDiffs = diffFuncsFiltered funcIsPublic prog1 prog2
typeDiffs = diffTypesFiltered typeIsPublic prog1 prog2
opDiffs = diffOpsFiltered (\_ _ -> True) prog1 prog2
in succeedIO $ (Nothing, funcDiffs, typeDiffs, opDiffs)
else succeedIO $ (Just $ Addition mod, [], [], [])
else succeedIO $ (Just $ Removal mod, [], [], [])
......
......@@ -28,7 +28,7 @@ import AbstractCurry.Types ( CurryProg (..), CFuncDecl (..), CVisibility (..)
, CVarIName, QName)
import Char (isAlphaNum)
import Directory (createDirectory, doesDirectoryExist, getTemporaryDirectory)
import Distribution (installDir, lookupModuleSource)
import Distribution (lookupModuleSource)
import FilePath ((</>), joinPath)
import Function (both)
import List ( intercalate, intersect, nub, splitOn, isPrefixOf, isInfixOf
......@@ -44,9 +44,8 @@ import Analysis.Termination ( productivityAnalysis, Productivity(..) )
import Analysis.TypeUsage ( typesInValuesAnalysis )
import CASS.Server ( analyzeGeneric )
import CPM.AbstractCurry ( readAbstractCurryFromPath, readAbstractCurryFromDeps
, loadPathForPackage )
import CPM.Config (Config)
import CPM.AbstractCurry ( readAbstractCurryFromDeps, loadPathForPackage )
import CPM.Config ( Config (curryExec) )
import CPM.Diff.API as APIDiff
import CPM.Diff.CurryComments (readComments, getFuncComment)
import CPM.Diff.Rename (prefixPackageAndDeps)
......@@ -145,7 +144,7 @@ infoText :: String
infoText = unlines
[ "Running behavior diff where the raw output of CurryCheck is shown."
, "The test operations are named after the operations they compare."
, "If a test fails, their implementations differ." ]
, "If a test fails, their implementations semantically differ." ]
--- Compare the behavior of two package versions using CurryCheck.
---
......@@ -181,7 +180,7 @@ diffBehavior cfg repo gc info useanalysis cmods = getBaseTemp |>=
putStrLn $
"Comparing operations " ++ showFuncNames filteredNames ++ "\n"
genCurryCheckProgram cfg repo gc filteredFuncs info acyCache loadpath
|> callCurryCheck info baseTmp
|> callCurryCheck cfg info baseTmp
where
printRemoved removed =
if null removed then done
......@@ -206,10 +205,10 @@ renderRemoved rs =
reasonText NonTerm = text "Possibly non-terminating"
--- Runs CurryCheck on the generated program.
callCurryCheck :: ComparisonInfo -> String -> IO (ErrorLogger ())
callCurryCheck info baseTmp = do
callCurryCheck :: Config -> ComparisonInfo -> String -> IO (ErrorLogger ())
callCurryCheck cfg info baseTmp = do
oldPath <- getEnviron "CURRYPATH"
let currybin = installDir </> "bin" </> "curry"
let currybin = curryExec cfg
currypath = infDirA info ++ ":" ++ infDirB info
setEnviron "CURRYPATH" currypath
log Debug ("Run `curry check Compare' in `" ++ baseTmp ++ "' with") |>
......@@ -769,14 +768,13 @@ findFunctionsToCompare :: Config
-> IO (ErrorLogger (ACYCache, [String],
[(Bool,CFuncDecl)], [(CFuncDecl, FilterReason)]))
findFunctionsToCompare cfg repo gc dirA dirB useanalysis cmods =
loadPackageSpec dirA |>=
\pkgA -> loadPackageSpec dirB |>=
\pkgB -> resolveAndCopyDependencies cfg repo gc dirA |>=
\depsA -> succeedIO
(maybe (intersect (exportedModules pkgA) (exportedModules pkgB))
id
cmods )|>=
\mods -> log Debug ("Comparing modules: "++ intercalate " " mods) |>
loadPackageSpec dirA |>= \pkgA ->
loadPackageSpec dirB |>= \pkgB ->
resolveAndCopyDependencies cfg repo gc dirA |>= \depsA ->
succeedIO (maybe (intersect (exportedModules pkgA) (exportedModules pkgB))
id
cmods) |>= \mods ->
log Debug ("Comparing modules: "++ intercalate " " mods) |>
APIDiff.compareModulesInDirs cfg repo gc dirA dirB (Just mods) |>= \diffs ->
findAllFunctions dirA dirB pkgA depsA emptyACYCache mods |>=
\(acy, allFuncs) ->
......@@ -795,20 +793,20 @@ findFunctionsToCompare cfg repo gc dirA dirB useanalysis cmods =
filterNoCompare dirA dirB depsA `areNoCompareThenFilter`
filterNonMatchingTypes dirA dirB depsA `areNonMatchingThenFilter`
filterFuncArg dirA dirB depsA `haveFuncArgThenFilter`
liftFilter id ) |>= terminationFilter dirA dirB depsA useanalysis
liftFilter id ) |>= terminationFilter pkgA dirA depsA useanalysis
--- Filters out functions which are possibly non-terminating and
--- non-productive, and mark productive functions so that they are
--- tested not by standard equality.
terminationFilter :: String -> String -> [Package] -> Bool
terminationFilter :: Package -> String -> [Package] -> Bool
-> (ACYCache, [CFuncDecl], [(CFuncDecl, FilterReason)])
-> IO (ErrorLogger (ACYCache, [String], [(Bool,CFuncDecl)],
[(CFuncDecl, FilterReason)]))
terminationFilter _ _ _ False (a,fs,rm) =
succeedIO (a, [], map (\f->(False,f)) fs, rm)
terminationFilter dirA _ depsA True (acy, funcs, rm) = do
let currypath = loadPathForPackage dirA depsA
mods = nub (map (fst . funcName) funcs)
terminationFilter pkgA dirA depsA True (acy, funcs, rm) = do
let currypath = loadPathForPackage pkgA dirA depsA
mods = nub (map (fst . funcName) funcs)
ainfo <- analyzeModules "productivity" productivityAnalysis currypath mods
-- compute functions which should be definitely compared (due to TERMINATE
-- or PRODUCTIVE pragmas):
......@@ -1148,13 +1146,13 @@ findAllFunctions dirA dirB _ deps acyCache mods =
foldEL findForMod (acyCache, []) mods |>=
\(a, fs) -> succeedIO (a, nub fs)
where
findForMod (acy,_) mod =
findForMod (acy,fdecls) mod =
readCached dirA deps acy mod |>= \(_, progA) ->
readCached dirB deps acy mod |>= \(acy'', progB) ->
let funcsA = filter isPublic $ functions progA
funcsB = filter isPublic $ functions progB
in succeedIO (acy'', nubBy (\a b -> funcName a == funcName b)
(funcsA ++ funcsB))
in succeedIO (acy'', fdecls ++ nubBy (\a b -> funcName a == funcName b)
(funcsA ++ funcsB))
--- Checks whether a function is public.
isPublic :: CFuncDecl -> Bool
......
......@@ -71,7 +71,8 @@ copyMod origDir deps dest nameMap (name, _) = do
if dirExists
then return ()
else createDirectory (takeDirectory destPath)
transformAbstractCurryInDeps origDir deps (applyModuleRenames nameMap) name destPath
transformAbstractCurryInDeps origDir deps (applyModuleRenames nameMap)
name destPath
where
newName = case lookup name nameMap of
Nothing -> name
......
......@@ -18,12 +18,13 @@ module CPM.ErrorLogger
, failIO
, log
, showLogEntry
, infoMessage, debugMessage
, infoMessage, debugMessage, fromErrorLogger
) where
import Global
import Pretty
import Profile -- for show run-time
import System (exitWith)
infixl 0 |>=
infixl 0 |>
......@@ -184,3 +185,14 @@ infoMessage msg = (log Info msg |> succeedIO ()) >> done
--- Prints a debug message in the standard IO monad.
debugMessage :: String -> IO ()
debugMessage msg = (log Debug msg |> succeedIO ()) >> done
--- Transforms an error logger actions into a standard IO action.
--- It shows all messages and, if the result is not available,
--- exits with a non-zero code.
fromErrorLogger :: IO (ErrorLogger a) -> IO a
fromErrorLogger a = do
(msgs, err) <- a
mapIO showLogEntry msgs
case err of
Right v -> return v
Left m -> showLogEntry m >> exitWith 1
......@@ -4,13 +4,13 @@
module CPM.Main where
import Char ( toLower )
import CSV ( showCSV )
import Directory ( doesFileExist, getAbsolutePath, doesDirectoryExist
, createDirectory, createDirectoryIfMissing
, getDirectoryContents, getModificationTime
, renameFile, removeFile, setCurrentDirectory )
import Distribution ( installDir, stripCurrySuffix, addCurrySubdir
, curryCompiler )
import Distribution ( stripCurrySuffix, addCurrySubdir )
import Either
import FilePath ( (</>), splitSearchPath, takeExtension )
import IO ( hFlush, stdout )
......@@ -25,7 +25,7 @@ import CPM.ErrorLogger
import CPM.FileUtil ( fileInPath, joinSearchPath, safeReadFile, whenFileExists
, ifFileExists, inDirectory, removeDirectoryComplete )
import CPM.Config ( Config ( packageInstallDir, binInstallDir
, binPackageDir )
, binPackageDir, curryExec )
, readConfigurationWithDefault )
import CPM.PackageCache.Global ( GlobalCache, readInstalledPackagesFromDir
, installFromZip, checkoutPackage
......@@ -44,7 +44,7 @@ cpmBanner :: String
cpmBanner = unlines [bannerLine,bannerText,bannerLine]
where
bannerText =
"Curry Package Manager <curry-language.org/tools/cpm> (version of 27/03/2017)"
"Curry Package Manager <curry-language.org/tools/cpm> (version of 31/03/2017)"
bannerLine = take (length bannerText) (repeat '-')
main :: IO ()
......@@ -263,9 +263,10 @@ diffOpts s = case optCommand s of
_ -> DiffOptions Nothing Nothing True True True
readLogLevel :: String -> Either String LogLevel
readLogLevel s = if s == "debug"
then Right $ Debug
else Right $ Info
readLogLevel s = case map toLower s of
"debug" -> Right Debug
"info" -> Right Info
_ -> Left $ "Illegal verbosity value: " ++ s
readRcOption :: String -> Either String (String,String)
readRcOption s =
......@@ -515,19 +516,23 @@ compiler o cfg getRepo getGC =
tryFindLocalPackageSpec "." |>= \specDir ->
loadCurryPathFromCache specDir |>=
maybe (computePackageLoadPath specDir) succeedIO |>= \currypath ->
log Info ("Starting Curry with CURRYPATH " ++ currypath) |>
log Info ("Starting '" ++ currybin ++ "' with") |>
log Info ("CURRYPATH=" ++ currypath) |>
do setEnviron "CURRYPATH" $ currypath
ecode <- system $ "curry " ++ comCommand o
ecode <- system $ currybin ++ " " ++ comCommand o
unsetEnviron "CURRYPATH"
unless (ecode==0) (exitWith ecode)
succeedIO ()
where
currybin = curryExec cfg
computePackageLoadPath pkgdir =
getRepo >>= \repo -> getGC >>= \gc ->
resolveAndCopyDependencies cfg repo gc pkgdir |>= \pkgs ->
loadPackageSpec pkgdir |>= \pkg ->
resolveAndCopyDependenciesForPackage cfg repo gc pkgdir pkg |>= \pkgs ->
getAbsolutePath pkgdir >>= \abs -> succeedIO () |>
succeedIO (abs </> "src") |>= \srcDir ->
let currypath = joinSearchPath (srcDir : dependencyPathsSeparate pkgs abs)
let srcdirs = map (abs </>) (sourceDirsOf pkg)
currypath = joinSearchPath (srcdirs ++ dependencyPathsSeparate pkgs abs)
in saveCurryPathToCache pkgdir currypath >> succeedIO currypath
......@@ -569,6 +574,7 @@ install :: InstallOptions -> Config -> Repository -> GlobalCache
-> IO (ErrorLogger ())
install (InstallOptions Nothing Nothing _) cfg repo gc =
tryFindLocalPackageSpec "." |>= \specDir ->
cleanCurryPathCache specDir |>
installLocalDependencies cfg repo gc specDir |>= \ (pkg,_) ->
installExecutable cfg repo pkg specDir
install (InstallOptions (Just pkg) Nothing pre) cfg repo gc = do
......@@ -601,10 +607,8 @@ installExecutable cfg repo pkg pkgdir =
getEnviron "PATH" >>= \path ->
log Info ("Compiling main module: " ++ mainmod) |>
let cmd = unwords $
[":set", if levelGte Debug lvl then "v1" else "v0"] ++
(if curryCompiler == "pakcs" && not (levelGte Debug lvl)
then [":set","-warn"] else []) ++
[":load", mainmod, ":save", ":quit"]
[":set", if levelGte Debug lvl then "v1" else "v0",
":load", mainmod, ":save", ":quit"]
bindir = binInstallDir cfg
binexec = bindir </> name
in writePackageConfig cfg pkgdir pkg |>
......@@ -613,7 +617,7 @@ installExecutable cfg repo pkg pkgdir =
log Info ("Installing executable '" ++ name ++ "' into '" ++
bindir ++ "'") |>
(whenFileExists binexec (backupExistingBin binexec) >>
-- renaming might not work across file systems:
-- renaming might not work across file systems, hence we move:
system (unwords ["mv", mainmod, binexec]) >>
checkPath path bindir))
(executableSpec pkg)
......@@ -692,19 +696,23 @@ search (SearchOptions q) _ repo = putStr rendered >> succeedIO ()
upgrade :: UpgradeOptions -> Config -> Repository -> GlobalCache
-> IO (ErrorLogger ())
upgrade (UpgradeOptions Nothing) cfg repo gc = tryFindLocalPackageSpec "." |>=
\specDir -> log Info "Upgrading all packages" |>
upgrade (UpgradeOptions Nothing) cfg repo gc =
tryFindLocalPackageSpec "." |>= \specDir ->
cleanCurryPathCache specDir |>
log Info "Upgrading all packages" |>
upgradeAllPackages cfg repo gc specDir
upgrade (UpgradeOptions (Just pkg)) cfg repo gc =
tryFindLocalPackageSpec "." |>=
\specDir -> log Info ("Upgrade " ++ pkg) |>
tryFindLocalPackageSpec "." |>= \specDir ->
log Info ("Upgrade " ++ pkg) |>
upgradeSinglePackage cfg repo gc specDir pkg
link :: LinkOptions -> Config -> Repository -> GlobalCache
-> IO (ErrorLogger ())
link (LinkOptions src) _ _ _ = tryFindLocalPackageSpec "." |>=
\specDir -> log Info ("Linking '" ++ src ++ "' into local package cache") |>
link (LinkOptions src) _ _ _ =
tryFindLocalPackageSpec "." |>= \specDir ->
cleanCurryPathCache specDir |>
log Info ("Linking '" ++ src ++ "' into local package cache") |>
linkToLocalCache src specDir
--- `test` command: run `curry check` on exported or top-level modules
......@@ -721,13 +729,20 @@ test opts cfg getRepo getGC =
then putStrLn "No modules to be tested!" >> succeedIO ()
else foldEL (\_ -> execTest aspecDir) () tests
where
execTest apkgdir (dir,mods) = do
putStrLn $ "Testing modules (in directory '" ++ dir ++ "', " ++
"with CurryCheck, showing raw output):\n" ++
currycheck = curryExec cfg ++ " check"
execTest apkgdir (PackageTest dir mods ccopts) = do
putStrLn $ "Running CurryCheck (" ++ currycheck ++
(if null ccopts then "" else " " ++ ccopts) ++ ")\n" ++
"(in directory '" ++ dir ++
"', showing raw output) on modules:\n" ++
unwords mods ++ "\n"
inDirectory dir $
let currysubdir = apkgdir </> addCurrySubdir dir
debugMessage $ "Removing directory: " ++ currysubdir
system (unwords ["rm", "-rf", currysubdir])
inDirectory (apkgdir </> dir) $
execWithPkgDir
(ExecOptions (installDir </> "bin" </> "curry check " ++ unwords mods) [])
(ExecOptions (unwords (currycheck : ccopts : mods)) [])
cfg getRepo getGC apkgdir
testsuites spec mainprogs = case testModules opts of
......@@ -735,11 +750,11 @@ test opts cfg getRepo getGC =
in if null exports
then if null mainprogs
then []
else [("src",mainprogs)]
else [("src",exports)])
(\ (PackageTests tests) -> tests)
else [PackageTest "src" mainprogs ""]
else [PackageTest "src" exports ""])
id
(testSuite spec)
Just ms -> [("src",ms)]
Just ms -> [PackageTest "src" ms ""]
--- Get the names of all Curry modules containing in a directory.
--- Modules in subdirectories are returned as hierarchical modules.
......@@ -823,10 +838,11 @@ execWithPkgDir o cfg getRepo getGC specDir =
where
computePackageLoadPath pkgdir =
getRepo >>= \repo -> getGC >>= \gc ->
resolveAndCopyDependencies cfg repo gc pkgdir |>= \pkgs ->
loadPackageSpec pkgdir |>= \pkg ->
resolveAndCopyDependenciesForPackage cfg repo gc pkgdir pkg |>= \pkgs ->
getAbsolutePath pkgdir >>= \abs -> succeedIO () |>
succeedIO (abs </> "src") |>= \srcDir ->
let currypath = joinSearchPath (srcDir : dependencyPathsSeparate pkgs abs)
let srcdirs = map (abs </>) (sourceDirsOf pkg)
currypath = joinSearchPath (srcdirs ++ dependencyPathsSeparate pkgs abs)
in saveCurryPathToCache pkgdir currypath >> succeedIO currypath
......@@ -836,9 +852,11 @@ cleanPackage ll =
tryFindLocalPackageSpec "." |>= \specDir ->
loadPackageSpec specDir |>= \pkg ->
let dotcpm = specDir </> ".cpm"
srcdirs = [specDir </> "src"]
testdirs = maybe [] (\ (PackageTests tests) -> map fst tests)
(testSuite pkg)
srcdirs = map (specDir </>) (sourceDirsOf pkg)
testdirs = map (specDir </>)
(maybe []
(map (\ (PackageTest m _ _) -> m))
(testSuite pkg))
rmdirs = dotcpm : map addCurrySubdir (srcdirs ++ testdirs)
in log ll ("Removing directories: " ++ unwords rmdirs) |>
(system (unwords (["rm", "-rf"] ++ rmdirs)) >> succeedIO ())
......@@ -898,21 +916,22 @@ newPackage = do
-- Caching the current CURRYPATH of a package for faster startup.
--- The name of the cache file in a package directory.
curryPathCachFile :: String -> String
curryPathCachFile pkgdir = pkgdir </> ".cpm" </> "currypath_cache"
curryPathCacheFile :: String -> String
curryPathCacheFile pkgdir = pkgdir </> ".cpm" </> "currypath_cache"