Packages
fnord
0.9.2
0.9.40
0.9.39
0.9.38
0.9.37
0.9.36
0.9.35
0.9.34
0.9.33
0.9.32
0.9.31
0.9.30
0.9.29
0.9.28
0.9.27
0.9.26
0.9.25
0.9.24
0.9.23
0.9.22
0.9.21
0.9.20
0.9.19
0.9.18
0.9.17
0.9.16
0.9.15
0.9.14
0.9.13
0.9.12
0.9.11
0.9.10
0.9.9
0.9.8
0.9.7
0.9.6
0.9.5
0.9.4
0.9.3
0.9.2
0.9.1
0.9.0
0.8.99
0.8.98
0.8.97
0.8.96
0.8.95
0.8.94
0.8.93
0.8.92
0.8.91
0.8.90
0.8.89
0.8.88
0.8.87
0.8.86
0.8.85
0.8.84
0.8.83
0.8.82
0.8.81
0.8.80
0.8.79
0.8.78
0.8.77
0.8.76
0.8.75
0.8.74
0.8.73
0.8.72
0.8.71
0.8.70
0.8.69
0.8.68
0.8.67
0.8.66
0.8.65
0.8.64
0.8.63
0.8.62
0.8.61
0.8.60
0.8.59
0.8.58
0.8.57
0.8.56
0.8.55
0.8.54
0.8.53
0.8.52
0.8.51
0.8.50
0.8.49
0.8.48
0.8.47
0.8.46
0.8.45
0.8.44
0.8.43
0.8.42
0.8.41
0.8.40
0.8.39
0.8.38
0.8.37
0.8.36
0.8.35
0.8.34
0.8.33
0.8.32
0.8.31
0.8.30
0.8.29
0.8.27
0.8.26
0.8.25
0.8.24
0.8.23
0.8.22
0.8.21
0.8.20
0.8.19
0.8.18
0.8.17
0.8.16
0.8.15
0.8.14
0.8.13
0.8.12
0.8.11
0.8.1
0.8.0
0.7.24
0.7.23
0.7.22
0.7.21
0.7.20
0.7.19
0.7.18
0.7.17
0.7.16
0.7.15
0.7.14
0.7.13
0.7.12
0.7.11
0.7.10
0.7.9
0.7.8
0.7.7
0.7.6
0.7.5
0.7.3
0.7.2
0.7.1
0.7.0
0.6.9
0.6.8
0.6.7
0.6.6
0.6.5
0.6.4
0.6.3
0.6.1
0.6.0
0.5.9
0.5.8
0.5.7
0.5.6
0.5.5
0.5.4
0.5.3
0.5.2
0.5.1
0.5.0
0.4.44
0.4.43
0.4.42
0.4.41
0.4.40
0.4.39
0.4.38
0.4.37
0.4.36
0.4.35
0.4.34
0.4.33
0.4.32
0.4.30
0.4.29
0.4.28
0.4.27
0.4.26
0.4.25
0.4.24
0.4.23
0.4.22
0.4.21
0.4.20
0.4.19
0.4.18
0.4.17
0.4.16
0.4.15
0.4.14
0.4.13
0.4.12
0.4.11
0.4.10
0.4.9
0.4.8
0.4.7
0.4.6
0.4.5
0.4.4
0.4.3
0.4.2
0.4.1
0.4.0
0.3.0
0.2.0
0.1.0
AI code archaeology
Current section
Files
Jump to
Current section
Files
lib/memory/global.ex
defmodule Memory.Global do
@moduledoc """
Global memory storage implementation for the `Memory` behaviour.
Memories are stored as JSON files in `~/.fnord/memory`.
"""
# ----------------------------------------------------------------------------
# Behaviour Implementation
# ----------------------------------------------------------------------------
@behaviour Memory
@impl Memory
def init() do
with {:ok, _path} <- ensure_storage_path() do
drop_old_storage()
:ok
end
end
@impl Memory
def list() do
with {:ok, files} <- File.ls(storage_path()) do
files
|> Enum.filter(&String.ends_with?(&1, ".json"))
|> Enum.map(fn file ->
file
|> Path.rootname()
|> Memory.slug_to_title()
end)
|> then(&{:ok, &1})
end
end
@impl Memory
def exists?(title) do
title
|> file_path()
|> File.exists?()
end
@impl Memory
def read(title) do
path = file_path(title)
with true <- exists?(title),
{:ok, content} <- read_file(path),
{:ok, memory} <- Memory.unmarshal(content) do
{:ok, memory}
else
false -> {:error, :not_found}
end
end
@impl Memory
def save(memory) do
path = file_path(memory)
with {:ok, json} <- Memory.marshal(memory),
{:ok, _result} <- write_file(path, json) do
:ok
end
end
@impl Memory
def forget(title) do
title
|> file_path()
|> rm_path()
end
@impl Memory
def is_available?(), do: true
# ----------------------------------------------------------------------------
# Internals
# ----------------------------------------------------------------------------
defp storage_path() do
Store.store_home()
|> Path.join("memory")
end
defp old_storage_path() do
Store.store_home()
|> Path.join("memories")
end
defp ensure_storage_path() do
path = storage_path()
with false <- File.exists?(path),
:ok <- File.mkdir_p(path) do
{:ok, path}
else
true -> {:ok, path}
end
end
defp drop_old_storage() do
path = old_storage_path()
if File.exists?(path) do
UI.debug("memory:global", "Removing old global memory storage at #{path}")
File.rm_rf!(path)
end
end
defp file_path(title) when is_binary(title) do
slug = Memory.title_to_slug(title)
Path.join(storage_path(), "#{slug}.json")
end
defp file_path(%Memory{title: title}) do
file_path(title)
end
defp read_file(path) do
case FileLock.with_lock(path, fn -> File.read(path) end) do
{:ok, {:ok, contents}} ->
{:ok, contents}
{:ok, {:error, reason}} ->
{:error, reason}
{:error, reason} ->
{:error, reason}
end
end
defp write_file(path, json) do
FileLock.with_lock(path, fn -> File.write(path, json) end)
end
defp rm_path(path) do
case FileLock.with_lock(path, fn -> File.rm(path) end) do
{:ok, :ok} -> :ok
{:ok, {:error, reason}} -> {:error, reason}
{:error, reason} -> {:error, reason}
{:callback_error, reason} -> {:error, reason}
end
end
end