packages feed

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 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