summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/SlackBuilder/LatestVersionCheck.hs53
-rw-r--r--src/Main.hs22
-rw-r--r--tests/SlackBuilder/LatestVersionCheckSpec.hs35
3 files changed, 57 insertions, 53 deletions
diff --git a/lib/SlackBuilder/LatestVersionCheck.hs b/lib/SlackBuilder/LatestVersionCheck.hs
index 9002cce..82142e6 100644
--- a/lib/SlackBuilder/LatestVersionCheck.hs
+++ b/lib/SlackBuilder/LatestVersionCheck.hs
@@ -11,7 +11,6 @@ module SlackBuilder.LatestVersionCheck
, latestPackagist
, latestText
, match
- , stableTagTransform
) where
import SlackBuilder.Config
@@ -47,22 +46,12 @@ import qualified Data.Aeson.KeyMap as KeyMap
import GHC.Records (HasField(..))
import Control.Monad.Trans.Reader (asks)
import Control.Monad.IO.Class (MonadIO(..))
-import Control.Monad ((>=>))
data PackageOwner = PackageOwner
{ owner :: Text
, name :: Text
} deriving (Eq, Show)
--- | Removes the leading "v" from the version string and returns the result if
--- it looks like a version.
-stableTagTransform :: Text -> Maybe Text
-stableTagTransform = Text.stripPrefix "v" >=> checkForStable
- where
- checkForStable tag
- | Text.any (`elem` ['-', '+']) tag = Nothing
- | otherwise = Just tag
-
data MatchState = MatchState
{ ignoring :: Bool
, matched :: Text
@@ -72,28 +61,43 @@ data MatchState = MatchState
data MatchToken
= OpenParenMatchToken
| CloseParenMatchToken
- | AsteriskMatchToken (Maybe Char)
+ | AsteriskMatchToken
| SymbolMatchToken Char
+ | OneOfMatchToken [Char]
deriving (Eq, Show)
+-- | Removes the leading "v" from the version string and returns the result if
+-- it looks like a version.
match :: Text -> Text -> Maybe Text
match fullPattern input =
case Text.foldl' go (Just startState) input of
Just state@MatchState{ pattern' = [] } -> Just $ getField @"matched" state
Just state@MatchState{ pattern' = [CloseParenMatchToken] } ->
Just $ getField @"matched" state
- Just state@MatchState{ pattern' = [AsteriskMatchToken _] } ->
+ Just state@MatchState{ pattern' = [AsteriskMatchToken] } ->
+ Just $ getField @"matched" state
+ Just state@MatchState{ pattern' = [OneOfMatchToken _] } ->
Just $ getField @"matched" state
_ -> Nothing
where
- reserved = ['*', '(', ')']
+ digits = toEnum <$> [fromEnum '0' .. fromEnum '9']
parsePattern :: Text -> [MatchToken]
parsePattern input'
+ | Just (firstChar, remaining) <- Text.uncons input'
+ , firstChar == '\\' =
+ case Text.uncons remaining of
+ Nothing -> []
+ Just ('d', remaining') -> OneOfMatchToken digits
+ : parsePattern remaining'
+ Just ('.', remaining') -> OneOfMatchToken ('.' : digits)
+ : parsePattern remaining'
+ Just ('\\', remaining') -> SymbolMatchToken '\\'
+ : parsePattern remaining'
+ Just (_, remaining') -> parsePattern remaining'
| Just (firstChar, remaining) <- Text.uncons input' =
let token =
case firstChar of
'*' -> AsteriskMatchToken
- $ Text.find (not . (`elem` reserved)) remaining
'(' -> OpenParenMatchToken
')' -> CloseParenMatchToken
s -> SymbolMatchToken s
@@ -109,14 +113,16 @@ match fullPattern input =
case token of
OpenParenMatchToken -> go (Just state{ ignoring = True, pattern' = remaining }) nextCharacter
CloseParenMatchToken -> go (Just state{ ignoring = False, pattern' = remaining }) nextCharacter
- AsteriskMatchToken stopChar
- | Just nextCharacter == stopChar ->
- go (Just state{ pattern' = remaining }) nextCharacter
- | otherwise -> Just $ matchSymbolToken state nextCharacter
+ AsteriskMatchToken -> Just $ matchSymbolToken state nextCharacter
SymbolMatchToken patternCharacter
| patternCharacter == nextCharacter -> Just
$ matchSymbolToken state{ pattern' = remaining } nextCharacter
| otherwise -> Nothing
+ OneOfMatchToken chars
+ | nextCharacter `elem` chars ->
+ Just $ matchSymbolToken state nextCharacter
+ | otherwise ->
+ go (Just state{ pattern' = remaining }) nextCharacter
go _ _ = Nothing
matchSymbolToken state nextCharacter
| getField @"ignoring" state = state
@@ -214,9 +220,9 @@ $(deriveJSON defaultOptions ''GhQuery)
latestGitHub
:: PackageOwner
- -> (Text -> Maybe Text)
+ -> Text
-> SlackBuilderT (Maybe Text)
-latestGitHub PackageOwner{..} versionTransform = do
+latestGitHub PackageOwner{..} pattern' = do
ghToken' <- SlackBuilderT $ asks ghToken
ghResponse <- runReq defaultHttpConfig $
let uri = https "api.github.com" /: "graphql"
@@ -238,14 +244,13 @@ latestGitHub PackageOwner{..} versionTransform = do
$ responseBody ghResponse
refs' = Vector.reverse
$ Vector.catMaybes
- $ versionTransform . getField @"name" <$> ghNodes
- liftIO $ print $ getField @"name" <$> ghNodes
+ $ match pattern' . getField @"name" <$> ghNodes
pure $ refs' !? 0
where
githubQuery =
"query ($name: String!, $owner: String!) {\n\
\ repository(name: $name, owner: $owner) {\n\
- \ refs(last: 10, query: \"!(RC3)\", refPrefix: \"refs/tags/\", orderBy: { field: TAG_COMMIT_DATE, direction: ASC }) {\n\
+ \ refs(last: 10, refPrefix: \"refs/tags/\", orderBy: { field: TAG_COMMIT_DATE, direction: ASC }) {\n\
\ nodes {\n\
\ id,\n\
\ name\n\
diff --git a/src/Main.hs b/src/Main.hs
index b51d4cd..ecabd76 100644
--- a/src/Main.hs
+++ b/src/Main.hs
@@ -45,7 +45,7 @@ autoUpdatable =
$ Package.StaticPlaceholder "https://github.com/universal-ctags/ctags/archive/"
:| templateTail
in Package.Updater
- { detectLatest = latestGitHub ghArguments stableTagTransform
+ { detectLatest = latestGitHub ghArguments "(v)\\."
, getVersion = reuploadWithTemplate template []
, is64 = False
}
@@ -77,7 +77,7 @@ autoUpdatable =
:| Package.VersionPlaceholder
: [Package.StaticPlaceholder "/jitsi-meet-x86_64.AppImage"]
in Package.Updater
- { detectLatest = latestGitHub ghArguments $ Text.stripPrefix "v"
+ { detectLatest = latestGitHub ghArguments "(v)*"
, getVersion = downloadWithTemplate template
, is64 = True
}
@@ -90,16 +90,12 @@ autoUpdatable =
{ owner = "php"
, name = "php-src"
}
- checkVersion x
- | not $ Text.isInfixOf "RC" x
- , Text.isPrefixOf "php-8.2." x = Text.stripPrefix "php-" x
- | otherwise = Nothing
template = Package.DownloadTemplate
$ Package.StaticPlaceholder "https://www.php.net/distributions/php-"
:| Package.VersionPlaceholder
: [Package.StaticPlaceholder ".tar.xz"]
in Package.Updater
- { detectLatest = latestGitHub ghArguments checkVersion
+ { detectLatest = latestGitHub ghArguments "(php-)8.2.\\d"
, getVersion = downloadWithTemplate template
, is64 = False
}
@@ -122,7 +118,7 @@ autoUpdatable =
:| Package.VersionPlaceholder
: templateTail
in Package.Updater
- { detectLatest = latestGitHub ghArguments stableTagTransform
+ { detectLatest = latestGitHub ghArguments "(v)\\."
, getVersion = reuploadWithTemplate template [RawCommand "go" ["mod", "vendor"]]
, is64 = False
}
@@ -142,7 +138,7 @@ autoUpdatable =
: Package.VersionPlaceholder
: [Package.StaticPlaceholder ".tar.gz"]
in Package.Updater
- { detectLatest = latestGitHub ghArguments stableTagTransform
+ { detectLatest = latestGitHub ghArguments "(v)\\."
, getVersion = reuploadWithTemplate template []
, is64 = False
}
@@ -183,7 +179,7 @@ autoUpdatable =
: Package.VersionPlaceholder
: [Package.StaticPlaceholder ".tar.gz"]
in Package.Updater
- { detectLatest = latestGitHub ghArguments $ Text.stripPrefix "v"
+ { detectLatest = latestGitHub ghArguments "(v)\\."
, getVersion = reuploadWithTemplate template []
, is64 = True
}
@@ -230,18 +226,18 @@ autoUpdatable =
dscannerArguments = PackageOwner{ owner = "dlang-community", name = "D-Scanner" }
dcdArguments = PackageOwner{ owner = "dlang-community", name = "DCD" }
latestDub = Package.Updater
- { detectLatest = latestGitHub dubArguments stableTagTransform
+ { detectLatest = latestGitHub dubArguments "(v)\\."
, getVersion = downloadWithTemplate dubTemplate
, is64 = False
}
latestDscanner = Package.Updater
- { detectLatest = latestGitHub dscannerArguments stableTagTransform
+ { detectLatest = latestGitHub dscannerArguments "(v)\\."
, getVersion = cloneFromGit dscannerURI "v"
, is64 = False
}
dcdURI = [uri|https://github.com/dlang-community/DCD.git|]
latestDcd = Package.Updater
- { detectLatest = latestGitHub dcdArguments stableTagTransform
+ { detectLatest = latestGitHub dcdArguments "(v)\\."
, getVersion = cloneFromGit dcdURI "v"
, is64 = False
}
diff --git a/tests/SlackBuilder/LatestVersionCheckSpec.hs b/tests/SlackBuilder/LatestVersionCheckSpec.hs
index 9abce99..bc4a0f2 100644
--- a/tests/SlackBuilder/LatestVersionCheckSpec.hs
+++ b/tests/SlackBuilder/LatestVersionCheckSpec.hs
@@ -11,30 +11,33 @@ import Test.Hspec (Spec, describe, it, shouldBe)
spec :: Spec
spec = do
- describe "stableTagTransform" $ do
- it "excludes tags with +" $
- let given = "v2.6.0+unreleased"
- actual = stableTagTransform given
- in actual `shouldBe` Nothing
-
- it "recognizes a stable version" $
- let given = "v2.6.0"
- actual = stableTagTransform given
- expected = Just "2.6.0"
- in actual `shouldBe` expected
-
describe "match" $ do
- it "matches an exact tag prefixed with v" $
+ it "matches an exact tag prefixed with v" $
let expected = Just "2.6.0"
actual = match "(v)2.6.0" "v2.6.0"
in actual `shouldBe` expected
- it "matches a glob pattern prefixed with v" $
+ it "matches a glob pattern prefixed with v" $
let expected = Just "2.6.0"
actual = match "(v)*" "v2.6.0"
in actual `shouldBe` expected
- it "ignores suffix after wildcard" $
+ it "matches digits" $
+ let expected = Just "2.6.0"
+ actual = match "(v)2.6.\\d" "v2.6.0"
+ in actual `shouldBe` expected
+
+ it "matches digits and dot" $
let expected = Just "2.6.0"
- actual = match "(v)*(-rc1)" "v2.6.0-rc1"
+ actual = match "(v)\\." "v2.6.0"
+ in actual `shouldBe` expected
+
+ it "rejects unexpected suffix" $
+ let expected = Nothing
+ actual = match "(v)\\." "v2.6.0-rc1"
+ in actual `shouldBe` expected
+
+ it "rejects remaining umatched characters" $
+ let expected = Nothing
+ actual = match "2.6.0-rc1" "2.6.0"
in actual `shouldBe` expected