Skip to content

Commit 7bb4dcb

Browse files
committed
Add revision information to plan.json
Closes #6186
1 parent d643706 commit 7bb4dcb

File tree

7 files changed

+94
-4
lines changed

7 files changed

+94
-4
lines changed

cabal-install/src/Distribution/Client/ProjectPlanOutput.hs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ import Distribution.Verbosity
6666
import Distribution.Client.Compat.Prelude
6767
import Prelude ()
6868

69+
import Control.Monad ((<=<))
70+
6971
import qualified Data.ByteString.Builder as BB
7072
import qualified Data.ByteString.Lazy as BS
7173
import qualified Data.Map as Map
@@ -158,6 +160,11 @@ encodePlanAsJson distDirLayout elaboratedInstallPlan elaboratedSharedConfig =
158160
, "id" J..= (jdisplay . installedUnitId) elab
159161
, "pkg-name" J..= (jdisplay . pkgName . packageId) elab
160162
, "pkg-version" J..= (jdisplay . pkgVersion . packageId) elab
163+
, -- The `x-revision` field is a feature of repos (not cabal itself),
164+
-- but it's needed for external tools to unambiguously fetch
165+
-- packages without having to use index-state and go through
166+
-- the whole repo index, so we include it in the plan file.
167+
"pkg-revision" J..= J.Number (elaboratedPackageToRevision elab)
161168
, "flags"
162169
J..= J.object
163170
[ PD.unFlagName fn J..= v
@@ -266,6 +273,13 @@ encodePlanAsJson distDirLayout elaboratedInstallPlan elaboratedSharedConfig =
266273
, "uri" J..= J.String (show (remoteRepoURI repoRemote))
267274
]
268275

276+
elaboratedPackageToRevision :: ElaboratedConfiguredPackage -> Double
277+
elaboratedPackageToRevision =
278+
fromMaybe 0
279+
. (readMaybe <=< lookup "x-revision")
280+
. PD.customFieldsPD
281+
. elabPkgDescription
282+
269283
sourceRepoToJ :: SourceRepoMaybe -> J.Value
270284
sourceRepoToJ SourceRepositoryPackage{..} =
271285
J.object $
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{-# LANGUAGE OverloadedStrings #-}
2+
import Distribution.Types.PackageName (PackageName, mkPackageName)
3+
import Test.Cabal.Prelude
4+
import Test.Cabal.DecodeShowBuildInfo
5+
import Test.Cabal.Plan
6+
import Data.Maybe (mapMaybe)
7+
8+
getRevisionFor :: PackageName -> InstallItem -> Maybe Revision
9+
getRevisionFor pkgName (AConfiguredGlobal configuredGlobal)
10+
| configuredGlobalPackageName configuredGlobal == pkgName =
11+
Just $ configuredGlobalRevision configuredGlobal
12+
getRevisionFor _ _ = Nothing
13+
14+
main = cabalTest $ recordMode DoNotRecord $ do
15+
let go = do
16+
cabal "build" ["--dry-run", "all"]
17+
withPlan $ do
18+
Just plan <- testPlan `fmap` getTestEnv
19+
let [fooRev] = mapMaybe (getRevisionFor $ mkPackageName "foo") $ planInstallPlan plan
20+
let [barRev] = mapMaybe (getRevisionFor $ mkPackageName "bar") $ planInstallPlan plan
21+
assertEqual "revision of package foo" fooRev $ Revision 0
22+
assertEqual "revision of package bar" barRev $ Revision 1337
23+
withRepo "repo" go
24+
cabal "clean" []
25+
withRemoteRepo "repo" $ do
26+
cabal "update" []
27+
go
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
name: pkg
2+
version: 1.0
3+
build-type: Simple
4+
cabal-version: >= 1.2
5+
6+
executable my-exe
7+
main-is: Main.hs
8+
build-depends: base, foo, bar
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
name: bar
2+
version: 1.0
3+
build-type: Simple
4+
cabal-version: >= 1.2
5+
x-revision: 1337
6+
7+
library
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
name: foo
2+
version: 1.0
3+
build-type: Simple
4+
cabal-version: >= 1.2
5+
6+
library

cabal-testsuite/src/Test/Cabal/Plan.hs

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,21 @@
1+
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
12
{-# LANGUAGE OverloadedStrings #-}
23
{-# OPTIONS_GHC -Wno-orphans #-}
34
-- | Utilities for understanding @plan.json@.
45
module Test.Cabal.Plan (
5-
Plan,
6+
Plan(..),
67
DistDirOrBinFile(..),
8+
InstallItem(..),
9+
ConfiguredGlobal(..),
10+
Revision(..),
711
planDistDir,
812
buildInfoFile,
913
) where
1014

11-
import Distribution.Parsec (simpleParsec)
15+
import Distribution.Parsec (simpleParsec, eitherParsec)
1216
import Distribution.Pretty (prettyShow)
1317
import Distribution.Types.ComponentName
18+
import Distribution.Types.Version
1419
import Distribution.Package
1520
import qualified Data.Text as Text
1621
import Data.Aeson
@@ -32,15 +37,22 @@ data ConfiguredInplace = ConfiguredInplace
3237
{ configuredInplaceDistDir :: FilePath
3338
, configuredInplaceBuildInfo :: Maybe FilePath
3439
, configuredInplacePackageName :: PackageName
40+
, configuredInplaceVersion :: Version
41+
, configuredInplaceRevision :: Revision
3542
, configuredInplaceComponentName :: Maybe ComponentName }
3643
deriving Show
3744

3845
data ConfiguredGlobal = ConfiguredGlobal
3946
{ configuredGlobalBinFile :: Maybe FilePath
4047
, configuredGlobalPackageName :: PackageName
48+
, configuredGlobalVersion :: Version
49+
, configuredGlobalRevision :: Revision
4150
, configuredGlobalComponentName :: Maybe ComponentName }
4251
deriving Show
4352

53+
newtype Revision = Revision Int
54+
deriving (Show, Eq, FromJSON)
55+
4456
instance FromJSON Plan where
4557
parseJSON (Object v) = fmap Plan (v .: "install-plan")
4658
parseJSON invalid = typeMismatch "Plan" invalid
@@ -65,22 +77,29 @@ instance FromJSON ConfiguredInplace where
6577
dist_dir <- v .: "dist-dir"
6678
build_info <- v .:? "build-info"
6779
pkg_name <- v .: "pkg-name"
80+
pkg_version <- v .: "pkg-version"
81+
pkg_revision <- v .: "pkg-revision"
6882
component_name <- v .:? "component-name"
69-
return (ConfiguredInplace dist_dir build_info pkg_name component_name)
83+
return (ConfiguredInplace dist_dir build_info pkg_name pkg_version pkg_revision component_name)
7084
parseJSON invalid = typeMismatch "ConfiguredInplace" invalid
7185

7286
instance FromJSON ConfiguredGlobal where
7387
parseJSON (Object v) = do
7488
bin_file <- v .:? "bin-file"
7589
pkg_name <- v .: "pkg-name"
90+
pkg_version <- v .: "pkg-version"
91+
pkg_revision <- v .: "pkg-revision"
7692
component_name <- v .:? "component-name"
77-
return (ConfiguredGlobal bin_file pkg_name component_name)
93+
return (ConfiguredGlobal bin_file pkg_name pkg_version pkg_revision component_name)
7894
parseJSON invalid = typeMismatch "ConfiguredGlobal" invalid
7995

8096
instance FromJSON PackageName where
8197
parseJSON (String t) = return (mkPackageName (Text.unpack t))
8298
parseJSON invalid = typeMismatch "PackageName" invalid
8399

100+
instance FromJSON Version where
101+
parseJSON = withText "Version" $ either fail pure . eitherParsec . Text.unpack
102+
84103
instance FromJSON ComponentName where
85104
parseJSON (String t) =
86105
case simpleParsec s of

changelog.d/pr-10980

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
synopsis: Added revision information to `plan.json`
2+
packages: cabal-install
3+
prs: #10980
4+
issues: #6186
5+
6+
description: {
7+
The contents of `x-revision` `.cabal` fields are now available in `plan.json`.
8+
They are located under `pkg-src.repo.pkg-revision`, have type `Number`, and are only available for `repo-tar` repositories of type `remote-repo` or `secure-repo`.
9+
}

0 commit comments

Comments
 (0)