fedora-packages (empty) → 0.0.1
raw patch · 12 files changed
+612/−0 lines, 12 filesdep +HsOpenSSLdep +aesondep +basesetup-changed
Dependencies added: HsOpenSSL, aeson, base, bytestring, containers, hlint, hspec, http-streams, io-streams, lens, text
Files
- LICENSE +30/−0
- Setup.hs +2/−0
- fedora-packages.cabal +67/−0
- src/Fedora/Packages.hs +51/−0
- src/Fedora/Packages/API.hs +90/−0
- src/Fedora/Packages/Builds.hs +127/−0
- src/Fedora/Packages/Config.hs +34/−0
- src/Fedora/Packages/Lens.hs +32/−0
- src/Fedora/Packages/Releases.hs +72/−0
- src/Fedora/Packages/Search.hs +94/−0
- tests/Spec.hs +1/−0
- tests/hlint.hs +12/−0
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2014, Ricky Elrod++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++ * Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ * Redistributions in binary form must reproduce the above+ copyright notice, this list of conditions and the following+ disclaimer in the documentation and/or other materials provided+ with the distribution.++ * Neither the name of Ricky Elrod nor the names of other+ contributors may be used to endorse or promote products derived+ from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ fedora-packages.cabal view
@@ -0,0 +1,67 @@+name: fedora-packages+version: 0.0.1+synopsis: Haskell interface to the Fedora Packages webapp API.+description: Provides access to the (<https://apps.fedoraproject.org/packages/ Fedora Packages>) API.+homepage: https://github.com/CodeBlock/fedora-packages-hs+license: BSD3+license-file: LICENSE+author: Ricky Elrod+maintainer: ricky@elrod.me+copyright: (c) 2014 Ricky Elrod+category: Web+build-type: Simple+cabal-version: >=1.10++library+ exposed-modules: Fedora.Packages+ , Fedora.Packages.API+ , Fedora.Packages.Builds+ , Fedora.Packages.Config+ , Fedora.Packages.Lens+ , Fedora.Packages.Releases+ , Fedora.Packages.Search++ build-depends: aeson >= 0.6+ , base >=4.6 && <4.7+ , bytestring >= 0.10+ , containers >= 0.5+ , http-streams >= 0.7+ , HsOpenSSL >= 0.10+ , io-streams >= 1.1+ , lens >= 4 && < 5+ , text >= 0.11+ hs-source-dirs: src+ default-language: Haskell2010+ ghc-options: -Wall -O2+++test-suite hunit+ hs-source-dirs: tests src+ main-is: Spec.hs+ type: exitcode-stdio-1.0+ ghc-options: -Wall -threaded -rtsopts -with-rtsopts=-N+ default-language: Haskell2010+ build-depends: aeson >= 0.6+ , base >=4.6 && <4.7+ , bytestring >= 0.10+ , containers >= 0.5+ , http-streams >= 0.7+ , HsOpenSSL >= 0.10+ , io-streams >= 1.1+ , lens >= 4 && < 5+ , text >= 0.11+ -- And of course...+ , hspec ==1.8.*++test-suite hlint+ hs-source-dirs: tests+ main-is: hlint.hs+ type: exitcode-stdio-1.0+ default-language: Haskell2010+ ghc-options: -Wall -threaded -rtsopts -with-rtsopts=-N+ build-depends: base+ , hlint >= 1.7++source-repository head+ type: git+ location: git://github.com/CodeBlock/fedora-packages-hs.git
+ src/Fedora/Packages.hs view
@@ -0,0 +1,51 @@+-----------------------------------------------------------------------------+-- |+-- Copyright : (c) 2014 Ricky Elrod+-- License : BSD3+--+-- Maintainer : Ricky Elrod <ricky@elrod.me>+-- Stability : experimental+--+-- Provides a Haskell interface to the+-- <https://apps.fedoraproject.org/packages Fedora Packages> API.+--+-- This module simply re-exports all public modules within the fedora-packages+-- project.+--+-- Depending on usecase, it might be easiest to import this and Lens, as below:+--+-- > import Fedora.Packages+-- > import Fedora.Packages.Lens+-- > import Control.Lens+--+-- But keep in mind that this will clutter your namespace pretty badly, and+-- might not be ideal for all situations.+--+-- If you don't want to use lenses (but you should because they are awesome),+-- you can do this instead:+--+-- > import qualified Fedora.Packages as FedPackages+--+-- ...and then access everything using understored record-style getters, e.g.+-- @_packageName theBuild@.+--+-- Or you can import specific pieces of @Fedora.Packages.\<whatever\>@ instead+-- of importing @Fedora.Packages@ which re-exports everything.+--+-- If you do that, however, you'll want to import @Fedora.Packages.API@ and+-- @Fedora.Packages.Config@ as well, so that you have the necessary data types+-- for interacting with the API.+--+-- TL;DR: This is written to be very modular, and you are free to use it however+-- it best fits in with the rest of your project. Have fun!+----------------------------------------------------------------------------++module Fedora.Packages+ ( module F+ ) where++import Fedora.Packages.API as F+import Fedora.Packages.Builds as F+import Fedora.Packages.Config as F+import Fedora.Packages.Releases as F+import Fedora.Packages.Search as F
+ src/Fedora/Packages/API.hs view
@@ -0,0 +1,90 @@+{-# LANGUAGE OverloadedStrings #-}++-----------------------------------------------------------------------------+-- |+-- Copyright : (c) 2014 Ricky Elrod+-- License : BSD3+--+-- Maintainer : Ricky Elrod <ricky@elrod.me>+-- Stability : experimental+--+-- Functions and datatypes for directly calling out to the API and handling+-- queries to and responses from it.+----------------------------------------------------------------------------++module Fedora.Packages.API+ ( -- * Responses+ StandardResults (..)+ -- * Requests+ , Query (..)+ , apiGet+ ) where++import Fedora.Packages.Config++import Control.Applicative+import Control.Monad (mzero)+import Data.Aeson+import qualified Data.ByteString as S+import Data.Monoid+import Network.Http.Client+import OpenSSL (withOpenSSL)++----------------------------------------------------------------------------+-- Responses+----------------------------------------------------------------------------++data StandardResults a = StandardResults {+ _srRows :: [a]+ , _srRowsPerPage :: Int+ , _srStartRow :: Int+ , _srTotalRows :: Int+ , _srVisibleRows :: Int+ } deriving (Eq, Show)++instance FromJSON a => FromJSON (StandardResults a) where+ parseJSON (Object v) = StandardResults <$>+ v .: "rows"+ <*> v .: "rows_per_page"+ <*> v .: "start_row"+ <*> v .: "total_rows"+ <*> v .: "visible_rows"+ parseJSON _ = mzero++----------------------------------------------------------------------------+-- Requests+----------------------------------------------------------------------------++-- | Sets things that are common to all requests that we make.+prepareRequest :: Method -> S.ByteString -> RequestBuilder ()+prepareRequest m url = do+ http m url+ setAccept "application/json"+ setContentType "application/json"++finishRequest :: FromJSON a => Connection -> IO a+finishRequest cnx = do+ x <- receiveResponse cnx jsonHandler+ closeConnection cnx+ return x++-- | Perform a GET request to the API.+apiGet :: FromJSON a => S.ByteString -> PackagesConfig -> IO a+apiGet url c = withOpenSSL $ do+ cnx <- establishConnection (_baseurl c)+ q <- buildRequest $ prepareRequest GET ("/packages/fcomm_connector/" <> url)+ sendRequest cnx q emptyBody+ finishRequest cnx+++data Query a = Query {+ _qSearch :: a+ , _qRowsPerPage :: Int+ , _qStartRow :: Int+ } deriving (Eq, Show)++instance ToJSON a => ToJSON (Query a) where+ toJSON (Query s r sr) = object [ "filters" .= s+ , "rows_per_page" .= r+ , "start_row" .= sr+ ]
+ src/Fedora/Packages/Builds.hs view
@@ -0,0 +1,127 @@+{-# LANGUAGE OverloadedStrings #-}++-----------------------------------------------------------------------------+-- |+-- Copyright : (c) 2014 Ricky Elrod+-- License : BSD3+--+-- Maintainer : Ricky Elrod <ricky@elrod.me>+-- Stability : experimental+--+-- Provides functions and datatypes for accessing information about Fedora+-- package builds.+----------------------------------------------------------------------------++module Fedora.Packages.Builds+ ( Build (..)+ , BuildsFilter (..)+ , BuildState (..)+ , CompletionTimeDisplay (..)+ , builds+ ) where++import Fedora.Packages.API+import Fedora.Packages.Config++import Control.Applicative+import Control.Monad (mzero)+import Data.Aeson hiding (Success)+import qualified Data.ByteString.Lazy as LS+import Data.Monoid hiding (All)+import qualified Data.Text as T++data BuildState =+ All+ | Building+ | Success+ | Failed+ | Cancelled+ | Deleted+ deriving (Eq, Show)++buildStateToText :: BuildState -> T.Text+buildStateToText All = ""+buildStateToText Building = "0"+buildStateToText Success = "1"+buildStateToText Deleted = "2"+buildStateToText Failed = "3"+buildStateToText Cancelled = "4"++data BuildsFilter = BuildsFilter {+ _bfPackage :: T.Text+ , _bfState :: BuildState+ } deriving (Eq, Show)++instance ToJSON BuildsFilter where+ toJSON (BuildsFilter p s) = object [ "package" .= p+ , "state" .= buildStateToText s+ ]++data CompletionTimeDisplay = CompletionTimeDisplay {+ _elapsed :: T.Text+ , _time :: T.Text+ , _when :: T.Text+ } deriving (Eq, Show)++instance FromJSON CompletionTimeDisplay where+ parseJSON (Object v) = CompletionTimeDisplay <$>+ v .: "elapsed"+ <*> v .: "time"+ <*> v .: "when"+ parseJSON _ = mzero++data Build = Build {+ _buildId :: Int+ , _completionTime :: T.Text+ , _completionTimeDisplay :: CompletionTimeDisplay+ , _completionTs :: Double+ , _creationEventId :: Int+ , _creationTime :: T.Text+ , _creationTs :: Double+ , _epoch :: Maybe Double+ , _name' :: T.Text+ , _nvr :: T.Text+ , _ownerId :: Int+ , _ownerName :: T.Text+ , _packageId :: Int+ , _packageName :: T.Text+ , _packageRelease :: T.Text+ , _state :: Int+ , _stateStr :: T.Text+ , _taskId :: Int+ , _version :: T.Text+ , _volumeId :: Int+ , _volumeName :: T.Text+ } deriving (Eq, Show)++instance FromJSON Build where+ parseJSON (Object v) = Build <$>+ v .: "build_id"+ <*> v .: "completion_time"+ <*> v .: "completion_time_display"+ <*> v .: "completion_ts"+ <*> v .: "creation_event_id"+ <*> v .: "creation_time"+ <*> v .: "creation_ts"+ <*> v .:? "epoch"+ <*> v .: "name"+ <*> v .: "nvr"+ <*> v .: "owner_id"+ <*> v .: "owner_name"+ <*> v .: "package_id"+ <*> v .: "package_name"+ <*> v .: "release"+ <*> v .: "state"+ <*> v .: "state_str"+ <*> v .: "task_id"+ <*> v .: "version"+ <*> v .: "volume_id"+ <*> v .: "volume_name"+ parseJSON _ = mzero++-- | Query to find builds for a given package.+builds :: PackagesConfig -- ^ The configuration to use.+ -> Query BuildsFilter -- ^ The search query to send.+ -> IO (StandardResults Build)+builds c s =+ apiGet ("koji/query/query_builds/" <> LS.toStrict (encode s)) c
+ src/Fedora/Packages/Config.hs view
@@ -0,0 +1,34 @@+{-# LANGUAGE OverloadedStrings #-}++-----------------------------------------------------------------------------+-- |+-- Copyright : (c) 2014 Ricky Elrod+-- License : BSD3+--+-- Maintainer : Ricky Elrod <ricky@elrod.me>+-- Stability : experimental+--+-- Used for configuring how to connect to the Fedora Packages API.+----------------------------------------------------------------------------++module Fedora.Packages.Config+ ( PackagesConfig (..)+ , defaultConfig+ , stagingConfig+ ) where++import Network.Http.Client++data PackagesConfig = PackagesConfig {+ _baseurl :: URL -- ^ The base URL (with protocol) of Fedora Packages.+} deriving (Eq, Show)++-- | The default configuration, which points to the production instance of+-- Fedora Packages.+defaultConfig :: PackagesConfig+defaultConfig = PackagesConfig "https://apps.fedoraproject.org"++-- | The staging configuration, which points to the staging instance of Fedora+-- Packages.+stagingConfig :: PackagesConfig+stagingConfig = PackagesConfig "https://apps.stg.fedoraproject.org"
+ src/Fedora/Packages/Lens.hs view
@@ -0,0 +1,32 @@+{-# LANGUAGE TemplateHaskell #-}++-----------------------------------------------------------------------------+-- |+-- Copyright : (c) 2014 Ricky Elrod+-- License : BSD3+--+-- Maintainer : Ricky Elrod <ricky@elrod.me>+-- Stability : experimental+--+-- Provides lenses for data types found within Fedora.Packages.+----------------------------------------------------------------------------++module Fedora.Packages.Lens where++import Control.Lens (makeLenses)++import Fedora.Packages.API+import Fedora.Packages.Config+import Fedora.Packages.Builds+import Fedora.Packages.Releases+import Fedora.Packages.Search++makeLenses ''Build+makeLenses ''BuildsFilter+makeLenses ''CompletionTimeDisplay+makeLenses ''PackagesConfig+makeLenses ''Package+makeLenses ''Release+makeLenses ''SearchFilter+makeLenses ''StandardResults+makeLenses ''Query
+ src/Fedora/Packages/Releases.hs view
@@ -0,0 +1,72 @@+{-# LANGUAGE OverloadedStrings #-}++-----------------------------------------------------------------------------+-- |+-- Copyright : (c) 2014 Ricky Elrod+-- License : BSD3+--+-- Maintainer : Ricky Elrod <ricky@elrod.me>+-- Stability : experimental+--+-- Provides functions and datatypes for getting release information about Fedora+-- packages.+----------------------------------------------------------------------------++module Fedora.Packages.Releases+ ( Release (..)+ , releases+ , releases'+ ) where++import Fedora.Packages.API+import Fedora.Packages.Config++import Control.Applicative+import Control.Monad (mzero)+import Data.Aeson+import qualified Data.ByteString.Lazy as LS+import Data.Monoid+import qualified Data.Text as T++data Release = Release {+ _release :: T.Text+ , _stableVersion :: T.Text+ , _testingVersion :: T.Text+ } deriving (Eq, Show)++instance FromJSON Release where+ parseJSON (Object v) = Release <$>+ v .: "release"+ <*> v .: "stable_version"+ <*> v .: "testing_version"+ parseJSON _ = mzero++data ReleasesFilter = ReleasesFilter {+ _rfPackage :: T.Text+ } deriving (Eq, Show)++instance ToJSON ReleasesFilter where+ toJSON (ReleasesFilter s) = object [ "package" .= s ]++-- | Obtain release information about a package.+releases :: PackagesConfig -- ^ The configuration to use.+ -> T.Text -- ^ The name of the package to look up.+ -> IO (StandardResults Release)+releases c s =+ let rJson = Query (ReleasesFilter s) 1 0+ in+ apiGet ("bodhi/query/query_active_releases/" <> LS.toStrict (encode rJson)) c++-- | Helper method to query for release information without having to worry+-- about traversing into 'StandardResults'.+--+-- This is provided because this is one of the few places where the paging+-- information probably really doesn't matter.+--+-- Equivalent to:+--+-- > _srRows <$> releases c q+releases' :: PackagesConfig -- ^ The configuration to use.+ -> T.Text -- ^ The name of the package to look up.+ -> IO [Release]+releases' c q = _srRows <$> releases c q
+ src/Fedora/Packages/Search.hs view
@@ -0,0 +1,94 @@+{-# LANGUAGE OverloadedStrings #-}++-----------------------------------------------------------------------------+-- |+-- Copyright : (c) 2014 Ricky Elrod+-- License : BSD3+--+-- Maintainer : Ricky Elrod <ricky@elrod.me>+-- Stability : experimental+--+-- Provides functions and datatypes for searching Fedora Packages.+----------------------------------------------------------------------------++module Fedora.Packages.Search+ ( Package (..)+ , Subpackage (..)+ , SearchFilter (..)+ , packageInfo+ , search+ ) where++import Fedora.Packages.API+import Fedora.Packages.Config++import Control.Applicative+import Control.Monad (mzero)+import Data.Aeson+import qualified Data.ByteString.Lazy as LS+import Data.Maybe (listToMaybe)+import Data.Monoid+import qualified Data.Text as T++data SearchFilter = SearchFilter {+ _sfSearch :: T.Text+ } deriving (Eq, Show)++instance ToJSON SearchFilter where+ toJSON (SearchFilter s) = object [ "search" .= s ]++data Package = Package {+ _develOwner :: T.Text+ , _icon :: T.Text+ , _link :: T.Text+ , _name :: T.Text+ , _subPackages :: Maybe [Subpackage]+ , _summary :: T.Text+ , _upstreamUrl :: T.Text+ , _description :: T.Text+ } deriving (Eq, Show)++instance FromJSON Package where+ parseJSON (Object v) = Package <$>+ v .: "devel_owner"+ <*> v .: "icon"+ <*> v .: "link"+ <*> v .: "name"+ <*> v .: "sub_pkgs"+ <*> v .: "summary"+ <*> v .: "upstream_url"+ <*> v .: "description"+ parseJSON _ = mzero++data Subpackage = Subpackage {+ _subIcon :: T.Text+ , _subLink :: T.Text+ , _subName :: T.Text+ , _subSummary :: T.Text+ , _subDescription :: T.Text+ } deriving (Eq, Show)++instance FromJSON Subpackage where+ parseJSON (Object v) = Subpackage <$>+ v .: "icon"+ <*> v .: "link"+ <*> v .: "name"+ <*> v .: "summary"+ <*> v .: "description"+ parseJSON _ = mzero++-- | Search Fedora Packages for a given pattern.+search :: PackagesConfig -- ^ The configuration to use.+ -> Query SearchFilter -- ^ The search query to send.+ -> IO (StandardResults Package)+search c s =+ apiGet ("xapian/query/search_packages/" <> LS.toStrict (encode s)) c++-- | Search Fedora Packages and return the package if an exact one is found.+packageInfo :: PackagesConfig -> T.Text -> IO (Maybe Package)+packageInfo c q = do+ s <- search c (Query (SearchFilter q) 1 0)+ let rows = _srRows s+ matches = filter (\x -> _name x == q) rows+ in+ return $ listToMaybe matches
+ tests/Spec.hs view
@@ -0,0 +1,1 @@+{-# OPTIONS_GHC -F -pgmF hspec-discover #-}
+ tests/hlint.hs view
@@ -0,0 +1,12 @@+module Main where++import Control.Monad+import Language.Haskell.HLint+import System.Environment+import System.Exit++main :: IO ()+main = do+ args <- getArgs+ hints <- hlint $ ["src", "--cpp-define=HLINT", "--cpp-ansi"] ++ args+ unless (null hints) exitFailure