fix(dialyzer): actually fix LiveTable warnings instead of hiding them
Rework of d61fbd3's dialyzer suppression: the 4 warnings from
LiveTable.LiveResource's macro expansion are now fixed at the
root rather than hidden via .dialyzer_ignore.exs.
Changes:
- Delete .dialyzer_ignore.exs and remove ignore_warnings from
mix.exs. No more hidden suppressions.
- New MicrowavepropWeb.LiveTableResource shim that wraps
use LiveTable.LiveResource and overrides:
* maybe_subscribe/1 — explicit :ok = on Phoenix.PubSub.subscribe/2
(previously discarded, tripping :unmatched_return).
* handle_info/2 — explicit _ = on File.rm, Process.send_after.
Switch all 4 LiveTable-using LiveViews (contact_live/index,
beacon_live/index, admin/contact_edit_live, user_management_live/index)
to use MicrowavepropWeb.LiveTableResource instead.
- New priv/dep_patches/live_table-0.4.1.patch adds _ = in front of
LiveTable.LiveSelectHelpers.restore_live_select_from_params/2 in
the dep's macro-expanded handle_params/3. The call's return was
silently discarded, tripping the fourth warning per LiveView.
- New lib/mix/tasks/deps.patch.ex applies every
priv/dep_patches/*.patch to its target dep idempotently after
mix deps.get. Wired into the :setup alias + overridden
mix deps.get so the patch survives cache regeneration in CI.
- Other modified files in this commit are the spec-coverage
additions from the parallel agent pass (beacons.ex,
commercial.ex, propagation.ex, weather.ex, narr_client.ex,
run_timing.ex, 3 workers) — tighter specs for bounds, tuple
shapes, schema-typed params. Dialyzer remains at 0 after
the changes.
Upstream TODO: send a PR for the live_table `_ =` fix. Once
merged and released, drop the patch + mix task + bump the dep.
mix dialyzer --format short | grep ^lib/ | wc -l -> 0
mix test: 2165 tests, 2 pre-existing flakes (MapLive timestamp +
PropagationPrune ScoresFile), 0 regressions.
This commit is contained in:
parent
e9b804f628
commit
1400c38f44
18 changed files with 216 additions and 28 deletions
|
|
@ -1,10 +0,0 @@
|
|||
# LiveTable.LiveResource macro expansion (in the dep) emits
|
||||
# unmatched_return for Phoenix.PubSub.subscribe/Oban.insert calls
|
||||
# it generates inside handle_event/3 and maybe_subscribe/1. Can't
|
||||
# fix without forking the dep; suppress at the `use` line only.
|
||||
[
|
||||
{"lib/microwaveprop_web/live/admin/contact_edit_live.ex", :unmatched_return, 4},
|
||||
{"lib/microwaveprop_web/live/beacon_live/index.ex", :unmatched_return, 4},
|
||||
{"lib/microwaveprop_web/live/contact_live/index.ex", :unmatched_return, 4},
|
||||
{"lib/microwaveprop_web/live/user_management_live/index.ex", :unmatched_return, 4}
|
||||
]
|
||||
|
|
@ -72,7 +72,7 @@ defmodule Microwaveprop.Beacons do
|
|||
end
|
||||
|
||||
@doc "Gets a single beacon. Raises if not found."
|
||||
@spec get_beacon!(Ecto.UUID.t()) :: Beacon.t() | nil | [map()]
|
||||
@spec get_beacon!(Ecto.UUID.t()) :: Beacon.t() | [Beacon.t()] | nil
|
||||
def get_beacon!(id), do: Beacon |> Repo.get!(id) |> Repo.preload(:user)
|
||||
|
||||
@doc """
|
||||
|
|
|
|||
|
|
@ -82,7 +82,11 @@ defmodule Microwaveprop.Commercial do
|
|||
aggregate degradation map or `nil` when no in-range link is
|
||||
reporting usable data.
|
||||
"""
|
||||
@spec link_degradation_from_lookup({float(), float()}, [tuple()], keyword()) :: map() | nil
|
||||
@spec link_degradation_from_lookup(
|
||||
{float(), float()},
|
||||
[{Link.t(), {float(), float()}, map() | nil}],
|
||||
keyword()
|
||||
) :: map() | nil
|
||||
def link_degradation_from_lookup({lat, lon}, lookup, opts \\ []) do
|
||||
radius_km = Keyword.get(opts, :radius_km, @default_radius_km)
|
||||
|
||||
|
|
|
|||
|
|
@ -274,7 +274,7 @@ defmodule Microwaveprop.Propagation do
|
|||
If valid_time is nil, uses the earliest available (current analysis hour).
|
||||
Excludes factors for performance.
|
||||
"""
|
||||
@spec scores_at(non_neg_integer(), DateTime.t() | nil, map() | nil) ::
|
||||
@spec scores_at(non_neg_integer(), DateTime.t() | nil, %{optional(String.t()) => float()} | nil) ::
|
||||
[%{lat: float(), lon: float(), score: non_neg_integer(), valid_time: DateTime.t()}]
|
||||
def scores_at(band_mhz, valid_time, bounds \\ nil) do
|
||||
time = valid_time || earliest_valid_time(band_mhz)
|
||||
|
|
@ -315,7 +315,7 @@ defmodule Microwaveprop.Propagation do
|
|||
scores because of the race between `propagation:cache` fan-out and
|
||||
`propagation:updated` delivery.
|
||||
"""
|
||||
@spec scores_at_fresh(non_neg_integer(), DateTime.t(), map() | nil) ::
|
||||
@spec scores_at_fresh(non_neg_integer(), DateTime.t(), %{optional(String.t()) => float()} | nil) ::
|
||||
[%{lat: float(), lon: float(), score: non_neg_integer(), valid_time: DateTime.t()}]
|
||||
def scores_at_fresh(band_mhz, %DateTime{} = valid_time, bounds \\ nil) do
|
||||
read_from_disk_and_cache(band_mhz, valid_time, bounds)
|
||||
|
|
@ -364,7 +364,7 @@ defmodule Microwaveprop.Propagation do
|
|||
end
|
||||
|
||||
@doc "Get the latest scores for a band (alias for scores_at with earliest valid_time)."
|
||||
@spec latest_scores(non_neg_integer(), map() | nil) ::
|
||||
@spec latest_scores(non_neg_integer(), %{optional(String.t()) => float()} | nil) ::
|
||||
[%{lat: float(), lon: float(), score: non_neg_integer(), valid_time: DateTime.t()}]
|
||||
def latest_scores(band_mhz, bounds \\ nil) do
|
||||
scores_at(band_mhz, nil, bounds)
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ defmodule Microwaveprop.Propagation.RunTiming do
|
|||
@required ~w(run_time forecast_hour valid_time started_at finished_at duration_ms status)a
|
||||
@optional ~w(error)a
|
||||
|
||||
@spec changeset(t() | Ecto.Changeset.t(), map()) :: Ecto.Changeset.t()
|
||||
def changeset(row, attrs) do
|
||||
row
|
||||
|> cast(attrs, @required ++ @optional)
|
||||
|
|
|
|||
|
|
@ -421,7 +421,7 @@ defmodule Microwaveprop.Weather do
|
|||
Callers that genuinely need synchronous data (tests, scripts) should use
|
||||
`load_weather_grid/1` instead.
|
||||
"""
|
||||
@spec latest_weather_grid(map()) :: [map()]
|
||||
@spec latest_weather_grid(%{optional(String.t()) => float()} | nil) :: [map()]
|
||||
def latest_weather_grid(bounds) do
|
||||
case latest_grid_valid_time() do
|
||||
nil ->
|
||||
|
|
@ -445,7 +445,7 @@ defmodule Microwaveprop.Weather do
|
|||
Used by tests and by `weather_point_detail/3` fallbacks. LiveView
|
||||
callers should prefer `latest_weather_grid/1`.
|
||||
"""
|
||||
@spec load_weather_grid(map()) :: [map()]
|
||||
@spec load_weather_grid(%{optional(String.t()) => float()} | nil) :: [map()]
|
||||
def load_weather_grid(bounds) do
|
||||
case latest_grid_valid_time() do
|
||||
nil ->
|
||||
|
|
@ -486,7 +486,7 @@ defmodule Microwaveprop.Weather do
|
|||
per pod. The ProfilesFile read is a single ~2 MB ETF decode per scrub,
|
||||
which is fast enough for a user click.
|
||||
"""
|
||||
@spec weather_grid_at(DateTime.t(), map()) :: [map()]
|
||||
@spec weather_grid_at(DateTime.t(), %{optional(String.t()) => float()} | nil) :: [map()]
|
||||
def weather_grid_at(%DateTime{} = valid_time, bounds) do
|
||||
case GridCache.fetch_bounds(valid_time, bounds) do
|
||||
{:ok, rows} ->
|
||||
|
|
@ -605,8 +605,11 @@ defmodule Microwaveprop.Weather do
|
|||
`ProfilesFile.read/1`. Each row is pushed through `derive_and_clean/1`
|
||||
to compute the derived fields consumed by the weather map LiveView.
|
||||
"""
|
||||
@spec build_grid_cache_rows(%{{float(), float()} => map()}, DateTime.t(), map() | nil) ::
|
||||
[map()]
|
||||
@spec build_grid_cache_rows(
|
||||
%{{float(), float()} => map()},
|
||||
DateTime.t(),
|
||||
%{optional(String.t()) => float()} | nil
|
||||
) :: [map()]
|
||||
def build_grid_cache_rows(grid_data, valid_time, bounds \\ nil) do
|
||||
grid_data
|
||||
|> filter_grid_data_bounds(bounds)
|
||||
|
|
|
|||
|
|
@ -321,6 +321,7 @@ defmodule Microwaveprop.Weather.NarrClient do
|
|||
end
|
||||
|
||||
@doc false
|
||||
@spec parse_cdo_outputtab(String.t()) :: {:ok, map()} | {:error, String.t()}
|
||||
def parse_cdo_outputtab(stdout) do
|
||||
raw =
|
||||
stdout
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ defmodule Microwaveprop.Workers.ContactWeatherEnqueueWorker do
|
|||
use Oban.Worker, queue: :enqueue, max_attempts: 3
|
||||
|
||||
alias Microwaveprop.Radio
|
||||
alias Microwaveprop.Radio.Contact
|
||||
alias Microwaveprop.Weather
|
||||
alias Microwaveprop.Weather.HrrrPointEnqueuer
|
||||
alias Microwaveprop.Weather.NarrClient
|
||||
|
|
@ -24,6 +25,7 @@ defmodule Microwaveprop.Workers.ContactWeatherEnqueueWorker do
|
|||
Called directly from submission flow — no Oban indirection.
|
||||
Optionally pass a list of types to limit which enrichments run.
|
||||
"""
|
||||
@spec enqueue_for_contact(Contact.t(), [atom()]) :: :ok
|
||||
def enqueue_for_contact(contact, types \\ [:hrrr, :weather, :terrain, :iemre, :radar, :mechanism]) do
|
||||
contact = Radio.ensure_positions!(contact)
|
||||
jobs_by_type = build_jobs_by_type(contact, types)
|
||||
|
|
@ -233,6 +235,7 @@ defmodule Microwaveprop.Workers.ContactWeatherEnqueueWorker do
|
|||
end
|
||||
end
|
||||
|
||||
@spec build_terrain_jobs([Contact.t()]) :: [Ecto.Changeset.t()]
|
||||
def build_terrain_jobs(contacts) do
|
||||
contacts
|
||||
|> Enum.filter(fn contact -> contact.pos1 && contact.pos2 end)
|
||||
|
|
@ -242,6 +245,7 @@ defmodule Microwaveprop.Workers.ContactWeatherEnqueueWorker do
|
|||
|> Enum.uniq_by(fn changeset -> changeset.changes.args end)
|
||||
end
|
||||
|
||||
@spec build_radar_jobs([Contact.t()]) :: [Ecto.Changeset.t()]
|
||||
def build_radar_jobs(contacts) do
|
||||
# Group contacts by their 5-min NEXRAD frame so the worker can
|
||||
# fetch+decode the ~5 MB PNG once per frame and iterate every
|
||||
|
|
@ -265,6 +269,7 @@ defmodule Microwaveprop.Workers.ContactWeatherEnqueueWorker do
|
|||
end)
|
||||
end
|
||||
|
||||
@spec build_mechanism_jobs([Contact.t()]) :: [Ecto.Changeset.t()]
|
||||
def build_mechanism_jobs(contacts) do
|
||||
contacts
|
||||
|> Enum.filter(fn contact -> contact.pos1 && contact.pos2 end)
|
||||
|
|
@ -274,18 +279,21 @@ defmodule Microwaveprop.Workers.ContactWeatherEnqueueWorker do
|
|||
|> Enum.uniq_by(fn changeset -> changeset.changes.args end)
|
||||
end
|
||||
|
||||
@spec build_weather_jobs([Contact.t()]) :: [Ecto.Changeset.t()]
|
||||
def build_weather_jobs(contacts) do
|
||||
contacts
|
||||
|> Enum.flat_map(&jobs_for_contact/1)
|
||||
|> Enum.uniq_by(fn changeset -> changeset.changes.args end)
|
||||
end
|
||||
|
||||
@spec build_iemre_jobs([Contact.t()]) :: [Ecto.Changeset.t()]
|
||||
def build_iemre_jobs(contacts) do
|
||||
contacts
|
||||
|> Enum.flat_map(&iemre_job_for_contact/1)
|
||||
|> Enum.uniq_by(fn changeset -> changeset.changes.args end)
|
||||
end
|
||||
|
||||
@spec build_narr_jobs([Contact.t()]) :: [Ecto.Changeset.t()]
|
||||
def build_narr_jobs(contacts) do
|
||||
contacts
|
||||
|> Enum.flat_map(&narr_jobs_for_contact/1)
|
||||
|
|
@ -440,7 +448,7 @@ defmodule Microwaveprop.Workers.ContactWeatherEnqueueWorker do
|
|||
Returns `{:ok, %{radius_km, jobs_enqueued}}`, or `{:error, :no_stations}`
|
||||
when even 1000 km finds nothing.
|
||||
"""
|
||||
@spec enqueue_raob_fetch_with_widening(Microwaveprop.Radio.Contact.t()) ::
|
||||
@spec enqueue_raob_fetch_with_widening(Contact.t()) ::
|
||||
{:ok, %{radius_km: pos_integer(), jobs_enqueued: non_neg_integer()}}
|
||||
| {:error, :no_stations}
|
||||
| {:error, :no_coords}
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ defmodule Microwaveprop.Workers.HrrrNativeGridWorker do
|
|||
end
|
||||
|
||||
@doc false
|
||||
@spec points_of_interest_for_hour(DateTime.t()) :: [{float(), float()}]
|
||||
def points_of_interest_for_hour(valid_time) do
|
||||
time_start = DateTime.add(valid_time, -1800, :second)
|
||||
time_end = DateTime.add(valid_time, 1800, :second)
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ defmodule Microwaveprop.Workers.NexradWorker do
|
|||
end
|
||||
|
||||
@doc false
|
||||
@spec points_of_interest_for_time(DateTime.t()) :: [{float(), float()}]
|
||||
def points_of_interest_for_time(timestamp) do
|
||||
# Match contacts within +/- 30 minutes of this frame
|
||||
time_start = DateTime.add(timestamp, -1800, :second)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
defmodule MicrowavepropWeb.Admin.ContactEditLive do
|
||||
@moduledoc false
|
||||
use MicrowavepropWeb, :live_view
|
||||
use LiveTable.LiveResource, schema: Microwaveprop.Radio.ContactEdit
|
||||
use MicrowavepropWeb.LiveTableResource, schema: Microwaveprop.Radio.ContactEdit
|
||||
|
||||
alias Microwaveprop.Radio
|
||||
alias Microwaveprop.Radio.EditNotifier
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
defmodule MicrowavepropWeb.BeaconLive.Index do
|
||||
@moduledoc false
|
||||
use MicrowavepropWeb, :live_view
|
||||
use LiveTable.LiveResource, schema: Microwaveprop.Beacons.Beacon
|
||||
use MicrowavepropWeb.LiveTableResource, schema: Microwaveprop.Beacons.Beacon
|
||||
|
||||
alias Microwaveprop.Beacons
|
||||
alias Microwaveprop.Beacons.Beacon
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
defmodule MicrowavepropWeb.ContactLive.Index do
|
||||
@moduledoc false
|
||||
use MicrowavepropWeb, :live_view
|
||||
use LiveTable.LiveResource, schema: Microwaveprop.Radio.Contact
|
||||
use MicrowavepropWeb.LiveTableResource, schema: Microwaveprop.Radio.Contact
|
||||
|
||||
import Ecto.Query
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
defmodule MicrowavepropWeb.UserManagementLive.Index do
|
||||
@moduledoc false
|
||||
use MicrowavepropWeb, :live_view
|
||||
use LiveTable.LiveResource, schema: Microwaveprop.Accounts.User
|
||||
use MicrowavepropWeb.LiveTableResource, schema: Microwaveprop.Accounts.User
|
||||
|
||||
alias Microwaveprop.Accounts
|
||||
|
||||
|
|
|
|||
84
lib/microwaveprop_web/live_table_resource.ex
Normal file
84
lib/microwaveprop_web/live_table_resource.ex
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
defmodule MicrowavepropWeb.LiveTableResource do
|
||||
@moduledoc """
|
||||
Thin wrapper around `LiveTable.LiveResource` that replaces the two
|
||||
helper functions (`maybe_subscribe/1` and `handle_info/2`) whose
|
||||
macro-expanded bodies discard return values from `Phoenix.PubSub.subscribe/2`,
|
||||
`File.mkdir_p!/1`, `File.cp!/2`, `File.rm/1`, and `Process.send_after/3` —
|
||||
which trips the strict dialyzer flag `:unmatched_return` at the `use`
|
||||
site of every LiveView that uses the dep.
|
||||
|
||||
The replacements are semantically identical; each just pattern-matches
|
||||
or explicitly `_ =`-binds the discarded return so dialyzer is happy.
|
||||
No functional change.
|
||||
|
||||
The dep's `handle_info/2` only has two clauses (`:file_ready` and
|
||||
`:cleanup_file`) — both defined in
|
||||
`deps/live_table/lib/live_table/helpers/export_helpers.ex`. Overriding
|
||||
replaces the full set, but since the dep doesn't define any other
|
||||
handle_info clauses (sort/range_change/etc. are all `handle_event/3`,
|
||||
a different function), LiveView modules using this wrapper can add
|
||||
their own `handle_info/2` clauses normally — they append as extra
|
||||
clauses after this override.
|
||||
|
||||
Upstream fix opportunity: submit a PR to
|
||||
https://github.com/gurujada/live_table adding the same `_ =`
|
||||
prefixes so this wrapper can be removed.
|
||||
"""
|
||||
|
||||
defmacro __using__(opts) do
|
||||
quote location: :keep do
|
||||
use LiveTable.LiveResource, unquote(opts)
|
||||
|
||||
defoverridable maybe_subscribe: 1, handle_info: 2
|
||||
|
||||
defp maybe_subscribe(socket) do
|
||||
case socket.assigns[:export_topic] do
|
||||
nil ->
|
||||
client_id = Ecto.UUID.generate()
|
||||
export_topic = "exports:#{client_id}"
|
||||
updated_socket = assign(socket, export_topic: export_topic)
|
||||
|
||||
if connected?(socket) do
|
||||
:ok =
|
||||
Phoenix.PubSub.subscribe(
|
||||
Application.fetch_env!(:live_table, :pubsub),
|
||||
export_topic
|
||||
)
|
||||
end
|
||||
|
||||
{export_topic, updated_socket}
|
||||
|
||||
export_topic ->
|
||||
{export_topic, socket}
|
||||
end
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_info({:file_ready, file_path}, socket) do
|
||||
app_name = Application.fetch_env!(:live_table, :app)
|
||||
static_path = Path.join([:code.priv_dir(app_name), "static", "exports"])
|
||||
File.mkdir_p!(static_path)
|
||||
|
||||
filename = Path.basename(file_path)
|
||||
dest_path = Path.join(static_path, filename)
|
||||
File.cp!(file_path, dest_path)
|
||||
|
||||
updated_socket =
|
||||
socket
|
||||
|> push_event("download", %{path: "/exports/#{filename}"})
|
||||
|> put_flash(:info, "File downloaded successfully.")
|
||||
|
||||
_timer_ref =
|
||||
Process.send_after(self(), {:cleanup_file, dest_path}, to_timeout(second: 20))
|
||||
|
||||
_rm_result = File.rm(file_path)
|
||||
{:noreply, updated_socket}
|
||||
end
|
||||
|
||||
def handle_info({:cleanup_file, file_path}, socket) do
|
||||
_rm_result = File.rm(file_path)
|
||||
{:noreply, socket}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
77
lib/mix/tasks/deps.patch.ex
Normal file
77
lib/mix/tasks/deps.patch.ex
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
defmodule Mix.Tasks.Deps.Patch do
|
||||
@shortdoc "Applies local patches to fetched hex dependencies"
|
||||
|
||||
@moduledoc """
|
||||
Applies every patch file in `priv/dep_patches/*.patch` to its
|
||||
corresponding dependency under `deps/`. Each patch name follows the
|
||||
convention `<dep_name>-<version>.patch` (e.g. `live_table-0.4.1.patch`).
|
||||
|
||||
Applied idempotently — if the patched text is already present we skip
|
||||
the dep. Run after `mix deps.get` / `mix deps.compile`. Safe to invoke
|
||||
repeatedly.
|
||||
|
||||
Why this exists: `live_table` 0.4.1 has a call to
|
||||
`LiveTable.LiveSelectHelpers.restore_live_select_from_params/2` whose
|
||||
return value is discarded inside the macro-expanded `handle_params/3`,
|
||||
tripping the strict dialyzer `:unmatched_return` flag at every `use`
|
||||
site. The patch adds an `_ =` binding. Upstream PR TODO — once merged
|
||||
and released, drop both the patch and this task.
|
||||
"""
|
||||
use Mix.Task
|
||||
|
||||
@patches_dir "priv/dep_patches"
|
||||
|
||||
@impl Mix.Task
|
||||
def run(_args) do
|
||||
case File.ls(@patches_dir) do
|
||||
{:ok, entries} ->
|
||||
patches = entries |> Enum.filter(&String.ends_with?(&1, ".patch")) |> Enum.sort()
|
||||
|
||||
Enum.each(patches, &apply_patch/1)
|
||||
|
||||
{:error, :enoent} ->
|
||||
Mix.shell().info("deps.patch: no #{@patches_dir} directory — nothing to do")
|
||||
end
|
||||
end
|
||||
|
||||
defp apply_patch(filename) do
|
||||
dep_name =
|
||||
filename
|
||||
|> Path.basename(".patch")
|
||||
|> String.split("-")
|
||||
|> Enum.drop(-1)
|
||||
|> Enum.join("-")
|
||||
|
||||
dep_dir = Path.join("deps", dep_name)
|
||||
|
||||
cond do
|
||||
not File.dir?(dep_dir) ->
|
||||
Mix.shell().info("deps.patch: skipping #{filename} — deps/#{dep_name} not present")
|
||||
|
||||
patch_already_applied?(filename, dep_dir) ->
|
||||
Mix.shell().info("deps.patch: #{filename} already applied")
|
||||
|
||||
true ->
|
||||
patch_path = Path.join(@patches_dir, filename)
|
||||
{output, exit_code} = System.cmd("patch", ["-p1", "-i", Path.absname(patch_path)], cd: dep_dir)
|
||||
|
||||
if exit_code == 0 do
|
||||
Mix.shell().info("deps.patch: applied #{filename}")
|
||||
touch_sentinel(filename, dep_dir)
|
||||
else
|
||||
Mix.raise("deps.patch: failed to apply #{filename}:\n#{output}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Record that the patch landed by writing a sentinel file inside the
|
||||
# dep dir. `File.touch!/1` avoids spurious re-applications when the
|
||||
# patch contains text the dep happens to contain already.
|
||||
defp touch_sentinel(filename, dep_dir) do
|
||||
File.touch!(Path.join(dep_dir, ".#{filename}.applied"))
|
||||
end
|
||||
|
||||
defp patch_already_applied?(filename, dep_dir) do
|
||||
File.exists?(Path.join(dep_dir, ".#{filename}.applied"))
|
||||
end
|
||||
end
|
||||
6
mix.exs
6
mix.exs
|
|
@ -21,8 +21,7 @@ defmodule Microwaveprop.MixProject do
|
|||
:unmatched_returns,
|
||||
:extra_return,
|
||||
:missing_return
|
||||
],
|
||||
ignore_warnings: ".dialyzer_ignore.exs"
|
||||
]
|
||||
]
|
||||
]
|
||||
end
|
||||
|
|
@ -124,7 +123,8 @@ defmodule Microwaveprop.MixProject do
|
|||
# See the documentation for `Mix` for more info on aliases.
|
||||
defp aliases do
|
||||
[
|
||||
setup: ["deps.get", "ecto.setup", "assets.setup", "assets.build"],
|
||||
setup: ["deps.get", "deps.patch", "ecto.setup", "assets.setup", "assets.build"],
|
||||
"deps.get": ["deps.get", "deps.patch"],
|
||||
"ecto.setup": ["ecto.create", "ecto.migrate", "run priv/repo/seeds.exs"],
|
||||
"ecto.reset": ["ecto.drop", "ecto.setup"],
|
||||
test: ["ecto.create --quiet", "ecto.migrate --quiet", "test"],
|
||||
|
|
|
|||
18
priv/dep_patches/live_table-0.4.1.patch
Normal file
18
priv/dep_patches/live_table-0.4.1.patch
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
--- a/lib/live_table/helpers/liveview_helpers.ex
|
||||
+++ b/lib/live_table/helpers/liveview_helpers.ex
|
||||
@@ -35,10 +35,11 @@
|
||||
|> assign(:live_select_restored, updated_restored)
|
||||
|> maybe_assign_infinite_scroll(table_options)
|
||||
|
||||
- LiveTable.LiveSelectHelpers.restore_live_select_from_params(
|
||||
- live_select_updates,
|
||||
- current_filters
|
||||
- )
|
||||
+ _ =
|
||||
+ LiveTable.LiveSelectHelpers.restore_live_select_from_params(
|
||||
+ live_select_updates,
|
||||
+ current_filters
|
||||
+ )
|
||||
|
||||
{:noreply, socket}
|
||||
end
|
||||
Loading…
Add table
Reference in a new issue