Commit 911a8429 authored by Michael Hanus 's avatar Michael Hanus
Browse files

CPM updated from package repository

parent bdad0760
......@@ -4,6 +4,7 @@
"author": "Bernd Brassel <bbr@informatik.uni-kiel.de>",
"maintainer": "Michael Hanus <mh@informatik.uni-kiel.de>",
"synopsis": "A tool to add missing type signatures in a Curry program",
"category": [ "Programming" ],
"dependencies": {
},
"description":
......
......@@ -20,6 +20,23 @@ in \cite{HanusSkrlac14}.
In the following, CASS is presented from a perspective
of a programmer who is interested to analyze Curry programs.
\subsection{Installation}
The current implementation of CASS is a package
managed by the Curry Package Manager CPM
(see also Section~\ref{sec-cpm}).
Thus, to install the newest version of CASS, use the following commands:
%
\begin{curry}
> cpm update
> cpm installbin cass
\end{curry}
%
This downloads the newest package, compiles it, and places
the executable \code{cass} into the directory \code{\$HOME/.cpm/bin}.
Hence it is recommended to add this directory to your path
in order to execute CASS as described below.
\subsection{Using CASS to Analyze Programs}
CASS is intended to analyze various operational properties
......@@ -29,7 +46,7 @@ Since most of these analyses are based on abstract interpretations,
they usually approximate program properties.
To see the list of all available analyses, use the help option of CASS:
\begin{curry}
> curry analyze -h
> cass -h
Usage: $\ldots$
$\vdots$
Registered analyses names:
......@@ -41,7 +58,7 @@ $\vdots$
More information about the meaning of the various analyses
can be obtained by adding the short name of the analysis:
\begin{curry}
> curry analyze -h Deterministic
> cass -h Deterministic
$\ldots$
\end{curry}
For instance, consider the following Curry module \code{Rev.curry}:
......@@ -63,14 +80,14 @@ CASS supports three different usage modes to analyze this program.
\subsubsection{Batch Mode}
In the batch mode, CASS is started as a separate application
via the shell command \code{curry analyze},
via the shell command \code{cass},
where the analysis name and the name of the module to be analyzed
must be provided:\footnote{More output is generated when
the parameter \code{debugLevel} is changed in the configuration file
\code{.curryanalysisrc} which is installed in the user's home directory
when CASS is started for the first time.}
\begin{curry}
> curry analyze Demand Rev
> cass Demand Rev
append : demanded arguments: 1
main : demanded arguments: 1,2
rev : demanded arguments: 1
......@@ -156,7 +173,7 @@ in the file \code{\cyshome/currytools/CASS/Protocol.txt} and sketched below.
To start CASS in the server mode, one has to execute the command
\begin{curry}
> curry analyze --server [ -p <port> ]
> cass --server [ -p <port> ]
\end{curry}
where an optional port number for the communication can be
provided. Otherwise, a free port number is chosen and shown. In the
......@@ -210,7 +227,7 @@ commands. Finally, \code{StopServer} terminates the CASS server.
For instance, if we start CASS by
\begin{curry}
> curry analyze --server -p 12345
> cass --server -p 12345
\end{curry}
we can communicate with CASS as follows (user inputs are prefixed by \ccode{>});
\begin{curry}
......
......@@ -570,7 +570,8 @@ the configuration options of CPM, see Section~\ref{sec:config}.
package's name, author, synopsis and its dependency specifications.
\item[\fbox{\code{info $package$ [--all]}}]
Prints information on the newest known version of the given package.
Prints information on the newest known version (compatible to the
current compiler) of the given package.
The option \code{--all} shows more information.
\item[\fbox{\code{info $package$ $version$ [--all]}}]
......@@ -578,10 +579,16 @@ Prints basic information on the given package version.
The option \code{--all} shows more information.
\item[\fbox{\code{list [--all] [--csv]}}] List the names and synopses of all
packages in the central package index.
packages of the central package index.
The option \code{--all} shows also all package versions.
The option \code{--csv} shows the information in CSV format.
\item[\fbox{\code{list --category [--csv]}}]
List the category names together with the packages belonging to this
category (see Section~\ref{sec:reference})
of the central package index.
The option \code{--csv} shows the information in CSV format.
\item[\fbox{\code{search $query$}}] Searches the names and synopses of all
packages in the central package index for a term.
......@@ -593,7 +600,8 @@ Furthermore, if the current package contains an executable application,
the application is compiled and the executable is installed
(unless the option \code{-n} or \code{--noexec} is set).
\item[\fbox{\code{install $package$ [--$pre$]}}] Installs the newest version of
\item[\fbox{\code{install $package$ [--$pre$]}}] Installs the newest version
(compatible to the current compiler) of
a package to the global package cache. \code{--$pre$} enables the installation
of pre-release versions.
......@@ -612,8 +620,8 @@ for this package.
of a package from the global package cache.
\item[\fbox{\code{checkout $package$ [--$pre$]}}]
Checks out the newest version of a package
into the local directory \code{$package$}
Checks out the newest version (compatible to the current compiler)
of a package into the local directory \code{$package$}
in order to test its operations or install a binary of the package.
\code{--$pre$} enables the installation of pre-release versions.
......@@ -623,7 +631,8 @@ into the local directory \code{$package$}
in order to test its operations or install a binary of the package..
\item[\fbox{\code{installbin $package$ [--$pre$]}}]
Install the binary provided by the newest version of a package.
Install the binary provided by the newest version
(compatible to the current compiler) of a package.
The binary is installed into the directory \code{\$HOME/.cpm/bin}
(this location can be changed via the \code{\$HOME/.cpmrc} configuration file
or by the CPM option \code{--define}, see Section~\ref{sec:config}).
......@@ -776,6 +785,19 @@ names are \code{pakcs} and \code{kics2}. If this field is missing or contains
an empty JSON object, the package is assumed to be compatible to all compilers
in all versions.
The compiler compatibility of a package is also relevant when
some version of a package should be examined or installed
(with CPM commands \code{info}, \code{checkout}, \code{install},
\code{installbin}).
If a newest package should be installed, i.e., no specific version
number is provided, then only the newest version
which is compatible to the current Curry compiler
(see also Section~\ref{sec:config} for configuration option \code{curry_bin})
is considered.
Similarly, the current package is executed
(CPM commands \code{curry} and \code{test})
only if the current Curry compiler is compatible to this package.
\item[\fbox{\code{source}}] A JSON object specifying where the version of the
package described in the specification can be obtained. See
Section~\ref{sec:publishing-a-package} for details.
......
......@@ -6,17 +6,22 @@
module CPM.Config
( Config ( Config, packageInstallDir, binInstallDir, repositoryDir
, binPackageDir, packageIndexRepository, curryExec )
, readConfiguration, readConfigurationWithDefault, defaultConfig ) where
, binPackageDir, packageIndexRepository, curryExec
, compilerVersion )
, readConfiguration, readConfigurationWithDefault, defaultConfig
, showCompilerVersion ) where
import Char (isSpace, toLower)
import Directory (getHomeDirectory, createDirectoryIfMissing)
import Distribution (installDir, curryCompiler)
import Distribution (installDir, curryCompiler, curryCompilerMinorVersion
, curryCompilerMajorVersion)
import FilePath ((</>))
import Function ((***))
import List (splitOn, intersperse)
import IOExts (evalCmd)
import List (split, splitOn, intersperse)
import Maybe (mapMaybe)
import PropertyFile (readPropertyFile)
import Read (readInt)
import CPM.ErrorLogger
import CPM.FileUtil (ifFileExists)
......@@ -42,6 +47,8 @@ data Config = Config {
, packageIndexRepository :: String
--- The executable of the Curry system used to compile and check packages
, curryExec :: String
--- The compiler version (name,major,minor) used to compile packages
, compilerVersion :: (String,Int,Int)
}
--- CPM's default configuration values. These are used if no .cpmrc file is found
......@@ -53,7 +60,34 @@ defaultConfig = Config
, repositoryDir = "$HOME/.cpm/index"
, binPackageDir = "$HOME/.cpm/bin_packages"
, packageIndexRepository = packageIndexURI
, curryExec = installDir </> "bin" </> curryCompiler }
, curryExec = installDir </> "bin" </> curryCompiler
, compilerVersion = (curryCompiler, curryCompilerMajorVersion,
curryCompilerMinorVersion)
}
--- Shows the compiler version in the configuration.
showCompilerVersion :: Config -> String
showCompilerVersion cfg =
let (cname,cmaj,cmin) = compilerVersion cfg
in cname ++ ' ' : show cmaj ++ "." ++ show cmin
--- Sets the correct compiler version in the configuration.
setCompilerVersion :: Config -> IO Config
setCompilerVersion cfg =
if curryExec cfg == installDir </> "bin" </> curryCompiler
then return cfg { compilerVersion = currVersion }
else do (c1,sname,_) <- evalCmd (curryExec cfg) ["--compiler-name"] ""
(c2,svers,_) <- evalCmd (curryExec cfg) ["--numeric-version"] ""
when (c1 > 0 || c2 > 0) $
error $ "Cannot determine compiler version"
let cname = strip sname
cvers = strip svers
(majs:mins:_) = split (=='.') cvers
debugMessage $ "Compiler version: " ++ cname ++ " " ++ cvers
return cfg { compilerVersion = (cname, readInt majs, readInt mins) }
where
currVersion = (curryCompiler, curryCompilerMajorVersion,
curryCompilerMinorVersion)
--- Reads the .cpmrc file from the user's home directory (if present) and merges
--- its contents into the default configuration. Resolves the $HOME variable
......@@ -78,8 +112,10 @@ readConfigurationWithDefault defsettings = do
(settingsFromFile ++ stripProps defsettings)
case mergedSettings of
Left e -> return $ Left e
Right s' -> replaceHome s' >>= \s'' -> createDirectories s'' >>
return (Right s'')
Right s0 -> do s1 <- replaceHome s0
createDirectories s1
s2 <- setCompilerVersion s1
return $ Right s2
replaceHome :: Config -> IO Config
replaceHome cfg = do
......@@ -121,8 +157,9 @@ mergeConfigSettings cfg props = applyEither setters cfg
--- @param opts - the options
stripProps :: [(String, String)] -> [(String, String)]
stripProps = map ((map toLower . strip) *** strip)
where
strip s = reverse $ dropWhile isSpace $ reverse $ dropWhile isSpace s
strip :: String -> String
strip = reverse . dropWhile isSpace . reverse . dropWhile isSpace
--- A map from option names to functions that will update a configuration
--- record with a value for that option.
......
......@@ -172,7 +172,8 @@ findLatestVersion ls p pre = case findAllVersions ls p pre of
--- @param p the name of the package
--- @param v the package version
findVersion :: LookupSet -> String -> Version -> Maybe Package
findVersion ls p v = maybeHead $ filter ((== v) . version) $ findAllVersions ls p True
findVersion ls p v =
maybeHead $ filter ((== v) . version) $ findAllVersions ls p True
maybeHead :: [a] -> Maybe a
maybeHead [] = Nothing
......
......@@ -14,7 +14,7 @@ import Distribution ( stripCurrySuffix, addCurrySubdir )
import Either
import FilePath ( (</>), splitSearchPath, takeExtension )
import IO ( hFlush, stdout )
import List ( intercalate, split, splitOn )
import List ( groupBy, intercalate, nub, split, splitOn )
import Sort ( sortBy )
import System ( getArgs, getEnviron, setEnviron, system, unsetEnviron
, exitWith )
......@@ -24,14 +24,14 @@ import OptParse
import CPM.ErrorLogger
import CPM.FileUtil ( fileInPath, joinSearchPath, safeReadFile, whenFileExists
, ifFileExists, inDirectory, removeDirectoryComplete )
import CPM.Config ( Config ( packageInstallDir, binInstallDir
, binPackageDir, curryExec )
, readConfigurationWithDefault )
import CPM.Config ( Config ( packageInstallDir, binInstallDir
, binPackageDir, curryExec )
, readConfigurationWithDefault, showCompilerVersion )
import CPM.PackageCache.Global ( GlobalCache, readInstalledPackagesFromDir
, installFromZip, checkoutPackage
, uninstallPackage )
import CPM.Package
import CPM.Resolution ( showResult )
import CPM.Resolution ( isCompatibleToCompiler, showResult )
import CPM.Repository ( Repository, readRepository, findVersion, listPackages
, findLatestVersion, updateRepository, searchPackages )
import CPM.PackageCache.Runtime ( dependencyPathsSeparate, writePackageConfig )
......@@ -44,7 +44,7 @@ cpmBanner :: String
cpmBanner = unlines [bannerLine,bannerText,bannerLine]
where
bannerText =
"Curry Package Manager <curry-language.org/tools/cpm> (version of 03/04/2017)"
"Curry Package Manager <curry-language.org/tools/cpm> (version of 10/04/2017)"
bannerLine = take (length bannerText) (repeat '-')
main :: IO ()
......@@ -173,8 +173,10 @@ data InfoOptions = InfoOptions
, infoAll :: Bool }
data ListOptions = ListOptions
{ listAll :: Bool
, listCSV :: Bool }
{ listAll :: Bool -- list all versions of each package
, listCSV :: Bool -- list in CSV format
, listCat :: Bool -- list all categories
}
data SearchOptions = SearchOptions
{ searchQuery :: String }
......@@ -226,7 +228,7 @@ infoOpts s = case optCommand s of
listOpts :: Options -> ListOptions
listOpts s = case optCommand s of
List opts -> opts
_ -> ListOptions False False
_ -> ListOptions False False False
searchOpts :: Options -> SearchOptions
searchOpts s = case optCommand s of
......@@ -449,14 +451,18 @@ optionParser = optParser
{ listAll = True } })
( short "a"
<> long "all"
<> help "Show all versions"
<> optional )
<> help "Show all versions" )
<.> flag (\a -> Right $ a { optCommand = List (listOpts a)
{ listCSV = True } })
( short "c"
( short "t"
<> long "csv"
<> help "Show in CSV format"
<> optional ) )
<> help "Show in CSV table format" )
<.> flag (\a -> Right $ a { optCommand = List (listOpts a)
{ listCat = True } })
( short "c"
<> long "category"
<> help "Show all categories" )
)
<|> command "search" (help "Search the package repository") Right
( arg (\s a -> Right $ a { optCommand = Search (searchOpts a) { searchQuery = s } })
( metavar "QUERY"
......@@ -498,8 +504,8 @@ info :: InfoOptions -> Config -> Repository -> GlobalCache
info (InfoOptions Nothing Nothing allinfos) _ repo gc =
tryFindLocalPackageSpec "." |>= \specDir ->
loadPackageSpec specDir |>= printInfo allinfos repo gc
info (InfoOptions (Just pkg) Nothing allinfos) _ repo gc =
case findLatestVersion repo pkg False of
info (InfoOptions (Just pkg) Nothing allinfos) cfg repo gc =
case findLatestVersion cfg repo pkg False of
Nothing -> failIO $
"Package '" ++ pkg ++ "' not found in package repository."
Just p -> printInfo allinfos repo gc p
......@@ -518,9 +524,11 @@ printInfo allinfos repo gc pkg =
compiler :: CompilerOptions -> Config -> IO Repository -> IO GlobalCache
-> IO (ErrorLogger ())
compiler o cfg getRepo getGC =
tryFindLocalPackageSpec "." |>= \specDir ->
loadCurryPathFromCache specDir |>=
maybe (computePackageLoadPath specDir) succeedIO |>= \currypath ->
tryFindLocalPackageSpec "." |>= \pkgdir ->
loadPackageSpec pkgdir |>= \pkg ->
checkCompiler cfg pkg >>
loadCurryPathFromCache pkgdir |>=
maybe (computePackageLoadPath pkgdir pkg) succeedIO |>= \currypath ->
log Info ("Starting '" ++ currybin ++ "' with") |>
log Info ("CURRYPATH=" ++ currypath) |>
do setEnviron "CURRYPATH" $ currypath
......@@ -531,9 +539,9 @@ compiler o cfg getRepo getGC =
where
currybin = curryExec cfg
computePackageLoadPath pkgdir =
getRepo >>= \repo -> getGC >>= \gc ->
loadPackageSpec pkgdir |>= \pkg ->
computePackageLoadPath pkgdir pkg =
getRepo >>= \repo ->
getGC >>= \gc ->
resolveAndCopyDependenciesForPackage cfg repo gc pkgdir pkg |>= \pkgs ->
getAbsolutePath pkgdir >>= \abs -> succeedIO () |>
let srcdirs = map (abs </>) (sourceDirsOf pkg)
......@@ -544,7 +552,7 @@ compiler o cfg getRepo getGC =
checkout :: CheckoutOptions -> Config -> Repository -> GlobalCache
-> IO (ErrorLogger ())
checkout (CheckoutOptions pkg Nothing pre) cfg repo gc =
case findLatestVersion repo pkg pre of
case findLatestVersion cfg repo pkg pre of
Nothing -> failIO $ "Package '" ++ pkg ++
"' not found in package repository."
Just p -> acquireAndInstallPackageWithDependencies cfg repo gc p |>
......@@ -581,15 +589,15 @@ installbin opts cfg repo gc = do
install :: InstallOptions -> Config -> Repository -> GlobalCache
-> IO (ErrorLogger ())
install (InstallOptions Nothing Nothing _ instexec) cfg repo gc =
tryFindLocalPackageSpec "." |>= \specDir ->
cleanCurryPathCache specDir |>
installLocalDependencies cfg repo gc specDir |>= \ (pkg,_) ->
if instexec then installExecutable cfg repo pkg specDir else succeedIO ()
tryFindLocalPackageSpec "." |>= \pkgdir ->
cleanCurryPathCache pkgdir |>
installLocalDependencies cfg repo gc pkgdir |>= \ (pkg,_) ->
if instexec then installExecutable cfg repo pkg pkgdir else succeedIO ()
install (InstallOptions (Just pkg) Nothing pre _) cfg repo gc = do
fileExists <- doesFileExist pkg
if fileExists
then installFromZip cfg pkg
else case findLatestVersion repo pkg pre of
else case findLatestVersion cfg repo pkg pre of
Nothing -> failIO $ "Package '" ++ pkg ++
"' not found in package repository."
Just p -> acquireAndInstallPackageWithDependencies cfg repo gc p
......@@ -601,11 +609,18 @@ install (InstallOptions (Just pkg) (Just ver) _ _) cfg repo gc =
install (InstallOptions Nothing (Just _) _ _) _ _ _ =
failIO "Must specify package name"
--- Checks the compiler compatibility.
checkCompiler :: Config -> Package -> IO ()
checkCompiler cfg pkg =
unless (isCompatibleToCompiler cfg pkg)
(error $ "Incompatible compiler: " ++ showCompilerVersion cfg)
--- Installs the executable specified in the package in the
--- bin directory of CPM (compare .cpmrc).
installExecutable :: Config -> Repository -> Package -> String
-> IO (ErrorLogger ())
installExecutable cfg repo pkg pkgdir =
checkCompiler cfg pkg >>
-- we read the global cache again since it might be modified by
-- the installation of the package:
getGlobalCache cfg >>= \gc ->
......@@ -652,8 +667,8 @@ uninstall (UninstallOptions (Just _) Nothing) _ _ _ =
uninstall (UninstallOptions Nothing (Just _)) _ _ _ =
log Error "Please provide a package and version number!"
uninstall (UninstallOptions Nothing Nothing) cfg _ _ =
tryFindLocalPackageSpec "." |>= \specDir ->
loadPackageSpec specDir |>= \pkg ->
tryFindLocalPackageSpec "." |>= \pkgdir ->
loadPackageSpec pkgdir |>= \pkg ->
maybe (succeedIO ())
(\ (PackageExecutable name _) ->
let binexec = binInstallDir cfg </> name
......@@ -671,25 +686,47 @@ tryFindVersion pkg ver repo = case findVersion repo pkg ver of
--- Lists all packages in the given repository.
listCmd :: ListOptions -> Config -> Repository -> IO (ErrorLogger ())
listCmd (ListOptions lv csv) _ repo = putStr rendered >> succeedIO ()
listCmd (ListOptions lv csv cat) _ repo =
if cat then putStr (renderCats catgroups) >> succeedIO ()
else putStr (renderPkgs allpkgs) >> succeedIO ()
where
results = concatMap (if lv then id else ((:[]) . head))
-- all packages (and versions if `lv`)
allpkgs = concatMap (if lv then id else ((:[]) . head))
(sortBy (\ps1 ps2 -> name (head ps1) <= name (head ps2))
(listPackages repo))
rendered =
if csv
then showCSV (head columns : drop 2 columns)
else render (table columns [nameLen + 4, 66 - nameLen, 10]) ++
"\nUse 'cpm info PACKAGE' for more information about a package." ++
"\nUse 'cpm update' to download the newest package index.\n"
-- all categories together with their package names:
catgroups =
let newpkgs = map head (listPackages repo)
catpkgs = concatMap (\p -> map (\c -> (c, name p)) (category p)) newpkgs
nocatps = map name (filter (null . category) newpkgs)
in map (\cg -> (fst (head cg), map snd cg))
(groupBy (\ (c1,_) (c2,_) -> c1==c2) (nub $ sortBy (<=) catpkgs)) ++
if null nocatps then []
else [("???", nub $ sortBy (<=) nocatps)]
renderPkgs pkgs =
let namelen = foldl max 4 $ map (length . name) pkgs
header = [ ["Name", "Synopsis", "Version"]
, ["----", "--------", "-------"]]
formatPkg p = [name p, synopsis p, showVersion (version p)]
columns = header ++ map formatPkg pkgs
in renderTable [namelen + 4, 66 - namelen, 10] columns
renderCats catgrps =
let namelen = foldl max 8 $ map (length . fst) catgrps
header = [ ["Category", "Packages"]
, ["--------", "--------"]]
columns = header ++ map (\ (c,ns) -> [c, unwords ns]) catgrps
in renderTable [namelen + 4, 76 - namelen] columns
renderTable colsizes cols =
if csv then showCSV (head cols : drop 2 cols)
else render (table cols colsizes) ++ cpmInfo
header = [ ["Name", "Synopsis", "Version"]
, ["----", "--------", "-------"]]
cpmInfo = "\nUse 'cpm info PACKAGE' for more information about a package." ++
"\nUse 'cpm update' to download the newest package index.\n"
formatPkg p = [name p, synopsis p, showVersion (version p)]
columns = header ++ map formatPkg results
nameLen = foldl max 0 $ map (length . name) results
search :: SearchOptions -> Config -> Repository -> IO (ErrorLogger ())
search (SearchOptions q) _ repo = putStr rendered >> succeedIO ()
......@@ -729,10 +766,11 @@ test :: TestOptions -> Config -> IO Repository -> IO GlobalCache
-> IO (ErrorLogger ())
test opts cfg getRepo getGC =
tryFindLocalPackageSpec "." |>= \specDir ->
loadPackageSpec specDir |>= \localSpec -> do
loadPackageSpec specDir |>= \pkg -> do
checkCompiler cfg pkg
aspecDir <- getAbsolutePath specDir
mainprogs <- curryModulesInDir (aspecDir </> "src")
let tests = testsuites localSpec mainprogs
let tests = testsuites pkg mainprogs
if null tests
then putStrLn "No modules to be tested!" >> succeedIO ()
else foldEL (\_ -> execTest aspecDir) () tests
......@@ -803,7 +841,7 @@ diff opts cfg repo gc =
diffBehaviorIfEnabled specDir localSpec diffv
where
getDiffVersion localname = case diffVersion opts of
Nothing -> case findLatestVersion repo localname False of
Nothing -> case findLatestVersion cfg repo localname False of
Nothing -> failIO $ "No other version of local package '" ++
localname ++ "' found in package repository."
Just p -> succeedIO (version p)
......
......@@ -562,7 +562,8 @@ dependenciesFromJObject kv = if any isLeft dependencies
--- Reads the compiler compatibility constraints of a package from the
--- key-value-pairs of a JObject.
compilerCompatibilityFromJObject :: [(String, JValue)] -> Either String [CompilerCompatibility]
compilerCompatibilityFromJObject :: [(String, JValue)]
-> Either String [CompilerCompatibility]
compilerCompatibilityFromJObject kv = if any isLeft compilerCompats
then Left $ intercalate "; " (lefts compilerCompats)
else Right $ rights compilerCompats
......
......@@ -52,7 +52,7 @@ resolveDependenciesForPackageCopy :: Config -> Package -> Repository
-> IO (ErrorLogger ResolutionResult)
resolveDependenciesForPackageCopy cfg pkg repo gc dir =
lookupSetForPackageCopy cfg pkg repo gc dir |>= \lookupSet ->
resolveDependenciesFromLookupSet pkg lookupSet
resolveDependenciesFromLookupSet cfg pkg lookupSet
--- Calculates the lookup set needed for dependency resolution on a package
--- copy.
......@@ -78,10 +78,11 @@ lookupSetForPackageCopy cfg _ repo gc dir =
else Just p
--- Resolves dependencies for a package.
resolveDependenciesForPackage :: Package -> Repository -> GC.GlobalCache
resolveDependenciesForPackage :: Config -> Package -> Repository
-> GC.GlobalCache
-> IO (ErrorLogger ResolutionResult)
resolveDependenciesForPackage pkg repo gc =
resolveDependenciesFromLookupSet pkg lookupSet
resolveDependenciesForPackage cfg pkg repo gc =
resolveDependenciesFromLookupSet cfg pkg lookupSet
where
lsRepo = LS.addPackages LS.emptySet (allPackages repo) LS.FromRepository
-- Find all packages that are in the global cache, but not in the repo
......@@ -95,7 +96,7 @@ acquireAndInstallPackageWithDependencies :: Config -> Repository
-> GC.GlobalCache -> Package
-> IO (ErrorLogger ())
acquireAndInstallPackageWithDependencies cfg repo gc pkg =
resolveDependenciesForPackage pkg repo gc |>=
resolveDependenciesForPackage cfg pkg repo gc |>=
\result -> GC.installMissingDependencies cfg gc (resolvedPackages result) |>
GC.acquireAndInstallPackage cfg pkg
......@@ -129,7 +130,8 @@ upgradeSinglePackage :: Config -> Repository -> GC.GlobalCache -> String
upgradeSinglePackage cfg repo gc dir pkgName = loadPackageSpec dir |>=
\pkgSpec -> lookupSetForPackageCopy cfg pkgSpec repo gc dir |>=
\originalLS -> let transitiveDeps = pkgName : allTransitiveDependencies originalLS pkgName in
resolveDependenciesFromLookupSet pkgSpec (LS.setLocallyIgnored originalLS transitiveDeps) |>=
resolveDependenciesFromLookupSet cfg pkgSpec
(LS.setLocallyIgnored originalLS transitiveDeps) |>=
\result -> GC.installMissingDependencies cfg gc (resolvedPackages result) |>
log Info (showDependencies result) |>
copyDependencies cfg gc pkgSpec (resolvedPackages result) dir
......
......@@ -26,10 +26,11 @@ import List
import FilePath
import System (system)
import CPM.Config (Config, repositoryDir, packageIndexRepository)
import CPM.Config (Config, repositoryDir, packageIndexRepository)
import CPM.ErrorLogger
import CPM.Package
import CPM.FileUtil ( checkAndGetDirectoryContents, inDirectory )
import CPM.FileUtil ( checkAndGetDirectoryContents, inDirectory )
import CPM.Resolution ( isCompatibleToCompiler )
data Repository = Repository [Package]
......@@ -44,12 +45,13 @@ emptyRepository = Repository []
--- @param p the name of the package to search for
--- @param pre should pre-release versions be included?
findAllVersions :: Repository -> String -> Bool -> [Package]
findAllVersions (Repository ps) p pre = sortedByVersion $ preFiltered $ sameName ps
where
sortedByVersion = sortBy (\a b -> (version a) `vgt` (version b))
preFiltered = filter filterPre
sameName = filter ((== p) . name)
filterPre p' = pre || (not . isPreRelease . version) p'
findAllVersions (Repository ps) p pre =
sortedByVersion $ preFiltered $ sameName ps
where
sortedByVersion = sortBy (\a b -> (version a) `vgt` (version b))
preFiltered = filter filterPre
sameName = filter ((== p) . name)
filterPre p' = pre || (not . isPreRelease . version) p'
--- Search the names and synopses of all packages in the repository for a
--- particular term. Lower/upercase is ignored for the search.
......@@ -81,19 +83,22 @@ listPackages (Repository ps) =
--- Finds the latest version of a package.
---
--- @param cfg - the current CPM configuration
--- @param repo - the central package index
--- @param p - the package to search for
--- @param pre - include pre-release versions
findLatestVersion :: Repository -> String -> Bool -> Maybe Package
findLatestVersion repo p pre = case findAllVersions repo p pre of
[] -> Nothing
(x:_) -> Just x
findLatestVersion :: Config -> Repository -> String -> Bool -> Maybe Package
findLatestVersion cfg repo pn pre =
case filter (isCompatibleToCompiler cfg) (findAllVersions repo pn pre) of
[] -> Nothing
(p:_) -> Just p
--- Finds a specific version of a package.
findVersion :: Repository -> String -> Version -> Maybe Package
findVersion repo p v = maybeHead $ filter ((== v) . version) $ findAllVersions repo p True
where maybeHead [] = Nothing
maybeHead (x:_) = Just x
findVersion repo p v =
maybeHead $ filter ((== v) . version) $ findAllVersions repo p True
where maybeHead [] = Nothing
maybeHead (x:_) = Just x
--- Get all packages in the central package index.
allPackages :: Repository -> [Package]
......
......@@ -13,10 +13,9 @@ module CPM.Resolution
, transitiveDependencies
, resolve
, resolveDependenciesFromLookupSet
, isCompatibleToCompiler
) where
import Distribution (curryCompiler, curryCompilerMinorVersion
, curryCompilerMajorVersion)
import Either
import List
import Pretty
......@@ -24,25 +23,27 @@ import Sort
import Maybe