shahryarjb
Getting basic information of a elixir project from GitHub
Hi, Please consider you have a project in GitHub and before running and getting it with mix deps task you want to get some basic information like what is the version and name of this library from mix.exs file.
So regex is not a good way because some people put version as global variable like @version, hence I need to run whole the mix.exs and get the version and name from it.
What is your suggesting to get mix.exs as string from GitHub and compile it? For example, and get the name and version from it or another information before installing it.
I do not know Code.eval_string(code) is useful for me and safe? All the examples in the document is about a function or operation, but not about a full module:
{:module, MishkaDeveloperTools.MixProject,
<<70, 79, 82, 49, 0, 0, 11, 156, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 1, 5,
0, 0, 0, 25, 38, 69, 108, 105, 120, 105, 114, 46, 77, 105, 115, 104, 107, 97,
68, 101, 118, 101, 108, 111, 112, 101, 114, ...>>, {:package, 0}}
After evaluating the module, I do not know how to get version for example:
MishkaDeveloperTools.MixProject.project()
Thank you in advance
Most Liked Responses
hst337
Code.eval_string is not safe. I’d suggest Code.string_to_quoted
hst337
You can just travese AST with functions provided in macro. You should look for field version in project funcion. If it contains, @version, than look for @version attirbute. If it contains something else, than there’s no safe way to fetch a version without executing code defined in this module
LostKobrakai
The AST of a keyword list is not a keyword list by itself, so you cannot use Keyword to access things. AST is an abstraction of written code, and not of the data represented by that code. You’ll need more manual approaches for filtering out the information you need.
A rather naive appraoch to getting to the information you seek would be like this:
{_ast, acc} =
Macro.postwalk(ast, %{version: nil, attributes: %{}}, fn
{:@, _, [{name, _, value}]} = ast, acc when is_atom(name) and not is_nil(value) ->
{ast, put_in(acc.attributes[name], value)}
{:version, {:@, _, [{name, _, nil}]}} = ast, acc ->
{ast, Map.put(acc, :version, {:attribute, name})}
{:version, value} = ast, acc ->
{ast, Map.put(acc, :version, value)}
ast, acc ->
{ast, acc}
end)
acc
# %{attributes: %{version: ["0.0.7"]}, version: {:attribute, :version}}
However you’d want to be more cautious as currently any later keyword list with a :version key would overwrite the returned result.
What you’re doing here is very brittle, as you’re trying to interpret code without running it, which can easily break by someone not sticking to conventions closely.








