Commit 350b017e authored by Michael Hanus 's avatar Michael Hanus

diff command: version is now optional

parent bd4d114c
......@@ -265,12 +265,12 @@ following them as much as possible as still encouraged. Release $1.0.0$ is
considered to be the first stable version.
\end{itemize}
%
To aid you in following these rules, CPM provides the \verb|diff| command.
\verb|diff| can be used to compare the types and behavior of a package's public
To aid you in following these rules, CPM provides the \code{diff} command.
\code{diff} can be used to compare the types and behavior of a package's public
API between two versions of that package. If it finds any differences, it checks
whether they are acceptable under semantic versioning for the difference in
version numbers between the two package versions. To use \verb|diff|, you need
to be in the directory of one of the versions, i.e. your copy for development,
version numbers between the two package versions. To use \code{diff}, you need
to be in the directory of one of the versions, i.e., your copy for development,
and have the other version installed in CPM's global package cache (see the
\verb|cpm install| command). For example, if you are developing version $1.3.0$
of the JSON package and want to make sure you have not introduced any breaking
......@@ -469,13 +469,16 @@ these modules are checked, otherwise all modules in the directory \code{src}
Using the option \code{--modules}, one can also specify a comma-separated
list of module names to be checked.
\item[\fbox{\code{diff $version$}}]
\item[\fbox{\code{diff [$version$]}}]
Compares the API and behavior of the current package to another
version of the same package.
If the version option is missing, the latest version of the current package
found in the repository is used for comparison.
If the options \code{--api-only} or \code{--behavior-only} are added,
the only the API or the behavior are compared, respectively.
then only the API or the behavior are compared, respectively.
Using the option \code{--modules}, one can also specify a comma-separated
list of module names to be compared.
list of module names to be compared. Without this option,
all exported modules are compared.
\item[\fbox{\code{exec $command$}}] Executes an arbitrary command with the
\verb|CURRYPATH| environment variable set to the paths of all dependencies of
......@@ -561,8 +564,9 @@ package described in the specification can be obtained. See
Section~\ref{sec:publishing-a-package} for details.
\item[\fbox{\code{exportedModules}}] A list of modules intended for use by
consumers of the package. These are the modules compared by the \verb|cpm diff|
command. Note that modules not in this list are still accessible to consumers
consumers of the package. These are the modules compared by the \code{cpm diff}
command or checked by the \code{cpm check} command.
Note that modules not in this list are still accessible to consumers
of the package.
\end{description}
......
......@@ -5,8 +5,7 @@
--------------------------------------------------------------------------------
module CPM.Config
( cpmBanner
, Config (Config, packageInstallDir, repositoryDir, packageIndexRepository)
( Config (Config, packageInstallDir, repositoryDir, packageIndexRepository)
, readConfiguration, defaultConfig) where
import Char (isSpace)
......@@ -25,14 +24,6 @@ packageIndexURI = "https://git.ps.informatik.uni-kiel.de/curry/cpm-index.git"
-- if you have an ssh access to git.ps:
-- "ssh://git@git.ps.informatik.uni-kiel.de:55055/curry/cpm-index.git"
-- Banner of this tool:
cpmBanner :: String
cpmBanner = unlines [bannerLine,bannerText,bannerLine]
where
bannerText =
"Curry Package Manager <curry-language.org/tools/cpm> (version of 05/02/2017)"
bannerLine = take (length bannerText) (repeat '-')
--- Data type containing the main configuration of CPM.
data Config = Config {
--- The directory where locally installed packages are stored
......
......@@ -133,7 +133,7 @@ getBaseTemp = getTemporaryDirectory >>=
--- This message is printed before CurryCheck is executed.
infoText :: String
infoText = unlines
[ "Now running behavior diff where the raw output of CurryCheck is shown."
[ "Running behavior diff where the raw output of CurryCheck is shown."
, "The test functions are named after the functions they compare."
, "If a test fails, their implementations differ." ]
......
......@@ -19,7 +19,7 @@ import Boxes (table, render)
import OptParse
import CPM.ErrorLogger
import CPM.FileUtil (fileInPath, joinSearchPath)
import CPM.Config (cpmBanner, Config (packageInstallDir), readConfiguration)
import CPM.Config (Config (packageInstallDir), readConfiguration)
import CPM.PackageCache.Global (GlobalCache, readInstalledPackagesFromDir
, installFromZip, checkoutPackage
, uninstallPackage)
......@@ -32,6 +32,14 @@ import CPM.PackageCopy
import CPM.Diff.API as APIDiff
import qualified CPM.Diff.Behavior as BDiff
-- Banner of this tool:
cpmBanner :: String
cpmBanner = unlines [bannerLine,bannerText,bannerLine]
where
bannerText =
"Curry Package Manager <curry-language.org/tools/cpm> (version of 06/02/2017)"
bannerLine = take (length bannerText) (repeat '-')
main :: IO ()
main = do
args <- getArgs
......@@ -159,9 +167,9 @@ data CheckOptions = CheckOptions
{ checkModules :: Maybe [String] }
data DiffOptions = DiffOptions
{ diffVersion :: Version
, diffModules :: Maybe [String]
, diffAPI :: Bool
{ diffVersion :: Maybe Version
, diffModules :: Maybe [String]
, diffAPI :: Bool
, diffBehavior :: Bool }
checkoutOpts :: Options -> CheckoutOptions
......@@ -222,7 +230,7 @@ checkOpts s = case optCommand s of
diffOpts :: Options -> DiffOptions
diffOpts s = case optCommand s of
Diff opts -> opts
_ -> DiffOptions (0, 0, 0, Nothing) Nothing True True
_ -> DiffOptions Nothing Nothing True True
readLogLevel :: String -> Either String LogLevel
readLogLevel s = if s == "debug"
......@@ -335,10 +343,14 @@ optionParser = optParser
<> help
"The modules to be checked, separate multiple modules by comma"
<> optional ) )
<|> command "diff" (help "Diff the current package against another version") Right
( arg (\s a -> readVersion' s >.> \v -> a { optCommand = Diff (diffOpts a) { diffVersion = v } })
<|> command "diff" (help "Diff the current package against another version")
(\a -> Right $ a { optCommand = Diff (diffOpts a) })
( arg (\s a -> readVersion' s >.> \v -> a
{ optCommand = Diff (diffOpts a)
{ diffVersion = Just v } })
( metavar "VERSION"
<> help "The other package version.")
<> help "The other package version. If no version is specified, cpm diffs against the latest repository version."
<> optional )
<.> option (\s a -> Right $ a { optCommand = Diff (diffOpts a)
{ diffModules = Just $ splitOn "," s } })
( long "modules"
......@@ -502,7 +514,7 @@ listCmd (ListOptions lv csv) _ repo = putStr rendered >> succeedIO ()
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.\n"
"\nUse 'cpm info PACKAGE' for more information about a package.\n"
header = [ ["Name", "Synopsis", "Version"]
, ["----", "--------", "-------"]]
......@@ -581,31 +593,48 @@ curryModulesInDir dir = getModules "" dir
diff :: DiffOptions -> Config -> Repository -> GlobalCache
-> IO (ErrorLogger ())
diff o cfg repo gc = tryFindLocalPackageSpec "." |>=
\specDir -> loadPackageSpec specDir |>=
\localSpec -> diffAPIIfEnabled specDir localSpec |>
diffBehaviorIfEnabled specDir localSpec
diff opts cfg repo gc =
tryFindLocalPackageSpec "." |>= \specDir ->
loadPackageSpec specDir |>= \localSpec ->
let localname = name localSpec
localv = version localSpec
showlocalv = showVersion localv
in
getDiffVersion localname |>= \diffv ->
if diffv == localv
then failIO $ "Cannot diff identical package versions " ++ showlocalv
else putStrLn ("Comparing local version " ++ showlocalv ++
" and repository version " ++ showVersion diffv ++ ":\n") >>
diffAPIIfEnabled specDir localSpec diffv |>
diffBehaviorIfEnabled specDir localSpec diffv
where
modules spec = case diffModules o of
getDiffVersion localname = case diffVersion opts of
Nothing -> case findLatestVersion repo localname False of
Nothing -> failIO $ "No other version of local package '" ++
localname ++ "' found in package repository."
Just p -> succeedIO (version p)
Just v -> succeedIO v
modules spec = case diffModules opts of
Nothing -> exportedModules spec
Just ms -> ms
diffAPIIfEnabled specDir localSpec =
if diffAPI o
then (putStrLn "Now running API diff..." >> putStrLn "" >> succeedIO ()) |>
diffAPIIfEnabled specDir localSpec diffversion =
if diffAPI opts
then (putStrLn "Running API diff..." >> putStrLn "" >> succeedIO ()) |>
APIDiff.compareModulesFromPackageAndDir cfg repo gc specDir
(name localSpec) (diffVersion o) (diffModules o) |>=
(name localSpec) diffversion (diffModules opts) |>=
\diffResults ->
let diffOut = APIDiff.showDifferences (map snd diffResults)
(version localSpec) (diffVersion o)
(version localSpec) diffversion
in unless (null diffOut) (putStrLn diffOut >> putStrLn "") >>
succeedIO ()
else succeedIO ()
diffBehaviorIfEnabled specDir localSpec =
if diffBehavior o
diffBehaviorIfEnabled specDir localSpec diffversion =
if diffBehavior opts
then BDiff.preparePackageAndDir cfg repo gc specDir (name localSpec)
(diffVersion o) |>=
diffversion |>=
\i -> BDiff.diffBehavior cfg repo gc i (modules localSpec)
else succeedIO ()
......
......@@ -160,7 +160,8 @@ tryFindLocalPackageSpec dir = do
existsLocal <- doesFileExist $ dir </> "package.json"
if existsLocal
then succeedIO dir
else log Debug ("No package.json in " ++ (show dir) ++ ", trying " ++ (show $ dir </> "..")) |> do
else log Debug ("No package.json in " ++ show dir ++ ", trying " ++
show (dir </> "..")) |> do
parentExists <- doesDirectoryExist $ dir </> ".."
if parentExists
then tryFindLocalPackageSpec $ dir </> ".."
......@@ -250,6 +251,6 @@ renderPackageInfo allinfos _ gc pkg = pPrint doc
showParaField fgetter fname = case fgetter pkg of
Nothing -> empty
Just s -> bold $ text fname <$$>
Just s -> bold (text fname) <$$>
indent 4 (fillSep (map text (words s)))
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