porte (empty) → 0.0.2
raw patch · 7 files changed
+293/−0 lines, 7 filesdep +basedep +bytestringdep +containerssetup-changed
Dependencies added: base, bytestring, containers, stringsearch
Files
- LICENSE +23/−0
- Porte/Ports.hs +144/−0
- Porte/Statistics.hs +19/−0
- Porte/Tool.hs +84/−0
- Porte/porte.hs +3/−0
- Setup.hs +2/−0
- porte.cabal +18/−0
+ LICENSE view
@@ -0,0 +1,23 @@+Copyright (C) 2008 Samy Al Bahra+All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions+are met:+ 1. Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.+ 2. 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.++ THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ Porte/Ports.hs view
@@ -0,0 +1,144 @@+module Porte.Ports where+import Control.Exception+import Control.Monad+import Data.ByteString.Search.KnuthMorrisPratt+import qualified Data.ByteString.Lazy.Char8 as B+import qualified Data.ByteString.Char8 as C +import qualified Data.List as L+import qualified System.IO as I+import qualified System.Environment as E++portsIndex = "/usr/ports/INDEX-8"+portsPrefix = "/usr/ports/"++type Name = B.ByteString+type DistributionName = B.ByteString +type Path = B.ByteString+type Prefix = B.ByteString+type Comment = B.ByteString+type DescriptionPath = B.ByteString+type PortDescription = Maybe B.ByteString+type Maintainer = B.ByteString+type Categories = [B.ByteString]+type ExtractDepends = [B.ByteString]+type PatchDepends = [B.ByteString]+type FetchDepends = [B.ByteString]+type BuildDepends = [B.ByteString]+type RunDepends = [B.ByteString]+type Website = B.ByteString++data Port = Port {+ name :: Name,+ distributionName :: DistributionName,+ path :: Path,+ comment :: Comment,+ descriptionPath :: DescriptionPath,+ maintainer :: Maintainer,+ categories :: Categories,+ buildDepends :: BuildDepends,+ website :: Website,+ extractDepends :: ExtractDepends+ } deriving (Eq, Show, Read)++type PortField = Port -> B.ByteString+type PortQuery = [(PortField, String)]++toField :: String -> Maybe PortField+toField "name" = Just name+toField "package" = Just distributionName+toField "distributionName" = Just distributionName+toField "path" = Just path+toField "comment" = Just comment+toField "category" = Just category+toField "maintainer" = Just maintainer+toField "website" = Just website+toField _ = Nothing++search :: PortQuery -> [Port] -> [Port]+search (x:xs) p =+ search xs $ filter f p+ where+ f p = case (matchSL (C.pack $ snd x) (fst x p)) of+ [] -> False+ _ -> True +search _ p = p++find :: PortQuery -> [Port] -> [Port]+find (x:xs) p = find xs $ filter f p+ where+ f p = (B.pack $ snd x) == (fst x p)+find _ p = p++description :: Port -> IO (Maybe B.ByteString)+description p =+ do+ o <- try $ (B.readFile . B.unpack . descriptionPath) p+ case (o) of+ Left h -> return Nothing + Right h -> return $ Just $ B.filter (/= '\n') h++glue :: (Port -> [B.ByteString]) -> Port -> B.ByteString+glue f p = B.concat $ L.intersperse (B.pack " ") (f p) +category = glue categories +buildDepend = glue buildDepends+extractDepend = glue extractDepends++parseEntry :: B.ByteString -> Port+parseEntry =+ parseEntry' . B.split '|' + where+ parseEntry' + (name :+ path :+ prefix : + comment :+ pkgDescr :+ maintainer :+ categories :+ buildDepends :+ runDepends :+ website :+ extractDepends : _) =+ Port (B.tail . B.dropWhile (/= '/') $ path')+ (name)+ (path')+ (comment)+ (pkgDescr)+ (maintainer)+ (B.words categories)+ (B.words buildDepends)+ (website)+ (B.words extractDepends)+ where+ path' = B.drop (B.length $ B.pack portsPrefix) $ path++parseIndex :: B.ByteString -> [Port]+parseIndex = map parseEntry . B.lines++index :: (Maybe String) -> IO [Port]+index (Just []) = index (Just portsIndex)+index Nothing = do+ o <- try $ E.getEnv "INDEX"+ case o of+ Right h -> index $ Just h+ _ -> index $ Just portsIndex+index (Just path) = do+ o <- try $ B.readFile path+ case o of+ Left h -> error $ "INDEX file (" ++ path ++ ") could not be opened"+ Right h -> return $ parseIndex h ++putPorts :: [PortField] -> [Port] -> IO ()+putPorts f = hPutPorts I.stdout f++hPutPorts :: I.Handle -> [PortField] -> [Port] -> IO ()+hPutPorts h f p = forM_ p (hPutPort h f)++putPort :: [PortField] -> Port -> IO ()+putPort f = hPutPort I.stdout f++hPutPort :: I.Handle -> [PortField] -> Port -> IO ()+hPutPort h [f] p = B.hPut h (f p) >> I.hPutChar h '\n' +hPutPort h (f:fs) p = B.hPut h (f p) >> I.hPutStr h ", " >> hPutPort h fs p +hPutPort h _ p = I.hPutChar h '\n' +
+ Porte/Statistics.hs view
@@ -0,0 +1,19 @@+module Porte.Statistics where+import qualified Data.ByteString.Lazy.Char8 as B+import qualified Porte.Ports as P+import qualified Data.Map as M +import qualified System.IO as I+import Text.Printf(printf)++type FrequencyMap = M.Map B.ByteString Int+type FieldFrequency = (B.ByteString, Int) ++mapFrequency :: [B.ByteString] -> FrequencyMap +mapFrequency (x:xs) = M.insertWith' (+) x 1 $ mapFrequency xs+mapFrequency _ = M.empty++fieldsFrequency f r = M.assocs $ mapFrequency (concat $ map f r)+fieldFrequency f r = M.assocs $ mapFrequency (map f r)++printFrequency :: FieldFrequency -> IO ()+printFrequency (a, b) = I.putStr (printf "%5d " b) >> B.putStrLn a
+ Porte/Tool.hs view
@@ -0,0 +1,84 @@+module Porte.Tool(toolMain) where+import System.Environment+import System.Exit+import Control.Monad+import qualified Data.ByteString.Lazy.Char8 as B+import qualified Porte.Ports as P+import qualified Porte.Statistics as S+import qualified System.IO as I++version = "0.0.2"++-- Generic port print format+printFormat = [P.path, P.comment, P.website]++-- Exception raising toField+toField :: String -> P.PortField+toField f =+ case (P.toField f) of+ Nothing -> error $ "Unknown field: " ++ f+ Just f -> f++-- Statistics mode+doStatistics :: [String] -> IO ()+doStatistics (a:m:_) =+ case a of+ "frequency" -> case m of+ "categories" -> doOutput $ S.fieldsFrequency P.categories + "buildDepends" -> doOutput $ S.fieldsFrequency P.buildDepends+ "extractDepends" -> doOutput $ S.fieldsFrequency P.extractDepends+ _ -> doOutput $ S.fieldFrequency (toField m) + _ -> error $ "Unknown statistics mode"+ where+ doOutput f = P.index Nothing >>= flip forM_ S.printFrequency . f +doStatistics _ = toolUsage >> die++-- List all available ports in INDEX+doIndex :: IO ()+doIndex =+ P.index Nothing >>= P.putPorts printFormat ++-- Build port query from user input+parseSearch :: [String] -> P.PortQuery+parseSearch q =+ build [] q+ where+ build p (f:q:qs) = build ((toField f, q) : p) qs + build p (_:[]) = error "Parse error"+ build p _ = p ++-- Generic search action+genericSearch :: (P.PortQuery -> [P.Port] -> [P.Port]) -> [String] -> IO ()+genericSearch f [] = exit+genericSearch f q = do+ ports <- P.index Nothing+ P.putPorts printFormat $ (f . parseSearch) q ports++doSearch q = genericSearch P.search q +doFind q = genericSearch P.find q ++die = exitWith (ExitFailure 1)+exit = exitWith (ExitSuccess)++hToolUsage :: I.Handle -> IO ()+hToolUsage h = I.hPutStrLn h "Usage: porte [-hvlsfS]" ++toolUsage = hToolUsage I.stderr++printVersion :: IO ()+printVersion = I.putStrLn $ "Porte.Tool " ++ version++toolMain = do+ argv <- getArgs+ case (null argv) of + True -> toolUsage >> die+ _ -> case (head argv) of+ "-h" -> hToolUsage I.stdout+ "-v" -> printVersion+ "-l" -> doIndex+ "-s" -> doSearch $ tail argv+ "-f" -> doFind $ tail argv+ "-S" -> doStatistics $ tail argv+ _ -> toolUsage >> die ++
+ Porte/porte.hs view
@@ -0,0 +1,3 @@+import Porte.Tool ++main = toolMain
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ porte.cabal view
@@ -0,0 +1,18 @@+Name: porte+Version: 0.0.2+Cabal-Version: >= 1.2+Synopsis: FreeBSD ports interface+Description: Haskell FreeBSD ports analysis library+Category: System+License: BSD3+License-file: LICENSE+Author: Samy Al Bahra+Maintainer: sbahra@kerneled.org+Build-Type: Simple++Library+ Build-Depends: base, bytestring, containers, stringsearch+ Exposed-Modules: Porte.Tool Porte.Statistics Porte.Ports++Executable porte+ Main-is: Porte/porte.hs