git-freq 0.0.1 → 0.0.2
raw patch · 4 files changed
+103/−1 lines, 4 files
Files
- git-freq.cabal +6/−1
- src/Git/Freq.hs +72/−0
- src/Git/Freq/Source.hs +19/−0
- src/Git/Freq/Version.hs +6/−0
git-freq.cabal view
@@ -1,5 +1,5 @@ Name: git-freq-Version: 0.0.1+Version: 0.0.2 Author: Fujimura Daisuke<me@fujimuradaisuke.com> Maintainer: Fujimura Daisuke<me@fujimuradaisuke.com> License: BSD3@@ -14,6 +14,7 @@ Main-Is: Main.hs Default-Language: Haskell2010 GHC-Options: -Wall+ -fno-warn-name-shadowing Hs-Source-Dirs: src Build-Depends: base >= 4 && < 5 , bytestring@@ -21,11 +22,15 @@ , optparse-applicative , process , text+ Other-modules: Git.Freq+ , Git.Freq.Source+ , Git.Freq.Version 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
+ src/Git/Freq.hs view
@@ -0,0 +1,72 @@+{-# 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 Git.Freq.Source (Source)+import qualified Git.Freq.Source as Source++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++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++sumChanges :: [Change] -> Result+sumChanges = foldl incrementChange Map.empty++incrementChange :: Result -> Change -> Result+incrementChange result (fileName,numstat@(a,d)) = Map.alter f fileName result+ 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++freq' :: Source a => a -> IO [Change]+freq' source = do+ changes <- walk source []+ return $ sortResult . Map.toList $ sumChanges changes
+ src/Git/Freq/Source.hs view
@@ -0,0 +1,19 @@+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 view
@@ -0,0 +1,6 @@+module Git.Freq.Version+ ( version+ ) where++version :: String+version = "0.0.2"