Skip to content

Commit 307b71d

Browse files
authored
Merge pull request purescript#2544 from purescript/include-tag-date
Add git tag time to psc-publish JSON
2 parents 2e2b337 + 9d065d8 commit 307b71d

File tree

5 files changed

+71
-11
lines changed

5 files changed

+71
-11
lines changed

src/Language/PureScript/Docs/Types.hs

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,19 @@ import Control.Arrow (first, (***))
1010
import Control.Monad (when)
1111
import Control.Monad.Error.Class (catchError)
1212

13-
import Data.Monoid ((<>))
1413
import Data.Aeson ((.=))
1514
import Data.Aeson.BetterErrors
1615
import Data.ByteString.Lazy (ByteString)
1716
import Data.Either (isLeft, isRight)
18-
import Data.Maybe (mapMaybe, fromMaybe)
17+
import Data.Maybe (mapMaybe, fromMaybe, maybeToList)
18+
import Data.Monoid ((<>))
1919
import Data.Text (Text)
20+
import Data.Time.Clock (UTCTime)
21+
import qualified Data.Time.Format as TimeFormat
2022
import Data.Version
21-
import qualified Data.Vector as V
2223
import qualified Data.Aeson as A
2324
import qualified Data.Text as T
25+
import qualified Data.Vector as V
2426

2527
import qualified Language.PureScript as P
2628

@@ -40,6 +42,10 @@ data Package a = Package
4042
{ pkgMeta :: PackageMeta
4143
, pkgVersion :: Version
4244
, pkgVersionTag :: Text
45+
-- TODO: When this field was introduced, it was given the Maybe type for the
46+
-- sake of backwards compatibility, as older JSON blobs will not include the
47+
-- field. It should eventually be changed to just UTCTime.
48+
, pkgTagTime :: Maybe UTCTime
4349
, pkgModules :: [Module]
4450
, pkgBookmarks :: [Bookmark]
4551
, pkgResolvedDependencies :: [(PackageName, Version)]
@@ -62,6 +68,7 @@ verifyPackage verifiedUser Package{..} =
6268
Package pkgMeta
6369
pkgVersion
6470
pkgVersionTag
71+
pkgTagTime
6572
pkgModules
6673
pkgBookmarks
6774
pkgResolvedDependencies
@@ -72,6 +79,29 @@ verifyPackage verifiedUser Package{..} =
7279
packageName :: Package a -> PackageName
7380
packageName = bowerName . pkgMeta
7481

82+
-- |
83+
-- The time format used for serializing package tag times in the JSON format.
84+
-- This is the ISO 8601 date format which includes a time and a timezone.
85+
--
86+
jsonTimeFormat :: String
87+
jsonTimeFormat = "%Y-%m-%dT%H:%M:%S%z"
88+
89+
-- |
90+
-- Convenience function for formatting a time in the format expected by this
91+
-- module.
92+
--
93+
formatTime :: UTCTime -> String
94+
formatTime =
95+
TimeFormat.formatTime TimeFormat.defaultTimeLocale jsonTimeFormat
96+
97+
-- |
98+
-- Convenience function for parsing a time in the format expected by this
99+
-- module.
100+
--
101+
parseTime :: String -> Maybe UTCTime
102+
parseTime =
103+
TimeFormat.parseTimeM False TimeFormat.defaultTimeLocale jsonTimeFormat
104+
75105
data Module = Module
76106
{ modName :: P.ModuleName
77107
, modComments :: Maybe Text
@@ -275,6 +305,7 @@ data PackageError
275305
| InvalidFixity
276306
| InvalidKind Text
277307
| InvalidDataDeclType Text
308+
| InvalidTime
278309
deriving (Show, Eq, Ord)
279310

280311
type Bookmark = InPackage (P.ModuleName, Text)
@@ -320,13 +351,18 @@ asPackage minimumVersion uploader = do
320351
Package <$> key "packageMeta" asPackageMeta .! ErrorInPackageMeta
321352
<*> key "version" asVersion
322353
<*> key "versionTag" asText
354+
<*> keyMay "tagTime" (withString parseTimeEither)
323355
<*> key "modules" (eachInArray asModule)
324356
<*> key "bookmarks" asBookmarks .! ErrorInPackageMeta
325357
<*> key "resolvedDependencies" asResolvedDependencies
326358
<*> key "github" asGithub
327359
<*> key "uploader" uploader
328360
<*> pure compilerVersion
329361

362+
parseTimeEither :: String -> Either PackageError UTCTime
363+
parseTimeEither =
364+
maybe (Left InvalidTime) Right . parseTime
365+
330366
asUploadedPackage :: Version -> Parse PackageError UploadedPackage
331367
asUploadedPackage minVersion = asPackage minVersion asNotYetKnown
332368

@@ -359,6 +395,8 @@ displayPackageError e = case e of
359395
"Invalid kind: \"" <> str <> "\""
360396
InvalidDataDeclType str ->
361397
"Invalid data declaration type: \"" <> str <> "\""
398+
InvalidTime ->
399+
"Invalid time"
362400

363401
instance A.FromJSON a => A.FromJSON (Package a) where
364402
parseJSON = toAesonParser displayPackageError
@@ -550,7 +588,7 @@ asSourceSpan = P.SourceSpan <$> key "name" asString
550588

551589
instance A.ToJSON a => A.ToJSON (Package a) where
552590
toJSON Package{..} =
553-
A.object
591+
A.object $
554592
[ "packageMeta" .= pkgMeta
555593
, "version" .= showVersion pkgVersion
556594
, "versionTag" .= pkgVersionTag
@@ -562,7 +600,8 @@ instance A.ToJSON a => A.ToJSON (Package a) where
562600
, "github" .= pkgGithub
563601
, "uploader" .= pkgUploader
564602
, "compilerVersion" .= showVersion P.version
565-
]
603+
] ++
604+
fmap (\t -> "tagTime" .= formatTime t) (maybeToList pkgTagTime)
566605

567606
instance A.ToJSON NotYetKnown where
568607
toJSON _ = A.Null

src/Language/PureScript/Publish.hs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,13 @@ import Data.List (stripPrefix, (\\), nubBy)
3939
import Data.List.NonEmpty (NonEmpty(..))
4040
import Data.List.Split (splitOn)
4141
import Data.Maybe
42-
import Data.Version
43-
import qualified Data.SPDX as SPDX
4442
import Data.Text (Text)
4543
import qualified Data.Text as T
4644
import qualified Data.Text.Lazy as TL
4745
import qualified Data.Text.Lazy.Encoding as TL
46+
import Data.Time.Clock (UTCTime)
47+
import Data.Version
48+
import qualified Data.SPDX as SPDX
4849

4950
import Safe (headMay)
5051

@@ -67,13 +68,15 @@ data PublishOptions = PublishOptions
6768
{ -- | How to obtain the version tag and version that the data being
6869
-- generated will refer to.
6970
publishGetVersion :: PrepareM (Text, Version)
71+
, publishGetTagTime :: Text -> PrepareM UTCTime
7072
, -- | What to do when the working tree is dirty
7173
publishWorkingTreeDirty :: PrepareM ()
7274
}
7375

7476
defaultPublishOptions :: PublishOptions
7577
defaultPublishOptions = PublishOptions
7678
{ publishGetVersion = getVersionFromGitTag
79+
, publishGetTagTime = getTagTime
7780
, publishWorkingTreeDirty = userError DirtyWorkingTree
7881
}
7982

@@ -139,6 +142,7 @@ preparePackage' opts = do
139142
checkLicense pkgMeta
140143

141144
(pkgVersionTag, pkgVersion) <- publishGetVersion opts
145+
pkgTagTime <- Just <$> publishGetTagTime opts pkgVersionTag
142146
pkgGithub <- getBowerRepositoryInfo pkgMeta
143147
(pkgBookmarks, pkgModules) <- getModulesAndBookmarks
144148

@@ -200,6 +204,13 @@ getVersionFromGitTag = do
200204
digits <- stripPrefix "v" str
201205
(str,) <$> D.parseVersion' digits
202206

207+
-- | Given a git tag, get the time it was created.
208+
getTagTime :: Text -> PrepareM UTCTime
209+
getTagTime tag = do
210+
out <- readProcess' "git" ["show", T.unpack tag, "--no-patch", "--format=%aI"] ""
211+
let time = headMay (lines out) >>= D.parseTime
212+
maybe (internalError (CouldntParseGitTagDate tag)) pure time
213+
203214
getBowerRepositoryInfo :: PackageMeta -> PrepareM (D.GithubUser, D.GithubRepo)
204215
getBowerRepositoryInfo = either (userError . BadRepositoryField) return . tryExtract
205216
where

src/Language/PureScript/Publish/ErrorsWarnings.hs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ data RepositoryFieldError
7373
-- | An error that probably indicates a bug in this module.
7474
data InternalError
7575
= JSONError JSONSource (ParseError BowerError)
76+
| CouldntParseGitTagDate Text
7677
deriving (Show)
7778

7879
data JSONSource
@@ -289,6 +290,9 @@ displayInternalError e = case e of
289290
[ "Error in JSON " ++ displayJSONSource src ++ ":"
290291
, T.unpack (Bower.displayError r)
291292
]
293+
CouldntParseGitTagDate tag ->
294+
[ "Unable to parse the date for a git tag: " ++ T.unpack tag
295+
]
292296

293297
displayJSONSource :: JSONSource -> String
294298
displayJSONSource s = case s of

tests/TestDocs.hs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,16 @@ import Prelude ()
99
import Prelude.Compat
1010

1111
import Control.Arrow (first)
12+
import Control.Monad.IO.Class (liftIO)
1213

13-
import Data.Version (Version(..))
14-
import Data.Monoid
15-
import Data.Maybe (fromMaybe)
16-
import Data.List ((\\))
1714
import Data.Foldable
15+
import Data.List ((\\))
16+
import Data.Maybe (fromMaybe)
17+
import Data.Monoid
1818
import Data.Text (Text)
1919
import qualified Data.Text as T
20+
import Data.Time.Clock (getCurrentTime)
21+
import Data.Version (Version(..))
2022
import System.Exit
2123

2224
import qualified Language.PureScript as P
@@ -32,6 +34,7 @@ import TestUtils
3234
publishOpts :: Publish.PublishOptions
3335
publishOpts = Publish.defaultPublishOptions
3436
{ Publish.publishGetVersion = return testVersion
37+
, Publish.publishGetTagTime = const (liftIO getCurrentTime)
3538
, Publish.publishWorkingTreeDirty = return ()
3639
}
3740
where testVersion = ("v999.0.0", Version [999,0,0] [])

tests/TestPscPublish.hs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@
44

55
module TestPscPublish where
66

7+
import Control.Monad.IO.Class (liftIO)
78
import System.Exit (exitFailure)
89
import Data.ByteString.Lazy (ByteString)
10+
import Data.Time.Clock (getCurrentTime)
911
import qualified Data.Aeson as A
1012
import Data.Version
1113

@@ -38,6 +40,7 @@ roundTrip pkg =
3840
testRunOptions :: PublishOptions
3941
testRunOptions = defaultPublishOptions
4042
{ publishGetVersion = return testVersion
43+
, publishGetTagTime = const (liftIO getCurrentTime)
4144
, publishWorkingTreeDirty = return ()
4245
}
4346
where testVersion = ("v999.0.0", Version [999,0,0] [])

0 commit comments

Comments
 (0)