Ignore asset directories if they are empty

macOS removes files from the temporary directory but
keeps the directory. This would cause LiveView to
misbehave as it would assume all assets are checked out.
This commit is contained in:
José Valim 2022-05-13 14:41:05 +02:00
parent c131826733
commit 49492771f3
2 changed files with 26 additions and 3 deletions

View file

@ -209,14 +209,14 @@ defmodule Livebook.Session do
def fetch_assets(pid, hash) do def fetch_assets(pid, hash) do
local_assets_path = local_assets_path(hash) local_assets_path = local_assets_path(hash)
if File.exists?(local_assets_path) do if non_empty_dir?(local_assets_path) do
:ok :ok
else else
with {:ok, runtime, archive_path} <- with {:ok, runtime, archive_path} <-
GenServer.call(pid, {:get_runtime_and_archive_path, hash}, @timeout) do GenServer.call(pid, {:get_runtime_and_archive_path, hash}, @timeout) do
fun = fn -> fun = fn ->
# Make sure the file hasn't been fetched by this point # Make sure the file hasn't been fetched by this point
unless File.exists?(local_assets_path) do unless non_empty_dir?(local_assets_path) do
{:ok, archive_binary} = Runtime.read_file(runtime, archive_path) {:ok, archive_binary} = Runtime.read_file(runtime, archive_path)
extract_archive!(archive_binary, local_assets_path) extract_archive!(archive_binary, local_assets_path)
end end
@ -232,6 +232,10 @@ defmodule Livebook.Session do
end end
end end
defp non_empty_dir?(path) do
match?({:ok, [_ | _]}, File.ls(path))
end
@doc """ @doc """
Sends notebook attributes update to the server. Sends notebook attributes update to the server.
""" """
@ -1067,7 +1071,10 @@ defmodule Livebook.Session do
FileSystem.File.remove(tmp_dir) FileSystem.File.remove(tmp_dir)
end end
defp local_assets_path(hash) do @doc """
Returns a local path to the directory for all assets for hash.
"""
def local_assets_path(hash) do
Path.join([livebook_tmp_path(), "assets", encode_path_component(hash)]) Path.join([livebook_tmp_path(), "assets", encode_path_component(hash)])
end end

View file

@ -152,6 +152,22 @@ defmodule LivebookWeb.SessionControllerTest do
assert redirected_to(conn, 301) == assert redirected_to(conn, 301) ==
Routes.session_path(conn, :show_cached_asset, hash, ["main.js"]) Routes.session_path(conn, :show_cached_asset, hash, ["main.js"])
{:ok, asset_path} = Session.local_asset_path(hash, "main.js")
assert File.exists?(asset_path)
end
test "fetches assets and redirects even on empty asset directories", %{conn: conn} do
%{notebook: notebook, hash: hash} = notebook_with_js_output()
assets_path = Session.local_assets_path(hash)
File.mkdir_p!(assets_path)
conn = start_session_and_request_asset(conn, notebook, hash)
assert redirected_to(conn, 301) ==
Routes.session_path(conn, :show_cached_asset, hash, ["main.js"])
assert File.exists?(Path.join(assets_path, "main.js"))
end end
test "skips the session if assets are in cache", %{conn: conn} do test "skips the session if assets are in cache", %{conn: conn} do