Commit 080e4ca0 authored by Michael Hanus 's avatar Michael Hanus
Browse files

CPM updated

parent a3de2890
......@@ -468,23 +468,31 @@ revision that represents the version:
}
\end{lstlisting}
%
There is also a shorthand, \code{\$version}, available to automatically use a
tag consisting of the letter \code{v} followed by the current version number,
as in the example above. Specifying \code{\$version} as the tag and then tagging
each version in the format \code{v1.2.3} is preferred, since it does not require
changing the source location in the \code{package.json} file every time a new
There is also a shorthand, \code{\$version}, available to
automatically use a tag consisting of the letter \code{v} followed by
the current version number, as in the example above. Specifying
\code{\$version} as the tag and then tagging each version in the
format \code{v1.2.3} is preferred, since it does not require changing
the source location in the \code{package.json} file every time a new
version is released.
After you have published the files for your new package version, you have to add
the corresponding package specification to the central package index. The
central package index is just a Git repository containing a directory for each
package, which contain subdirectories for all versions of that package which in
turn contain the package specification files. So the specification for version
$1.0.5$ of the \code{json} package would be located in \code{json/1.0.5/package.json}.
If you have access to the Git repository containing the central package index,
then you can add the package specification yourself.
Otherwise, send your package specification file to
\url{packages@curry-language.org} in order to publish it.
If one already has a repository with another tagging scheme,
one can also place the string \code{\$version\$}
in the tag, which will be automatically replaced by the current
version number. Thus, the tag \ccode{\$version} is equivalent
to the tag \ccode{v\$version\$}.
After you have published the files for your new package version, you
have to add the corresponding package specification to the central
package index. The central package index is just a Git repository
containing a directory for each package, which contain subdirectories
for all versions of that package which in turn contain the package
specification files. So the specification for version $1.0.5$ of the
\code{json} package would be located in
\code{json/1.0.5/package.json}. If you have access to the Git
repository containing the central package index, then you can add the
package specification yourself. Otherwise, send your package
specification file to \url{packages@curry-language.org} in order to
publish it.
\section{Configuration}
......@@ -581,9 +589,13 @@ The option \code{--all} shows more information.
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 (compatible to the current compiler) of the central package index.
The option \code{--all} shows also all package versions.
\item[\fbox{\code{list [--versions] [--csv]}}]
List the names and synopses of all packages of the central package index.
Unless the option \code{--versions} is set, only the newest version
of a package (compatible to the current compiler) is shown.
The option \code{--versions} shows all versions of the packages.
If a package is not compatible to the current compiler, then
the package version is shown as \ccode{???}.
The option \code{--csv} shows the information in CSV format.
\item[\fbox{\code{list --category [--csv]}}]
......@@ -592,9 +604,17 @@ 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 (compatible to the current compiler)
of the central package index for a term.
\item[\fbox{\code{search [--module] $query$}}]
Searches the names, synopses, and exported module names of all
packages of the central package index for occurrences of the given
search term.
If the option \code{--module} is set, then the search is restricted
to occurrences of an exported module. Thus, the package
exporting the module \code{JSON.Data} can be found by the command
%
\begin{lstlisting}
> cpm search --module JSON.Data
\end{lstlisting}
\item[\fbox{\code{update}}] Updates the local copy of the central package index
to the newest available version.
......@@ -678,7 +698,7 @@ Using the option \code{--modules}, one can also specify a comma-separated
list of module names to be tested.
\item[\fbox{\code{doc}}]
Generates an HTML documentation of the current package with CurryDoc.
Generates the HTML documentation of the current package with CurryDoc.
If the package specification contains a list of exported modules
(see Section~\ref{sec:reference}),
then these modules are documented.
......@@ -756,7 +776,7 @@ for semantic versioning version numbers.
\item[\fbox{\code{author*}}] The package's author. This is a free-form field,
the suggested format is either a name or a name followed by an email address in
angle brackets -- e.g. \code{John Doe <john@doe.com>}. Multiple authors should
angle brackets, e.g., \code{John Doe <john@doe.com>}. Multiple authors should
be separated by commas.
\item[\fbox{\code{maintainer}}] The current maintainers of the package, if
......@@ -764,6 +784,10 @@ different from the original authors. This field allows the current maintainers
to indicate the best person or persons to contact about the package while
attributing the original authors.
The suggested format is a name followed by an email address in
angle brackets, e.g., \code{John Doe <john@doe.com>}.
Multiple maintainers should be separated by commas.
\item[\fbox{\code{synopsis*}}] A short form summary of the package's purpose.
It should be kept as short as possible (ideally, less than 100 characters).
......
......@@ -11,7 +11,7 @@ module CPM.Config
, readConfiguration, readConfigurationWithDefault, defaultConfig
, showCompilerVersion ) where
import Char (isSpace, toLower)
import Char (toLower)
import Directory (getHomeDirectory, createDirectoryIfMissing)
import Distribution (installDir, curryCompiler, curryCompilerMinorVersion
, curryCompilerMajorVersion)
......@@ -25,6 +25,7 @@ import Read (readInt)
import CPM.ErrorLogger
import CPM.FileUtil (ifFileExists)
import CPM.Helpers (strip)
--- The location of the central package index.
packageIndexURI :: String
......@@ -158,9 +159,6 @@ mergeConfigSettings cfg props = applyEither setters cfg
stripProps :: [(String, String)] -> [(String, String)]
stripProps = map ((map toLower . strip) *** strip)
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.
keySetters :: [(String, String -> Config -> Config)]
......
......@@ -32,10 +32,10 @@ import Distribution (lookupModuleSource)
import FilePath ((</>), joinPath)
import Function (both)
import List ( intercalate, intersect, nub, splitOn, isPrefixOf, isInfixOf
, find, delete, (\\), nubBy)
import Maybe (isJust, fromJust, fromMaybe, listToMaybe)
import Pretty (pPrint, text, indent, vcat, (<+>), (<$$>))
import System (system, getEnviron, setEnviron, unsetEnviron)
, find, delete, (\\), nubBy )
import Maybe ( isJust, fromJust, fromMaybe, listToMaybe )
import Pretty ( pPrint, text, indent, vcat, (<+>), (<$$>) )
import System ( getEnviron, setEnviron, unsetEnviron )
import Analysis.Types ( Analysis )
import Analysis.ProgInfo ( ProgInfo, emptyProgInfo, combineProgInfo
......@@ -213,7 +213,7 @@ callCurryCheck cfg info baseTmp = do
setEnviron "CURRYPATH" currypath
log Debug ("Run `curry check Compare' in `" ++ baseTmp ++ "' with") |>
log Debug ("CURRYPATH=" ++ currypath) |> succeedIO ()
ecode <- inDirectory baseTmp $ system (currybin ++ " check Compare")
ecode <- inDirectory baseTmp $ showExecCmd (currybin ++ " check Compare")
setEnviron "CURRYPATH" oldPath
log Debug "CurryCheck finished" |> succeedIO ()
if ecode==0
......
......@@ -19,12 +19,13 @@ module CPM.ErrorLogger
, log
, showLogEntry
, infoMessage, debugMessage, fromErrorLogger
, showExecCmd, execQuietCmd
) where
import Global
import Pretty
import Profile -- for show run-time
import System (exitWith)
import System (exitWith, system)
infixl 0 |>=
infixl 0 |>
......@@ -196,3 +197,15 @@ fromErrorLogger a = do
case err of
Right v -> return v
Left m -> showLogEntry m >> exitWith 1
--- Executes a system command and show the command as debug message.
showExecCmd :: String -> IO Int
showExecCmd cmd = debugMessage ("Executing: " ++ cmd) >> system cmd
--- Executes a parameterized system command.
--- The parameter is set to `-q` unless the LogLevel is Debug.
execQuietCmd :: (String -> String) -> IO Int
execQuietCmd cmd = do
ll <- getLogLevel
debugMessage $ "Executing: " ++ cmd ""
system $ cmd (if ll == Debug then "" else "-q")
--- Some auxiliary operations that might fit better into system libraries.
module CPM.Helpers ( strip ) where
import Char ( isSpace )
strip :: String -> String
strip = reverse . dropWhile isSpace . reverse . dropWhile isSpace
......@@ -16,8 +16,7 @@ import FilePath ( (</>), splitSearchPath, takeExtension )
import IO ( hFlush, stdout )
import List ( groupBy, intercalate, nub, split, splitOn )
import Sort ( sortBy )
import System ( getArgs, getEnviron, setEnviron, system, unsetEnviron
, exitWith )
import System ( getArgs, getEnviron, setEnviron, unsetEnviron, exitWith )
import Boxes (table, render)
import OptParse
......@@ -45,7 +44,7 @@ cpmBanner :: String
cpmBanner = unlines [bannerLine,bannerText,bannerLine]
where
bannerText =
"Curry Package Manager <curry-language.org/tools/cpm> (version of 27/04/2017)"
"Curry Package Manager <curry-language.org/tools/cpm> (version of 04/05/2017)"
bannerLine = take (length bannerText) (repeat '-')
main :: IO ()
......@@ -178,13 +177,15 @@ data InfoOptions = InfoOptions
}
data ListOptions = ListOptions
{ listAll :: Bool -- list all versions of each package
{ listVers :: Bool -- list all versions of each package
, listCSV :: Bool -- list in CSV format
, listCat :: Bool -- list all categories
}
data SearchOptions = SearchOptions
{ searchQuery :: String }
{ searchQuery :: String
, searchModule :: Bool
}
data UpgradeOptions = UpgradeOptions
{ upgrTarget :: Maybe String }
......@@ -246,7 +247,7 @@ listOpts s = case optCommand s of
searchOpts :: Options -> SearchOptions
searchOpts s = case optCommand s of
Search opts -> opts
_ -> SearchOptions ""
_ -> SearchOptions "" False
upgradeOpts :: Options -> UpgradeOptions
upgradeOpts s = case optCommand s of
......@@ -541,9 +542,9 @@ optionParser = optParser
listArgs =
flag (\a -> Right $ a { optCommand =
List (listOpts a) { listAll = True } })
( short "a"
<> long "all"
List (listOpts a) { listVers = True } })
( short "v"
<> long "versions"
<> help "Show all versions" )
<.> flag (\a -> Right $ a { optCommand =
List (listOpts a) { listCSV = True } })
......@@ -557,10 +558,15 @@ optionParser = optParser
<> help "Show all categories" )
searchArgs =
arg (\s a -> Right $ a { optCommand = Search (searchOpts a)
{ searchQuery = s } })
( metavar "QUERY"
<> help "The search term" )
flag (\a -> Right $ a { optCommand = Search (searchOpts a)
{ searchModule = True } })
( short "m"
<> long "module"
<> help "Search an exported module" )
<.> arg (\s a -> Right $ a { optCommand = Search (searchOpts a)
{ searchQuery = s } })
( metavar "QUERY"
<> help "The search term" )
upgradeArgs =
arg (\s a -> Right $ a { optCommand = Upgrade (upgradeOpts a)
......@@ -574,8 +580,8 @@ optionParser = optParser
( metavar "SOURCE"
<> help "The directory to link" )
-- Check if operating system executables we depend on are present on the current
-- system.
-- Check if operating system executables we depend on are present on the
-- current system.
checkExecutables :: IO [String]
checkExecutables = do
present <- mapIO fileInPath listOfExecutables
......@@ -631,7 +637,7 @@ compiler o cfg getRepo getGC =
log Info ("Starting '" ++ currybin ++ "' with") |>
log Info ("CURRYPATH=" ++ currypath) |>
do setEnviron "CURRYPATH" $ currypath
ecode <- system $ currybin ++ " " ++ comCommand o
ecode <- showExecCmd $ currybin ++ " " ++ comCommand o
unsetEnviron "CURRYPATH"
unless (ecode==0) (exitWith ecode)
succeedIO ()
......@@ -692,7 +698,7 @@ install (InstallOptions Nothing Nothing _ instexec) cfg repo gc =
cleanCurryPathCache pkgdir |>
installLocalDependencies cfg repo gc pkgdir |>= \ (pkg,_) ->
writePackageConfig cfg pkgdir pkg |>
if instexec then installExecutable cfg repo pkg pkgdir else succeedIO ()
if instexec then installExecutable cfg repo pkg else succeedIO ()
install (InstallOptions (Just pkg) Nothing pre _) cfg repo gc = do
fileExists <- doesFileExist pkg
if fileExists
......@@ -717,9 +723,8 @@ checkCompiler cfg pkg =
--- 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 =
installExecutable :: Config -> Repository -> Package -> IO (ErrorLogger ())
installExecutable cfg repo pkg =
checkCompiler cfg pkg >>
-- we read the global cache again since it might be modified by
-- the installation of the package:
......@@ -740,13 +745,13 @@ installExecutable cfg repo pkg pkgdir =
bindir ++ "'") |>
(whenFileExists binexec (backupExistingBin binexec) >>
-- renaming might not work across file systems, hence we move:
system (unwords ["mv", mainmod, binexec]) >>
showExecCmd (unwords ["mv", mainmod, binexec]) >>
checkPath path bindir))
(executableSpec pkg)
where
backupExistingBin binexec = do
let binexecbak = binexec ++ ".bak"
system $ "rm -f " ++ binexecbak
showExecCmd $ "rm -f " ++ binexecbak
renameFile binexec binexecbak
infoMessage $ "Existing executable '" ++ binexec ++ "' saved to '" ++
binexecbak ++ "'."
......@@ -783,22 +788,29 @@ tryFindVersion pkg ver repo = case findVersion repo pkg ver of
"' not found in package repository."
Just p -> succeedIO $ p
--- Lists all (compiler-compatible) packages in the given repository.
--- Lists all (compiler-compatible if `lall` is false) packages
--- in the given repository.
listCmd :: ListOptions -> Config -> Repository -> IO (ErrorLogger ())
listCmd (ListOptions lv csv cat) cfg repo =
let listresult = if cat then renderCats catgroups
else renderPkgs allpkgs
in putStr listresult >> succeedIO ()
where
-- filter all packages compatible to the current compiler but leave at least
-- one package
filterCompatPkgs pkgs =
let comppkgs = filter (isCompatibleToCompiler cfg) pkgs
in if null comppkgs then take 1 pkgs else comppkgs
-- all packages (and versions if `lv`)
allpkgs = concatMap (if lv then id else ((:[]) . head))
allpkgs = concatMap (if lv then id else ((:[]) . head . filterCompatPkgs))
(sortBy (\ps1 ps2 -> name (head ps1) <= name (head ps2))
(listPackages cfg repo))
(listPackages repo))
-- all categories together with their package names:
catgroups =
let pkgid p = name p ++ '-' : showVersion (version p)
newpkgs = map head (listPackages cfg repo)
let pkgid p = name p ++ '-' : showVersionIfCompatible cfg p
newpkgs = map (head . filterCompatPkgs) (listPackages repo)
catpkgs = concatMap (\p -> map (\c -> (c, pkgid p)) (category p))
newpkgs
nocatps = map pkgid (filter (null . category) newpkgs)
......@@ -808,11 +820,11 @@ listCmd (ListOptions lv csv cat) cfg repo =
else [("???", nub $ sortBy (<=) nocatps)]
renderPkgs pkgs =
let (colsizes,rows) = packageVersionAsTable pkgs
let (colsizes,rows) = packageVersionAsTable cfg pkgs
in renderTable colsizes rows
renderCats catgrps =
let namelen = foldl max 2 $ map (length . fst) catgrps
let namelen = foldl max 8 $ map (length . fst) catgrps
header = [ ["Category", "Packages"]
, ["--------", "--------"]]
rows = header ++ map (\ (c,ns) -> [c, unwords ns]) catgrps
......@@ -824,16 +836,23 @@ listCmd (ListOptions lv csv cat) cfg repo =
-- Format a list of packages by showing their names, synopsis, and versions
-- as table rows. Returns also the column sizes.
packageVersionAsTable :: [Package] -> ([Int],[[String]])
packageVersionAsTable pkgs = (colsizes, rows)
packageVersionAsTable :: Config -> [Package] -> ([Int],[[String]])
packageVersionAsTable cfg pkgs = (colsizes, rows)
where
namelen = foldl max 2 $ map (length . name) pkgs
namelen = foldl max 4 $ map (length . name) pkgs
colsizes = [namelen + 2, 68 - namelen, 10]
header = [ ["Name", "Synopsis", "Version"]
, ["----", "--------", "-------"]]
rows = header ++ map formatPkg pkgs
formatPkg p = [name p, synopsis p, showVersion (version p)]
formatPkg p = [name p, synopsis p, showVersionIfCompatible cfg p]
--- Shows the version of a package if it is compatible with the
--- current compiler, otherwise shows "???".
showVersionIfCompatible :: Config -> Package -> String
showVersionIfCompatible cfg p =
if isCompatibleToCompiler cfg p then showVersion (version p)
else "???"
cpmInfo :: String
cpmInfo = "Use 'cpm info PACKAGE' for more information about a package."
......@@ -843,10 +862,10 @@ cpmUpdate = "Use 'cpm update' to download the newest package index."
--- Search in all (compiler-compatible) packages in the given repository.
search :: SearchOptions -> Config -> Repository -> IO (ErrorLogger ())
search (SearchOptions q) cfg repo = putStr rendered >> succeedIO ()
search (SearchOptions q smod) cfg repo = putStr rendered >> succeedIO ()
where
results = sortBy (\p1 p2 -> name p1 <= name p2) (searchPackages cfg repo q)
(colsizes,rows) = packageVersionAsTable results
results = sortBy (\p1 p2 -> name p1 <= name p2) (searchPackages repo smod q)
(colsizes,rows) = packageVersionAsTable cfg results
rendered = unlines $
if null results
then ["No packages found for '" ++ q, "", cpmUpdate]
......@@ -888,23 +907,28 @@ docCmd opts cfg getRepo getGC =
mainmod = maybe Nothing
(\ (PackageExecutable _ emain) -> Just emain)
(executableSpec pkg)
docmods <- maybe (if null exports
then maybe (curryModulesInDir (specDir </> "src"))
(\m -> return [m])
mainmod
else return exports)
return
(docModules opts)
(docmods,apidoc) <-
maybe (if null exports
then maybe (curryModulesInDir (specDir </> "src") >>=
\ms -> return (ms,True))
(\m -> return ([m],False))
mainmod
else return (exports,True))
(\ms -> return (ms,True))
(docModules opts)
if null docmods
then putStrLn "No modules to be documented!" >> succeedIO ()
else
if length docmods == 1
then runDocCmd specDir [currydoc, docdir, head docmods]
else foldEL (\_ -> docModule specDir docdir) () docmods |>
if apidoc
then foldEL (\_ -> docModule specDir docdir) () docmods |>
runDocCmd specDir
([currydoc, "--onlyindexhtml", docdir] ++ docmods) |>
([currydoc, "--title", apititle pkg, "--onlyindexhtml",
docdir] ++ docmods) |>
log Info ("Documentation generated in '"++docdir++"'")
else runDocCmd specDir [currydoc, docdir, head docmods]
where
apititle pkg = "\"API Documentation of Package '" ++ name pkg ++ "'\""
currydoc = curryExec cfg ++ " doc"
docModule pkgdir docdir mod =
......@@ -949,7 +973,7 @@ test opts cfg getRepo getGC =
then unwords (checkcmd : mods)
else scriptcmd
debugMessage $ "Removing directory: " ++ currysubdir
system (unwords ["rm", "-rf", currysubdir])
showExecCmd (unwords ["rm", "-rf", currysubdir])
inDirectory (apkgdir </> dir) $
execWithPkgDir (ExecOptions testcmd []) cfg getRepo getGC apkgdir
......@@ -1039,7 +1063,7 @@ execWithPkgDir o cfg getRepo getGC specDir =
let execpath = joinSearchPath (exePath o ++ splitSearchPath currypath)
in log Debug ("Setting CURRYPATH to " ++ execpath) |>
do setEnviron "CURRYPATH" execpath
ecode <- system (exeCommand o)
ecode <- showExecCmd (exeCommand o)
unsetEnviron "CURRYPATH"
unless (ecode==0) (exitWith ecode)
succeedIO ()
......@@ -1067,7 +1091,7 @@ cleanPackage ll =
(testSuite pkg))
rmdirs = nub (dotcpm : map addCurrySubdir (srcdirs ++ testdirs))
in log ll ("Removing directories: " ++ unwords rmdirs) |>
(system (unwords (["rm", "-rf"] ++ rmdirs)) >> succeedIO ())
(showExecCmd (unwords $ ["rm", "-rf"] ++ rmdirs) >> succeedIO ())
--- Creates a new package by asking some questions.
newPackage :: NewOptions -> IO (ErrorLogger ())
......
......@@ -12,8 +12,10 @@ module CPM.Package
, Package (..), emptyPackage
, Dependency (..)
, showVersion
, replaceVersionInTag
, readVersion
, packageIdEq
, showPackageSource
, readVersionConstraint
, readVersionConstraints
, readPackageSpec
......@@ -40,7 +42,7 @@ module CPM.Package
) where
import Char
import List (intercalate, isInfixOf)
import List (intercalate, intersperse, isInfixOf, splitOn)
import FilePath ((</>))
import SetFunctions
import JSON.Data
......@@ -120,7 +122,8 @@ data PackageSource = Http String
| FileSource String
--- A Git revision.
--- @cons Tag - A tag
--- @cons Tag - A tag which might contain the string `$version$` which will
--- be replaced by the package version
--- @cons Ref - A Git 'commitish', i.e. a SHA, a branch name, a tag name etc.
--- @cons VersionAsTag - Use the package version prefixed with a 'v' as the tag
data GitRevision = Tag String
......@@ -280,20 +283,41 @@ loadPackageSpec dir = do
packageIdEq :: Package -> Package -> Bool
packageIdEq p1 p2 = (name p1) == (name p2) && (version p1) == (version p2)
--- Shows the package source in human-readable format.
showPackageSource :: Package -> String
showPackageSource pkg = case source pkg of
Nothing -> "No source specified"
Just s -> showSource s
where
showSource (Git url rev) = "Git " ++ url ++ showGitRev rev
showSource (Http url) = url
showSource (FileSource url) = "File " ++ url
showGitRev (Just (Ref ref)) = "@" ++ ref
showGitRev (Just (Tag tag)) = "@" ++ replaceVersionInTag pkg tag
showGitRev (Just VersionAsTag) = "@v" ++ (showVersion $ version pkg)
showGitRev Nothing = ""
--- Replace the string `$version$` in a tag string by the current version.
replaceVersionInTag :: Package -> String -> String
replaceVersionInTag pkg =
concat . intersperse (showVersion $ version pkg) . splitOn "$version$"
--- Less than operator for versions.
vlt :: Version -> Version -> Bool
vlt (majorA, minorA, patchA, preA) (majorB, minorB, patchB, preB) = major || minor || patch || pre
where
major = majorA < majorB
minor = majorA <= majorB && minorA < minorB
patch = majorA <= majorB && minorA <= minorB && patchA < patchB
pre = case preA of
Nothing -> case preB of
Nothing -> patch
Just _ -> majorA <= majorB && minorA <= minorB && patchA <= patchB
Just a -> case preB of
Nothing -> False
Just b -> a `ltPre` b
vlt (majorA, minorA, patchA, preA) (majorB, minorB, patchB, preB) =
major || minor || patch || pre
where
major = majorA < majorB
minor = majorA <= majorB && minorA < minorB
patch = majorA <= majorB && minorA <= minorB && patchA < patchB
pre = case preA of
Nothing -> case preB of
Nothing -> patch
Just _ -> majorA <= majorB && minorA <= minorB && patchA <= patchB
Just a -> case preB of
Nothing -> False
Just b -> a `ltPre` b
ltPre :: String -> String -> Bool
ltPre a b | isNumeric a && isNumeric b = readInt a < readInt b
......
......@@ -28,7 +28,6 @@ import Either
import List
import Maybe (isJust)
import FilePath
import System (system)
import CPM.Config (Config, packageInstallDir)
import CPM.ErrorLogger
......@@ -97,7 +96,7 @@ copyPackage :: Config -> Package -> String -> IO (ErrorLogger ())
copyPackage cfg pkg dir = do
exists <- doesDirectoryExist srcDir
if not exists
then failIO $ "Package " ++ (packageId pkg) ++ " not installed"
then failIO $ "Package '" ++ packageId pkg ++ "' not installed"
else copyDirectory srcDir dir >> succeedIO ()
where
srcDir = installedPackageDir cfg pkg
......@@ -106,55 +105,47 @@ copyPackage cfg pkg dir = do
--- installs it to the global package cache.
acquireAndInstallPackage :: Config -> Package -> IO (ErrorLogger ())
acquireAndInstallPackage cfg pkg = case (source pkg) of
Nothing -> failIO $ "No source specified for " ++ (packageId pkg)
Just s -> log Info ("Installing package from " ++ showSource s) |>
installFromSource cfg pkg s
where
showSource (Git url rev) = "Git " ++ url ++ showGitRev rev
showSource (Http url) = url
showSource (FileSource url) = "File " ++ url
showGitRev (Just (Ref ref)) = "@" ++ ref
showGitRev (Just (Tag tag)) = "@" ++ tag
showGitRev (Just VersionAsTag) = "@v" ++ (showVersion $ version pkg)
showGitRev Nothing = ""
Nothing -> failIO $ "No source specified for " ++ packageId pkg
Just s -> log Info ("Installing package from " ++ showPackageSource pkg) |>
installFromSource cfg pkg s
--- Installs a package from the given package source to the global package
--- cache.
installFromSource :: Config -> Package -> PackageSource -> IO (ErrorLogger ())
installFromSource cfg pkg (Git url rev) = do
pkgDirExists <- doesDirectoryExist pkgDir
if pkgDirExists
then
log Info $ "Package " ++ packageId pkg ++ " already installed, skipping"
log Info $ "Package '" ++ packageId pkg ++ "' already installed, skipping"
else do
c <- inDirectory (packageInstallDir cfg) $ system cloneCommand
c <- inDirectory (packageInstallDir cfg) $ execQuietCmd cloneCommand
if c == 0
then case rev of
Nothing -> checkoutGitRef pkgDir "HEAD"
Just (Tag tag) -> checkoutGitRef pkgDir tag
Just (Tag tag) -> checkoutGitRef pkgDir
(replaceVersionInTag pkg tag)
Just (Ref ref) -> checkoutGitRef pkgDir ref
Just VersionAsTag -> let tag = "v" ++ (showVersion $ version pkg)
in checkoutGitRef pkgDir tag |>
log Info ("Package " ++ (packageId pkg) ++
" installed")
Just VersionAsTag ->
let tag = "v" ++ (showVersion $ version pkg)
in checkoutGitRef pkgDir tag |>
log Info ("Package '" ++ packageId pkg ++ "' installed")
else removeDirectoryComplete pkgDir >>
failIO ("Failed to clone repository from '" ++ url ++
"', return code " ++ show c)
where
pkgDir = (packageInstallDir cfg) </> (packageId pkg)
cloneCommand = "git clone " ++ (quote url) ++ " " ++ (quote $ packageId pkg)
pkgDir = packageInstallDir cfg </> packageId pkg
cloneCommand q = unwords ["git clone", q, quote url, quote $ packageId pkg]
installFromSource cfg pkg (FileSource zip) = do
absZip <- getAbsolutePath zip
pkgDirExists <- doesDirectoryExist pkgDir
if pkgDirExists
then
log Info $ "Package " ++ packageId pkg ++ " already installed, skipping"
log Info $ "Package '" ++ packageId pkg ++ "' already installed, skipping"
else do
createDirectory pkgDir
c <- inTempDir $ system $ "unzip -qq -d " ++ (quote pkgDir) ++
" " ++ (quote absZip)