2017-03-31 22:10:16 +03:00
|
|
|
{-# LANGUAGE DataKinds, GADTs #-}
|
2017-03-31 18:52:51 +03:00
|
|
|
module Command
|
|
|
|
( module C
|
|
|
|
) where
|
|
|
|
|
|
|
|
import Command.Diff as C
|
|
|
|
import Command.Parse as C
|
2017-03-31 19:58:17 +03:00
|
|
|
import Control.Monad.Free.Freer
|
2017-04-01 00:03:17 +03:00
|
|
|
import Data.Functor.Both
|
2017-03-31 22:53:49 +03:00
|
|
|
import Data.List ((\\))
|
2017-03-31 22:45:33 +03:00
|
|
|
import Data.RandomWalkSimilarity
|
2017-03-31 22:10:16 +03:00
|
|
|
import Data.Record
|
2017-03-31 21:28:36 +03:00
|
|
|
import Data.String
|
|
|
|
import Debug.Trace (traceEventIO)
|
2017-03-31 22:33:24 +03:00
|
|
|
import Diff
|
2017-03-31 22:10:16 +03:00
|
|
|
import Info
|
2017-03-31 22:45:33 +03:00
|
|
|
import Interpreter
|
2017-03-31 21:28:36 +03:00
|
|
|
import qualified Git
|
|
|
|
import Git.Blob
|
|
|
|
import Git.Libgit2
|
2017-04-03 19:04:54 +03:00
|
|
|
import Git.Libgit2.Backend
|
2017-03-31 21:28:36 +03:00
|
|
|
import Git.Repository
|
|
|
|
import Git.Types
|
|
|
|
import GitmonClient
|
2017-03-31 22:10:16 +03:00
|
|
|
import Language
|
2017-03-31 19:58:17 +03:00
|
|
|
import Prologue
|
2017-04-01 00:03:17 +03:00
|
|
|
import Renderer
|
2017-03-31 19:58:17 +03:00
|
|
|
import Source
|
2017-03-31 22:10:16 +03:00
|
|
|
import Syntax
|
|
|
|
import Term
|
2017-03-31 19:58:17 +03:00
|
|
|
|
|
|
|
data CommandF f where
|
|
|
|
ReadFile :: FilePath -> CommandF SourceBlob
|
2017-04-03 19:04:54 +03:00
|
|
|
ReadFilesAtSHAs :: FilePath -> [FilePath] -> [FilePath] -> String -> String -> CommandF [(SourceBlob, SourceBlob)]
|
2017-03-31 21:28:36 +03:00
|
|
|
|
2017-03-31 22:22:26 +03:00
|
|
|
Parse :: Language -> SourceBlob -> CommandF (Term (Syntax Text) (Record DefaultFields))
|
2017-03-31 21:28:36 +03:00
|
|
|
|
2017-03-31 22:33:24 +03:00
|
|
|
Diff :: Term (Syntax Text) (Record DefaultFields) -> Term (Syntax Text) (Record DefaultFields) -> CommandF (Diff (Syntax Text) (Record DefaultFields))
|
|
|
|
|
2017-04-01 00:03:17 +03:00
|
|
|
RenderDiff :: DiffRenderer fields output -> SourceBlob -> SourceBlob -> Diff (Syntax Text) (Record fields) -> CommandF output
|
2017-03-31 21:28:36 +03:00
|
|
|
|
|
|
|
-- parallelize diffs of a list of paths + git shas
|
|
|
|
-- alternateObjectDirs??
|
2017-03-31 19:58:17 +03:00
|
|
|
|
|
|
|
type Command = Freer CommandF
|
2017-03-31 19:58:27 +03:00
|
|
|
|
2017-03-31 22:29:15 +03:00
|
|
|
|
|
|
|
-- Evaluation
|
|
|
|
|
2017-03-31 19:58:27 +03:00
|
|
|
runCommand :: Command a -> IO a
|
|
|
|
runCommand = iterFreerA $ \ command yield -> case command of
|
2017-04-03 19:02:40 +03:00
|
|
|
ReadFile path -> runReadFile path >>= yield
|
2017-04-03 19:04:54 +03:00
|
|
|
ReadFilesAtSHAs gitDir alternateObjectDirs paths sha1 sha2 -> runReadFilesAtSHAs gitDir alternateObjectDirs paths sha1 sha2 >>= yield
|
2017-04-03 19:02:40 +03:00
|
|
|
Parse language blob -> runParse language blob >>= yield
|
|
|
|
Diff term1 term2 -> yield (runDiff term1 term2)
|
|
|
|
RenderDiff renderer blob1 blob2 diff -> yield (runRenderDiff renderer blob1 blob2 diff)
|
|
|
|
|
|
|
|
runReadFile :: FilePath -> IO SourceBlob
|
|
|
|
runReadFile path = do
|
|
|
|
source <- readAndTranscodeFile path
|
|
|
|
return (sourceBlob source path)
|
|
|
|
|
2017-04-03 19:04:54 +03:00
|
|
|
runReadFilesAtSHAs :: FilePath -> [FilePath] -> [FilePath] -> String -> String -> IO [(SourceBlob, SourceBlob)]
|
|
|
|
runReadFilesAtSHAs gitDir alternateObjectDirs paths sha1 sha2 = withRepository lgFactory gitDir $ do
|
|
|
|
repo <- getRepository
|
|
|
|
for_ alternateObjectDirs (liftIO . odbBackendAddPath repo . toS)
|
2017-04-03 19:02:40 +03:00
|
|
|
|
|
|
|
liftIO $ traceEventIO ("START readFilesAtSHAs: " <> show paths)
|
|
|
|
|
|
|
|
tree1 <- treeForSha sha1
|
|
|
|
tree2 <- treeForSha sha2
|
|
|
|
|
|
|
|
paths <- case paths of
|
|
|
|
(_ : _) -> pure paths
|
|
|
|
[] -> do
|
|
|
|
a <- pathsForTree tree1
|
|
|
|
b <- pathsForTree tree2
|
|
|
|
|
|
|
|
pure $! (a \\ b) <> (b \\ a)
|
|
|
|
|
|
|
|
blobs <- for paths $ \ path -> (,) <$> blobForPathInTree path tree1 <*> blobForPathInTree path tree2
|
|
|
|
|
|
|
|
|
|
|
|
liftIO $! traceEventIO ("END readFilesAtSHAs: " <> show paths)
|
|
|
|
return blobs
|
|
|
|
where treeForSha sha = do
|
|
|
|
obj <- parseObjOid (toS sha)
|
|
|
|
commit <- reportGitmon "cat-file" $ lookupCommit obj
|
|
|
|
reportGitmon "cat-file" $ lookupTree (commitTree commit)
|
|
|
|
blobForPathInTree path tree = do
|
|
|
|
entry <- reportGitmon "ls-tree" $ treeEntry tree (toS path)
|
|
|
|
case entry of
|
|
|
|
Just (BlobEntry entryOid entryKind) -> do
|
|
|
|
blob <- reportGitmon "cat-file" $ lookupBlob entryOid
|
|
|
|
contents <- blobToByteString blob
|
|
|
|
transcoded <- liftIO $ transcode contents
|
|
|
|
let oid = renderObjOid $ blobOid blob
|
|
|
|
pure $! SourceBlob transcoded (toS oid) path (Just (toSourceKind entryKind))
|
|
|
|
_ -> pure $! emptySourceBlob path
|
|
|
|
pathsForTree tree = do
|
|
|
|
blobEntries <- reportGitmon "ls-tree" $ treeBlobEntries tree
|
|
|
|
return $! fmap (\ (p, _, _) -> toS p) blobEntries
|
|
|
|
|
|
|
|
toSourceKind (Git.PlainBlob mode) = Source.PlainBlob mode
|
|
|
|
toSourceKind (Git.ExecutableBlob mode) = Source.ExecutableBlob mode
|
|
|
|
toSourceKind (Git.SymlinkBlob mode) = Source.SymlinkBlob mode
|
|
|
|
|
|
|
|
runParse :: Language -> SourceBlob -> IO (Term (Syntax Text) (Record DefaultFields))
|
2017-04-03 19:05:52 +03:00
|
|
|
runParse = parserForLanguage
|
2017-04-03 19:02:40 +03:00
|
|
|
|
|
|
|
runDiff :: Term (Syntax Text) (Record DefaultFields) -> Term (Syntax Text) (Record DefaultFields) -> Diff (Syntax Text) (Record DefaultFields)
|
|
|
|
runDiff term1 term2 = stripDiff (diffTerms (decorate term1) (decorate term2))
|
|
|
|
where decorate = defaultFeatureVectorDecorator getLabel
|
|
|
|
getLabel :: TermF (Syntax Text) (Record DefaultFields) a -> (Category, Maybe Text)
|
|
|
|
getLabel (h :< t) = (Info.category h, case t of
|
|
|
|
Leaf s -> Just s
|
|
|
|
_ -> Nothing)
|
|
|
|
|
|
|
|
runRenderDiff :: DiffRenderer fields output -> SourceBlob -> SourceBlob -> Diff (Syntax Text) (Record fields) -> output
|
2017-04-03 19:05:52 +03:00
|
|
|
runRenderDiff renderer = (runDiffRenderer' renderer .) . both
|