packages feed

cabal-query (empty) → 0.1

raw patch · 6 files changed

+238/−0 lines, 6 filesdep +Cabaldep +MissingHdep +basesetup-changed

Dependencies added: Cabal, MissingH, base, bytestring, derive, ghc, mtl, tar, template-haskell, uniplate

Files

+ LICENSE view
@@ -0,0 +1,29 @@+Copyright (c) 2009, Max Desyatov+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 the author nor the names of his 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
+ cabal-query.cabal view
@@ -0,0 +1,30 @@+name:            cabal-query+version:         0.1+copyright:       (c) 2009 Max Desyatov+category:        System+maintainer:      Max Desyatov <explicitcall at gmail.com>+author:          Max Desyatov+license:         BSD3+license-file:    LICENSE+cabal-version:   >= 1.6+synopsis:        Helpers for quering .cabal files or hackageDB's 00-index.tar+description:     This package was written to assist you at finding a set of packages,+                 which satisfy your needs.  At the moment it doesn't have a standalone executable,+                 but you can do the queries from your Haskell code.+stability:       Experimental+build-type:      Simple+homepage:        http://github.com/explicitcall/cabal-query+bug-reports:     http://github.com/explicitcall/cabal-query/issues++library+  exposed-modules: Distribution.Query+  other-modules:   Distribution.Query.TH,+                   Distribution.Query.Types+  hs-source-dirs:  src+  ghc-options:     -Wall -fno-warn-orphans+  build-depends:   base >= 4 && < 5, mtl, template-haskell, derive, Cabal >= 1.6 && < 1.7,+                   MissingH, uniplate, bytestring, tar, ghc >= 6.10 && < 6.11++source-repository head+  type:      git+  location:  git://github.com/explicitcall/cabal-query.git
+ src/Distribution/Query.hs view
@@ -0,0 +1,88 @@+{-# LANGUAGE ScopedTypeVariables #-}++-- | This package uses "Data.Generics.PlateData", so+--+-- * when Cabal package format changes, we don't have to rewrite anything+--+-- * all queries are statically typed+--+-- * as a disadvantage, we may suffer some performance loss when doing very complex queries,+--   anyway most of processing goes while we read package descriptions, not querying them+--+-- Example of enduser querying code:+--+-- @+--module Main where+--+-- import qualified Data.ByteString.Lazy as B+--import System.Environment+--import Distribution.Query+--import Distribution.Compiler+--import Distribution.License+--import Distribution.ModuleName hiding (main)+--import Distribution.Package+--import Distribution.PackageDescription+--import Distribution.Version+--import Distribution.Text+--import Language.Haskell.Extension+--+-- main = (head \`fmap\` getArgs) >>=+--        B.readFile >>=+--        mapM_ (putStrLn . show . (\x -> (display $ package x, display $ license x))) .+--        queryIndex (Not (Id (== GPL)) :& Not (Id (== BSD3)))+-- @+--+-- You can query any field of 'PackageDescription' no matter how deep it is.+-- You don't need to provide any type signature for comparison functions,+-- which are wrapped in 'Id', as long as you use data constructors for which type can be inferred.+--+-- See 'PackageDescription' fields for details.+module Distribution.Query+    ( queryFiles+    , queryIndex+    , module Distribution.Query.Types ) where++import Codec.Archive.Tar as T hiding (unpack)+import Data.ByteString.Internal (w2c)+import Data.ByteString.Lazy (ByteString)+import qualified Data.ByteString.Lazy as B+import Data.Generics.PlateData+import Data.Maybe+import Distribution.PackageDescription+import Distribution.PackageDescription.Parse++import Distribution.Query.Types++-- | Queries an index file, which is commonly located at+-- <~/.cabal/packages/hackage.haskell.org/00-index.tar> in POSIX systems.+queryIndex :: Query+           -> ByteString           -- ^ The index file must be read as lazy ByteString+           -> [PackageDescription] -- ^ Returns a list of package descriptions which satisfy the query+queryIndex q = procQuery q . foldEntries foldF [] (const []) . T.read+    where+      foldF :: Entry -> [PackageDescription] -> [PackageDescription]+      foldF c rest =+          case entryContent c of+            NormalFile s _ -> maybe rest (:rest) $ parsePD s+            _              -> rest++parsePD :: ByteString -> Maybe PackageDescription+parsePD s =+    case (parsePackageDescription $ map w2c $ B.unpack s) of+      ParseOk _ x -> Just $ packageDescription x+      _           -> Nothing++-- | Queries .cabal files.+queryFiles :: Query+           -> [ByteString]         -- ^ All files must be read as lazy ByteStrings+           -> [PackageDescription] -- ^ Returns a list of package descriptions which satisfy the query+queryFiles q = procQuery q . catMaybes . map parsePD++procQuery :: Query -> [PackageDescription] -> [PackageDescription]+procQuery q = filter (doQuery q)++doQuery :: Query -> PackageDescription -> Bool+doQuery (Id  f)    pd = or [f x | x <- universeBi pd]+doQuery (Not q)    pd = not $ doQuery q pd+doQuery (q1 :& q2) pd = doQuery q1 pd && doQuery q2 pd+doQuery (q1 :| q2) pd = doQuery q1 pd || doQuery q2 pd
+ src/Distribution/Query/TH.hs view
@@ -0,0 +1,8 @@+module Distribution.Query.TH where++import MonadUtils+import Data.DeriveTH+import Language.Haskell.TH++deriveMany :: Derivation -> [Name] -> Q [Dec]+deriveMany = concatMapM . derive
+ src/Distribution/Query/Types.hs view
@@ -0,0 +1,81 @@+{-# LANGUAGE TemplateHaskell, GADTs #-}+module Distribution.Query.Types+    ( Query(..) ) where++import Data.Data+import Data.DeriveTH+import Data.List.Utils (join)+import Distribution.Compiler+import Distribution.License+import Distribution.ModuleName hiding (main)+import Distribution.Package+import Distribution.PackageDescription+import Distribution.Version+import Language.Haskell.Extension++import Distribution.Query.TH++-- | Heterogenous query tree.  Example of constructed query:+--+-- > Not (Id (== GPL)) :& Not (Id (== BSD3))+--+-- 'Id' takes comparison function as its argument.+-- Commonly this must be a partially applied ('/=') or ('==').+-- Data instance is required for 'PackageDescription' traversal.+-- All appropriate instances are generated automagically,+-- so you don't have to bother as long as Cabal doesn't change its+-- package description format.+data Query where+    (:&) :: Query -> Query -> Query+    (:|) :: Query -> Query -> Query+    Not  :: Query -> Query+    Id   :: Data a => (a -> Bool) -> Query++$(deriveMany makeTypeable+  [''PackageDescription+  ,''Executable+  ,''Library+  ,''BuildType+  ,''VersionRange+  ,''Dependency+  ,''SourceRepo+  ,''CompilerFlavor+  ,''License+  ,''PackageIdentifier+  ,''BuildInfo+  ,''ModuleName+  ,''PackageName+  ,''RepoType+  ,''RepoKind+  ,''Extension])++$(deriveMany makeData+  [''PackageDescription+  ,''Executable+  ,''Library+  ,''BuildType+  ,''VersionRange+  ,''Dependency+  ,''SourceRepo+  ,''CompilerFlavor+  ,''License+  ,''PackageIdentifier+  ,''BuildInfo+  ,''PackageName+  ,''RepoType+  ,''RepoKind+  ,''Extension+  ,''Version])++-- Workaround for ModuleName, see http://code.google.com/p/ndmitchell/issues/detail?id=209+instance Data ModuleName where+    gfoldl  _ z   = z . simple . join "." . components+    gunfold _ z _ = z $ simple ""+    toConstr    _ = con_C+    dataTypeOf  _ = ty_T++con_C :: Constr+con_C = mkConstr ty_T "ModuleName" [] Prefix++ty_T :: DataType+ty_T = mkDataType "Distribution.ModuleName.ModuleName" [con_C]