packages feed

git-freq 0.0.2 → 0.0.3

raw patch · 6 files changed

+101/−137 lines, 6 filesdep +io-streamssetup-changed

Dependencies added: io-streams

Files

− Setup.hs
@@ -1,2 +0,0 @@-import Distribution.Simple-main = defaultMain
git-freq.cabal view
@@ -1,47 +1,48 @@-Name:                   git-freq-Version:                0.0.2-Author:                 Fujimura Daisuke<me@fujimuradaisuke.com>-Maintainer:             Fujimura Daisuke<me@fujimuradaisuke.com>-License:                BSD3-License-File:           LICENSE-Synopsis:               A Git subcommand to show total addition, deletion per file-Description:            A Git subcommand to show total addition, deletion per file-Cabal-Version:          >= 1.10-Homepage:               https://github.com/fujimura/git-freq-Build-Type:             Simple+name: git-freq+version: 0.0.3+cabal-version: >=1.10+build-type: Simple+license: BSD3+license-file: LICENSE+maintainer: Fujimura Daisuke<me@fujimuradaisuke.com>+homepage: https://github.com/fujimura/git-freq+synopsis: A Git subcommand to show total addition, deletion per file+description:+    A Git subcommand to show total addition, deletion per file+author: Fujimura Daisuke<me@fujimuradaisuke.com> -Executable git-freq-  Main-Is:              Main.hs-  Default-Language:     Haskell2010-  GHC-Options:          -Wall-                        -fno-warn-name-shadowing-  Hs-Source-Dirs:       src-  Build-Depends:        base >= 4 && < 5-                      , bytestring-                      , containers-                      , optparse-applicative-                      , process-                      , text-  Other-modules:        Git.Freq-                      , Git.Freq.Source-                      , Git.Freq.Version+source-repository head+    type: git+    location: git@github.com:fujimura/git-freq.git -test-suite spec-  Main-Is:              Spec.hs-  Default-Language:     Haskell2010-  GHC-Options:          -Wall-                        -fno-warn-name-shadowing-  Hs-Source-Dirs:       src-                      , test-  Type:                 exitcode-stdio-1.0-  Build-Depends:        base-                      , bytestring-                      , containers-                      , hspec-                      , optparse-applicative-                      , process-                      , text+executable git-freq+    main-is: Main.hs+    build-depends:+        base >=4 && <5,+        bytestring -any,+        containers -any,+        io-streams -any,+        optparse-applicative -any,+        process -any,+        text -any+    default-language: Haskell2010+    hs-source-dirs: src+    other-modules:+        Git.Freq+    ghc-options: -Wall -fno-warn-name-shadowing -Source-Repository head-  Type:                 git-  Location:             git@github.com:fujimura/git-freq.git+test-suite spec+    type: exitcode-stdio-1.0+    main-is: Spec.hs+    build-depends:+        base -any,+        bytestring -any,+        containers -any,+        io-streams -any,+        hspec -any,+        optparse-applicative -any,+        process -any,+        text -any+    default-language: Haskell2010+    hs-source-dirs: src test+    ghc-options: -Wall -fno-warn-name-shadowing
src/Git/Freq.hs view
@@ -1,46 +1,46 @@ {-# LANGUAGE OverloadedStrings #-} module Git.Freq where -import           Control.Arrow   ((***))-import           Data.List       (sortBy)-import           Data.Map.Strict (Map)-import qualified Data.Map.Strict as Map-import           Data.Monoid-import           Data.Text       (Text)-import qualified Data.Text       as T-import qualified Data.Text.IO    as T-import           System.Process  (runInteractiveProcess)-import           Text.Read       (readMaybe)+import           Control.Arrow      ((***))+import           Data.ByteString    (ByteString)+import           Data.List          (sortBy)+import           Data.Map.Strict    (Map)+import qualified Data.Map.Strict    as Map+import           Data.Text          (Text)+import qualified Data.Text          as T+import qualified Data.Text.Encoding as T+import qualified Data.Text.IO       as T+import           Text.Read          (readMaybe) -import           Git.Freq.Source (Source)-import qualified Git.Freq.Source as Source+import           System.IO.Streams  (InputStream)+import qualified System.IO.Streams  as Streams  type FileName = Text type NumStat = (Int, Int) type Change = (FileName, NumStat) type Result = Map FileName NumStat -parseLine :: Text -> Maybe Change-parseLine = go . T.splitOn (T.pack "\t")-    where go :: [Text] -> Maybe Change-          go (_:_:"":_) = Nothing-          go (added:deleted:filename:_) =-            case (readIntMaybe added, readIntMaybe deleted) of-                (Just a, Just d) -> Just (filename, (a, d))-                _                -> Nothing-          go _ = Nothing-          readIntMaybe x = readMaybe (T.unpack x) :: Maybe Int+freq :: [FilePath] -> IO ()+freq paths = do+    r <- getNumStatStream paths >>= freq'+    mapM_ render (sortResult $ Map.toList r) -walk :: Source a => a -> [Change] -> IO [Change]-walk h changes = do-    eof <- Source.isEOF h-    if eof then return changes-           else do-             l <- Source.getLine h-             case parseLine l of-               Just c  -> walk h (c:changes)-               Nothing -> walk h changes+getNumStatStream :: [FilePath] -> IO (InputStream ByteString)+getNumStatStream paths = do+  let args = ["log"+             , "--numstat"+             , "--pretty=\"%0\""+             ] ++ paths +  (_,is,_,_) <- Streams.runInteractiveProcess "git" args Nothing Nothing+  return is++freq' :: InputStream ByteString -> IO Result+freq' is = Streams.lines is >>=+           Streams.map (parseLine . T.decodeUtf8) >>=+           Streams.mapMaybe id >>=+           Streams.fold incrementChange Map.empty+ sumChanges :: [Change] -> Result sumChanges = foldl incrementChange Map.empty @@ -49,24 +49,20 @@   where     f numstat' = Just $ maybe numstat ((a+) *** (d+)) numstat' -render :: Change -> IO ()-render (fileName,(added,deleted)) =-    T.putStrLn . T.pack . mconcat $ [T.unpack fileName, ",",  show added, ",", show deleted]- sortResult :: [Change] -> [Change] sortResult = let f (_,(xa,xd)) (_,(ya,yd)) = (ya+yd) `compare` (xa+xd) in sortBy f -freq :: [FilePath] -> IO ()-freq paths = do-    let args = ["log"-               , "--numstat"-               , "--pretty=\"%0\""-               ] ++ paths--    (_,out,_,_) <- runInteractiveProcess "git" args Nothing Nothing-    freq' out >>= mapM_ render+parseLine :: Text -> Maybe Change+parseLine = go . T.splitOn (T.pack "\t")+    where go :: [Text] -> Maybe Change+          go (_:_:"":_) = Nothing+          go (added:deleted:filename:_) =+            case (readIntMaybe added, readIntMaybe deleted) of+                (Just a, Just d) -> Just (filename, (a, d))+                _                -> Nothing+          go _ = Nothing+          readIntMaybe x = readMaybe (T.unpack x) :: Maybe Int -freq' :: Source a => a -> IO [Change]-freq' source = do-    changes <- walk source []-    return $ sortResult . Map.toList $ sumChanges changes+render :: Change -> IO ()+render (fileName,(added,deleted)) =+    T.putStrLn . T.pack . mconcat $ [T.unpack fileName, ",",  show added, ",", show deleted]
− src/Git/Freq/Source.hs
@@ -1,19 +0,0 @@-module Git.Freq.Source-  ( Source-  , getLine-  , isEOF-  ) where--import           Data.Text    (Text)-import qualified Data.Text.IO as T-import           Prelude      hiding (getLine)-import           System.IO    (Handle)-import qualified System.IO    as IO--class Source s where-    isEOF :: s -> IO Bool-    getLine :: s -> IO Text--instance Source Handle where-    isEOF = IO.hIsEOF-    getLine = T.hGetLine
− src/Git/Freq/Version.hs
@@ -1,6 +0,0 @@-module Git.Freq.Version-  ( version-  ) where--version :: String-version = "0.0.2"
src/Main.hs view
@@ -1,32 +1,26 @@ module Main where +import           Data.Version        (showVersion) import           Git.Freq-import qualified Git.Freq.Version    as Version import           Options.Applicative-+import qualified Paths_git_freq      (version) -data Config = Config-  { version :: Bool-  , paths :: [FilePath]-  }+filePaths :: Parser [FilePath]+filePaths = many (argument str (metavar "PATH..." <> help "Target paths")) -config :: Parser Config-config = Config-  <$> switch-      (long "version" <> short 'v' <> help "Show version")-  <*> many-      (argument str (metavar "PATH..." <> help "Target paths"))+version :: Parser (a -> a)+version = infoOption (showVersion Paths_git_freq.version)+  (  short 'v'+  <> long "version"+  <> help "Print version information" )  main :: IO ()-main = do-    (Config showVersion paths) <- execParser opts-    if showVersion then putStrLn Version.version-                   else freq paths+main = execParser opts >>= freq   where-    opts = info (helper <*> config)+    opts = info (helper <*> version <*> filePaths)       ( fullDesc       <> progDesc (unlines [ "Total addition, deletion per file will be shown as a csv in following format:"                             , "`file name, addition, deletion`"                             ]) -     <> header "git-freq - Show frequently changed code in the repository")+     <> header "git-freq - Show frequently changed code in a repository")