mirror of
https://github.com/Start9Labs/registry.git
synced 2026-03-26 02:11:53 +00:00
Updates/pkg hardware (#137)
* add ability to specify package architectures for publish script, as well as deindex them * implement and adjust filtering for package hardware requirements; adjust for legacy and new query params paths * augment test manifest and fix ram query * fixes * fix ram for other routes * rework filtering logic to eliminate hack db call * fix hanging issue and other dataset consistency issues * adjust arch param * cleanup * fix package manifest parsing * make index package arches optional * rename from embassy-sdk to start-sdk and embassy-publish to registr-publish * fix ram comparison * increase upload timeout * fix serialization and deserialization of devices jsonb database field * cleanup * another deserialization fix * revert change; better error message and test case * fix jsonb serialization freal * cleanup * fix jsonb deserialization * fix lookup of device value * parse empty device object as null
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -30,6 +30,7 @@ version
|
|||||||
**/*.s9pk
|
**/*.s9pk
|
||||||
**/appmgr
|
**/appmgr
|
||||||
0.3.0_features.md
|
0.3.0_features.md
|
||||||
|
**/start-sdk
|
||||||
**/embassy-sdk
|
**/embassy-sdk
|
||||||
start9-registry.prof
|
start9-registry.prof
|
||||||
start9-registry.hp
|
start9-registry.hp
|
||||||
@@ -40,3 +41,4 @@ shell.nix
|
|||||||
testdata/
|
testdata/
|
||||||
lbuild.sh
|
lbuild.sh
|
||||||
icon
|
icon
|
||||||
|
resources/apps/text-generation-webui
|
||||||
2
Makefile
2
Makefile
@@ -5,4 +5,4 @@ profile:
|
|||||||
cabal:
|
cabal:
|
||||||
cabal build
|
cabal build
|
||||||
# this step is specific for m1 devices ie. aarch64-osx
|
# this step is specific for m1 devices ie. aarch64-osx
|
||||||
sudo cp dist-newstyle/build/aarch64-osx/ghc-9.2.5/start9-registry-0.2.1/x/embassy-publish/build/embassy-publish/embassy-publish /usr/local/bin/
|
sudo cp dist-newstyle/build/aarch64-osx/ghc-9.2.5/start9-registry-0.2.1/x/registry-publish/build/registry-publish/registry-publish /usr/local/bin/
|
||||||
|
|||||||
10
README.md
10
README.md
@@ -23,13 +23,13 @@ cd registry
|
|||||||
```
|
```
|
||||||
- run `make`
|
- run `make`
|
||||||
|
|
||||||
### Set up embassy-publish tool
|
### Set up registry-publish tool
|
||||||
|
|
||||||
- run `apt install libgmp-dev zlib1g-dev libtinfo-dev libpq-dev` (on macOS `brew install libmpd zlib-ng libtiff`)
|
- run `apt install libgmp-dev zlib1g-dev libtinfo-dev libpq-dev` (on macOS `brew install libmpd zlib-ng libtiff`)
|
||||||
- run `stack install` (recommended: include the installation path in your $PATH after running this command)
|
- run `stack install` (recommended: include the installation path in your $PATH after running this command)
|
||||||
- update your shell to include the installation path of the copied executables from `stack install`. i.e. `nano ~./zshrc` add `export PATH=$PATH:/your/path/here` to zshrc; save and exit nano. Run `source ~/.zshrc`
|
- update your shell to include the installation path of the copied executables from `stack install`. i.e. `nano ~./zshrc` add `export PATH=$PATH:/your/path/here` to zshrc; save and exit nano. Run `source ~/.zshrc`
|
||||||
- run `embassy-publish init --bash` (or --zsh / --fish depending on your preferred shell)
|
- run `registry-publish init --bash` (or --zsh / --fish depending on your preferred shell)
|
||||||
- run `embassy-publish reg add -l <URL> -n <NAME> -u <USER> -p <PASS>` (include https:// in your URL)
|
- run `registry-publish reg add -l <URL> -n <NAME> -u <USER> -p <PASS>` (include https:// in your URL)
|
||||||
- take the hash that is emitted by this command and submit it to the registry owner
|
- take the hash that is emitted by this command and submit it to the registry owner
|
||||||
|
|
||||||
### Setting up a registry dev environment
|
### Setting up a registry dev environment
|
||||||
@@ -40,8 +40,8 @@ cd registry
|
|||||||
- set PG_PASSWORD to the password for that user
|
- set PG_PASSWORD to the password for that user
|
||||||
- set SSL_AUTO to false
|
- set SSL_AUTO to false
|
||||||
- set RESOURCES_PATH to an empty directory you wish to use as your package repository
|
- set RESOURCES_PATH to an empty directory you wish to use as your package repository
|
||||||
- install `embassy-sdk`
|
- install `start-sdk`
|
||||||
- set STATIC_BIN to the path that contains `embassy-sdk`
|
- set STATIC_BIN to the path that contains `start-sdk`
|
||||||
|
|
||||||
## APIs
|
## APIs
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ ip-from-header: "_env:YESOD_IP_FROM_HEADER:false"
|
|||||||
# In development, they default to the inverse.
|
# In development, they default to the inverse.
|
||||||
#
|
#
|
||||||
detailed-logging: true
|
detailed-logging: true
|
||||||
# should-log-all: false
|
# should-log-all: true
|
||||||
# reload-templates: false
|
# reload-templates: false
|
||||||
# mutable-static: false
|
# mutable-static: false
|
||||||
# skip-combining: false
|
# skip-combining: false
|
||||||
|
|||||||
2
hie.yaml
2
hie.yaml
@@ -7,4 +7,4 @@ cradle:
|
|||||||
- path: "./test"
|
- path: "./test"
|
||||||
component: "start9-registry:test:start9-registry-test"
|
component: "start9-registry:test:start9-registry-test"
|
||||||
- path: "./cli"
|
- path: "./cli"
|
||||||
component: "start9-registry:exe:embassy-publish"
|
component: "start9-registry:exe:registry-publish"
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ dependencies:
|
|||||||
- monad-logger
|
- monad-logger
|
||||||
- monad-logger-extras
|
- monad-logger-extras
|
||||||
- monad-loops
|
- monad-loops
|
||||||
|
- multimap
|
||||||
- network-uri
|
- network-uri
|
||||||
- optparse-applicative
|
- optparse-applicative
|
||||||
- parallel
|
- parallel
|
||||||
@@ -53,6 +54,8 @@ dependencies:
|
|||||||
- process
|
- process
|
||||||
- protolude
|
- protolude
|
||||||
- rainbow
|
- rainbow
|
||||||
|
- regex-base
|
||||||
|
- regex-tdfa
|
||||||
- shakespeare
|
- shakespeare
|
||||||
- template-haskell
|
- template-haskell
|
||||||
- terminal-progress-bar
|
- terminal-progress-bar
|
||||||
@@ -63,6 +66,7 @@ dependencies:
|
|||||||
- unliftio
|
- unliftio
|
||||||
- unordered-containers
|
- unordered-containers
|
||||||
- unix
|
- unix
|
||||||
|
- utility-ht
|
||||||
- wai
|
- wai
|
||||||
- wai-cors
|
- wai-cors
|
||||||
- wai-extra
|
- wai-extra
|
||||||
@@ -107,7 +111,7 @@ executables:
|
|||||||
when:
|
when:
|
||||||
- condition: flag(library-only)
|
- condition: flag(library-only)
|
||||||
buildable: false
|
buildable: false
|
||||||
embassy-publish:
|
registry-publish:
|
||||||
source-dirs: cli
|
source-dirs: cli
|
||||||
main: Main.hs
|
main: Main.hs
|
||||||
ghc-options:
|
ghc-options:
|
||||||
|
|||||||
@@ -16,6 +16,13 @@
|
|||||||
"build": [
|
"build": [
|
||||||
"make"
|
"make"
|
||||||
],
|
],
|
||||||
|
"hardware-requirements": {
|
||||||
|
"device": {
|
||||||
|
"processor": "intel",
|
||||||
|
"display": "r'^{.*}$'"
|
||||||
|
},
|
||||||
|
"ram": "8"
|
||||||
|
},
|
||||||
"release-notes": "Upgrade to EmbassyOS v0.3.0",
|
"release-notes": "Upgrade to EmbassyOS v0.3.0",
|
||||||
"license": "mit",
|
"license": "mit",
|
||||||
"wrapper-repo": "https://github.com/Start9Labs/lnd-wrapper",
|
"wrapper-repo": "https://github.com/Start9Labs/lnd-wrapper",
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ import Handler.Admin (
|
|||||||
PackageList (..),
|
PackageList (..),
|
||||||
)
|
)
|
||||||
import Lib.External.AppMgr (sourceManifest)
|
import Lib.External.AppMgr (sourceManifest)
|
||||||
import Lib.Types.Core (PkgId (..))
|
import Lib.Types.Core (PkgId (..), OsArch)
|
||||||
import Lib.Types.Emver (Version (..))
|
import Lib.Types.Emver (Version (..))
|
||||||
import Lib.Types.Manifest (PackageManifest (..))
|
import Lib.Types.Manifest (PackageManifest (..))
|
||||||
import Network.HTTP.Client.Conduit (
|
import Network.HTTP.Client.Conduit (
|
||||||
@@ -109,7 +109,6 @@ import Options.Applicative (
|
|||||||
help,
|
help,
|
||||||
helper,
|
helper,
|
||||||
info,
|
info,
|
||||||
liftA3,
|
|
||||||
long,
|
long,
|
||||||
mappend,
|
mappend,
|
||||||
metavar,
|
metavar,
|
||||||
@@ -205,12 +204,16 @@ import Yesod (
|
|||||||
logError,
|
logError,
|
||||||
logWarn,
|
logWarn,
|
||||||
)
|
)
|
||||||
|
import Prelude (read)
|
||||||
|
import Options.Applicative (some)
|
||||||
|
import Control.Applicative.HT (lift4)
|
||||||
|
|
||||||
|
|
||||||
data Upload = Upload
|
data Upload = Upload
|
||||||
{ publishRepoName :: !String
|
{ publishRepoName :: !String
|
||||||
, publishPkg :: !(Maybe FilePath)
|
, publishPkg :: !(Maybe FilePath)
|
||||||
, publishIndex :: !Bool
|
, publishIndex :: !Bool
|
||||||
|
, publishArches :: !(Maybe [OsArch])
|
||||||
}
|
}
|
||||||
deriving (Show)
|
deriving (Show)
|
||||||
|
|
||||||
@@ -253,7 +256,7 @@ data Command
|
|||||||
| CmdRegDel !String
|
| CmdRegDel !String
|
||||||
| CmdRegList
|
| CmdRegList
|
||||||
| CmdUpload !Upload
|
| CmdUpload !Upload
|
||||||
| CmdIndex !String !String !Version !Bool
|
| CmdIndex !String !String !Version !(Maybe [OsArch]) !Bool
|
||||||
| CmdListUnindexed !String
|
| CmdListUnindexed !String
|
||||||
| CmdCatAdd !String !String !(Maybe String) !(Maybe Int)
|
| CmdCatAdd !String !String !(Maybe String) !(Maybe Int)
|
||||||
| CmdCatDel !String !String
|
| CmdCatDel !String !String
|
||||||
@@ -267,7 +270,7 @@ cfgLocation = getHomeDirectory <&> \d -> d </> ".embassy/publish.dhall"
|
|||||||
|
|
||||||
|
|
||||||
parseInit :: Parser (Maybe Shell)
|
parseInit :: Parser (Maybe Shell)
|
||||||
parseInit = subparser $ command "init" (info go $ progDesc "Initializes embassy-publish config") <> metavar "init"
|
parseInit = subparser $ command "init" (info go $ progDesc "Initializes registry-publish config") <> metavar "init"
|
||||||
where
|
where
|
||||||
shells = [Bash, Fish, Zsh]
|
shells = [Bash, Fish, Zsh]
|
||||||
go = headMay . fmap fst . filter snd . zip shells <$> for shells (switch . long . toS . toLower . show)
|
go = headMay . fmap fst . filter snd . zip shells <$> for shells (switch . long . toS . toLower . show)
|
||||||
@@ -281,7 +284,7 @@ parsePublish =
|
|||||||
"upload"
|
"upload"
|
||||||
where
|
where
|
||||||
go =
|
go =
|
||||||
liftA3
|
lift4
|
||||||
Upload
|
Upload
|
||||||
(strOption (short 't' <> long "target" <> metavar "NAME" <> help "Name of registry in publish.dhall"))
|
(strOption (short 't' <> long "target" <> metavar "NAME" <> help "Name of registry in publish.dhall"))
|
||||||
( optional $
|
( optional $
|
||||||
@@ -289,7 +292,17 @@ parsePublish =
|
|||||||
(short 'p' <> long "package" <> metavar "S9PK" <> help "File path of the package to publish")
|
(short 'p' <> long "package" <> metavar "S9PK" <> help "File path of the package to publish")
|
||||||
)
|
)
|
||||||
(switch (short 'i' <> long "index" <> help "Index the package after uploading"))
|
(switch (short 'i' <> long "index" <> help "Index the package after uploading"))
|
||||||
|
( optional $
|
||||||
|
some parseArch
|
||||||
|
)
|
||||||
|
|
||||||
|
parseArch :: Parser OsArch
|
||||||
|
parseArch = read <$> strOption
|
||||||
|
( short 'a'
|
||||||
|
<> long "arches"
|
||||||
|
<> metavar "ARCHES"
|
||||||
|
<> help "Single element of package architectures type. Options include x86_64 and aarch64."
|
||||||
|
)
|
||||||
|
|
||||||
parseRepoAdd :: Parser Command
|
parseRepoAdd :: Parser Command
|
||||||
parseRepoAdd = subparser $ command "add" (info go $ progDesc "Add a registry to your config") <> metavar "add"
|
parseRepoAdd = subparser $ command "add" (info go $ progDesc "Add a registry to your config") <> metavar "add"
|
||||||
@@ -349,6 +362,7 @@ parseIndexHelper b =
|
|||||||
<$> strOption (short 't' <> long "target" <> metavar "REGISTRY_NAME")
|
<$> strOption (short 't' <> long "target" <> metavar "REGISTRY_NAME")
|
||||||
<*> strArgument (metavar "PKG")
|
<*> strArgument (metavar "PKG")
|
||||||
<*> strArgument (metavar "VERSION")
|
<*> strArgument (metavar "VERSION")
|
||||||
|
<*> optional (some parseArch)
|
||||||
<*> pure b
|
<*> pure b
|
||||||
|
|
||||||
|
|
||||||
@@ -430,7 +444,7 @@ cliMain =
|
|||||||
CmdRegDel s -> regRm s
|
CmdRegDel s -> regRm s
|
||||||
CmdRegList -> regLs
|
CmdRegList -> regLs
|
||||||
CmdUpload up -> upload up
|
CmdUpload up -> upload up
|
||||||
CmdIndex name pkg v shouldIndex -> if shouldIndex then index name pkg v else deindex name pkg v
|
CmdIndex name pkg v arches shouldIndex -> if shouldIndex then index name pkg v arches else deindex name pkg v arches
|
||||||
CmdListUnindexed name -> listUnindexed name
|
CmdListUnindexed name -> listUnindexed name
|
||||||
CmdCatAdd target cat desc pri -> catAdd target cat desc pri
|
CmdCatAdd target cat desc pri -> catAdd target cat desc pri
|
||||||
CmdCatDel target cat -> catDel target cat
|
CmdCatDel target cat -> catDel target cat
|
||||||
@@ -447,13 +461,13 @@ init sh = do
|
|||||||
for_ sh $ \case
|
for_ sh $ \case
|
||||||
Bash -> do
|
Bash -> do
|
||||||
let bashrc = home </> ".bashrc"
|
let bashrc = home </> ".bashrc"
|
||||||
appendFile bashrc "source <(embassy-publish --bash-completion-script `which embassy-publish`)\n"
|
appendFile bashrc "source <(registry-publish --bash-completion-script `which registry-publish`)\n"
|
||||||
Fish -> do
|
Fish -> do
|
||||||
let fishrc = home </> ".config" </> "fish" </> "config.fish"
|
let fishrc = home </> ".config" </> "fish" </> "config.fish"
|
||||||
appendFile fishrc "source <(embassy-publish --fish-completion-script `which embassy-publish`)\n"
|
appendFile fishrc "source <(registry-publish --fish-completion-script `which registry-publish`)\n"
|
||||||
Zsh -> do
|
Zsh -> do
|
||||||
let zshcompleter = "/usr/local/share/zsh/site-functions/_embassy-publish"
|
let zshcompleter = "/usr/local/share/zsh/site-functions/_registry-publish"
|
||||||
res <- readProcess "embassy-publish" ["--zsh-completion-script", "`which embassy-publish`"] ""
|
res <- readProcess "registry-publish" ["--zsh-completion-script", "`which registry-publish`"] ""
|
||||||
writeFile zshcompleter (toS res)
|
writeFile zshcompleter (toS res)
|
||||||
|
|
||||||
|
|
||||||
@@ -495,7 +509,7 @@ regLs = do
|
|||||||
|
|
||||||
|
|
||||||
upload :: Upload -> IO ()
|
upload :: Upload -> IO ()
|
||||||
upload (Upload name mpkg shouldIndex) = do
|
upload (Upload name mpkg shouldIndex arches) = do
|
||||||
PublishCfgRepo{..} <- findNameInCfg name
|
PublishCfgRepo{..} <- findNameInCfg name
|
||||||
pkg <- case mpkg of
|
pkg <- case mpkg of
|
||||||
Nothing -> do
|
Nothing -> do
|
||||||
@@ -515,7 +529,7 @@ upload (Upload name mpkg shouldIndex) = do
|
|||||||
noBody <-
|
noBody <-
|
||||||
parseRequest ("POST " <> show publishCfgRepoLocation <> "/admin/v0/upload")
|
parseRequest ("POST " <> show publishCfgRepoLocation <> "/admin/v0/upload")
|
||||||
<&> setRequestHeaders [("accept", "text/plain")]
|
<&> setRequestHeaders [("accept", "text/plain")]
|
||||||
<&> setRequestResponseTimeout (responseTimeoutMicro (600_000_000)) -- 10 minutes
|
<&> setRequestResponseTimeout (responseTimeoutMicro (5_400_000_000)) -- 90 minutes
|
||||||
<&> applyBasicAuth (B8.pack publishCfgRepoUser) (B8.pack publishCfgRepoPass)
|
<&> applyBasicAuth (B8.pack publishCfgRepoUser) (B8.pack publishCfgRepoPass)
|
||||||
size <- getFileSize pkg
|
size <- getFileSize pkg
|
||||||
bar <- newProgressBar defStyle 30 (Progress 0 (fromIntegral size) ())
|
bar <- newProgressBar defStyle 30 (Progress 0 (fromIntegral size) ())
|
||||||
@@ -539,18 +553,18 @@ upload (Upload name mpkg shouldIndex) = do
|
|||||||
exitWith $ ExitFailure 1
|
exitWith $ ExitFailure 1
|
||||||
Right a -> pure a
|
Right a -> pure a
|
||||||
let pkgId = toS $ unPkgId packageManifestId
|
let pkgId = toS $ unPkgId packageManifestId
|
||||||
index name pkgId packageManifestVersion
|
index name pkgId packageManifestVersion arches
|
||||||
putChunkLn $ fromString ("Successfully indexed " <> pkgId <> "@" <> show packageManifestVersion) & fore green
|
putChunkLn $ fromString ("Successfully indexed " <> pkgId <> "@" <> show packageManifestVersion) & fore green
|
||||||
where
|
where
|
||||||
sfs2prog :: StreamFileStatus -> Progress ()
|
sfs2prog :: StreamFileStatus -> Progress ()
|
||||||
sfs2prog StreamFileStatus{..} = Progress (fromIntegral readSoFar) (fromIntegral fileSize) ()
|
sfs2prog StreamFileStatus{..} = Progress (fromIntegral readSoFar) (fromIntegral fileSize) ()
|
||||||
|
|
||||||
index :: String -> String -> Version -> IO ()
|
index :: String -> String -> Version -> (Maybe [OsArch]) -> IO ()
|
||||||
index name pkg v = performHttp name "POST" [i|/admin/v0/index|] (IndexPkgReq (PkgId $ toS pkg) v)
|
index name pkg v arches = performHttp name "POST" [i|/admin/v0/index|] (IndexPkgReq (PkgId $ toS pkg) v arches)
|
||||||
|
|
||||||
|
|
||||||
deindex :: String -> String -> Version -> IO ()
|
deindex :: String -> String -> Version -> (Maybe [OsArch]) -> IO ()
|
||||||
deindex name pkg v = performHttp name "POST" [i|/admin/v0/deindex|] (IndexPkgReq (PkgId $ toS pkg) v)
|
deindex name pkg v arches = performHttp name "POST" [i|/admin/v0/deindex|] (IndexPkgReq (PkgId $ toS pkg) v arches)
|
||||||
|
|
||||||
|
|
||||||
listUnindexed :: String -> IO ()
|
listUnindexed :: String -> IO ()
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import Database.Persist.Sql (
|
|||||||
SqlBackend,
|
SqlBackend,
|
||||||
)
|
)
|
||||||
import Lib.Types.Core (
|
import Lib.Types.Core (
|
||||||
PkgId, OsArch (X86_64, AARCH64_NONFREE),
|
PkgId, OsArch (X86_64, AARCH64),
|
||||||
)
|
)
|
||||||
import Lib.Types.Emver (Version)
|
import Lib.Types.Emver (Version)
|
||||||
import Model (
|
import Model (
|
||||||
@@ -31,7 +31,7 @@ import Startlude (
|
|||||||
getCurrentTime,
|
getCurrentTime,
|
||||||
maybe,
|
maybe,
|
||||||
($),
|
($),
|
||||||
(.), Bool (False),
|
(.), Bool (False), fst, bimap,
|
||||||
)
|
)
|
||||||
import System.FilePath (takeExtension)
|
import System.FilePath (takeExtension)
|
||||||
import UnliftIO (
|
import UnliftIO (
|
||||||
@@ -55,7 +55,6 @@ import Database.Esqueleto.Experimental (
|
|||||||
asc,
|
asc,
|
||||||
desc,
|
desc,
|
||||||
from,
|
from,
|
||||||
groupBy,
|
|
||||||
ilike,
|
ilike,
|
||||||
in_,
|
in_,
|
||||||
innerJoin,
|
innerJoin,
|
||||||
@@ -97,7 +96,7 @@ import Model (
|
|||||||
VersionRecordNumber,
|
VersionRecordNumber,
|
||||||
VersionRecordPkgId,
|
VersionRecordPkgId,
|
||||||
VersionRecordTitle,
|
VersionRecordTitle,
|
||||||
VersionRecordUpdatedAt, PkgRecordHidden
|
VersionRecordUpdatedAt, PkgRecordHidden, VersionPlatformRam
|
||||||
),
|
),
|
||||||
Key (unPkgRecordKey),
|
Key (unPkgRecordKey),
|
||||||
PkgCategory,
|
PkgCategory,
|
||||||
@@ -114,77 +113,52 @@ import Startlude (
|
|||||||
snd,
|
snd,
|
||||||
sortOn,
|
sortOn,
|
||||||
($>),
|
($>),
|
||||||
(<$>),
|
(<$>), Int,
|
||||||
)
|
)
|
||||||
|
import Database.Esqueleto.Experimental (isNothing)
|
||||||
|
import Database.Esqueleto.Experimental ((<=.))
|
||||||
|
|
||||||
serviceQuerySource ::
|
serviceQuerySource ::
|
||||||
(MonadResource m, MonadIO m) =>
|
(MonadResource m, MonadIO m) =>
|
||||||
Maybe Text ->
|
Maybe Text ->
|
||||||
Text ->
|
Text ->
|
||||||
Maybe OsArch ->
|
[OsArch] ->
|
||||||
ConduitT () (Entity VersionRecord) (ReaderT SqlBackend m) ()
|
Maybe Int ->
|
||||||
serviceQuerySource mCat query mOsArch = selectSource $ do
|
ConduitT () (Entity VersionRecord, Entity VersionPlatform) (ReaderT SqlBackend m) ()
|
||||||
case mOsArch of
|
serviceQuerySource mCat query arches mRam = selectSource $ do
|
||||||
Just osArch -> do
|
(service, vp) <- case mCat of
|
||||||
service <- case mCat of
|
|
||||||
Nothing -> do
|
|
||||||
(service :& vp :& pr) <- from $ table @VersionRecord
|
|
||||||
`innerJoin` table @VersionPlatform `on` (\(service :& vp) -> (VersionPlatformPkgId === VersionRecordPkgId) (vp :& service))
|
|
||||||
`innerJoin` table @PkgRecord `on` (\(v :& _ :& p) -> (PkgRecordId === VersionRecordPkgId) (p :& v))
|
|
||||||
where_ (service ^. VersionRecordNumber ==. vp ^. VersionPlatformVersionNumber)
|
|
||||||
where_ (vp ^. VersionPlatformArch ==. val osArch)
|
|
||||||
where_ (pr ^. PkgRecordHidden ==. val False)
|
|
||||||
where_ $ queryInMetadata query service
|
|
||||||
pure service
|
|
||||||
Just category -> do
|
|
||||||
(service :& _ :& cat :& vp :& pr) <-
|
|
||||||
from $
|
|
||||||
table @VersionRecord
|
|
||||||
`innerJoin` table @PkgCategory `on` (VersionRecordPkgId === PkgCategoryPkgId)
|
|
||||||
`innerJoin` table @Category `on` (\(_ :& a :& b) -> (PkgCategoryCategoryId === CategoryId) (a :& b))
|
|
||||||
`innerJoin` table @VersionPlatform `on` (\(service :& _ :& _ :& vp) -> (VersionPlatformPkgId === VersionRecordPkgId) (vp :& service))
|
|
||||||
`innerJoin` table @PkgRecord `on` (\(v :& _ :& _ :& _ :& p) -> (PkgRecordId === VersionRecordPkgId) (p :& v))
|
|
||||||
-- if there is a cateogry, only search in category
|
|
||||||
-- weight title, short, long (bitcoin should equal Bitcoin Core)
|
|
||||||
where_ $ cat ^. CategoryName ==. val category &&. queryInMetadata query service
|
|
||||||
where_ (service ^. VersionRecordNumber ==. vp ^. VersionPlatformVersionNumber)
|
|
||||||
where_ (vp ^. VersionPlatformArch ==. val osArch)
|
|
||||||
where_ (pr ^. PkgRecordHidden ==. val False)
|
|
||||||
pure service
|
|
||||||
groupBy (service ^. VersionRecordPkgId, service ^. VersionRecordNumber)
|
|
||||||
orderBy
|
|
||||||
[ asc (service ^. VersionRecordPkgId)
|
|
||||||
, desc (service ^. VersionRecordNumber)
|
|
||||||
, desc (service ^. VersionRecordUpdatedAt)
|
|
||||||
]
|
|
||||||
pure service
|
|
||||||
Nothing -> do
|
Nothing -> do
|
||||||
service <- case mCat of
|
(service :& vp :& pr) <- from $ table @VersionRecord
|
||||||
Nothing -> do
|
`innerJoin` table @VersionPlatform `on` (\(service :& vp) -> (VersionPlatformPkgId === VersionRecordPkgId) (vp :& service))
|
||||||
(service :& pr) <- from $ table @VersionRecord
|
`innerJoin` table @PkgRecord `on` (\(v :& _ :& p) -> (PkgRecordId === VersionRecordPkgId) (p :& v))
|
||||||
`innerJoin` table @PkgRecord `on` (\(v :& p) -> (PkgRecordId === VersionRecordPkgId) (p :& v))
|
where_ (service ^. VersionRecordNumber ==. vp ^. VersionPlatformVersionNumber)
|
||||||
where_ $ queryInMetadata query service
|
where_ (vp ^. VersionPlatformArch `in_` (valList arches))
|
||||||
where_ (pr ^. PkgRecordHidden ==. val False)
|
where_ (vp ^. VersionPlatformRam <=. val mRam ||. isNothing (vp ^. VersionPlatformRam))
|
||||||
pure service
|
where_ (pr ^. PkgRecordHidden ==. val False)
|
||||||
Just category -> do
|
where_ $ queryInMetadata query service
|
||||||
(service :& _ :& cat :& pr) <-
|
pure (service, vp)
|
||||||
from $
|
Just category -> do
|
||||||
table @VersionRecord
|
(service :& _ :& cat :& vp :& pr) <-
|
||||||
`innerJoin` table @PkgCategory `on` (VersionRecordPkgId === PkgCategoryPkgId)
|
from $
|
||||||
`innerJoin` table @Category `on` (\(_ :& a :& b) -> (PkgCategoryCategoryId === CategoryId) (a :& b))
|
table @VersionRecord
|
||||||
`innerJoin` table @PkgRecord `on` (\(v :& _ :& _ :& p) -> (PkgRecordId === VersionRecordPkgId) (p :& v))
|
`innerJoin` table @PkgCategory `on` (VersionRecordPkgId === PkgCategoryPkgId)
|
||||||
-- if there is a cateogry, only search in category
|
`innerJoin` table @Category `on` (\(_ :& a :& b) -> (PkgCategoryCategoryId === CategoryId) (a :& b))
|
||||||
-- weight title, short, long (bitcoin should equal Bitcoin Core)
|
`innerJoin` table @VersionPlatform `on` (\(service :& _ :& _ :& vp) -> (VersionPlatformPkgId === VersionRecordPkgId) (vp :& service))
|
||||||
where_ $ cat ^. CategoryName ==. val category &&. queryInMetadata query service
|
`innerJoin` table @PkgRecord `on` (\(v :& _ :& _ :& _ :& p) -> (PkgRecordId === VersionRecordPkgId) (p :& v))
|
||||||
where_ (pr ^. PkgRecordHidden ==. val False)
|
-- if there is a cateogry, only search in category
|
||||||
pure service
|
-- weight title, short, long (bitcoin should equal Bitcoin Core)
|
||||||
groupBy (service ^. VersionRecordPkgId, service ^. VersionRecordNumber)
|
where_ $ cat ^. CategoryName ==. val category &&. queryInMetadata query service
|
||||||
orderBy
|
where_ (service ^. VersionRecordNumber ==. vp ^. VersionPlatformVersionNumber)
|
||||||
[ asc (service ^. VersionRecordPkgId)
|
where_ (vp ^. VersionPlatformArch `in_` (valList arches))
|
||||||
, desc (service ^. VersionRecordNumber)
|
where_ (vp ^. VersionPlatformRam <=. val mRam ||. isNothing (vp ^. VersionPlatformRam))
|
||||||
, desc (service ^. VersionRecordUpdatedAt)
|
where_ (pr ^. PkgRecordHidden ==. val False)
|
||||||
]
|
pure (service, vp)
|
||||||
pure service
|
orderBy
|
||||||
|
[ asc (service ^. VersionRecordPkgId)
|
||||||
|
, desc (service ^. VersionRecordNumber)
|
||||||
|
, desc (service ^. VersionRecordUpdatedAt)
|
||||||
|
]
|
||||||
|
pure (service, vp)
|
||||||
|
|
||||||
queryInMetadata :: Text -> SqlExpr (Entity VersionRecord) -> (SqlExpr (Value Bool))
|
queryInMetadata :: Text -> SqlExpr (Entity VersionRecord) -> (SqlExpr (Value Bool))
|
||||||
queryInMetadata query service =
|
queryInMetadata query service =
|
||||||
@@ -193,20 +167,15 @@ queryInMetadata query service =
|
|||||||
||. (service ^. VersionRecordTitle `ilike` (%) ++. val query ++. (%))
|
||. (service ^. VersionRecordTitle `ilike` (%) ++. val query ++. (%))
|
||||||
|
|
||||||
|
|
||||||
getPkgDataSource :: (MonadResource m, MonadIO m) => [PkgId] -> Maybe OsArch -> ConduitT () (Entity VersionRecord) (ReaderT SqlBackend m) ()
|
getPkgDataSource :: (MonadResource m, MonadIO m) => [PkgId] -> [OsArch] -> Maybe Int -> ConduitT () (Entity VersionRecord, Entity VersionPlatform) (ReaderT SqlBackend m) ()
|
||||||
getPkgDataSource pkgs mOsArch = selectSource $ do
|
getPkgDataSource pkgs arches mRam = selectSource $ do
|
||||||
case mOsArch of
|
(pkgData :& vp) <- from $ table @VersionRecord
|
||||||
Just osArch -> do
|
`innerJoin` table @VersionPlatform `on` (\(service :& vp) -> (VersionPlatformPkgId === VersionRecordPkgId) (vp :& service))
|
||||||
(pkgData :& vp) <- from $ table @VersionRecord
|
where_ (pkgData ^. VersionRecordNumber ==. vp ^. VersionPlatformVersionNumber)
|
||||||
`innerJoin` table @VersionPlatform `on` (\(service :& vp) -> (VersionPlatformPkgId === VersionRecordPkgId) (vp :& service))
|
where_ (vp ^. VersionPlatformArch `in_` (valList arches))
|
||||||
where_ (pkgData ^. VersionRecordNumber ==. vp ^. VersionPlatformVersionNumber)
|
where_ (vp ^. VersionPlatformRam <=. val mRam ||. isNothing (vp ^. VersionPlatformRam))
|
||||||
where_ (vp ^. VersionPlatformArch ==. val osArch)
|
where_ (pkgData ^. VersionRecordPkgId `in_` valList (PkgRecordKey <$> pkgs))
|
||||||
where_ (pkgData ^. VersionRecordPkgId `in_` valList (PkgRecordKey <$> pkgs))
|
pure (pkgData, vp)
|
||||||
pure pkgData
|
|
||||||
Nothing -> do
|
|
||||||
pkgData <- from $ table @VersionRecord
|
|
||||||
where_ (pkgData ^. VersionRecordPkgId `in_` valList (PkgRecordKey <$> pkgs))
|
|
||||||
pure pkgData
|
|
||||||
|
|
||||||
|
|
||||||
getPkgDependencyData ::
|
getPkgDependencyData ::
|
||||||
@@ -249,18 +218,18 @@ getCategoriesFor pkg = fmap (fmap entityVal) $
|
|||||||
|
|
||||||
collateVersions ::
|
collateVersions ::
|
||||||
MonadUnliftIO m =>
|
MonadUnliftIO m =>
|
||||||
ConduitT (Entity VersionRecord) (PkgId, [VersionRecord]) (ReaderT SqlBackend m) ()
|
ConduitT (Entity VersionRecord, Entity VersionPlatform) (PkgId, [(VersionRecord, VersionPlatform)]) (ReaderT SqlBackend m) ()
|
||||||
collateVersions = awaitForever $ \v0 -> do
|
collateVersions = awaitForever $ \(v0, vp) -> do
|
||||||
let pkg = unPkgRecordKey . versionRecordPkgId $ entityVal v0
|
let pkg = unPkgRecordKey . versionRecordPkgId $ entityVal v0
|
||||||
let pull = do
|
let pull = do
|
||||||
mvn <- await
|
mvn <- await
|
||||||
case mvn of
|
case mvn of
|
||||||
Nothing -> pure Nothing
|
Nothing -> pure Nothing
|
||||||
Just vn -> do
|
Just vn -> do
|
||||||
let pkg' = unPkgRecordKey . versionRecordPkgId $ entityVal vn
|
let pkg' = unPkgRecordKey . versionRecordPkgId $ entityVal $ fst vn
|
||||||
if pkg == pkg' then pure (Just vn) else leftover vn $> Nothing
|
if pkg == pkg' then pure (Just vn) else leftover vn $> Nothing
|
||||||
ls <- unfoldM pull
|
ls <- unfoldM pull
|
||||||
yield (pkg, fmap entityVal $ v0 : ls)
|
yield (pkg, bimap entityVal entityVal (v0, vp) : fmap (\(v, vp') -> (entityVal v, entityVal vp')) ls)
|
||||||
|
|
||||||
|
|
||||||
getDependencyVersions ::
|
getDependencyVersions ::
|
||||||
@@ -326,17 +295,36 @@ upsertPackageVersion PackageManifest{..} = do
|
|||||||
_res <- try @_ @SomeException $ insertKey pkgId (PkgRecord False now (Just now))
|
_res <- try @_ @SomeException $ insertKey pkgId (PkgRecord False now (Just now))
|
||||||
repsert (VersionRecordKey pkgId packageManifestVersion) ins
|
repsert (VersionRecordKey pkgId packageManifestVersion) ins
|
||||||
|
|
||||||
upsertPackageVersionPlatform :: (MonadUnliftIO m) => PackageManifest -> ReaderT SqlBackend m ()
|
upsertPackageVersionPlatform :: (MonadUnliftIO m) => (Maybe [OsArch]) -> PackageManifest -> ReaderT SqlBackend m ()
|
||||||
upsertPackageVersionPlatform PackageManifest{..} = do
|
upsertPackageVersionPlatform maybeArches PackageManifest{..} = do
|
||||||
now <- liftIO getCurrentTime
|
now <- liftIO getCurrentTime
|
||||||
let pkgId = PkgRecordKey packageManifestId
|
let pkgId = PkgRecordKey packageManifestId
|
||||||
let arches = [X86_64 .. AARCH64_NONFREE]
|
let arches = case packageHardwareArch of
|
||||||
let records = createVersionPlatformRecord now pkgId packageManifestVersion <$> arches
|
Just a -> a
|
||||||
|
Nothing -> case maybeArches of
|
||||||
|
Just a -> a
|
||||||
|
Nothing -> [X86_64, AARCH64]
|
||||||
|
let records = createVersionPlatformRecord now pkgId packageManifestVersion packageHardwareRam packageHardwareDevice <$> arches
|
||||||
repsertMany records
|
repsertMany records
|
||||||
where
|
where
|
||||||
createVersionPlatformRecord time id version arch = ((VersionPlatformKey id version arch), VersionPlatform
|
createVersionPlatformRecord time id version ram device arch = ((VersionPlatformKey id version arch), VersionPlatform
|
||||||
time
|
time
|
||||||
(Just time)
|
(Just time)
|
||||||
id
|
id
|
||||||
version
|
version
|
||||||
|
ram
|
||||||
|
device
|
||||||
arch)
|
arch)
|
||||||
|
|
||||||
|
getVersionPlatform ::
|
||||||
|
(Monad m, MonadIO m) =>
|
||||||
|
PkgRecordId ->
|
||||||
|
[OsArch] ->
|
||||||
|
ReaderT SqlBackend m [VersionPlatform]
|
||||||
|
getVersionPlatform pkgId arches = do
|
||||||
|
vps <- select $ do
|
||||||
|
v <- from $ table @VersionPlatform
|
||||||
|
where_ $ v ^. VersionPlatformPkgId ==. val pkgId
|
||||||
|
where_ (v ^. VersionPlatformArch `in_` (valList arches))
|
||||||
|
pure v
|
||||||
|
pure $ entityVal <$> vps
|
||||||
@@ -46,7 +46,7 @@ import Database.Persist (
|
|||||||
entityVal,
|
entityVal,
|
||||||
insert_,
|
insert_,
|
||||||
selectList,
|
selectList,
|
||||||
(=.),
|
(=.), PersistQueryWrite (deleteWhere),
|
||||||
)
|
)
|
||||||
import Database.Persist.Postgresql (runSqlPoolNoTransaction)
|
import Database.Persist.Postgresql (runSqlPoolNoTransaction)
|
||||||
import Database.Queries (upsertPackageVersion, upsertPackageVersionPlatform)
|
import Database.Queries (upsertPackageVersion, upsertPackageVersionPlatform)
|
||||||
@@ -67,12 +67,12 @@ import Lib.PkgRepository (
|
|||||||
getPackages,
|
getPackages,
|
||||||
getVersionsFor,
|
getVersionsFor,
|
||||||
)
|
)
|
||||||
import Lib.Types.Core (PkgId (unPkgId))
|
import Lib.Types.Core (PkgId (unPkgId), OsArch)
|
||||||
import Lib.Types.Emver (Version (..))
|
import Lib.Types.Emver (Version (..))
|
||||||
import Lib.Types.Manifest (PackageManifest (..))
|
import Lib.Types.Manifest (PackageManifest (..))
|
||||||
import Model (
|
import Model (
|
||||||
Category (..),
|
Category (..),
|
||||||
EntityField (EosHashHash),
|
EntityField (EosHashHash, VersionPlatformArch, VersionPlatformVersionNumber, VersionPlatformPkgId),
|
||||||
EosHash (EosHash),
|
EosHash (EosHash),
|
||||||
Key (AdminKey, PkgRecordKey, VersionRecordKey),
|
Key (AdminKey, PkgRecordKey, VersionRecordKey),
|
||||||
PkgCategory (PkgCategory),
|
PkgCategory (PkgCategory),
|
||||||
@@ -119,7 +119,7 @@ import Startlude (
|
|||||||
(>),
|
(>),
|
||||||
(&&),
|
(&&),
|
||||||
(||),
|
(||),
|
||||||
(<=)
|
(<=),
|
||||||
)
|
)
|
||||||
import System.FilePath (
|
import System.FilePath (
|
||||||
(<.>),
|
(<.>),
|
||||||
@@ -149,6 +149,7 @@ import Yesod.Auth (YesodAuth (maybeAuthId))
|
|||||||
import Yesod.Core.Types (JSONResponse (JSONResponse))
|
import Yesod.Core.Types (JSONResponse (JSONResponse))
|
||||||
import Database.Persist.Sql (runSqlPool)
|
import Database.Persist.Sql (runSqlPool)
|
||||||
import Data.List (elem, length)
|
import Data.List (elem, length)
|
||||||
|
import Database.Persist ((==.))
|
||||||
|
|
||||||
postPkgUploadR :: Handler ()
|
postPkgUploadR :: Handler ()
|
||||||
postPkgUploadR = do
|
postPkgUploadR = do
|
||||||
@@ -213,12 +214,14 @@ postEosUploadR = do
|
|||||||
data IndexPkgReq = IndexPkgReq
|
data IndexPkgReq = IndexPkgReq
|
||||||
{ indexPkgReqId :: !PkgId
|
{ indexPkgReqId :: !PkgId
|
||||||
, indexPkgReqVersion :: !Version
|
, indexPkgReqVersion :: !Version
|
||||||
|
, indexPkgReqArches :: !(Maybe [OsArch])
|
||||||
}
|
}
|
||||||
deriving (Eq, Show)
|
deriving (Eq, Show)
|
||||||
instance FromJSON IndexPkgReq where
|
instance FromJSON IndexPkgReq where
|
||||||
parseJSON = withObject "Index Package Request" $ \o -> do
|
parseJSON = withObject "Index Package Request" $ \o -> do
|
||||||
indexPkgReqId <- o .: "id"
|
indexPkgReqId <- o .: "id"
|
||||||
indexPkgReqVersion <- o .: "version"
|
indexPkgReqVersion <- o .: "version"
|
||||||
|
indexPkgReqArches <- o .:? "arches"
|
||||||
pure IndexPkgReq{..}
|
pure IndexPkgReq{..}
|
||||||
instance ToJSON IndexPkgReq where
|
instance ToJSON IndexPkgReq where
|
||||||
toJSON IndexPkgReq{..} = object ["id" .= indexPkgReqId, "version" .= indexPkgReqVersion]
|
toJSON IndexPkgReq{..} = object ["id" .= indexPkgReqId, "version" .= indexPkgReqVersion]
|
||||||
@@ -232,15 +235,22 @@ postPkgIndexR = do
|
|||||||
liftIO (decodeFileStrict manifest)
|
liftIO (decodeFileStrict manifest)
|
||||||
`orThrow` sendResponseText
|
`orThrow` sendResponseText
|
||||||
status404
|
status404
|
||||||
[i|Could not locate manifest for #{indexPkgReqId}@#{indexPkgReqVersion}|]
|
[i|Could not decode manifest for #{indexPkgReqId}@#{indexPkgReqVersion}|]
|
||||||
pool <- getsYesod appConnPool
|
pool <- getsYesod appConnPool
|
||||||
runSqlPoolNoTransaction (upsertPackageVersion man) pool Nothing
|
runSqlPoolNoTransaction (upsertPackageVersion man) pool Nothing
|
||||||
runSqlPool (upsertPackageVersionPlatform man) pool
|
runSqlPool (upsertPackageVersionPlatform indexPkgReqArches man) pool
|
||||||
|
|
||||||
postPkgDeindexR :: Handler ()
|
postPkgDeindexR :: Handler ()
|
||||||
postPkgDeindexR = do
|
postPkgDeindexR = do
|
||||||
IndexPkgReq{..} <- requireCheckJsonBody
|
IndexPkgReq{..} <- requireCheckJsonBody
|
||||||
runDB $ delete (VersionRecordKey (PkgRecordKey indexPkgReqId) indexPkgReqVersion)
|
case indexPkgReqArches of
|
||||||
|
Nothing -> runDB $ delete (VersionRecordKey (PkgRecordKey indexPkgReqId) indexPkgReqVersion)
|
||||||
|
Just a -> do
|
||||||
|
_ <- traverse (deleteArch indexPkgReqId indexPkgReqVersion) a
|
||||||
|
pure ()
|
||||||
|
where
|
||||||
|
deleteArch :: PkgId -> Version -> OsArch -> Handler ()
|
||||||
|
deleteArch id v a = runDB $ deleteWhere [VersionPlatformArch ==. a, VersionPlatformVersionNumber ==. v, VersionPlatformPkgId ==. PkgRecordKey id]
|
||||||
|
|
||||||
|
|
||||||
newtype PackageList = PackageList {unPackageList :: HashMap PkgId [Version]}
|
newtype PackageList = PackageList {unPackageList :: HashMap PkgId [Version]}
|
||||||
|
|||||||
@@ -19,8 +19,8 @@ import Database.Esqueleto.Experimental (
|
|||||||
)
|
)
|
||||||
import Foundation (Handler)
|
import Foundation (Handler)
|
||||||
import Handler.Package.V0.ReleaseNotes (ReleaseNotes (..))
|
import Handler.Package.V0.ReleaseNotes (ReleaseNotes (..))
|
||||||
import Handler.Util (queryParamAs, getArchQuery)
|
import Handler.Util (getOsArch, getOsVersion)
|
||||||
import Lib.Types.Emver (Version (unVersion), Version(Version), parseVersion)
|
import Lib.Types.Emver (Version (unVersion), Version(Version))
|
||||||
import Model (EntityField (..), OsVersion (..))
|
import Model (EntityField (..), OsVersion (..))
|
||||||
import Orphans.Emver ()
|
import Orphans.Emver ()
|
||||||
import Startlude (Down (..), Eq, Generic, Maybe (..), Ord ((<)), Text, filter, fst, head, pure, sortOn, ($), (&&&), (.), (<$>), (<&>), (<=))
|
import Startlude (Down (..), Eq, Generic, Maybe (..), Ord ((<)), Text, filter, fst, head, pure, sortOn, ($), (&&&), (.), (<$>), (<&>), (<=))
|
||||||
@@ -48,9 +48,9 @@ instance ToTypedContent EosRes where
|
|||||||
|
|
||||||
getEosVersionR :: Handler (JSONResponse (Maybe EosRes))
|
getEosVersionR :: Handler (JSONResponse (Maybe EosRes))
|
||||||
getEosVersionR = do
|
getEosVersionR = do
|
||||||
currentEosVersion <- fromMaybe Version { unVersion = (0,3,0,0) } <$> queryParamAs "eos-version" parseVersion
|
currentEosVersion <- fromMaybe Version { unVersion = (0,3,0,0) } <$> getOsVersion
|
||||||
-- defaults to raspberrypi for those on OS versions where we did not send this param yet
|
-- defaults to raspberrypi for those on OS versions where we did not send this param yet
|
||||||
arch <- fromMaybe RASPBERRYPI <$> getArchQuery
|
arch <- fromMaybe RASPBERRYPI <$> getOsArch
|
||||||
allEosVersions <- runDB $
|
allEosVersions <- runDB $
|
||||||
select $ do
|
select $ do
|
||||||
vers <- from $ table @OsVersion
|
vers <- from $ table @OsVersion
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import Data.String.Interpolate.IsString (
|
|||||||
i,
|
i,
|
||||||
)
|
)
|
||||||
import Foundation (Handler)
|
import Foundation (Handler)
|
||||||
import Handler.Package.V1.Index (getOsVersionQuery)
|
import Handler.Package.V1.Index (getOsVersionCompat)
|
||||||
import Handler.Util (
|
import Handler.Util (
|
||||||
fetchCompatiblePkgVersions,
|
fetchCompatiblePkgVersions,
|
||||||
getVersionSpecFromQuery,
|
getVersionSpecFromQuery,
|
||||||
@@ -40,7 +40,7 @@ import Yesod (
|
|||||||
|
|
||||||
getIconsR :: PkgId -> Handler TypedContent
|
getIconsR :: PkgId -> Handler TypedContent
|
||||||
getIconsR pkg = do
|
getIconsR pkg = do
|
||||||
osVersion <- getOsVersionQuery
|
osVersion <- getOsVersionCompat
|
||||||
osCompatibleVersions <- fetchCompatiblePkgVersions osVersion pkg
|
osCompatibleVersions <- fetchCompatiblePkgVersions osVersion pkg
|
||||||
spec <- getVersionSpecFromQuery
|
spec <- getVersionSpecFromQuery
|
||||||
preferMin <- versionPriorityFromQueryIsMin
|
preferMin <- versionPriorityFromQueryIsMin
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import Data.String.Interpolate.IsString (
|
|||||||
i,
|
i,
|
||||||
)
|
)
|
||||||
import Foundation (Handler)
|
import Foundation (Handler)
|
||||||
import Handler.Package.V1.Index (getOsVersionQuery)
|
import Handler.Package.V1.Index (getOsVersionCompat)
|
||||||
import Handler.Util (
|
import Handler.Util (
|
||||||
fetchCompatiblePkgVersions,
|
fetchCompatiblePkgVersions,
|
||||||
getVersionSpecFromQuery,
|
getVersionSpecFromQuery,
|
||||||
@@ -42,7 +42,7 @@ import Yesod (
|
|||||||
getInstructionsR :: PkgId -> Handler TypedContent
|
getInstructionsR :: PkgId -> Handler TypedContent
|
||||||
getInstructionsR pkg = do
|
getInstructionsR pkg = do
|
||||||
spec <- getVersionSpecFromQuery
|
spec <- getVersionSpecFromQuery
|
||||||
osVersion <- getOsVersionQuery
|
osVersion <- getOsVersionCompat
|
||||||
osCompatibleVersions <- fetchCompatiblePkgVersions osVersion pkg
|
osCompatibleVersions <- fetchCompatiblePkgVersions osVersion pkg
|
||||||
preferMin <- versionPriorityFromQueryIsMin
|
preferMin <- versionPriorityFromQueryIsMin
|
||||||
version <-
|
version <-
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
module Handler.Package.V0.Latest where
|
module Handler.Package.V0.Latest where
|
||||||
|
|
||||||
import Conduit (concatMapC, mapC, runConduit, sinkList, (.|))
|
import Conduit (concatMapC, mapC, runConduit, sinkList, (.|), mapMC)
|
||||||
import Data.Aeson (ToJSON (..), eitherDecode)
|
import Data.Aeson (ToJSON (..), eitherDecode)
|
||||||
import Data.ByteString.Lazy qualified as LBS
|
import Data.ByteString.Lazy qualified as LBS
|
||||||
import Data.HashMap.Strict (HashMap)
|
import Data.HashMap.Strict (HashMap)
|
||||||
@@ -10,15 +10,15 @@ import Data.List.NonEmpty.Extra qualified as NE
|
|||||||
import Data.Tuple.Extra (second)
|
import Data.Tuple.Extra (second)
|
||||||
import Database.Queries (collateVersions, getPkgDataSource)
|
import Database.Queries (collateVersions, getPkgDataSource)
|
||||||
import Foundation (Handler, RegistryCtx (appSettings))
|
import Foundation (Handler, RegistryCtx (appSettings))
|
||||||
import Handler.Package.V1.Index (getOsVersionQuery)
|
import Handler.Package.V1.Index (getOsVersionCompat, getRamQuery, getHardwareDevicesQuery)
|
||||||
import Lib.Error (S9Error (..))
|
import Lib.Error (S9Error (..))
|
||||||
import Lib.Types.Core (PkgId)
|
import Lib.Types.Core (PkgId)
|
||||||
import Lib.Types.Emver (Version (..), satisfies)
|
import Lib.Types.Emver (Version (..), satisfies)
|
||||||
import Model (VersionRecord (..))
|
import Model (VersionRecord (..))
|
||||||
import Network.HTTP.Types (status400)
|
import Network.HTTP.Types (status400)
|
||||||
import Startlude (Bool (True), Down (Down), Either (..), Generic, Maybe (..), NonEmpty, Show, const, encodeUtf8, filter, flip, nonEmpty, pure, ($), (.), (<$>), (<&>))
|
import Startlude (Bool (True), Down (Down), Either (..), Generic, Maybe (..), NonEmpty, Show, const, encodeUtf8, filter, flip, nonEmpty, pure, ($), (.), (<$>), (<&>), fst)
|
||||||
import Yesod (ToContent (..), ToTypedContent (..), YesodPersist (runDB), YesodRequest (reqGetParams), getRequest, sendResponseStatus)
|
import Yesod (ToContent (..), ToTypedContent (..), YesodPersist (runDB), YesodRequest (reqGetParams), getRequest, sendResponseStatus)
|
||||||
import Handler.Util (getArchQuery, filterDeprecatedVersions)
|
import Handler.Util (filterDeprecatedVersions, getPkgArch, filterDevices)
|
||||||
import Yesod.Core (getsYesod)
|
import Yesod.Core (getsYesod)
|
||||||
import Settings (AppSettings(communityVersion))
|
import Settings (AppSettings(communityVersion))
|
||||||
|
|
||||||
@@ -36,10 +36,12 @@ getVersionLatestR :: Handler VersionLatestRes
|
|||||||
getVersionLatestR = do
|
getVersionLatestR = do
|
||||||
getParameters <- reqGetParams <$> getRequest
|
getParameters <- reqGetParams <$> getRequest
|
||||||
osPredicate' <-
|
osPredicate' <-
|
||||||
getOsVersionQuery <&> \case
|
getOsVersionCompat <&> \case
|
||||||
Nothing -> const True
|
Nothing -> const True
|
||||||
Just v -> flip satisfies v
|
Just v -> flip satisfies v
|
||||||
osArch <- getArchQuery
|
pkgArch <- getPkgArch
|
||||||
|
ram <- getRamQuery
|
||||||
|
hardwareDevices <- getHardwareDevicesQuery
|
||||||
communityServiceDeprecationVersion <- getsYesod $ communityVersion . appSettings
|
communityServiceDeprecationVersion <- getsYesod $ communityVersion . appSettings
|
||||||
do
|
do
|
||||||
case lookup "ids" getParameters of
|
case lookup "ids" getParameters of
|
||||||
@@ -48,7 +50,7 @@ getVersionLatestR = do
|
|||||||
Left _ -> sendResponseStatus status400 (InvalidParamsE "get:ids" packages)
|
Left _ -> sendResponseStatus status400 (InvalidParamsE "get:ids" packages)
|
||||||
Right p -> do
|
Right p -> do
|
||||||
let packageList = (,Nothing) <$> p
|
let packageList = (,Nothing) <$> p
|
||||||
let source = getPkgDataSource p osArch
|
let source = getPkgDataSource p pkgArch ram
|
||||||
filteredPackages <-
|
filteredPackages <-
|
||||||
runDB $
|
runDB $
|
||||||
runConduit $
|
runConduit $
|
||||||
@@ -56,7 +58,12 @@ getVersionLatestR = do
|
|||||||
-- group conduit pipeline by pkg id
|
-- group conduit pipeline by pkg id
|
||||||
.| collateVersions
|
.| collateVersions
|
||||||
-- filter out versions of apps that are incompatible with the OS predicate
|
-- filter out versions of apps that are incompatible with the OS predicate
|
||||||
.| mapC (second (filter (osPredicate' . versionRecordOsVersion)))
|
.| mapC (second (filter (osPredicate' . versionRecordOsVersion . fst)))
|
||||||
|
-- filter hardware device compatability
|
||||||
|
.| mapMC (\(b,c) -> do
|
||||||
|
l <- filterDevices hardwareDevices c
|
||||||
|
pure (b, l)
|
||||||
|
)
|
||||||
-- filter out deprecated service versions after community registry release
|
-- filter out deprecated service versions after community registry release
|
||||||
.| mapC (second (filterDeprecatedVersions communityServiceDeprecationVersion osPredicate'))
|
.| mapC (second (filterDeprecatedVersions communityServiceDeprecationVersion osPredicate'))
|
||||||
-- prune empty version sets
|
-- prune empty version sets
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import Data.String.Interpolate.IsString (
|
|||||||
i,
|
i,
|
||||||
)
|
)
|
||||||
import Foundation (Handler)
|
import Foundation (Handler)
|
||||||
import Handler.Package.V1.Index (getOsVersionQuery)
|
import Handler.Package.V1.Index (getOsVersionCompat)
|
||||||
import Handler.Util (
|
import Handler.Util (
|
||||||
fetchCompatiblePkgVersions,
|
fetchCompatiblePkgVersions,
|
||||||
getVersionSpecFromQuery,
|
getVersionSpecFromQuery,
|
||||||
@@ -41,7 +41,7 @@ import Yesod (
|
|||||||
|
|
||||||
getLicenseR :: PkgId -> Handler TypedContent
|
getLicenseR :: PkgId -> Handler TypedContent
|
||||||
getLicenseR pkg = do
|
getLicenseR pkg = do
|
||||||
osVersion <- getOsVersionQuery
|
osVersion <- getOsVersionCompat
|
||||||
osCompatibleVersions <- fetchCompatiblePkgVersions osVersion pkg
|
osCompatibleVersions <- fetchCompatiblePkgVersions osVersion pkg
|
||||||
spec <- getVersionSpecFromQuery
|
spec <- getVersionSpecFromQuery
|
||||||
preferMin <- versionPriorityFromQueryIsMin
|
preferMin <- versionPriorityFromQueryIsMin
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import Data.String.Interpolate.IsString (
|
|||||||
i,
|
i,
|
||||||
)
|
)
|
||||||
import Foundation (Handler)
|
import Foundation (Handler)
|
||||||
import Handler.Package.V1.Index (getOsVersionQuery)
|
import Handler.Package.V1.Index (getOsVersionCompat)
|
||||||
import Handler.Util (
|
import Handler.Util (
|
||||||
addPackageHeader,
|
addPackageHeader,
|
||||||
fetchCompatiblePkgVersions,
|
fetchCompatiblePkgVersions,
|
||||||
@@ -42,7 +42,7 @@ import Yesod (
|
|||||||
|
|
||||||
getAppManifestR :: PkgId -> Handler TypedContent
|
getAppManifestR :: PkgId -> Handler TypedContent
|
||||||
getAppManifestR pkg = do
|
getAppManifestR pkg = do
|
||||||
osVersion <- getOsVersionQuery
|
osVersion <- getOsVersionCompat
|
||||||
osCompatibleVersions <- fetchCompatiblePkgVersions osVersion pkg
|
osCompatibleVersions <- fetchCompatiblePkgVersions osVersion pkg
|
||||||
versionSpec <- getVersionSpecFromQuery
|
versionSpec <- getVersionSpecFromQuery
|
||||||
preferMin <- versionPriorityFromQueryIsMin
|
preferMin <- versionPriorityFromQueryIsMin
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import Data.Aeson.Key (fromText)
|
|||||||
import Data.HashMap.Strict (HashMap)
|
import Data.HashMap.Strict (HashMap)
|
||||||
import Data.HashMap.Strict qualified as HM
|
import Data.HashMap.Strict qualified as HM
|
||||||
import Foundation (Handler)
|
import Foundation (Handler)
|
||||||
import Handler.Package.V1.Index (getOsVersionQuery)
|
import Handler.Package.V1.Index (getOsVersionCompat)
|
||||||
import Handler.Util (fetchCompatiblePkgVersions)
|
import Handler.Util (fetchCompatiblePkgVersions)
|
||||||
import Lib.Types.Core (PkgId)
|
import Lib.Types.Core (PkgId)
|
||||||
import Lib.Types.Emver (Version)
|
import Lib.Types.Emver (Version)
|
||||||
@@ -49,7 +49,7 @@ instance ToTypedContent ReleaseNotes where
|
|||||||
|
|
||||||
getReleaseNotesR :: PkgId -> Handler ReleaseNotes
|
getReleaseNotesR :: PkgId -> Handler ReleaseNotes
|
||||||
getReleaseNotesR pkg = do
|
getReleaseNotesR pkg = do
|
||||||
osVersion <- getOsVersionQuery
|
osVersion <- getOsVersionCompat
|
||||||
osCompatibleVersions <- fetchCompatiblePkgVersions osVersion pkg
|
osCompatibleVersions <- fetchCompatiblePkgVersions osVersion pkg
|
||||||
pure $ constructReleaseNotesApiRes osCompatibleVersions
|
pure $ constructReleaseNotesApiRes osCompatibleVersions
|
||||||
where
|
where
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import Database.Queries (
|
|||||||
)
|
)
|
||||||
import Foundation (Handler)
|
import Foundation (Handler)
|
||||||
import GHC.Show (show)
|
import GHC.Show (show)
|
||||||
import Handler.Package.V1.Index (getOsVersionQuery)
|
import Handler.Package.V1.Index (getOsVersionCompat)
|
||||||
import Handler.Util (
|
import Handler.Util (
|
||||||
addPackageHeader,
|
addPackageHeader,
|
||||||
fetchCompatiblePkgVersions,
|
fetchCompatiblePkgVersions,
|
||||||
@@ -79,7 +79,7 @@ getAppR file = do
|
|||||||
Nothing -> sendResponseStatus status416 ("Range Not Satisfiable" :: Text)
|
Nothing -> sendResponseStatus status416 ("Range Not Satisfiable" :: Text)
|
||||||
Just ranges -> pure $ Just ranges
|
Just ranges -> pure $ Just ranges
|
||||||
let pkg = PkgId . T.pack $ takeBaseName (show file)
|
let pkg = PkgId . T.pack $ takeBaseName (show file)
|
||||||
osVersion <- getOsVersionQuery
|
osVersion <- getOsVersionCompat
|
||||||
osCompatibleVersions <- fetchCompatiblePkgVersions osVersion pkg
|
osCompatibleVersions <- fetchCompatiblePkgVersions osVersion pkg
|
||||||
versionSpec <- getVersionSpecFromQuery
|
versionSpec <- getVersionSpecFromQuery
|
||||||
preferMin <- versionPriorityFromQueryIsMin
|
preferMin <- versionPriorityFromQueryIsMin
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import Data.String.Interpolate.IsString (
|
|||||||
i,
|
i,
|
||||||
)
|
)
|
||||||
import Foundation (Handler)
|
import Foundation (Handler)
|
||||||
import Handler.Package.V1.Index (getOsVersionQuery)
|
import Handler.Package.V1.Index (getOsVersionCompat)
|
||||||
import Handler.Util (
|
import Handler.Util (
|
||||||
fetchCompatiblePkgVersions,
|
fetchCompatiblePkgVersions,
|
||||||
getVersionSpecFromQuery,
|
getVersionSpecFromQuery,
|
||||||
@@ -61,7 +61,7 @@ instance ToTypedContent (Maybe AppVersionRes) where
|
|||||||
|
|
||||||
getPkgVersionR :: PkgId -> Handler AppVersionRes
|
getPkgVersionR :: PkgId -> Handler AppVersionRes
|
||||||
getPkgVersionR pkg = do
|
getPkgVersionR pkg = do
|
||||||
osVersion <- getOsVersionQuery
|
osVersion <- getOsVersionCompat
|
||||||
osCompatibleVersions <- fetchCompatiblePkgVersions osVersion pkg
|
osCompatibleVersions <- fetchCompatiblePkgVersions osVersion pkg
|
||||||
spec <- getVersionSpecFromQuery
|
spec <- getVersionSpecFromQuery
|
||||||
preferMin <- versionPriorityFromQueryIsMin
|
preferMin <- versionPriorityFromQueryIsMin
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import Data.HashMap.Strict qualified as HM
|
|||||||
import Data.List (lookup)
|
import Data.List (lookup)
|
||||||
import Data.List.NonEmpty qualified as NE
|
import Data.List.NonEmpty qualified as NE
|
||||||
import Data.Text qualified as T
|
import Data.Text qualified as T
|
||||||
|
import qualified Data.MultiMap as MM
|
||||||
import Database.Persist.Sql (SqlBackend)
|
import Database.Persist.Sql (SqlBackend)
|
||||||
import Database.Queries (
|
import Database.Queries (
|
||||||
collateVersions,
|
collateVersions,
|
||||||
@@ -28,7 +29,7 @@ import Database.Queries (
|
|||||||
import Foundation (Handler, Route (InstructionsR, LicenseR), RegistryCtx (appSettings))
|
import Foundation (Handler, Route (InstructionsR, LicenseR), RegistryCtx (appSettings))
|
||||||
import Handler.Package.Api (DependencyRes (..), PackageListRes (..), PackageRes (..))
|
import Handler.Package.Api (DependencyRes (..), PackageListRes (..), PackageRes (..))
|
||||||
import Handler.Types.Api (ApiVersion (..))
|
import Handler.Types.Api (ApiVersion (..))
|
||||||
import Handler.Util (basicRender, parseQueryParam, getArchQuery, filterDeprecatedVersions)
|
import Handler.Util (basicRender, parseQueryParam, filterDeprecatedVersions, filterDevices, getPkgArch)
|
||||||
import Lib.PkgRepository (PkgRepo, getIcon, getManifest)
|
import Lib.PkgRepository (PkgRepo, getIcon, getManifest)
|
||||||
import Lib.Types.Core (PkgId)
|
import Lib.Types.Core (PkgId)
|
||||||
import Lib.Types.Emver (Version, VersionRange (..), parseRange, satisfies, (<||))
|
import Lib.Types.Emver (Version, VersionRange (..), parseRange, satisfies, (<||))
|
||||||
@@ -90,6 +91,10 @@ import Data.Tuple (fst)
|
|||||||
import Database.Persist.Postgresql (entityVal)
|
import Database.Persist.Postgresql (entityVal)
|
||||||
import Yesod.Core (getsYesod)
|
import Yesod.Core (getsYesod)
|
||||||
import Data.List (head)
|
import Data.List (head)
|
||||||
|
import Yesod (YesodRequest(reqGetParams))
|
||||||
|
import Yesod (getRequest)
|
||||||
|
import Data.List (last)
|
||||||
|
import Data.Text (isPrefixOf)
|
||||||
|
|
||||||
data PackageReq = PackageReq
|
data PackageReq = PackageReq
|
||||||
{ packageReqId :: !PkgId
|
{ packageReqId :: !PkgId
|
||||||
@@ -115,46 +120,52 @@ data PackageMetadata = PackageMetadata
|
|||||||
getPackageIndexR :: Handler PackageListRes
|
getPackageIndexR :: Handler PackageListRes
|
||||||
getPackageIndexR = do
|
getPackageIndexR = do
|
||||||
osPredicate <-
|
osPredicate <-
|
||||||
getOsVersionQuery <&> \case
|
getOsVersionCompat <&> \case
|
||||||
Nothing -> const True
|
Nothing -> const True
|
||||||
Just v -> flip satisfies v
|
Just v -> flip satisfies v
|
||||||
osArch <- getArchQuery
|
pkgArch <- getPkgArch
|
||||||
|
ram <- getRamQuery
|
||||||
|
hardwareDevices <- getHardwareDevicesQuery
|
||||||
communityVersion <- getsYesod $ communityVersion . appSettings
|
communityVersion <- getsYesod $ communityVersion . appSettings
|
||||||
do
|
pkgIds <- getPkgIdsQuery
|
||||||
pkgIds <- getPkgIdsQuery
|
category <- getCategoryQuery
|
||||||
category <- getCategoryQuery
|
page <- fromMaybe 1 <$> getPageQuery
|
||||||
page <- fromMaybe 1 <$> getPageQuery
|
limit' <- fromMaybe 20 <$> getLimitQuery
|
||||||
limit' <- fromMaybe 20 <$> getLimitQuery
|
query <- T.strip . fromMaybe "" <$> lookupGetParam "query"
|
||||||
query <- T.strip . fromMaybe "" <$> lookupGetParam "query"
|
let (source, packageRanges) = case pkgIds of
|
||||||
let (source, packageRanges) = case pkgIds of
|
Nothing -> (serviceQuerySource category query pkgArch ram, const Any)
|
||||||
Nothing -> (serviceQuerySource category query osArch, const Any)
|
Just packages ->
|
||||||
Just packages ->
|
let s = getPkgDataSource (packageReqId <$> packages) pkgArch ram
|
||||||
let s = getPkgDataSource (packageReqId <$> packages) osArch
|
r = fromMaybe None . (flip lookup $ (packageReqId &&& packageReqVersion) <$> packages)
|
||||||
r = fromMaybe None . (flip lookup $ (packageReqId &&& packageReqVersion) <$> packages)
|
in (s, r)
|
||||||
in (s, r)
|
filteredPackages <-
|
||||||
filteredPackages <-
|
runDB $
|
||||||
runDB $
|
runConduit $
|
||||||
runConduit $
|
source
|
||||||
source
|
-- group conduit pipeline by pkg id
|
||||||
-- group conduit pipeline by pkg id
|
.| collateVersions
|
||||||
.| collateVersions
|
-- filter out versions of apps that are incompatible with the OS predicate
|
||||||
-- filter out versions of apps that are incompatible with the OS predicate
|
.| mapC (second (filter (osPredicate . versionRecordOsVersion . fst)))
|
||||||
.| mapC (second (filter (osPredicate . versionRecordOsVersion)))
|
-- filter hardware device compatability
|
||||||
-- filter out deprecated service versions after community registry release
|
.| mapMC (\(b,c) -> do
|
||||||
.| mapC (second (filterDeprecatedVersions communityVersion osPredicate))
|
l <- filterDevices hardwareDevices c
|
||||||
-- prune empty version sets
|
pure (b, l)
|
||||||
.| concatMapC (\(pkgId, vs) -> (pkgId,) <$> nonEmpty vs)
|
)
|
||||||
-- grab the latest matching version if it exists
|
-- filter out deprecated service versions after community registry release
|
||||||
.| concatMapC (\(a, b) -> (a,b,) <$> (selectLatestVersionFromSpec packageRanges b))
|
.| mapC (second (filterDeprecatedVersions communityVersion osPredicate))
|
||||||
-- construct
|
-- prune empty version sets
|
||||||
.| mapMC (\(a, b, c) -> PackageMetadata a b (versionRecordNumber c) <$> getCategoriesFor a)
|
.| concatMapC (\(pkgId, vs) -> (pkgId,) <$> nonEmpty vs)
|
||||||
-- pages start at 1 for some reason. TODO: make pages start at 0
|
-- grab the latest matching version if it exists
|
||||||
.| (dropC (limit' * (page - 1)) *> takeC limit')
|
.| concatMapC (\(a, b) -> (a,b,) <$> (selectLatestVersionFromSpec packageRanges b))
|
||||||
.| sinkList
|
-- construct
|
||||||
|
.| mapMC (\(a, b, c) -> PackageMetadata a b (versionRecordNumber c) <$> getCategoriesFor a)
|
||||||
|
-- pages start at 1 for some reason. TODO: make pages start at 0
|
||||||
|
.| (dropC (limit' * (page - 1)) *> takeC limit')
|
||||||
|
.| sinkList
|
||||||
|
|
||||||
-- NOTE: if a package's dependencies do not meet the system requirements, it is currently omitted from the list
|
-- NOTE: if a package's dependencies do not meet the system requirements, it is currently omitted from the list
|
||||||
pkgsWithDependencies <- runDB $ mapConcurrently (getPackageDependencies osPredicate) filteredPackages
|
pkgsWithDependencies <- runDB $ mapConcurrently (getPackageDependencies osPredicate) filteredPackages
|
||||||
PackageListRes <$> runConcurrently (zipWithM (Concurrently .* constructPackageListApiRes) filteredPackages pkgsWithDependencies)
|
PackageListRes <$> runConcurrently (zipWithM (Concurrently .* constructPackageListApiRes) filteredPackages pkgsWithDependencies)
|
||||||
|
|
||||||
getPkgIdsQuery :: Handler (Maybe [PackageReq])
|
getPkgIdsQuery :: Handler (Maybe [PackageReq])
|
||||||
getPkgIdsQuery = parseQueryParam "ids" (first toS . eitherDecodeStrict . encodeUtf8)
|
getPkgIdsQuery = parseQueryParam "ids" (first toS . eitherDecodeStrict . encodeUtf8)
|
||||||
@@ -172,9 +183,29 @@ getLimitQuery :: Handler (Maybe Int)
|
|||||||
getLimitQuery = parseQueryParam "per-page" ((flip $ note . mappend "Invalid 'per-page': ") =<< readMaybe)
|
getLimitQuery = parseQueryParam "per-page" ((flip $ note . mappend "Invalid 'per-page': ") =<< readMaybe)
|
||||||
|
|
||||||
|
|
||||||
getOsVersionQuery :: Handler (Maybe VersionRange)
|
getOsVersionCompatQueryLegacy :: Handler (Maybe VersionRange)
|
||||||
getOsVersionQuery = parseQueryParam "eos-version-compat" (first toS . Atto.parseOnly parseRange)
|
getOsVersionCompatQueryLegacy = parseQueryParam "eos-version-compat" (first toS . Atto.parseOnly parseRange)
|
||||||
|
|
||||||
|
getOsVersionCompatQuery :: Handler (Maybe VersionRange)
|
||||||
|
getOsVersionCompatQuery = parseQueryParam "os.compat" (first toS . Atto.parseOnly parseRange)
|
||||||
|
|
||||||
|
getOsVersionCompat :: Handler (Maybe VersionRange)
|
||||||
|
getOsVersionCompat = do
|
||||||
|
osVersion <- getOsVersionCompatQuery >>= \case
|
||||||
|
Just a -> pure $ Just a
|
||||||
|
Nothing -> getOsVersionCompatQueryLegacy
|
||||||
|
pure osVersion
|
||||||
|
|
||||||
|
getHardwareDevicesQuery :: Handler (MM.MultiMap Text Text)
|
||||||
|
getHardwareDevicesQuery = do
|
||||||
|
allParams <- reqGetParams <$> getRequest
|
||||||
|
-- [("hardware.device.processor","intel"),("hardware.device.display","led")]
|
||||||
|
let hardwareDeviceParams = filter (\(key, _) -> "hardware.device" `isPrefixOf` key) allParams
|
||||||
|
-- [("processor","intel"),("display","led")]
|
||||||
|
pure $ MM.fromList $ first (last . T.splitOn ".") <$> hardwareDeviceParams
|
||||||
|
|
||||||
|
getRamQuery :: Handler (Maybe Int)
|
||||||
|
getRamQuery = parseQueryParam "hardware.ram" ((flip $ note . mappend "Invalid 'ram': ") =<< readMaybe)
|
||||||
|
|
||||||
getPackageDependencies ::
|
getPackageDependencies ::
|
||||||
(MonadIO m, MonadLogger m, MonadResource m, Has PkgRepo r, MonadReader r m) =>
|
(MonadIO m, MonadLogger m, MonadResource m, Has PkgRepo r, MonadReader r m) =>
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
{-# LANGUAGE QuasiQuotes #-}
|
{-# LANGUAGE QuasiQuotes #-}
|
||||||
{-# LANGUAGE TemplateHaskell #-}
|
{-# LANGUAGE TemplateHaskell #-}
|
||||||
|
{-# OPTIONS_GHC -Wno-unused-imports #-}
|
||||||
|
|
||||||
module Handler.Util where
|
module Handler.Util where
|
||||||
|
|
||||||
@@ -17,13 +18,13 @@ import Data.String.Interpolate.IsString (
|
|||||||
import Data.Text qualified as T
|
import Data.Text qualified as T
|
||||||
import Data.Text.Lazy qualified as TL
|
import Data.Text.Lazy qualified as TL
|
||||||
import Data.Text.Lazy.Builder qualified as TB
|
import Data.Text.Lazy.Builder qualified as TB
|
||||||
import Database.Queries (fetchAllPkgVersions)
|
import Database.Queries (fetchAllPkgVersions, getVersionPlatform)
|
||||||
import Foundation
|
import Foundation
|
||||||
import Lib.PkgRepository (
|
import Lib.PkgRepository (
|
||||||
PkgRepo,
|
PkgRepo,
|
||||||
getHash,
|
getHash,
|
||||||
)
|
)
|
||||||
import Lib.Types.Core (PkgId, OsArch)
|
import Lib.Types.Core (PkgId, OsArch (..))
|
||||||
import Lib.Types.Emver (
|
import Lib.Types.Emver (
|
||||||
Version,
|
Version,
|
||||||
VersionRange,
|
VersionRange,
|
||||||
@@ -31,7 +32,7 @@ import Lib.Types.Emver (
|
|||||||
)
|
)
|
||||||
import Model (
|
import Model (
|
||||||
UserActivity (..),
|
UserActivity (..),
|
||||||
VersionRecord (versionRecordOsVersion, versionRecordDeprecatedAt),
|
VersionRecord (versionRecordOsVersion, versionRecordDeprecatedAt, versionRecordPkgId), VersionPlatform (versionPlatformDevice),
|
||||||
)
|
)
|
||||||
import Network.HTTP.Types (
|
import Network.HTTP.Types (
|
||||||
Status,
|
Status,
|
||||||
@@ -61,7 +62,7 @@ import Startlude (
|
|||||||
($),
|
($),
|
||||||
(.),
|
(.),
|
||||||
(<$>),
|
(<$>),
|
||||||
(>>=), note, (=<<)
|
(>>=), note, (=<<), catMaybes, all, encodeUtf8, toS, fmap, traceM, show, trace, any, or, (++), IO, putStrLn, map
|
||||||
)
|
)
|
||||||
import UnliftIO (MonadUnliftIO)
|
import UnliftIO (MonadUnliftIO)
|
||||||
import Yesod (
|
import Yesod (
|
||||||
@@ -80,6 +81,13 @@ import Yesod (
|
|||||||
import Yesod.Core (addHeader, logWarn)
|
import Yesod.Core (addHeader, logWarn)
|
||||||
import Lib.Error (S9Error (..))
|
import Lib.Error (S9Error (..))
|
||||||
import Data.Maybe (isJust)
|
import Data.Maybe (isJust)
|
||||||
|
import qualified Data.HashMap.Strict as HM
|
||||||
|
import Lib.Types.Manifest
|
||||||
|
import Text.Regex.TDFA ((=~))
|
||||||
|
import Data.Aeson (eitherDecodeStrict)
|
||||||
|
import Data.Bifunctor (Bifunctor(first))
|
||||||
|
import qualified Data.MultiMap as MM
|
||||||
|
import Startlude (bimap)
|
||||||
|
|
||||||
orThrow :: MonadHandler m => m (Maybe a) -> m a -> m a
|
orThrow :: MonadHandler m => m (Maybe a) -> m a -> m a
|
||||||
orThrow action other =
|
orThrow action other =
|
||||||
@@ -158,7 +166,7 @@ tickleMAU = do
|
|||||||
Nothing -> pure ()
|
Nothing -> pure ()
|
||||||
Just sid -> do
|
Just sid -> do
|
||||||
currentEosVersion <- queryParamAs "eos-version" parseVersion
|
currentEosVersion <- queryParamAs "eos-version" parseVersion
|
||||||
arch <- getArchQuery
|
arch <- getOsArch
|
||||||
now <- liftIO getCurrentTime
|
now <- liftIO getCurrentTime
|
||||||
void $ liftHandler $ runDB $ insertRecord $ UserActivity now sid currentEosVersion arch
|
void $ liftHandler $ runDB $ insertRecord $ UserActivity now sid currentEosVersion arch
|
||||||
|
|
||||||
@@ -174,11 +182,74 @@ fetchCompatiblePkgVersions osVersion pkg = do
|
|||||||
Nothing -> const True
|
Nothing -> const True
|
||||||
Just v -> flip satisfies v
|
Just v -> flip satisfies v
|
||||||
|
|
||||||
getArchQuery :: Handler (Maybe OsArch)
|
getOsArchQueryLegacy :: Handler (Maybe OsArch)
|
||||||
getArchQuery = parseQueryParam "arch" ((flip $ note . mappend "Invalid 'arch': ") =<< readMaybe)
|
getOsArchQueryLegacy = parseQueryParam "arch" ((flip $ note . mappend "Invalid 'arch': ") =<< readMaybe)
|
||||||
|
|
||||||
|
getOsArchQuery :: Handler (Maybe OsArch)
|
||||||
|
getOsArchQuery = parseQueryParam "os.arch" ((flip $ note . mappend "Invalid 'arch': ") =<< readMaybe)
|
||||||
|
|
||||||
|
getOsArch :: Handler (Maybe OsArch)
|
||||||
|
getOsArch = do
|
||||||
|
osArch <- getOsArchQuery >>= \case
|
||||||
|
Just a -> pure $ Just a
|
||||||
|
Nothing -> getOsArchQueryLegacy
|
||||||
|
pure osArch
|
||||||
|
|
||||||
|
getOsVersionLegacy :: Handler (Maybe Version)
|
||||||
|
getOsVersionLegacy = parseQueryParam "eos-version" ((flip $ note . mappend "Invalid 'eos-version': ") =<< readMaybe)
|
||||||
|
|
||||||
|
getOsVersionQuery :: Handler (Maybe Version)
|
||||||
|
getOsVersionQuery = parseQueryParam "os.version" ((flip $ note . mappend "Invalid 'os.version': ") =<< readMaybe)
|
||||||
|
|
||||||
|
getOsVersion :: Handler (Maybe Version)
|
||||||
|
getOsVersion = do
|
||||||
|
osVersion <- getOsVersionQuery >>= \case
|
||||||
|
Just a -> pure $ Just a
|
||||||
|
Nothing -> getOsVersionLegacy
|
||||||
|
pure osVersion
|
||||||
|
|
||||||
|
getPkgArch :: Handler [OsArch]
|
||||||
|
getPkgArch = do
|
||||||
|
arch <- parseQueryParam "hardware.arch" ((flip $ note . mappend "Invalid 'hardware.arch': ") =<< readMaybe)
|
||||||
|
case arch of
|
||||||
|
Just a -> pure [a]
|
||||||
|
Nothing -> do
|
||||||
|
getOsArch >>= \case
|
||||||
|
Just a -> pure [matchLegacyArch a]
|
||||||
|
Nothing -> pure [X86_64, AARCH64]
|
||||||
|
where
|
||||||
|
matchLegacyArch X86_64 = X86_64
|
||||||
|
matchLegacyArch AARCH64 = AARCH64
|
||||||
|
matchLegacyArch RASPBERRYPI = AARCH64
|
||||||
|
matchLegacyArch X86_64_NONFREE = X86_64
|
||||||
|
matchLegacyArch AARCH64_NONFREE = AARCH64
|
||||||
|
|
||||||
filterDeprecatedVersions :: Version -> (Version -> Bool) -> [VersionRecord] -> [VersionRecord]
|
filterDeprecatedVersions :: Version -> (Version -> Bool) -> [VersionRecord] -> [VersionRecord]
|
||||||
filterDeprecatedVersions communityVersion osPredicate vrs = do
|
filterDeprecatedVersions communityVersion osPredicate vrs = do
|
||||||
if (osPredicate communityVersion)
|
if (osPredicate communityVersion)
|
||||||
then filter (\v -> not $ isJust $ versionRecordDeprecatedAt v) $ vrs
|
then filter (\v -> not $ isJust $ versionRecordDeprecatedAt v) $ vrs
|
||||||
else vrs
|
else vrs
|
||||||
|
|
||||||
|
filterDevices :: (MonadUnliftIO m) => (MM.MultiMap Text Text) -> [(VersionRecord, VersionPlatform)] -> m [VersionRecord]
|
||||||
|
filterDevices hardwareDevices pkgRecords = do
|
||||||
|
pure $ catMaybes $ fmap (compareHd hardwareDevices) pkgRecords
|
||||||
|
where
|
||||||
|
compareHd :: MM.MultiMap Text Text -> (VersionRecord, VersionPlatform) -> Maybe VersionRecord
|
||||||
|
compareHd hd (vr, vp) = case versionPlatformDevice vp of
|
||||||
|
Nothing -> do
|
||||||
|
Just vr
|
||||||
|
Just d -> if areRegexMatchesEqual hd d
|
||||||
|
then Just vr
|
||||||
|
else Nothing
|
||||||
|
|
||||||
|
regexMatch :: RegexPattern -> Text -> Bool
|
||||||
|
regexMatch (RegexPattern pattern) text = text =~ pattern
|
||||||
|
|
||||||
|
areRegexMatchesEqual :: MM.MultiMap Text Text -> PackageDevice -> Bool
|
||||||
|
areRegexMatchesEqual textMap (PackageDevice regexMap) =
|
||||||
|
any checkMatch (HM.toList regexMap)
|
||||||
|
where
|
||||||
|
checkMatch :: (Text, RegexPattern) -> Bool
|
||||||
|
checkMatch (key, regexPattern) =
|
||||||
|
case MM.lookup key textMap of
|
||||||
|
val -> or $ regexMatch regexPattern <$> val
|
||||||
20
src/Lib/External/AppMgr.hs
vendored
20
src/Lib/External/AppMgr.hs
vendored
@@ -105,23 +105,23 @@ sourceManifest ::
|
|||||||
(ConduitT () ByteString m () -> m r) ->
|
(ConduitT () ByteString m () -> m r) ->
|
||||||
m r
|
m r
|
||||||
sourceManifest appmgrPath pkgFile sink = do
|
sourceManifest appmgrPath pkgFile sink = do
|
||||||
let appmgr = readProcessInheritStderr (appmgrPath </> "embassy-sdk") ["inspect", "manifest", pkgFile] ""
|
let appmgr = readProcessInheritStderr (appmgrPath </> "start-sdk") ["inspect", "manifest", pkgFile] ""
|
||||||
appmgr sink `catch` \ece ->
|
appmgr sink `catch` \ece ->
|
||||||
$logErrorSH ece *> throwIO (AppMgrE [i|embassy-sdk inspect manifest #{pkgFile}|] (eceExitCode ece))
|
$logErrorSH ece *> throwIO (AppMgrE [i|start-sdk inspect manifest #{pkgFile}|] (eceExitCode ece))
|
||||||
|
|
||||||
|
|
||||||
sourceIcon :: (MonadUnliftIO m, MonadLoggerIO m) => FilePath -> FilePath -> (ConduitT () ByteString m () -> m r) -> m r
|
sourceIcon :: (MonadUnliftIO m, MonadLoggerIO m) => FilePath -> FilePath -> (ConduitT () ByteString m () -> m r) -> m r
|
||||||
sourceIcon appmgrPath pkgFile sink = do
|
sourceIcon appmgrPath pkgFile sink = do
|
||||||
let appmgr = readProcessInheritStderr (appmgrPath </> "embassy-sdk") ["inspect", "icon", pkgFile] ""
|
let appmgr = readProcessInheritStderr (appmgrPath </> "start-sdk") ["inspect", "icon", pkgFile] ""
|
||||||
appmgr sink `catch` \ece ->
|
appmgr sink `catch` \ece ->
|
||||||
$logErrorSH ece *> throwIO (AppMgrE [i|embassy-sdk inspect icon #{pkgFile}|] (eceExitCode ece))
|
$logErrorSH ece *> throwIO (AppMgrE [i|start-sdk inspect icon #{pkgFile}|] (eceExitCode ece))
|
||||||
|
|
||||||
|
|
||||||
getPackageHash :: (MonadUnliftIO m, MonadLoggerIO m) => FilePath -> FilePath -> m ByteString
|
getPackageHash :: (MonadUnliftIO m, MonadLoggerIO m) => FilePath -> FilePath -> m ByteString
|
||||||
getPackageHash appmgrPath pkgFile = do
|
getPackageHash appmgrPath pkgFile = do
|
||||||
let appmgr = readProcessInheritStderr (appmgrPath </> "embassy-sdk") ["inspect", "hash", pkgFile] ""
|
let appmgr = readProcessInheritStderr (appmgrPath </> "start-sdk") ["inspect", "hash", pkgFile] ""
|
||||||
appmgr (\bsSource -> runConduit $ bsSource .| CL.foldMap id) `catch` \ece ->
|
appmgr (\bsSource -> runConduit $ bsSource .| CL.foldMap id) `catch` \ece ->
|
||||||
$logErrorSH ece *> throwIO (AppMgrE [i|embassy-sdk inspect hash #{pkgFile}|] (eceExitCode ece))
|
$logErrorSH ece *> throwIO (AppMgrE [i|start-sdk inspect hash #{pkgFile}|] (eceExitCode ece))
|
||||||
|
|
||||||
|
|
||||||
sourceInstructions ::
|
sourceInstructions ::
|
||||||
@@ -131,9 +131,9 @@ sourceInstructions ::
|
|||||||
(ConduitT () ByteString m () -> m r) ->
|
(ConduitT () ByteString m () -> m r) ->
|
||||||
m r
|
m r
|
||||||
sourceInstructions appmgrPath pkgFile sink = do
|
sourceInstructions appmgrPath pkgFile sink = do
|
||||||
let appmgr = readProcessInheritStderr (appmgrPath </> "embassy-sdk") ["inspect", "instructions", pkgFile] ""
|
let appmgr = readProcessInheritStderr (appmgrPath </> "start-sdk") ["inspect", "instructions", pkgFile] ""
|
||||||
appmgr sink `catch` \ece ->
|
appmgr sink `catch` \ece ->
|
||||||
$logErrorSH ece *> throwIO (AppMgrE [i|embassy-sdk inspect instructions #{pkgFile}|] (eceExitCode ece))
|
$logErrorSH ece *> throwIO (AppMgrE [i|start-sdk inspect instructions #{pkgFile}|] (eceExitCode ece))
|
||||||
|
|
||||||
|
|
||||||
sourceLicense ::
|
sourceLicense ::
|
||||||
@@ -143,6 +143,6 @@ sourceLicense ::
|
|||||||
(ConduitT () ByteString m () -> m r) ->
|
(ConduitT () ByteString m () -> m r) ->
|
||||||
m r
|
m r
|
||||||
sourceLicense appmgrPath pkgFile sink = do
|
sourceLicense appmgrPath pkgFile sink = do
|
||||||
let appmgr = readProcessInheritStderr (appmgrPath </> "embassy-sdk") ["inspect", "license", pkgFile] ""
|
let appmgr = readProcessInheritStderr (appmgrPath </> "start-sdk") ["inspect", "license", pkgFile] ""
|
||||||
appmgr sink `catch` \ece ->
|
appmgr sink `catch` \ece ->
|
||||||
$logErrorSH ece *> throwIO (AppMgrE [i|embassy-sdk inspect license #{pkgFile}|] (eceExitCode ece))
|
$logErrorSH ece *> throwIO (AppMgrE [i|start-sdk inspect license #{pkgFile}|] (eceExitCode ece))
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ import Startlude (
|
|||||||
show,
|
show,
|
||||||
symbolVal,
|
symbolVal,
|
||||||
($),
|
($),
|
||||||
(.), Enum,
|
(.), Enum, Applicative (..),
|
||||||
)
|
)
|
||||||
|
|
||||||
import Data.Aeson (
|
import Data.Aeson (
|
||||||
@@ -57,8 +57,8 @@ import Web.HttpApiData (
|
|||||||
ToHttpApiData,
|
ToHttpApiData,
|
||||||
)
|
)
|
||||||
import Yesod (PathPiece (..))
|
import Yesod (PathPiece (..))
|
||||||
import Prelude (read)
|
import Prelude (read, fail)
|
||||||
|
import Data.Aeson.Types (withText)
|
||||||
|
|
||||||
newtype PkgId = PkgId {unPkgId :: Text}
|
newtype PkgId = PkgId {unPkgId :: Text}
|
||||||
deriving stock (Eq, Ord)
|
deriving stock (Eq, Ord)
|
||||||
@@ -112,7 +112,14 @@ instance PersistField OsArch where
|
|||||||
instance PersistFieldSql OsArch where
|
instance PersistFieldSql OsArch where
|
||||||
sqlType _ = SqlString
|
sqlType _ = SqlString
|
||||||
instance FromJSON OsArch where
|
instance FromJSON OsArch where
|
||||||
parseJSON = parseJSON
|
parseJSON = withText "OsArch" $ \case
|
||||||
|
"x86_64" -> pure X86_64
|
||||||
|
"aarch64" -> pure AARCH64
|
||||||
|
"raspberrypi" -> pure RASPBERRYPI
|
||||||
|
"rasberrypi" -> pure RASPBERRYPI
|
||||||
|
"x86_64-nonfree" -> pure X86_64_NONFREE
|
||||||
|
"arch64-nonfree"-> pure AARCH64_NONFREE
|
||||||
|
_ -> fail "Invalid OsArch value"
|
||||||
instance ToJSON OsArch where
|
instance ToJSON OsArch where
|
||||||
toJSON = toJSON
|
toJSON = toJSON
|
||||||
|
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ import Startlude ( ($)
|
|||||||
)
|
)
|
||||||
|
|
||||||
import Control.Monad.Fail ( fail )
|
import Control.Monad.Fail ( fail )
|
||||||
import Data.Aeson ( ToJSONKey )
|
import Data.Aeson ( ToJSONKey, toJSON, Value(String))
|
||||||
import qualified Data.Attoparsec.Text as Atto
|
import qualified Data.Attoparsec.Text as Atto
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
import GHC.Base ( error )
|
import GHC.Base ( error )
|
||||||
@@ -81,9 +81,13 @@ import qualified GHC.Read as GHC
|
|||||||
( readsPrec )
|
( readsPrec )
|
||||||
import qualified GHC.Show as GHC
|
import qualified GHC.Show as GHC
|
||||||
( show )
|
( show )
|
||||||
|
import Dhall (Generic)
|
||||||
|
import Data.Aeson.Types (ToJSON)
|
||||||
|
|
||||||
-- | AppVersion is the core representation of the SemverQuad type.
|
-- | AppVersion is the core representation of the SemverQuad type.
|
||||||
newtype Version = Version { unVersion :: (Word, Word, Word, Word) } deriving (Eq, Ord, ToJSONKey, Hashable)
|
newtype Version = Version { unVersion :: (Word, Word, Word, Word) } deriving (Eq, Ord, Generic, ToJSONKey, Hashable)
|
||||||
|
instance ToJSON Version where
|
||||||
|
toJSON = String . show
|
||||||
instance Show Version where
|
instance Show Version where
|
||||||
show (Version (x, y, z, q)) =
|
show (Version (x, y, z, q)) =
|
||||||
let postfix = if q == 0 then "" else '.' : GHC.show q
|
let postfix = if q == 0 then "" else '.' : GHC.show q
|
||||||
|
|||||||
@@ -5,14 +5,30 @@
|
|||||||
module Lib.Types.Manifest where
|
module Lib.Types.Manifest where
|
||||||
|
|
||||||
import Control.Monad.Fail (MonadFail (..))
|
import Control.Monad.Fail (MonadFail (..))
|
||||||
import Data.Aeson (FromJSON (..), withObject, (.:), (.:?))
|
|
||||||
import Data.HashMap.Internal.Strict (HashMap)
|
import Data.HashMap.Internal.Strict (HashMap)
|
||||||
import Data.HashMap.Strict qualified as HM
|
import Data.HashMap.Strict qualified as HM
|
||||||
import Data.String.Interpolate.IsString (i)
|
import Data.String.Interpolate.IsString (i)
|
||||||
import Data.Text qualified as T
|
import Data.Text qualified as T
|
||||||
import Lib.Types.Core (PkgId)
|
import Lib.Types.Core (PkgId, OsArch)
|
||||||
import Lib.Types.Emver (Version (..), VersionRange)
|
import Lib.Types.Emver (Version (..), VersionRange)
|
||||||
import Startlude (ByteString, Eq, Generic, Hashable, Maybe (..), Monad ((>>=)), Read, Show, Text, for, pure, readMaybe, ($))
|
import Startlude (ByteString, Eq, Generic, Hashable, Maybe (..), Monad ((>>=)), Read, Show, Text, for, pure, readMaybe, ($), Int, (.), fmap, String, null, (<$>), otherwise)
|
||||||
|
import Data.Aeson
|
||||||
|
( eitherDecodeStrict,
|
||||||
|
(.:),
|
||||||
|
(.:?),
|
||||||
|
withObject,
|
||||||
|
withText,
|
||||||
|
FromJSON(parseJSON),
|
||||||
|
ToJSON(toJSON), encode )
|
||||||
|
import Database.Persist.Sql ( PersistFieldSql(..) )
|
||||||
|
import Database.Persist.Types (SqlType(..))
|
||||||
|
import Database.Persist (PersistValue(..))
|
||||||
|
import Data.Either (Either(..))
|
||||||
|
import Database.Persist.Class ( PersistField(..) )
|
||||||
|
import Data.Maybe (maybe)
|
||||||
|
import qualified Data.ByteString as BS
|
||||||
|
import Yesod.Persist (LiteralType(Escaped))
|
||||||
|
import Data.Aeson.Types (Value(Object), Parser)
|
||||||
|
|
||||||
|
|
||||||
data PackageManifest = PackageManifest
|
data PackageManifest = PackageManifest
|
||||||
@@ -26,6 +42,9 @@ data PackageManifest = PackageManifest
|
|||||||
, packageManifestAlerts :: !(HashMap ServiceAlert (Maybe Text))
|
, packageManifestAlerts :: !(HashMap ServiceAlert (Maybe Text))
|
||||||
, packageManifestDependencies :: !(HashMap PkgId PackageDependency)
|
, packageManifestDependencies :: !(HashMap PkgId PackageDependency)
|
||||||
, packageManifestEosVersion :: !Version
|
, packageManifestEosVersion :: !Version
|
||||||
|
, packageHardwareDevice :: !(Maybe PackageDevice)
|
||||||
|
, packageHardwareRam :: !(Maybe Int)
|
||||||
|
, packageHardwareArch :: !(Maybe [OsArch])
|
||||||
}
|
}
|
||||||
deriving (Show)
|
deriving (Show)
|
||||||
instance FromJSON PackageManifest where
|
instance FromJSON PackageManifest where
|
||||||
@@ -47,8 +66,16 @@ instance FromJSON PackageManifest where
|
|||||||
let packageManifestAlerts = HM.fromList a
|
let packageManifestAlerts = HM.fromList a
|
||||||
packageManifestDependencies <- o .: "dependencies"
|
packageManifestDependencies <- o .: "dependencies"
|
||||||
packageManifestEosVersion <- o .: "eos-version"
|
packageManifestEosVersion <- o .: "eos-version"
|
||||||
|
packageHardwareDevice <- o .:? "hardware-requirements" >>= maybe (pure Nothing) (.:? "devices") >>= parsePackageDevice
|
||||||
|
packageHardwareRam <- o .:? "hardware-requirements" >>= maybe (pure Nothing) (.:? "ram")
|
||||||
|
packageHardwareArch <- o .:? "hardware-requirements" >>= maybe (pure Nothing) (.:? "arch")
|
||||||
pure PackageManifest{..}
|
pure PackageManifest{..}
|
||||||
|
|
||||||
|
parsePackageDevice :: Maybe Value -> Parser (Maybe PackageDevice)
|
||||||
|
parsePackageDevice (Just (Object o))
|
||||||
|
| null o = pure Nothing
|
||||||
|
| otherwise = Just . PackageDevice <$> parseJSON (Object o)
|
||||||
|
parsePackageDevice _ = pure Nothing
|
||||||
|
|
||||||
data PackageDependency = PackageDependency
|
data PackageDependency = PackageDependency
|
||||||
{ packageDependencyOptional :: !(Maybe Text)
|
{ packageDependencyOptional :: !(Maybe Text)
|
||||||
@@ -63,22 +90,57 @@ instance FromJSON PackageDependency where
|
|||||||
packageDependencyDescription <- o .:? "description"
|
packageDependencyDescription <- o .:? "description"
|
||||||
pure PackageDependency{..}
|
pure PackageDependency{..}
|
||||||
|
|
||||||
|
-- Custom type for regex pattern
|
||||||
|
newtype RegexPattern = RegexPattern Text
|
||||||
|
deriving (Show, Eq, Generic)
|
||||||
|
|
||||||
|
instance FromJSON RegexPattern where
|
||||||
|
parseJSON = withText "RegexPattern" (pure . RegexPattern)
|
||||||
|
instance ToJSON RegexPattern where
|
||||||
|
toJSON (RegexPattern txt) = toJSON txt
|
||||||
|
|
||||||
|
newtype PackageDevice = PackageDevice { unPackageDevice :: HashMap Text RegexPattern }
|
||||||
|
deriving (Show, Eq, Generic)
|
||||||
|
|
||||||
|
instance FromJSON PackageDevice where
|
||||||
|
parseJSON = fmap PackageDevice . parseJSON
|
||||||
|
instance ToJSON PackageDevice where
|
||||||
|
toJSON = toJSON . unPackageDevice
|
||||||
|
|
||||||
|
instance PersistField PackageDevice where
|
||||||
|
toPersistValue = PersistLiteral_ Escaped . BS.toStrict . encode
|
||||||
|
fromPersistValue (PersistByteString t) = case eitherDecodeStrict t of
|
||||||
|
Left err -> Left $ T.pack err
|
||||||
|
Right val -> Right val
|
||||||
|
fromPersistValue _ = Left "Invalid JSON value in database ERR"
|
||||||
|
|
||||||
|
instance PersistFieldSql PackageDevice where
|
||||||
|
sqlType _ = SqlOther "JSONB"
|
||||||
data ServiceAlert = INSTALL | UNINSTALL | RESTORE | START | STOP
|
data ServiceAlert = INSTALL | UNINSTALL | RESTORE | START | STOP
|
||||||
deriving (Show, Eq, Generic, Hashable, Read)
|
deriving (Show, Eq, Generic, Hashable, Read)
|
||||||
|
|
||||||
|
|
||||||
-- >>> eitherDecode testManifest :: Either String PackageManifest
|
-- >>> eitherDecodeStrict testManifest :: Either String PackageManifest
|
||||||
|
-- Right (PackageManifest {packageManifestId = embassy-pages, packageManifestTitle = "Embassy Pages", packageManifestVersion = 0.1.3, packageManifestDescriptionLong = "Embassy Pages is a simple web server that uses directories inside File Browser to serve Tor websites.", packageManifestDescriptionShort = "Create Tor websites, hosted on your Embassy.", packageManifestReleaseNotes = "Upgrade to EmbassyOS v0.3.0", packageManifestIcon = Just "icon.png", packageManifestAlerts = fromList [(STOP,Nothing),(RESTORE,Nothing),(INSTALL,Nothing),(START,Nothing),(UNINSTALL,Nothing)], packageManifestDependencies = fromList [(filebrowser,PackageDependency {packageDependencyOptional = Nothing, packageDependencyVersion = >=2.14.1.1 <3.0.0, packageDependencyDescription = Just "Used to upload files to serve."})], packageManifestEosVersion = 0.3.0, packageHardwareDevice = Just (PackageDevice (fromList [("processor",RegexPattern "^[A-Za-z0-9]+$"),("display",RegexPattern "^[A-Za-z0-9]+$")])), packageHardwareRam = Just 8000000000, packageHardwareArch = Just [aarch64,x86_64]})
|
||||||
testManifest :: ByteString
|
testManifest :: ByteString
|
||||||
testManifest =
|
testManifest =
|
||||||
[i|{
|
[i|{
|
||||||
"id": "embassy-pages",
|
"id": "embassy-pages",
|
||||||
"title": "Embassy Pages",
|
"title": "Embassy Pages",
|
||||||
"version": "0.1.3",
|
"version": "0.1.3",
|
||||||
|
"eos-version": "0.3.0",
|
||||||
"description": {
|
"description": {
|
||||||
"short": "Create Tor websites, hosted on your Embassy.",
|
"short": "Create Tor websites, hosted on your Embassy.",
|
||||||
"long": "Embassy Pages is a simple web server that uses directories inside File Browser to serve Tor websites."
|
"long": "Embassy Pages is a simple web server that uses directories inside File Browser to serve Tor websites."
|
||||||
},
|
},
|
||||||
|
"hardware-requirements": {
|
||||||
|
"device": {
|
||||||
|
"processor": "^[A-Za-z0-9]+$",
|
||||||
|
"display": "^[A-Za-z0-9]+$"
|
||||||
|
},
|
||||||
|
"ram": 8000000000,
|
||||||
|
"arch": ["aarch64", "x86_64"]
|
||||||
|
},
|
||||||
"assets": {
|
"assets": {
|
||||||
"license": "LICENSE",
|
"license": "LICENSE",
|
||||||
"icon": "icon.png",
|
"icon": "icon.png",
|
||||||
|
|||||||
@@ -36,8 +36,9 @@ import Startlude (
|
|||||||
Text,
|
Text,
|
||||||
UTCTime,
|
UTCTime,
|
||||||
Word32,
|
Word32,
|
||||||
Bool
|
Bool,
|
||||||
)
|
)
|
||||||
|
import Lib.Types.Manifest (PackageDevice)
|
||||||
|
|
||||||
|
|
||||||
share
|
share
|
||||||
@@ -72,6 +73,8 @@ VersionPlatform
|
|||||||
updatedAt UTCTime Maybe
|
updatedAt UTCTime Maybe
|
||||||
pkgId PkgRecordId
|
pkgId PkgRecordId
|
||||||
versionNumber Version
|
versionNumber Version
|
||||||
|
ram Int Maybe
|
||||||
|
device PackageDevice Maybe
|
||||||
arch OsArch
|
arch OsArch
|
||||||
Primary pkgId versionNumber arch
|
Primary pkgId versionNumber arch
|
||||||
deriving Eq
|
deriving Eq
|
||||||
|
|||||||
@@ -35,8 +35,6 @@ import Lib.Types.Emver ( Version
|
|||||||
|
|
||||||
instance FromJSON Version where
|
instance FromJSON Version where
|
||||||
parseJSON = withText "Emver Version" $ either fail pure . Atto.parseOnly parseVersion
|
parseJSON = withText "Emver Version" $ either fail pure . Atto.parseOnly parseVersion
|
||||||
instance ToJSON Version where
|
|
||||||
toJSON = String . show
|
|
||||||
instance FromJSON VersionRange where
|
instance FromJSON VersionRange where
|
||||||
parseJSON = withText "Emver" $ either fail pure . Atto.parseOnly parseRange
|
parseJSON = withText "Emver" $ either fail pure . Atto.parseOnly parseRange
|
||||||
instance ToJSON VersionRange where
|
instance ToJSON VersionRange where
|
||||||
|
|||||||
Reference in New Issue
Block a user