Skip to content

Instantly share code, notes, and snippets.

@valderman
Last active May 11, 2017 23:21
Show Gist options
  • Save valderman/39fed55452ed0720093f6cfd288e994e to your computer and use it in GitHub Desktop.
Save valderman/39fed55452ed0720093f6cfd288e994e to your computer and use it in GitHub Desktop.
Calculate per-commit statistics for git repos
import Control.Shell
type CommitId = String
main = shell_ $ do
case cmdline of
[repo] -> inDirectory repo $ do
cids <- getCommitIds
formatDiffStat =<< zipWithM getDiffLines cids (drop 1 cids)
_ -> do
echo "usage: commitinspector <repo>"
getCommitIds :: Shell [CommitId]
getCommitIds = do
s <- capture $ run "git" ["--no-pager", "log", "--no-merges"] |> run "egrep" ["^commit"]
return [drop 7 ln | ln <- lines s]
getDiffLines :: CommitId -> CommitId -> Shell (Int, Int)
getDiffLines new old = do
diffstat <- capture $ run "git" ["diff", "--stat", old, new]
case lines diffstat of
[] -> return (0, 0)
_ -> return $ changes diffstat
where
changes = diffPair . map twoWords . drop 1 . breakAll (== ',') . lastLine
diffPair [[a, _], [d, _]] = (read a, read d)
diffPair [[count, what]]
| '+' `elem` what = (read count, 0)
| '-' `elem` what = (0, read count)
twoWords = take 2 . words
lastLine = last . lines
breakAll p xs =
case break p xs of
([], []) -> []
(s, []) -> [s]
(s, _:ss) -> s : breakAll p ss
formatDiffStat :: [(Int, Int)] -> Shell ()
formatDiffStat chs = do
echo $ init $ unlines
[ "Total # of commits: " ++ show commits
, "Total # of additions: " ++ show totalAdds
, "Total # of deletions: " ++ show totalDels
, "Avg. # of additions per commit: " ++ show avgAdds
, "Avg. # of deletions per commit: " ++ show avgDels
]
where
totalAdds = sum (map fst chs)
totalDels = sum (map snd chs)
total = totalAdds + totalDels
commits = length chs
avgAdds = fromIntegral totalAdds / fromIntegral commits
avgDels = fromIntegral totalDels / fromIntegral commits
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment