Packages
Fireside is a small Elixir library that allows importing code components (templates) into an existing Elixir project together with their dependencies. It also allows upgrading these components if they have a newer version available.
Current section
Files
Jump to
Current section
Files
lib/fireside.ex
defmodule Fireside do
@moduledoc false
def ensure_clean_git!() do
unless match?({"", 0}, System.cmd("git", ["status", "--porcelain"])) do
raise "Please stage or stash your current Git changes before continuing."
end
end
def calculate_hash(ast) do
:crypto.hash(:sha, Sourceror.to_string(ast)) |> Base.encode16()
end
def add_or_replace_fireside_lock(igniter, component_name, component_path) do
igniter =
for source <- Rewrite.sources(igniter.rewrite),
Rewrite.Source.get(source, :path) in igniter.assigns.imported_paths,
Rewrite.Source.get(source, :path) not in igniter.assigns.overwritable_paths,
reduce: igniter do
igniter ->
{new_quoted, hash} =
source
|> Rewrite.Source.get(:quoted)
|> compute_and_include_hash(component_name)
new_source =
Rewrite.Source.update(
source,
:quoted,
new_quoted
)
path = Rewrite.Source.get(source, :path)
%{igniter | rewrite: Rewrite.update!(igniter.rewrite, new_source)}
|> Igniter.update_assign(:hashes, %{path => hash}, fn hashes ->
Map.merge(hashes, %{path => hash})
end)
end
app_name = Igniter.Project.Application.app_name()
igniter
|> Igniter.Project.Config.configure_new(
"fireside.exs",
app_name,
[Fireside, component_name, :source],
:path
)
|> Igniter.Project.Config.configure_new(
"fireside.exs",
app_name,
[Fireside, component_name, :origin],
component_path
)
|> Igniter.Project.Config.configure(
"fireside.exs",
app_name,
[Fireside, component_name, :files],
igniter.assigns.hashes
)
end
def load_module(path) do
Code.require_file(path)
{:defmodule, _defmodule_meta, [{:__aliases__, _aliases_meta, module_name} | _rest]} =
path
|> File.read!()
|> Sourceror.parse_string!()
Module.concat(module_name)
end
def expand_fireside_includes(component_path, fireside_config) do
for kind <- [:lib, :tests, :test_supports, :overwritable],
Map.has_key?(fireside_config, kind),
reduce: %{} do
expanded_includes ->
includes = fireside_config[kind]
expanded_paths =
for glob <- includes, reduce: [] do
expanded_paths ->
expanded_paths ++
(Path.join(component_path, glob)
|> GlobEx.compile!()
|> GlobEx.ls())
end
Map.merge(expanded_includes, %{kind => expanded_paths})
end
end
defp compute_and_include_hash(ast, component_name) do
hash = Fireside.calculate_hash(ast)
{Sourceror.prepend_comments(
ast,
[
%{
line: 1,
previous_eol_count: 1,
next_eol_count: 1,
text: "#! fireside: #{component_name}:#{hash}"
},
%{
line: 1,
previous_eol_count: 1,
next_eol_count: 1,
text:
"#! fireside: DO NOT EDIT this file. Run `mix fireside.unlock #{component_name}` if you want to stop syncing."
}
],
:leading
), hash}
end
end