This repository has been archived by the owner on Apr 1, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* initial parser and tests * graph creation and testing * support git locators * srclib converter
- Loading branch information
Showing
9 changed files
with
262 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
module Strategy.Erlang.Rebar3Tree | ||
( discover | ||
, analyze | ||
|
||
, buildGraph | ||
, rebar3TreeParser | ||
, Rebar3Dep(..) | ||
) | ||
where | ||
|
||
import Prologue | ||
|
||
import Control.Carrier.Error.Either | ||
import qualified Data.Map.Strict as M | ||
import qualified Data.Text as T | ||
import Text.Megaparsec | ||
import Text.Megaparsec.Char | ||
|
||
import DepTypes | ||
import Discovery.Walk | ||
import Effect.Exec | ||
import Graphing (Graphing, unfold) | ||
import Types | ||
|
||
discover :: HasDiscover sig m => Path Abs Dir -> m () | ||
discover = walk $ \dir _ files -> do | ||
case find (\f -> (fileName f) == "rebar.config") files of | ||
Nothing -> pure () | ||
Just _ -> runSimpleStrategy "erlang-rebar3tree" ErlangGroup $ analyze dir | ||
|
||
pure WalkContinue | ||
|
||
rebar3TreeCmd :: Command | ||
rebar3TreeCmd = Command | ||
{ cmdNames = ["rebar3"] | ||
, cmdBaseArgs = ["tree", "-v"] | ||
, cmdAllowErr = Never | ||
} | ||
|
||
analyze :: (Has Exec sig m, Has (Error ExecErr) sig m) => Path Rel Dir -> m ProjectClosureBody | ||
analyze dir = mkProjectClosure dir <$> execParser rebar3TreeParser dir rebar3TreeCmd [] | ||
|
||
mkProjectClosure :: Path Rel Dir -> [Rebar3Dep] -> ProjectClosureBody | ||
mkProjectClosure dir deps = ProjectClosureBody | ||
{ bodyModuleDir = dir | ||
, bodyDependencies = dependencies | ||
, bodyLicenses = [] | ||
} | ||
where | ||
dependencies = ProjectDependencies | ||
{ dependenciesGraph = buildGraph deps | ||
, dependenciesOptimal = NotOptimal | ||
, dependenciesComplete = NotComplete | ||
} | ||
|
||
buildGraph :: [Rebar3Dep] -> Graphing Dependency | ||
buildGraph deps = unfold deps subDeps toDependency | ||
where | ||
toDependency Rebar3Dep{..} = | ||
Dependency { dependencyType = if T.isInfixOf "github.com" depLocation then GitType else HexType | ||
, dependencyName = if T.isInfixOf "github.com" depLocation then depLocation else depName | ||
, dependencyVersion = Just (CEq depVersion) | ||
, dependencyLocations = [] | ||
, dependencyEnvironments = [] | ||
, dependencyTags = M.empty | ||
} | ||
|
||
data Rebar3Dep = Rebar3Dep | ||
{ depName :: Text | ||
, depVersion :: Text | ||
, depLocation :: Text | ||
, subDeps :: [Rebar3Dep] | ||
} deriving (Eq, Ord, Show, Generic) | ||
|
||
type Parser = Parsec Void Text | ||
|
||
rebar3TreeParser :: Parser [Rebar3Dep] | ||
rebar3TreeParser = concat <$> ((try (rebarDep 0) <|> ignoredLine) `sepBy` eol) <* eof | ||
where | ||
isEndLine :: Char -> Bool | ||
isEndLine '\n' = True | ||
isEndLine '\r' = True | ||
isEndLine _ = False | ||
|
||
-- ignore content until the end of the line | ||
ignored :: Parser () | ||
ignored = () <$ takeWhileP (Just "ignored") (not . isEndLine) | ||
|
||
ignoredLine :: Parser [Rebar3Dep] | ||
ignoredLine = do | ||
ignored | ||
pure [] | ||
|
||
findName :: Parser Text | ||
findName = takeWhileP (Just "dep") (/= '─') | ||
|
||
findVersion :: Parser Text | ||
findVersion = takeWhileP (Just "version") (/= ' ') | ||
|
||
findLocation :: Parser Text | ||
findLocation = takeWhileP (Just "location") (/= ')') | ||
|
||
rebarDep :: Int -> Parser [Rebar3Dep] | ||
rebarDep depth = do | ||
_ <- chunk " " | ||
slashCount <- many " │" | ||
_ <- satisfy (\_ -> length slashCount == depth) | ||
|
||
_ <- chunk " & " <|> chunk " ├─ " <|> chunk " ├─ " <|> chunk " └─ " | ||
dep <- findName | ||
_ <- chunk "─" | ||
version <- findVersion | ||
_ <- chunk " (" | ||
location <- findLocation | ||
_ <- chunk ")" | ||
|
||
deps <- many $ try $ rebarRecurse $ depth + 1 | ||
|
||
pure [Rebar3Dep dep version location (concat deps)] | ||
|
||
rebarRecurse :: Int -> Parser [Rebar3Dep] | ||
rebarRecurse depth = do | ||
_ <- chunk "\n" | ||
deps <- rebarDep depth | ||
pure deps |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
module Erlang.Rebar3TreeSpec | ||
( spec | ||
) where | ||
|
||
import Prologue | ||
|
||
import qualified Data.Map.Strict as M | ||
import qualified Data.Text.IO as TIO | ||
import Text.Megaparsec | ||
|
||
import DepTypes | ||
import Graphing() | ||
import Strategy.Erlang.Rebar3Tree | ||
import GraphUtil | ||
|
||
import Test.Hspec | ||
|
||
dependencyOne :: Dependency | ||
dependencyOne = Dependency { dependencyType = GitType | ||
, dependencyName = "https://github.com/dep/one" | ||
, dependencyVersion = Just (CEq "1.0.0") | ||
, dependencyLocations = [] | ||
, dependencyEnvironments = [] | ||
, dependencyTags = M.empty | ||
} | ||
|
||
dependencyTwo :: Dependency | ||
dependencyTwo = Dependency { dependencyType = HexType | ||
, dependencyName = "two" | ||
, dependencyVersion = Just (CEq "2.0.0") | ||
, dependencyLocations = [] | ||
, dependencyEnvironments = [] | ||
, dependencyTags = M.empty | ||
} | ||
dependencyThree :: Dependency | ||
dependencyThree = Dependency { dependencyType = HexType | ||
, dependencyName = "three" | ||
, dependencyVersion = Just (CEq "3.0.0") | ||
, dependencyLocations = [] | ||
, dependencyEnvironments = [] | ||
, dependencyTags = M.empty | ||
} | ||
|
||
dependencyFour :: Dependency | ||
dependencyFour = Dependency { dependencyType = GitType | ||
, dependencyName = "https://github.com/dep/four" | ||
, dependencyVersion = Just (CEq "4.0.0") | ||
, dependencyLocations = [] | ||
, dependencyEnvironments = [] | ||
, dependencyTags = M.empty | ||
} | ||
|
||
dependencyFive :: Dependency | ||
dependencyFive = Dependency { dependencyType = HexType | ||
, dependencyName = "five" | ||
, dependencyVersion = Just (CEq "5.0.0") | ||
, dependencyLocations = [] | ||
, dependencyEnvironments = [] | ||
, dependencyTags = M.empty | ||
} | ||
|
||
depOne :: Rebar3Dep | ||
depOne = Rebar3Dep | ||
{ depName = "one" | ||
, depVersion = "1.0.0" | ||
, depLocation = "https://github.com/dep/one" | ||
, subDeps = [depTwo, depFour] | ||
} | ||
|
||
depTwo :: Rebar3Dep | ||
depTwo = Rebar3Dep | ||
{ depName = "two" | ||
, depVersion = "2.0.0" | ||
, depLocation = "hex package" | ||
, subDeps = [depThree] | ||
} | ||
|
||
depThree :: Rebar3Dep | ||
depThree = Rebar3Dep | ||
{ depName = "three" | ||
, depVersion = "3.0.0" | ||
, depLocation = "hex package" | ||
, subDeps = [] | ||
} | ||
|
||
depFour :: Rebar3Dep | ||
depFour = Rebar3Dep | ||
{ depName = "four" | ||
, depVersion = "4.0.0" | ||
, depLocation = "https://github.com/dep/four" | ||
, subDeps = [] | ||
} | ||
|
||
depFive :: Rebar3Dep | ||
depFive = Rebar3Dep | ||
{ depName = "five" | ||
, depVersion = "5.0.0" | ||
, depLocation = "hex package" | ||
, subDeps = [] | ||
} | ||
|
||
spec :: Spec | ||
spec = do | ||
contents <- runIO (TIO.readFile "test/Erlang/testdata/rebar3tree") | ||
|
||
describe "rebar3 tree analyzer" $ | ||
it "produces the expected output" $ do | ||
let res = buildGraph [depOne, depFive] | ||
expectDeps [dependencyOne, dependencyTwo, dependencyThree, dependencyFour, dependencyFive] res | ||
expectDirect [dependencyOne, dependencyFive] res | ||
expectEdges [(dependencyOne, dependencyTwo), (dependencyOne, dependencyFour), (dependencyTwo, dependencyThree)] res | ||
|
||
describe "rebar3 tree parser" $ do | ||
it "parses ideal rebar3 tree output" $ do | ||
case runParser rebar3TreeParser "" contents of | ||
Left failCode -> traceM $ show failCode | ||
Right result -> result `shouldMatchList` [depOne, depFive] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
├─ one─1.0.0 (https://github.com/dep/one) | ||
│ ├─ two─2.0.0 (hex package) | ||
│ │ └─ three─3.0.0 (hex package) | ||
│ └─ four─4.0.0 (https://github.com/dep/four) | ||
└─ five─5.0.0 (hex package) |