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
local_assets_path = local_assets_path(hash)
if File.exists?(local_assets_path) do
if non_empty_dir?(local_assets_path) do
:ok
else
with {:ok, runtime, archive_path} <-
GenServer.call(pid, {:get_runtime_and_archive_path, hash}, @timeout) do
fun = fn ->
# 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)
extract_archive!(archive_binary, local_assets_path)
end
@ -232,6 +232,10 @@ defmodule Livebook.Session do
end
end
defp non_empty_dir?(path) do
match?({:ok, [_ | _]}, File.ls(path))
end
@doc """
Sends notebook attributes update to the server.
"""
@ -1067,7 +1071,10 @@ defmodule Livebook.Session do
FileSystem.File.remove(tmp_dir)
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)])
end

View file

@ -152,6 +152,22 @@ defmodule LivebookWeb.SessionControllerTest do
assert redirected_to(conn, 301) ==
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
test "skips the session if assets are in cache", %{conn: conn} do