Commit f431516f authored by Michael Hanus 's avatar Michael Hanus
Browse files

CPM updated

parent fb06f63b
......@@ -219,12 +219,13 @@ creates a new project directory with a
\code{package.json} file for you.\footnote{The \code{new} command
also creates some other useful template files. Look into the
output of this command.}
Declare a dependency inside the new \code{package.json} file, e.g.:
Then declare the dependencies inside the new \code{package.json} file, e.g.:
\begin{lstlisting}
{
...,
"dependencies": {
"base": ">= 1.0.0, < 2.0.0",
"json": "~> 1.1.0"
}
}
......@@ -636,6 +637,24 @@ 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.
\item[\fbox{\code{BASE_VERSION}}]
The version of the base libraries which is used for package installations.
In the default case, the base version is the version of the system libraries
used by the Curry compiler. These system libraries are also available
as package \ccode{base} so that they can listed as a dependency
in the package specification.
If the base version of the package is identical to the base version
of the Curry compiler used by CPM, the installed copy
of the base libraries is ignored.\footnote{Since the system libraries
of a Curry compiler are usually pre-compiled, the usage of the
system libraries instead of the \code{base} package might result
in faster compilation times.}
If one uses a different base version, e.g., enforced by a package
dependency or by setting this configuration variable,
then this version of the base package is used.
Thus, one can use a package even if the current compiler
has a different version of the base libraries.
\end{description}
%
Note that one write the option names also in lowercase or omit
......@@ -710,6 +729,12 @@ This option adds the elapsed time to every info or debug output line.
The available commands of CPM are:
\begin{description}
\item[\fbox{\code{config}}]
Shows the current configuration of CPM
(see also Section~\ref{sec:config}).
The option \code{--all} shows also the names and version
of the packages installed in the global package cache.
\item[\fbox{\code{info}}] Gives information on the current package, e.g. the
package's name, author, synopsis and its dependency specifications.
......
......@@ -75,15 +75,14 @@ defaultConfig = Config
--- Shows the configuration.
showConfiguration :: Config -> String
showConfiguration cfg = unlines
[ "Current configuration:"
, "Compiler version : " ++ showCompilerVersion cfg
[ "Compiler version : " ++ showCompilerVersion cfg
, "Compiler base version : " ++ compilerBaseVersion cfg
, "Base version : " ++ baseVersion cfg
, "CURRYBIN : " ++ curryExec cfg
, "REPOSITORYPATH : " ++ repositoryDir cfg
, "PACKAGEINSTALLPATH : " ++ packageInstallDir cfg
, "BININSTALLPATH : " ++ binInstallDir cfg
, "APPPACKAGEPATH : " ++ appPackageDir cfg
, "BASE_VERSION : " ++ baseVersion cfg
, "CURRY_BIN : " ++ curryExec cfg
, "REPOSITORY_PATH : " ++ repositoryDir cfg
, "PACKAGE_INSTALL_PATH : " ++ packageInstallDir cfg
, "BIN_INSTALL_PATH : " ++ binInstallDir cfg
, "APP_PACKAGE_PATH : " ++ appPackageDir cfg
]
--- Shows the compiler version in the configuration.
......
......@@ -18,7 +18,7 @@ module CPM.FileUtil
, inDirectory
, recreateDirectory
, removeDirectoryComplete
, safeReadFile, checkAndGetDirectoryContents
, safeReadFile, checkAndGetVisibleDirectoryContents
, whenFileExists, ifFileExists
) where
......@@ -29,7 +29,7 @@ import Directory ( doesFileExist, doesDirectoryExist, getCurrentDirectory
import System ( system, getEnviron, exitWith )
import IOExts ( evalCmd, readCompleteFile )
import FilePath ( FilePath, replaceFileName, (</>), searchPathSeparator )
import List ( intercalate, splitOn )
import List ( intercalate, isPrefixOf, splitOn )
--- Joins a list of directories into a search path.
joinSearchPath :: [FilePath] -> String
......@@ -158,6 +158,13 @@ checkAndGetDirectoryContents dir = do
else do putStrLn $ "ERROR: Directory '" ++ dir ++ "' does not exist!"
exitWith 1
--- Returns the list of all visible entries in a directory (i.e., not starting
--- with '.') and terminates with an error message if the directory
--- does not exist.
checkAndGetVisibleDirectoryContents :: FilePath -> IO [FilePath]
checkAndGetVisibleDirectoryContents dir =
checkAndGetDirectoryContents dir >>= return . filter (not . isPrefixOf ".")
--- Performs an action when a file exists.
whenFileExists :: FilePath -> IO () -> IO ()
whenFileExists fname act = do
......
This diff is collapsed.
......@@ -8,9 +8,9 @@ module CPM.PackageCache.Global
, findAllVersions
, findNewestVersion
, findVersion
, isPackageInstalled
, packageInstalled
, installedPackageDir
, readInstalledPackagesFromDir
, readGlobalCache, readInstalledPackagesFromDir
, allPackages
, copyPackage
, installMissingDependencies
......@@ -34,11 +34,12 @@ import CPM.Config ( Config, packageInstallDir )
import CPM.ErrorLogger
import CPM.FileUtil ( copyDirectory, inTempDir, recreateDirectory, inDirectory
, removeDirectoryComplete, tempDir
, checkAndGetDirectoryContents, quote )
, checkAndGetVisibleDirectoryContents, quote )
import CPM.Package
import CPM.Repository
--- The global package cache.
------------------------------------------------------------------------------
--- The data type representing the global package cache.
data GlobalCache = GlobalCache [Package]
--- An empty package cache.
......@@ -49,6 +50,7 @@ emptyCache = GlobalCache []
allPackages :: GlobalCache -> [Package]
allPackages (GlobalCache ps) = ps
------------------------------------------------------------------------------
--- Finds all versions of a package in the global package cache.
---
--- @param gc - the global package cache
......@@ -89,10 +91,12 @@ isPackageInstalled db p = isJust $ findVersion db (name p) (version p)
--- The directory of a package in the global package cache. Does not check
--- whether the package is actually installed!
installedPackageDir :: Config -> Package -> String
installedPackageDir cfg pkg =
base </> (name pkg ++ "-" ++ (showVersion $ version pkg))
where
base = packageInstallDir cfg
installedPackageDir cfg pkg = packageInstallDir cfg </> packageId pkg
--- Checks whether a package is installed in the global cache.
packageInstalled :: Config -> Package -> IO Bool
packageInstalled cfg pkg =
doesDirectoryExist (installedPackageDir cfg pkg)
--- Copy a package version to a directory.
copyPackage :: Config -> Package -> String -> IO (ErrorLogger ())
......@@ -138,7 +142,7 @@ installFromSource cfg pkg (Git url rev) = do
failIO ("Failed to clone repository from '" ++ url ++
"', return code " ++ show c)
where
pkgDir = packageInstallDir cfg </> packageId pkg
pkgDir = installedPackageDir cfg pkg
cloneCommand q = unwords ["git clone", q, quote url, quote $ packageId pkg]
installFromSource cfg pkg (FileSource zip) = do
......@@ -156,7 +160,7 @@ installFromSource cfg pkg (FileSource zip) = do
else removeDirectoryComplete pkgDir >>
failIO ("Failed to unzip package, return code " ++ show c)
where
pkgDir = (packageInstallDir cfg) </> (packageId pkg)
pkgDir = installedPackageDir cfg pkg
installFromSource cfg pkg (Http url) = do
c <- inTempDir $ showExecCmd $ "curl -s -o package.zip " ++ quote url
......@@ -179,7 +183,7 @@ installFromSource cfg pkg (Http url) = do
else failIO $ "failed to unzip package.zip " ++ (show c')
else failIO $ "curl failed with " ++ (show c)
where
pkgDir = (packageInstallDir cfg) </> (packageId pkg)
pkgDir = installedPackageDir cfg pkg
--- Installs a package from a ZIP file to the global package cache.
installFromZip :: Config -> String -> IO (ErrorLogger ())
......@@ -226,9 +230,9 @@ missingPackages :: GlobalCache -> [Package] -> [Package]
missingPackages gc = filter (not . isPackageInstalled gc)
--- Checkout a package from the global package cache.
checkoutPackage :: Config -> Repository -> GlobalCache -> Package
checkoutPackage :: Config -> Package
-> IO (ErrorLogger ())
checkoutPackage cfg _ _ pkg = do
checkoutPackage cfg pkg = do
sexists <- doesDirectoryExist pkgDir
texists <- doesDirectoryExist codir
if texists
......@@ -238,22 +242,21 @@ checkoutPackage cfg _ _ pkg = do
else log Error $ "Package '" ++ pkgId ++ "' is not installed."
where
pkgId = packageId pkg
pkgDir = packageInstallDir cfg </> pkgId
pkgDir = installedPackageDir cfg pkg
codir = name pkg
logMsg = "Package '" ++ pkgId ++ "' checked out into directory '" ++
codir ++ "'."
--- Removes a package from the global package cache.
uninstallPackage :: Config -> Repository -> GlobalCache -> String -> Version
-> IO (ErrorLogger ())
uninstallPackage cfg _ _ pkg ver = do
uninstallPackage :: Config -> String -> Version -> IO (ErrorLogger ())
uninstallPackage cfg pkg ver = do
exists <- doesDirectoryExist pkgDir
if exists
then showExecCmd ("rm -Rf " ++ quote pkgDir) >> log Info logMsg
else log Info $ "Package '" ++ pkgId ++ "' is not installed."
where
pkgDir = (packageInstallDir cfg) </> pkgId
pkgId = pkg ++ "-" ++ showVersion ver
pkgDir = packageInstallDir cfg </> pkgId
pkgId = pkg ++ "-" ++ showVersion ver
logMsg = "Package '" ++ pkgId ++ "' uninstalled."
--- Tries to find a package in the global package cache.
......@@ -263,6 +266,14 @@ tryFindPackage gc name ver = case findVersion gc name ver of
Nothing -> failIO $ "Package " ++ name ++ "-" ++ showVersion ver ++
" could not be found."
--- Reads the global package cache.
readGlobalCache :: Config -> Repository -> IO (ErrorLogger GlobalCache)
readGlobalCache config repo = do
maybeGC <- readInstalledPackagesFromDir repo $ packageInstallDir config
case maybeGC of
Left err -> failIO $ "Error reading global package cache: " ++ err
Right gc -> succeedIO gc
--- Tries to read package specifications from a GC directory structure.
--- If some GC package directory has the same name as a package from
--- the repository index, the package specification from the repository
......@@ -273,8 +284,7 @@ readInstalledPackagesFromDir :: Repository -> String
-> IO (Either String GlobalCache)
readInstalledPackagesFromDir repo path = do
debugMessage $ "Reading global package cache from '" ++ path ++ "'..."
pkgDirs <- checkAndGetDirectoryContents path
pkgPaths <- return $ filter (not . isPrefixOf ".") pkgDirs
pkgPaths <- checkAndGetVisibleDirectoryContents path
specs <- mapIO loadPackageSpecFromDir pkgPaths
if null (lefts specs)
then do debugMessage "Finished reading global package cache"
......@@ -306,3 +316,5 @@ readInstalledPackagesFromDir repo path = do
else case readVersion (last ps) of
Nothing -> Nothing
Just v -> Just (intercalate "-" (take (l-1) ps), v)
------------------------------------------------------------------------------
......@@ -76,9 +76,8 @@ allPackages pkgDir = do
--- @param dir the package directory
--- @param gc the global package cache
--- @param pkg the package to copy
createLinkToGlobalCache :: Config -> String -> GlobalCache -> Package
-> IO (ErrorLogger ())
createLinkToGlobalCache cfg pkgDir _ pkg =
createLinkToGlobalCache :: Config -> String -> Package -> IO (ErrorLogger ())
createLinkToGlobalCache cfg pkgDir pkg =
createLink pkgDir (installedPackageDir cfg pkg) (packageId pkg) False
--- Links a list of packages from the global cache into the local cache. Does
......@@ -88,10 +87,10 @@ createLinkToGlobalCache cfg pkgDir _ pkg =
--- @param dir the package directory
--- @param gc the global package cache
--- @param pkgs the list of packages
linkPackages :: Config -> String -> GlobalCache -> [Package]
linkPackages :: Config -> String -> [Package]
-> IO (ErrorLogger ())
linkPackages cfg pkgDir gc pkgs =
mapEL (createLinkToGlobalCache cfg pkgDir gc) pkgs |> succeedIO ()
linkPackages cfg pkgDir pkgs =
mapEL (createLinkToGlobalCache cfg pkgDir) pkgs |> succeedIO ()
--- Tests whether a link in the local package cache points to a package in the
--- global package cache.
......@@ -100,8 +99,8 @@ linkPackages cfg pkgDir gc pkgs =
--- @param gc the global package cache
--- @param dir the package directory
--- @param name the name of the link
doesLinkPointToGlobalCache :: Config -> GlobalCache -> String -> String -> IO Bool
doesLinkPointToGlobalCache cfg _ pkgDir name = do
doesLinkPointToGlobalCache :: Config -> String -> String -> IO Bool
doesLinkPointToGlobalCache cfg pkgDir name = do
target <- linkTarget link
return $ isPrefixOf (packageInstallDir cfg) target
where
......
......@@ -31,7 +31,7 @@ import Text.Pretty hiding ( (</>) )
import CPM.AbstractCurry
import CPM.Config (Config, packageInstallDir, baseVersion)
import CPM.Repository (Repository, allPackages)
import CPM.Repository (Repository, allPackages, readRepository)
import qualified CPM.LookupSet as LS
import CPM.ErrorLogger
import CPM.FileUtil ( copyDirectory, recreateDirectory )
......@@ -77,7 +77,7 @@ lookupSetForPackageCopy cfg _ repo gc dir =
(GC.allPackages gc)
lsGC = addPackagesWOBase cfg lsRepo newInGC LS.FromGlobalCache
filterGCLinked p = do
points <- LocalCache.doesLinkPointToGlobalCache cfg gc dir (packageId p)
points <- LocalCache.doesLinkPointToGlobalCache cfg dir (packageId p)
return $ if points
then Nothing
else Just p
......@@ -98,10 +98,10 @@ resolveDependenciesForPackage cfg pkg repo gc =
--- Acquires a package and its dependencies and installs them to the global
--- package cache.
acquireAndInstallPackageWithDependencies :: Config -> Repository
-> GC.GlobalCache -> Package
acquireAndInstallPackageWithDependencies :: Config -> Repository -> Package
-> IO (ErrorLogger ())
acquireAndInstallPackageWithDependencies cfg repo gc pkg =
acquireAndInstallPackageWithDependencies cfg repo pkg =
GC.readGlobalCache cfg repo |>= \gc ->
resolveDependenciesForPackage cfg pkg repo gc |>=
\result -> GC.installMissingDependencies cfg gc (resolvedPackages result) |>
GC.acquireAndInstallPackage cfg pkg
......@@ -114,44 +114,46 @@ elemBy f (x:xs) = if f x
--- Links the dependencies of a package to its local cache and copies them to
--- its runtime cache.
copyDependencies :: Config -> GC.GlobalCache -> Package -> [Package] -> String
copyDependencies :: Config -> Package -> [Package] -> String
-> IO (ErrorLogger ())
copyDependencies cfg gc pkg pkgs dir =
LocalCache.linkPackages cfg dir gc pkgs |>
copyDependencies cfg pkg pkgs dir =
LocalCache.linkPackages cfg dir pkgs |>
RuntimeCache.copyPackages cfg pkgs' dir >> succeedIO ()
where
pkgs' = filter (/= pkg) pkgs
--- Upgrades all dependencies of a package copy.
upgradeAllPackages :: Config -> Repository -> GC.GlobalCache -> String
-> IO (ErrorLogger ())
upgradeAllPackages cfg repo gc dir =
upgradeAllPackages :: Config -> Repository -> String -> IO (ErrorLogger ())
upgradeAllPackages cfg repo dir =
loadPackageSpec dir |>= \pkgSpec ->
LocalCache.clearCache dir >> succeedIO () |>
installLocalDependencies cfg repo gc dir |>= \ (_,deps) ->
copyDependencies cfg gc pkgSpec deps dir
--- Upgrades a single dependencies and its transitive dependencies.
upgradeSinglePackage :: Config -> Repository -> GC.GlobalCache -> String
-> String -> IO (ErrorLogger ())
upgradeSinglePackage cfg repo gc dir pkgName = loadPackageSpec dir |>=
\pkgSpec -> lookupSetForPackageCopy cfg pkgSpec repo gc dir |>=
\originalLS -> let transitiveDeps = pkgName : allTransitiveDependencies originalLS pkgName in
installLocalDependencies cfg repo dir |>= \ (_,deps) ->
copyDependencies cfg pkgSpec deps dir
--- Upgrades a single package and its transitive dependencies.
upgradeSinglePackage :: Config -> Repository -> String -> String
-> IO (ErrorLogger ())
upgradeSinglePackage cfg repo dir pkgName =
loadPackageSpec dir |>= \pkgSpec ->
GC.readGlobalCache cfg repo |>= \gc ->
lookupSetForPackageCopy cfg pkgSpec repo gc dir |>= \originalLS ->
let transitiveDeps = pkgName : allTransitiveDependencies originalLS pkgName in
resolveDependenciesFromLookupSet cfg (setBaseDependency cfg pkgSpec)
(LS.setLocallyIgnored originalLS transitiveDeps) |>=
\result -> GC.installMissingDependencies cfg gc (resolvedPackages result) |>
log Info (showDependencies result) |>
copyDependencies cfg gc pkgSpec (resolvedPackages result) dir
copyDependencies cfg pkgSpec (resolvedPackages result) dir
--- Installs the dependencies of a package.
installLocalDependencies :: Config -> Repository -> GC.GlobalCache -> String
installLocalDependencies :: Config -> Repository -> String
-> IO (ErrorLogger (Package,[Package]))
installLocalDependencies cfg repo gc dir =
installLocalDependencies cfg repo dir =
loadPackageSpec dir |>= \pkgSpec ->
GC.readGlobalCache cfg repo |>= \gc ->
resolveDependenciesForPackageCopy cfg pkgSpec repo gc dir |>= \result ->
GC.installMissingDependencies cfg gc (resolvedPackages result) |>
log Info (showDependencies result) |>
copyDependencies cfg gc pkgSpec (resolvedPackages result) dir |>
copyDependencies cfg pkgSpec (resolvedPackages result) dir |>
succeedIO (pkgSpec, resolvedPackages result)
--- Links a directory into the local package cache. Used for `cypm link`.
......@@ -190,13 +192,20 @@ searchLocalPackageSpec dir = do
resolveAndCopyDependencies :: Config -> Repository -> GC.GlobalCache -> String
-> IO (ErrorLogger [Package])
resolveAndCopyDependencies cfg repo gc dir =
loadPackageSpec dir |>= resolveAndCopyDependenciesForPackage cfg repo gc dir
loadPackageSpec dir |>= resolveAndCopyDependenciesForPackage' cfg repo gc dir
--- Resolves the dependencies for a package copy and fills the package caches.
resolveAndCopyDependenciesForPackage ::
Config -> String -> Package -> IO (ErrorLogger [Package])
resolveAndCopyDependenciesForPackage cfg dir pkgSpec =
readRepository cfg >>= \repo ->
GC.readGlobalCache cfg repo |>= \gc ->
resolveAndCopyDependenciesForPackage' cfg repo gc dir pkgSpec
resolveAndCopyDependenciesForPackage' ::
Config -> Repository -> GC.GlobalCache -> String -> Package
-> IO (ErrorLogger [Package])
resolveAndCopyDependenciesForPackage cfg repo gc dir pkgSpec =
resolveAndCopyDependenciesForPackage' cfg repo gc dir pkgSpec =
resolveDependenciesForPackageCopy cfg pkgSpec repo gc dir |>= \result ->
let deps = resolvedPackages result
missingDeps = GC.missingPackages gc deps
......@@ -204,25 +213,27 @@ resolveAndCopyDependenciesForPackage cfg repo gc dir pkgSpec =
++ (intercalate "," $ map packageId missingDeps)
++ "\nUse `cypm install` to install missing dependencies."
in if null missingDeps
then copyDependencies cfg gc pkgSpec deps dir |>= \_ ->
then copyDependencies cfg pkgSpec deps dir |>= \_ ->
succeedIO deps
else failIO failMsg
--- Resolves the dependencies for a package copy.
resolveDependencies :: Config -> Repository -> GC.GlobalCache -> String
-> IO (ErrorLogger ResolutionResult)
resolveDependencies cfg repo gc dir = loadPackageSpec dir |->
log Info ("Read package spec from " ++ dir) |>=
\pkgSpec -> resolveDependenciesForPackageCopy cfg pkgSpec repo gc dir
resolveDependencies :: Config -> String -> IO (ErrorLogger ResolutionResult)
resolveDependencies cfg dir =
readRepository cfg >>= \repo ->
GC.readGlobalCache cfg repo |>= \gc ->
loadPackageSpec dir |->
log Info ("Read package spec from " ++ dir) |>= \pkgSpec ->
resolveDependenciesForPackageCopy cfg pkgSpec repo gc dir
--- Renders information on a package.
renderPackageInfo :: Bool -> Bool -> Maybe Bool -> Package -> String
renderPackageInfo allinfos plain mbinstalled pkg = pPrint doc
renderPackageInfo :: Bool -> Bool -> Bool -> Package -> String
renderPackageInfo allinfos plain installed pkg = pPrint doc
where
boldText s = (if plain then id else bold) $ text s
maxLen = 12
doc = vcat $ [ heading, rule
, maybe empty instTxt mbinstalled
, if allinfos then instTxt installed else empty
, ver, auth, maintnr, synop
, cats, deps, compilers, descr, execspec ] ++
if allinfos
......
......@@ -15,12 +15,11 @@ module CPM.Repository
, findAllVersions, findVersion, findLatestVersion
, searchPackages
, listPackages
, updateRepository
, updateRepositoryCache
, readPackageFromRepository
, useUpdateHelp, updateRepository, updateRepositoryCache
, readPackageFromRepository, getAllPackageVersions, getPackageVersion
) where
import Char ( toLower, toUpper )
import Char ( toLower )
import Directory
import Either
import FilePath
......@@ -28,14 +27,15 @@ import IO
import IOExts ( readCompleteFile )
import List
import ReadShowTerm ( showQTerm, readQTerm )
import System ( exitWith )
import System ( exitWith, system )
import Time
import CPM.Config ( Config, repositoryDir, packageIndexRepository
, packageInstallDir )
import CPM.ConfigPackage ( packageVersion )
import CPM.ErrorLogger
import CPM.Package
import CPM.FileUtil ( checkAndGetDirectoryContents, inDirectory
import CPM.FileUtil ( checkAndGetVisibleDirectoryContents, inDirectory
, whenFileExists, removeDirectoryComplete )
import CPM.Resolution ( isCompatibleToCompiler )
......@@ -125,12 +125,13 @@ allPackages :: Repository -> [Package]
allPackages (Repository ps) = ps
--- Reads all package specifications from the default repository.
--- Use the cache if is present or update the cache after reading.
--- If some errors occur, show them and terminate with exit status.
--- Uses the cache if it is present or update the cache after reading.
--- If some errors occur, show them and terminate with error exit status.
---
--- @param cfg the configuration to use
readRepository :: Config -> IO Repository
readRepository cfg = do
warnOldRepo cfg
mbrepo <- readRepositoryCache cfg
case mbrepo of
Nothing -> do
......@@ -143,19 +144,41 @@ readRepository cfg = do
exitWith 1
Just repo -> return repo
--- Sets the date of the last update by touching README.md.
setLastUpdate :: Config -> IO ()
setLastUpdate cfg =
system (unwords ["touch", repositoryDir cfg </> "README.md"]) >> done
--- Prints a warning if the repository index is older than 10 days.
warnOldRepo :: Config -> IO ()
warnOldRepo cfg = do
utime <- getModificationTime (repositoryDir cfg </> "README.md")
ctime <- getClockTime
let warntime = addDays 10 utime
when (compareClockTime ctime warntime == GT) $ do
-- We assume that clock time is measured in seconds (as in PAKCS or KiCS2)
let timediff = clockTimeToInt ctime - clockTimeToInt utime
days = timediff `div` (60*60*24)
putStrLn $ "Warning: your repository index is older than " ++
show days ++ " days."
putStrLn useUpdateHelp
useUpdateHelp :: String
useUpdateHelp = "Use 'cypm update' to download the newest package index."
--- Reads all package specifications from a repository.
---
--- @param path the location of the repository
readRepositoryFrom :: String -> IO (Repository, [String])
readRepositoryFrom path = do
debugMessage $ "Reading repository index from '" ++ path ++ "'..."
pkgDirs <- checkAndGetDirectoryContents path
pkgPaths <- return $ map (path </>) $ filter dirOrSpec pkgDirs
verDirs <- mapIO checkAndGetDirectoryContents pkgPaths
verPaths <- return $ concatMap (\ (d, p) -> map (d </>) (filter dirOrSpec p))
repos <- checkAndGetVisibleDirectoryContents path
pkgPaths <- mapIO getDir (map (path </>) repos) >>= return . concat
verDirs <- mapIO checkAndGetVisibleDirectoryContents pkgPaths
verPaths <- return $ concatMap (\ (d, p) -> map (d </>) p)
$ zip pkgPaths verDirs
specPaths <- return $ map (</> "package.json") verPaths
specs <- mapIO readPackageFile specPaths
specs <- mapIO readPackageFile specPaths
when (null (lefts specs)) $ debugMessage "Finished reading repository"
return $ (Repository $ rights specs, lefts specs)
where
......@@ -167,8 +190,7 @@ readRepositoryFrom path = do
Left err -> Left $ "Problem reading '" ++ f ++ "': " ++ err
Right s -> Right s
dirOrSpec d = (not $ isPrefixOf "." d) && takeExtension d /= ".md" &&
(not $ isPrefixOf repositoryCacheFileName (map toUpper d))
getDir d = doesDirectoryExist d >>= \b -> return $ if b then [d] else []
--- Updates the package index from the central Git repository.
......@@ -185,13 +207,15 @@ updateRepository cfg = do
then do
c <- inDirectory (repositoryDir cfg) $ execQuietCmd $ cleanPullCmd
if c == 0
then do updateRepositoryCache cfg
then do setLastUpdate cfg
updateRepositoryCache cfg
log Info "Successfully updated repository"
else failIO $ "Failed to update git repository, return code " ++ show c
else do
c <- inDirectory (repositoryDir cfg) $ execQuietCmd cloneCommand
if c == 0
then do updateRepositoryCache cfg
then do setLastUpdate cfg
updateRepositoryCache cfg
log Info "Successfully updated repository"
else failIO $ "Failed to update git repository, return code " ++ show c
where
......@@ -249,7 +273,8 @@ readRepositoryCache cfg = do
excache <- doesFileExist cf
if excache
then debugMessage ("Reading repository cache from '" ++ cf ++ "'...") >>
catch (readTermInCacheFile cf)
catch (readTermInCacheFile cf >>= \repo ->
debugMessage "Finished reading repository cache" >> return repo)
(\_ -> do infoMessage "Cleaning broken repository cache..."
cleanRepositoryCache cfg
return Nothing )
......@@ -293,3 +318,26 @@ readPackageFromRepository cfg pkg =
in loadPackageSpec pkgdir
------------------------------------------------------------------------------
-- Some operations to access the repository. In the future, these
-- operations might be implemented by a better database structure
-- of the repository to speed-up the repository access.
--- Retrieves all versions of a package with a given name from the repository.
---
--- @param cfg - the current CPM configuration
--- @param pkgname - the package name to be retrieved
--- @param pre - should pre-release versions be included?
getAllPackageVersions :: Config -> String -> Bool -> IO [Package]
getAllPackageVersions cfg pkgname pre =
readRepository cfg >>= \repo -> return (findAllVersions repo pkgname pre)
--- Retrieves a package with a given name and version from the repository.
---
--- @param cfg - the current CPM configuration
--- @param pkgname - the package name to be retrieved
--- @param ver - the requested version of the package
getPackageVersion :: Config -> String -> Version -> IO (Maybe Package)
getPackageVersion cfg pkgname ver =
readRepository cfg >>= \repo -> return (findVersion repo pkgname ver)
------------------------------------------------------------------------------
......@@ -71,7 +71,8 @@ resolutionSuccess (ResolutionFailure _) = False
--- Renders a dependency tree from a successful resolution.
showDependencies :: ResolutionResult -> String
showDependencies (ResolutionSuccess pkg deps) = showTree . mapTree (text . packageId) $ dependencyTree deps pkg
showDependencies (ResolutionSuccess pkg deps) =
showTree . mapTree (text . packageId) $ dependencyTree deps pkg
showDependencies (ResolutionFailure _) = "Resolution failed."
--- Renders a conflict resolution into a textual representation.
......@@ -80,12 +81,16 @@ showConflict (ResolutionSuccess _ _) = "Resolution succeeded."
showConflict (ResolutionFailure t) = case findRelevantConflict t of
Just c -> showConflictState c
Nothing -> case missingPackages $ clState $ findDeepestNode t of
[] -> "It failed for an unknown reason :("
(d@(Dependency p _):_) -> "There seems to be no version of package " ++ p ++ " that can satisfy the constraint " ++ showDependency d
[] -> "Conflict resolution failed for an unknown reason :(\n" ++
"Please clean your package ('cypm clean') and try again..."
(d@(Dependency p _):_) ->
"There seems to be no version of package " ++ p ++
" that can satisfy the constraint " ++ showDependency d
showConflictTree :: ResolutionResult -> String
showConflictTree (ResolutionSuccess _ _) = "Resolution succeeded."
showConflictTree (ResolutionFailure t) = showTree $ mapTree labeler $ cutBelowConflict t
showConflictTree (ResolutionFailure t) =
showTree $ mapTree labeler $ cutBelowConflict t
where
pkgId = text . packageId . actPackage
actChain a@(InitialA _) = pkgId a
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment