packages feed

packdeps 0.2.0 → 0.3.0

raw patch · 3 files changed

+120/−28 lines, 3 filesdep +aesondep +cautious-filedep ~tarPVP ok

version bump matches the API change (PVP)

Dependencies added: aeson, cautious-file

Dependency ranges changed: tar

API changes (from Hackage documentation)

+ Distribution.PackDeps: DescInfo :: String -> [Dependency] -> PackageIdentifier -> String -> DescInfo
+ Distribution.PackDeps: PackInfo :: Version -> Maybe DescInfo -> EpochTime -> PackInfo
+ Distribution.PackDeps: data PackInfo
+ Distribution.PackDeps: diDeps :: DescInfo -> [Dependency]
+ Distribution.PackDeps: diHaystack :: DescInfo -> String
+ Distribution.PackDeps: diPackage :: DescInfo -> PackageIdentifier
+ Distribution.PackDeps: diSynopsis :: DescInfo -> String
+ Distribution.PackDeps: piDesc :: PackInfo -> Maybe DescInfo
+ Distribution.PackDeps: piEpoch :: PackInfo -> EpochTime
+ Distribution.PackDeps: piVersion :: PackInfo -> Version

Files

Distribution/PackDeps.hs view
@@ -21,6 +21,9 @@     , getReverses       -- * Helpers     , diName+      -- * Internal+    , PackInfo (..)+    , DescInfo (..)     ) where  import System.Directory (getAppUserDataDirectory)@@ -29,6 +32,7 @@ import Data.List (foldl', group, sort, isInfixOf, isPrefixOf) import Data.Time (UTCTime (UTCTime), addUTCTime) import Data.Maybe (mapMaybe, catMaybes)+import Control.Exception (throw)  import Distribution.Package import Distribution.PackageDescription@@ -78,9 +82,9 @@ parseNewest :: L.ByteString -> Newest parseNewest = foldl' addPackage Map.empty . entriesToList . Tar.read -entriesToList :: Tar.Entries -> [Tar.Entry]+entriesToList :: Tar.Entries Tar.FormatError -> [Tar.Entry] entriesToList Tar.Done = []-entriesToList (Tar.Fail s) = error s+entriesToList (Tar.Fail s) = throw s entriesToList (Tar.Next e es) = e : entriesToList es  addPackage :: Newest -> Tar.Entry -> Newest@@ -231,8 +235,8 @@  -- | Find all packages depended upon by the given list of packages. deepDeps :: Newest -> [DescInfo] -> [DescInfo]-deepDeps newest dis =-    go Set.empty dis+deepDeps newest dis0 =+    go Set.empty dis0   where     go _ [] = []     go viewed (di:dis)@@ -243,9 +247,9 @@         viewed' = Set.insert name viewed         newDis = mapMaybe getDI $ diDeps di         getDI :: Dependency -> Maybe DescInfo-        getDI (Dependency (PackageName name) _) = do-            pi <- Map.lookup name newest-            piDesc pi+        getDI (Dependency (PackageName name') _) = do+            pi' <- Map.lookup name' newest+            piDesc pi'  diName :: DescInfo -> String diName =
packdeps.cabal view
@@ -1,5 +1,5 @@ name:            packdeps-version:         0.2.0+version:         0.3.0 license:         BSD3 license-file:    LICENSE author:          Michael Snoyman <michael@snoyman.com>@@ -21,7 +21,7 @@  library     build-depends:   base                      >= 4        && < 5-                   , tar                       >= 0.3.1    && < 0.4+                   , tar                       >= 0.4      && < 0.5                    , split                     >= 0.1.2.3  && < 0.2                    , bytestring                >= 0.9      && < 0.10                    , text                      >= 0.7      && < 0.12@@ -62,6 +62,8 @@                        , hamlet                        , yesod-newsfeed                        , yesod >= 0.10+                       , cautious-file             >= 1.0      && < 1.1+                       , aeson                     >= 0.6      && < 0.7     else         Buildable: False 
tools/packdeps-yesod.hs view
@@ -1,5 +1,6 @@ {-# LANGUAGE QuasiQuotes, TypeFamilies, OverloadedStrings, MultiParamTypeClasses #-} {-# LANGUAGE TemplateHaskell #-}+import Prelude hiding (writeFile) import Yesod import Yesod.AtomFeed import Yesod.Feed@@ -11,15 +12,22 @@ import Distribution.Package import Distribution.Text hiding (Text) import Control.Arrow-import Distribution.Version (withinRange)+import Distribution.Version (VersionRange, withinRange) import qualified Data.Map as Map import Data.Text (Text, pack, unpack, append) import Text.Hamlet (shamlet) import System.Environment (getArgs) import Data.List (sort)+import Data.Version (Version)+import System.IO.Cautious (writeFileL)+import qualified Data.ByteString.Lazy as L+import Data.Aeson+import Data.Aeson.Types (Parser)+import Control.Monad (mzero)+import Control.Applicative ((<$>), (<*>))  data PD = PD Newest Reverses-mkYesod "PD" [$parseRoutes|+mkYesod "PD" [parseRoutes| /favicon.ico FaviconR GET / RootR GET /feed FeedR GET@@ -32,12 +40,14 @@ /reverse ReverseListR GET /reverse/#Text ReverseR GET |]-instance Yesod PD where approot _ = ""+instance Yesod PD where+    approot = ApprootStatic ""  getFaviconR :: Handler () getFaviconR = sendFile "image/x-icon" "favicon.ico" -mainCassius = [$cassius|+mainCassius :: CssUrl (Route PD)+mainCassius = [cassius| body     font-family: Arial,Helvetica,sans-serif     width: 600px@@ -63,9 +73,10 @@     text-align: center |] +getRootR :: Handler RepHtml getRootR = defaultLayout $ do     setTitle "Hackage dependency monitor"-    addCassius mainCassius+    addCassius mainCassius :: Widget -- just get rid of a warning by using Widget     [whamlet| <h1>Hackage Dependency Monitor <form action="@{FeedR}">@@ -86,8 +97,12 @@     <a href="http://docs.yesodweb.com/">Powered by Yesod |] +isDeep :: Handler Bool isDeep = fmap (== Just "on") $ runInputGet $ iopt textField "deep" +getDeps :: Bool+        -> String+        -> Handler ([DescInfo], [((String, Version), ([(String, String)], UTCTime))]) getDeps deep needle = do     PD newest _ <- getYesod     let descs' = filterPackages needle newest@@ -110,7 +125,8 @@     let deepR = (FeedR, [("needle", needle), ("deep", "on")])     defaultLayout $ do         setTitle $ toHtml title-        addCassius [$cassius|body+        addCassius [cassius|+body     font-family: Arial,Helvetica,sans-serif     width: 600px     margin: 2em auto@@ -165,14 +181,19 @@                 <a href="http://hackage.haskell.org/package/#{name}">#{name} |] +getFeed2R :: Text -> Handler RepAtomRss getFeed2R needle = do     (_, deps) <- getDeps False $ unpack needle     feed2Helper needle deps +getFeed2DeepR :: Text -> Handler RepAtomRss getFeed2DeepR needle = do     (_, deps) <- getDeps True $ unpack needle     feed2Helper needle deps +feed2Helper :: Text+            -> [((String, Version), ([(String, String)], UTCTime))]+            -> Handler RepAtomRss feed2Helper needle deps = do     now <- liftIO getCurrentTime     newsFeed Feed@@ -185,13 +206,13 @@         , feedDescription = toHtml $ "Newer dependencies for " ++ unpack needle         }   where-    go' ((name, version), (deps, time)) = FeedEntry+    go' ((name, version), (deps', time)) = FeedEntry         { feedEntryLink = Feed3R needle (pack name) (pack $ display version) (pack $ show time)         , feedEntryUpdated = time         , feedEntryTitle = pack $ "Outdated dependencies for " ++ name ++ " " ++ display version         , feedEntryContent = [shamlet| <table border="1">-    $forall d <- deps+    $forall d <- deps'         <tr>             <th>#{fst d}             <td>#{snd d}@@ -203,16 +224,79 @@     redirect   $ "http://hackage.haskell.org/package/" `append` package +main :: IO () main = do     args <- getArgs-    if args == ["--save-newest"]+    if args == ["--save-reverses"]         then do             newest <- loadNewest-            writeFile "newest" $ show newest+            writeFileL "reverses" $ encode (newest, getReverses newest)         else do-            newest <- read `fmap` readFile "newest"-            warpDebug 5005 $ PD newest $ getReverses newest+            putStrLn "Loading reverses..."+            Just (newest, reverses) <- fmap decode' $ L.readFile "reverses"+            putStrLn "Done"+            warpDebug 5005 $ PD newest reverses +instance ToJSON Version where+    toJSON = toJSONShow+instance FromJSON Version where+    parseJSON = parseJSONRead++toJSONShow :: Show a => a -> Value+toJSONShow = String . pack . show++parseJSONRead :: Read a => Value -> Parser a+parseJSONRead (String t) =+    case reads $ unpack t of+        (v, _):_ -> return v+        _ -> mzero+parseJSON _ = mzero++instance ToJSON VersionRange where+    toJSON = toJSONShow+instance FromJSON VersionRange where+    parseJSON = parseJSONRead++instance ToJSON PackInfo where+    toJSON (PackInfo a b c) = Data.Aeson.object+        [ "version" .= a+        , "desc"    .= b+        , "epoch"   .= c+        ]++instance FromJSON PackInfo where+    parseJSON (Object v) = PackInfo+        <$> v .: "version"+        <*> v .: "desc"+        <*> v .: "epoch"+    parseJSON _ = mzero++instance ToJSON DescInfo where+    toJSON (DescInfo a b c d) = Data.Aeson.object+        [ "haystack" .= a+        , "deps" .= b+        , "package" .= c+        , "synopsis" .= d+        ]++instance FromJSON DescInfo where+    parseJSON (Object v) = DescInfo+        <$> v .: "haystack"+        <*> v .: "deps"+        <*> v .: "package"+        <*> v .: "synopsis"+    parseJSON _ = mzero++instance ToJSON PackageIdentifier where+    toJSON = toJSONShow+instance FromJSON PackageIdentifier where+    parseJSON = parseJSONRead++instance ToJSON Dependency where+    toJSON = toJSONShow+instance FromJSON Dependency where+    parseJSON = parseJSONRead+ getSpecificR :: Handler RepHtml getSpecificR = do     packages' <- lookupGetParams "package"@@ -225,7 +309,8 @@                 (_, v, WontAccept cd _) -> Just (v, cd)     defaultLayout $ do         setTitle $ toHtml title-        addCassius [$cassius|body+        addCassius [cassius|+body     font-family: Arial,Helvetica,sans-serif     width: 600px     margin: 2em auto@@ -264,6 +349,7 @@         <p>Invalid package name: #{fst p} |] +getSpecificFeedR :: Text -> Handler RepAtomRss getSpecificFeedR packages' = do     PD newest _ <- getYesod     let descs = mapMaybe (flip getPackage newest) $ words $ unpack packages'@@ -297,11 +383,11 @@  getReverseListR :: Handler RepHtml getReverseListR = do-    PD _ reverse <- getYesod+    PD _ reverse' <- getYesod     defaultLayout $ do         setTitle "Reverse Dependencies"         addCassius mainCassius-        addHamlet [$hamlet|+        addHamlet [hamlet| <h1>Reverse Dependencies <p>Please choose a package below to view its reverse dependencies: those packages that depend upon it. This listing will also tell you which packages are incompatible with the current version of the package. <table@@ -309,7 +395,7 @@         <th>Package         <th>Total Dependencies         <th>Total Outdated Dependencies-    $forall p <- Map.toList reverse+    $forall p <- Map.toList reverse'         <tr>             <td                 <a href=@{ReverseR $ pack $ fst p}>#{fst p}@@ -327,8 +413,8 @@  getReverseR :: Text -> Handler RepHtml getReverseR dep = do-    PD _ reverse <- getYesod-    (version, rels) <- maybe notFound return $ Map.lookup (unpack dep) reverse+    PD _ reverse' <- getYesod+    (version, rels) <- maybe notFound return $ Map.lookup (unpack dep) reverse'     defaultLayout $ do         setTitle [shamlet|Reverse dependencies for #{dep}|]         addCassius mainCassius@@ -340,7 +426,7 @@         <th>Accepted versions     $forall rel <- rels         <tr>-            $if Map.member (fst rel) reverse+            $if Map.member (fst rel) reverse'                 <td><a href=@{ReverseR $ pack $ fst rel}>#{fst rel}             $else                 <td>#{fst rel}