-
Notifications
You must be signed in to change notification settings - Fork 4
/
mess.exs
executable file
·58 lines (43 loc) · 2.48 KB
/
mess.exs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# Copyright (c) 2020 James Laver, mess Contributors
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
if not Code.ensure_loaded?(Mess) do
defmodule Mess do
@moduledoc """
Helper for using dependencies specified in simpler text files in an Elixir mix project.
"""
@sources [path: "deps.path", git: "deps.git", hex: "deps.hex"]
@newline ~r/(?:\r\n|[\r\n])/
@parser ~r/^(?<indent>\s*)((?<package>[a-z_][a-z0-9_]+)\s*=\s*"(?<value>[^"]+)")?(?<post>.*)/
@git_branch ~r/(?<repo>[^#]+)(#(?<branch>.+))?/
@doc "Takes a list of sources and a list of existing dependencies, and returns a new list of unique dependencies that include the packages specified in the sources. The sources list specifies where to find the list(s) of dependencies. Each source is a keyword list of a source type and the path to the file where those type of dependencies are specified. The possible source types are path, git, and hex."
def deps(sources \\ @sources, deps),
do: deps(Enum.flat_map(sources, fn {k, v} -> read(v, k) end), deps, :deps)
defp deps(packages, deps, :deps),
do: deps(Enum.flat_map(packages, &dep_spec/1), deps, :uniq)
defp deps(packages, deps, :uniq),
do: Enum.uniq_by(deps ++ packages, &elem(&1, 0))
defp read(path, kind) when is_binary(path), do: read(File.read(path), kind)
defp read({:error, :enoent}, _kind), do: []
defp read({:ok, file}, kind),
do: Enum.map(String.split(file, @newline), &read_line(&1, kind))
defp read_line(line, kind),
do: Map.put(Regex.named_captures(@parser, line), :kind, kind)
defp dep_spec(%{"package" => ""}), do: []
defp dep_spec(%{"package" => p, "value" => v, :kind => :hex}),
do: pkg(p, v, override: true)
defp dep_spec(%{"package" => p, "value" => v, :kind => :path}),
do: pkg(p, path: v, override: true)
defp dep_spec(%{"package" => p, "value" => v, :kind => :git}), do: git(v, p)
defp git(line, p) when is_binary(line),
do: git(Regex.named_captures(@git_branch, line), p)
defp git(%{"branch" => "", "repo" => r}, p),
do: pkg(p, git: r, override: true)
defp git(%{"branch" => b, "repo" => r}, p),
do: pkg(p, git: r, branch: b, override: true)
defp pkg(name, opts), do: [{String.to_atom(name), opts}]
defp pkg(name, version, opts), do: [{String.to_atom(name), version, opts}]
end
end