packages feed

codex 0.2.1.10 → 0.3

raw patch · 5 files changed

+56/−148 lines, 5 filesdep +cryptohashdep +http-clientdep +lensdep −curldep ~MissingHdep ~basedep ~codexPVP ok

version bump matches the API change (PVP)

Dependencies added: cryptohash, http-client, lens, network, wreq

Dependencies removed: curl

Dependency ranges changed: MissingH, base, codex, hackage-db, yaml

API changes (from Hackage documentation)

+ Codex: md5hash :: String -> String
+ Codex: openLazyURI :: Session -> String -> IO (Either String ByteString)
+ Codex: replace :: String -> String -> String -> String
- Codex: fetch :: Codex -> PackageIdentifier -> Action FilePath
+ Codex: fetch :: Session -> Codex -> PackageIdentifier -> Action FilePath

Files

codex.cabal view
@@ -1,5 +1,5 @@ name:                codex-version:             0.2.1.10+version:             0.3 synopsis:            A ctags file generator for cabal project dependencies. description:   This tool download and cache the source code of packages in your local hackage,@@ -29,26 +29,27 @@     Codex.Project     Codex.Internal     Distribution.Sandbox.Utils-  other-modules:-    Network.Curl.DownloadLazy   build-depends:       base                >= 4.6.0.1    && < 5     , bytestring          >= 0.10.0.2   && < 0.11     , Cabal               >= 1.18       && < 1.23+    , cryptohash          >= 0.11       && < 0.12     , containers          >= 0.5.0.0    && < 0.6-    , curl                >= 1.3.8      && < 1.4     , directory           >= 1.2.0.1    && < 1.3     , either              >= 4.3.0.1    && < 4.4     , filepath            >= 1.3.0.1    && < 1.5-    , hackage-db          >= 1.8        && < 2+    , hackage-db          >= 1.22       && < 2+    , http-client         >= 0.4        && < 0.5+    , lens                >= 4.6        && < 5     , machines            >= 0.2        && < 0.6     , machines-directory  >= 0.0.0.2    && < 0.3-    , MissingH            >= 1.2.1.0    && < 1.4+    -- , MissingH            >= 1.2.1.0    && < 1.4     , process             >= 1.1.0.2    && < 1.3     , tar                 >= 0.4.0.1    && < 0.5     , text                >= 1.1.1.3    && < 1.3     , transformers        >= 0.3.0.0    && < 0.5     , yaml                >= 0.8.8.3    && < 0.9+    , wreq                >= 0.3.0.1    && < 0.5     , zlib                >= 0.5.4.1    && < 0.6  executable codex@@ -72,7 +73,10 @@     , MissingH     , yaml     , monad-loops         >= 0.4.2      && < 0.5-    , codex               == 0.2.1.10+    , network             >= 2.6        && < 2.7+    , wreq+    , yaml                +    , codex               == 0.3  source-repository head   type:     git
codex/Main.hs view
@@ -6,6 +6,8 @@ import Data.List import Data.String.Utils import Distribution.Text+import Network.Socket (withSocketsDo)+import Network.Wreq.Session (withSession) import Paths_codex (version) import System.Directory import System.Environment@@ -63,13 +65,13 @@       either (const True) id <$> (runEitherT $ isUpdateRequired cx dependencies projectHash)     else return True -  if (shouldUpdate || force) then do+  if force || shouldUpdate then do     let workspaceProjects = if not $ currentProjectIncluded cx then workspaceProjects'         else (WorkspaceProject project ".") : workspaceProjects'     fileExist <- doesFileExist tagsFile     when fileExist $ removeFile tagsFile     putStrLn $ concat ["Updating ", display project]-    results <- traverse (retrying 3 . runEitherT . getTags) dependencies+    results <- withSession $ \s -> traverse (retrying 3 . runEitherT . getTags s) dependencies     _       <- traverse print . concat $ lefts results     res     <- runEitherT $ assembly cx dependencies projectHash workspaceProjects tagsFile     either print (const $ return ()) res@@ -77,11 +79,11 @@     putStrLn "Nothing to update."   where     tagsFile = tagsFileName cx-    getTags i = status cx i >>= \x -> case x of-      (Source Tagged)   -> return ()-      (Source Untagged) -> tags cx i >> getTags i-      (Archive)         -> extract cx i >> getTags i-      (Remote)          -> fetch cx i >> getTags i+    getTags s i = status cx i >>= \x -> case x of+      Source Tagged   -> return ()+      Source Untagged -> tags cx i >> getTags s i+      Archive         -> extract cx i >> getTags s i+      Remote          -> fetch s cx i >> getTags s i  help :: IO () help = putStrLn $@@ -100,7 +102,7 @@           , "Note: codex will browse the parent directory for cabal projects and use them as dependency over hackage when possible." ]  main :: IO ()-main = do+main = withSocketsDo $ do   cx    <- loadConfig   args  <- getArgs   run cx args where
src/Codex.hs view
@@ -1,17 +1,17 @@ module Codex (Codex(..), defaultTagsFileName, Verbosity, module Codex) where  import Control.Exception (try, SomeException)+import Control.Lens ((^.))+import Control.Lens.Review (bimap) import Control.Monad import Control.Monad.IO.Class import Control.Monad.Trans.Either-import Data.Hash.MD5 import Data.Machine import Data.Maybe-import Data.String.Utils hiding (join) import Distribution.Package import Distribution.Text import Distribution.Verbosity-import Network.Curl.DownloadLazy+import Network.HTTP.Client (HttpException) import System.Directory import System.Directory.Machine (files, directoryWalk) import System.FilePath@@ -19,17 +19,30 @@  import qualified Codec.Archive.Tar as Tar import qualified Codec.Compression.GZip as GZip+import qualified Crypto.Hash.MD5 as MD5+import qualified Data.ByteString.Char8 as C8 import qualified Data.ByteString.Lazy as BS import qualified Data.List as List import qualified Data.Text as Text import qualified Data.Text.Lazy as TextL import qualified Data.Text.Lazy.IO as TLIO+import qualified Network.Wreq as W+import qualified Network.Wreq.Session as WS+import qualified Text.Printf as Printf  import Codex.Internal import Codex.Project  -- TODO Replace the `Codex` context with a `Control.Reader.Monad `. +-- TODO Remove that function once using `Text` widely+replace :: String -> String -> String -> String+replace a b c = Text.unpack $ Text.replace (Text.pack a) (Text.pack b) (Text.pack c)++md5hash :: String -> String+md5hash = concatMap (Printf.printf "%02x") . C8.unpack . MD5.hash . C8.pack++ data Tagging = Tagged | Untagged   deriving (Eq, Show) @@ -46,10 +59,10 @@   deriving (Eq, Show, Read)  taggerCmd :: Tagger -> String-taggerCmd Ctags = "ctags --tag-relative=no --recurse -f '$TAGS' '$SOURCES'"-taggerCmd Hasktags = "hasktags --ctags --output='$TAGS' '$SOURCES'"-taggerCmd HasktagsEmacs = "hasktags --etags --output='$TAGS' '$SOURCES'"-taggerCmd HasktagsExtended = "hasktags --ctags --extendedctag --output='$TAGS' '$SOURCES'"+taggerCmd Ctags = "ctags --tag-relative=no --recurse -f \"$TAGS\" \"$SOURCES\""+taggerCmd Hasktags = "hasktags --ctags --output=\"$TAGS\" \"$SOURCES\""+taggerCmd HasktagsEmacs = "hasktags --etags --output=\"$TAGS\" \"$SOURCES\""+taggerCmd HasktagsExtended = "hasktags --ctags --extendedctag --output=\"$TAGS\" \"$SOURCES\""  taggerCmdRun :: Codex -> FilePath -> FilePath -> Action FilePath taggerCmdRun cx sources tags' = do@@ -65,18 +78,18 @@   either (left . show) return res  codexHash :: Codex -> String-codexHash cfg = md5s . Str $ show cfg+codexHash cfg = md5hash $ show cfg  dependenciesHash :: [PackageIdentifier] -> String-dependenciesHash xs = md5s . Str $ xs >>= display+dependenciesHash xs = md5hash $ xs >>= display  tagsFileHash :: Codex -> [PackageIdentifier] -> String -> String-tagsFileHash cx ds projectHash = md5s . Str $ concat [codexHash cx, dependenciesHash ds, projectHash]+tagsFileHash cx ds projectHash = md5hash $ concat [codexHash cx, dependenciesHash ds, projectHash]  computeCurrentProjectHash :: Codex -> IO String computeCurrentProjectHash cx = if not $ currentProjectIncluded cx then return "*" else do   xs <- runT $ (autoM getModificationTime) <~ (filtered p) <~ files <~ directoryWalk <~ source ["."]-  return . md5s . Str . show $ maximum xs+  return . md5hash . show $ maximum xs     where       p fp = any (\f -> f fp) (fmap List.isSuffixOf extensions)       extensions = [".hs", ".lhs", ".hsc"]@@ -102,16 +115,21 @@     (_, True) -> return Archive     (_, _)    -> return Remote -fetch :: Codex -> PackageIdentifier -> Action FilePath-fetch cx i = do+fetch :: WS.Session -> Codex -> PackageIdentifier -> Action FilePath+fetch s cx i = do   bs <- tryIO $ do     createDirectoryIfMissing True (packagePath cx i)-    openLazyURI url+    openLazyURI s url   either left write bs where     write bs = fmap (const archivePath) $ tryIO $ BS.writeFile archivePath bs     archivePath = packageArchive cx i     url = packageUrl i +openLazyURI :: WS.Session -> String -> IO (Either String BS.ByteString)+openLazyURI s = fmap (bimap showHttpEx (^. W.responseBody)) . try . WS.get s where+  showHttpEx :: HttpException -> String+  showHttpEx = show+ extract :: Codex -> PackageIdentifier -> Action FilePath extract cx i = fmap (const path) . tryIO $ read' path (packageArchive cx i) where   read' dir tar = Tar.unpack dir . Tar.read . GZip.decompress =<< BS.readFile tar@@ -139,7 +157,7 @@       let xs = concat $ fmap TextL.lines contents       let ys = if sorted then List.sort xs else xs       TLIO.writeFile o' $ TextL.unlines (concat [headers, ys])-    tags' i = packageTags cx i+    tags' = packageTags cx     headers = if tagsFileHeader cx then fmap TextL.pack [headerFormat, headerSorted, headerHash] else []     headerFormat = "!_TAG_FILE_FORMAT\t2"     headerSorted = concat ["!_TAG_FILE_SORTED\t", if sorted then "1" else "0"]
src/Codex/Project.hs view
@@ -3,7 +3,6 @@ import Control.Exception (try, SomeException) import Data.Function import Data.Maybe-import Data.String.Utils import Distribution.InstalledPackageInfo import Distribution.Hackage.DB (Hackage, readHackage) import Distribution.Package@@ -43,7 +42,7 @@ findPackageDescription :: FilePath -> IO (Maybe GenericPackageDescription) findPackageDescription root = do   files <- getDirectoryContents root-  traverse (readPackageDescription silent) $ fmap (\x -> root </> x) $ List.find (endswith ".cabal") files+  traverse (readPackageDescription silent) $ fmap (\x -> root </> x) $ List.find (List.isSuffixOf ".cabal") files  resolveCurrentProjectDependencies :: IO ProjectDependencies resolveCurrentProjectDependencies = do@@ -133,4 +132,4 @@       if isDirectory then readWorkspaceProject path else return Nothing     listDirectory fp = do       xs <- getDirectoryContents fp-      return . fmap (fp </>) $ filter (not . startswith ".") xs+      return . fmap (fp </>) $ filter (not . List.isPrefixOf ".") xs
− src/Network/Curl/DownloadLazy.hs
@@ -1,115 +0,0 @@--- TODO Remove once https://github.com/GaloisInc/curl/pull/11 is released.------------------------------------------------------------------------- |--- Module    : Network.Curl.DownloadLazy--- Copyright : (c) Don Stewart--- License   : BSD3------ Stability :  provisional--- Portability: posix------ This module is equivalent to download-curl's Network.Curl.Download.Lazy--- A binding to curl, an efficient, high level library for--- retrieving files using Uniform Resource Locators (URLs).------ Content may be retrieved as a lazy "ByteString".------ Error handling is encapsulated in the "Either" type.--------------------------------------------------------------------------module Network.Curl.DownloadLazy (-        -- * The basic lazy interface to network content-          openLazyURI-        , openLazyURIWithOpts--    ) where--import           Foreign-import           Network.Curl--import           Data.IORef--import qualified Data.ByteString.Internal      as S-import qualified Data.ByteString.Lazy.Internal as L------------------------------------------------------------------------------ | Download content specified by a url using curl, returning the--- content as a lazy "ByteString".------ If an error occurs, "Left" is returned, with a--- protocol-specific error string.------ Examples:------ > openLazyURI "http://haskell.org"----openLazyURI :: String -> IO (Either String L.ByteString)-openLazyURI = openLazyURIWithOpts []---- | Like openURI, but takes curl options.------ Examples:------ > openLazyURIWithOpts [CurlPost True] "http://haskell.org"----openLazyURIWithOpts :: [CurlOption] -> String -> IO (Either String L.ByteString)-openLazyURIWithOpts opts s = case parseURL s of-     Nothing  -> return $ Left $ "Malformed url: "++ s-     Just url -> do-        e <- getFile url opts-        return $ case e of-             Left err   -> Left $ "Failed to connect: " ++ err-             Right src  -> Right src----------------------------------------------------------------------------- Internal:-----newtype URL = URL String--parseURL :: String -> Maybe URL-parseURL s = Just (URL s) -- no parsing--getFile :: URL -> [CurlOption] -> IO (Either String L.ByteString)-getFile (URL url) flags = do-    h   <- initialize-    ref <- newIORef L.Empty--    _ <- setopt h (CurlFailOnError True)-    setDefaultSSLOpts h url-    _ <- setopt h (CurlURL url)-    _ <- setopt h (CurlWriteFunction (gather ref))-    mapM_ (setopt h) flags-    rc         <- perform h-    chunks     <- readIORef ref--    return $ if rc /= CurlOK-        then Left (show rc)-        else Right $! revSpine chunks----          fp <- newForeignPtr finalizerFree buf'---          return (Right $! S.fromForeignPtr fp 0 (fromIntegral sz))--gather :: IORef L.ByteString -> WriteFunction-gather r = writer $ \chunk -> do-    chunks <- readIORef r-    let chunks' = L.Chunk chunk chunks-    writeIORef r $! chunks'---- memcpy chunks of data into our bytestring.-writer :: (S.ByteString -> IO ()) -> WriteFunction-writer f src sz nelems _ = do-    let n' = sz * nelems-    f =<< S.create (fromIntegral n') (\dest -> S.memcpy dest (castPtr src) (fromIntegral n'))-    return n'----- reverse just the spine of a lazy bytestring-revSpine :: L.ByteString -> L.ByteString-revSpine l =  rev l L.Empty-  where-    rev L.Empty a        = a-    rev (L.Chunk x xs) a = rev xs (L.Chunk x a)