Packages

A Gleam library for building and orchestrating agents on the BEAM.

Current section

Files

Jump to
pig src pig@workspace@vfs.erl
Raw

src/pig@workspace@vfs.erl

-module(pig@workspace@vfs).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/pig/workspace/vfs.gleam").
-export([mkdir/2, write_file/3, read_file/2, read_file_lines/4, list_directory/2, grep/5, delete_file/2]).
-export_type([error/0, grep_match/0]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
?MODULEDOC(
" Virtual filesystem operations for pig workspace.\n"
"\n"
" File and directory operations backed by SQLite tables:\n"
" - `vfs_inode` — file metadata (mode, size, mtime)\n"
" - `vfs_dentry` — directory tree (name -> inode mapping)\n"
" - `vfs_data` — file content (chunked blobs)\n"
).
-type error() :: {sql_error, sqlight:error()} |
{not_found, binary()} |
{not_empty, binary()} |
{already_exists, binary()} |
{invalid_path, binary()}.
-type grep_match() :: {grep_match, binary(), integer(), binary()}.
-file("src/pig/workspace/vfs.gleam", 38).
-spec split_path(binary()) -> list(binary()).
split_path(Path) ->
_pipe = Path,
_pipe@1 = gleam@string:split(_pipe, <<"/"/utf8>>),
gleam@list:filter(_pipe@1, fun(S) -> S /= <<""/utf8>> end).
-file("src/pig/workspace/vfs.gleam", 45).
?DOC(" Validate path doesn't contain . or .. components.\n").
-spec validate_path(binary()) -> {ok, nil} | {error, error()}.
validate_path(Path) ->
case gleam_stdlib:contains_string(Path, <<".."/utf8>>) orelse gleam_stdlib:contains_string(
Path,
<<"/./"/utf8>>
) of
true ->
{error, {invalid_path, Path}};
false ->
{ok, nil}
end.
-file("src/pig/workspace/vfs.gleam", 61).
-spec walk_path(sqlight:connection(), list(binary()), integer(), binary()) -> {ok,
integer()} |
{error, error()}.
walk_path(Conn, Components, Current_ino, Original_path) ->
case Components of
[] ->
{ok, Current_ino};
[Name | Rest] ->
_pipe = sqlight:'query'(
<<"SELECT ino FROM vfs_dentry WHERE parent_ino = ? AND name = ?"/utf8>>,
Conn,
[sqlight:int(Current_ino), sqlight:text(Name)],
gleam@dynamic@decode:at(
[0],
{decoder, fun gleam@dynamic@decode:decode_int/1}
)
),
_pipe@1 = gleam@result:map_error(
_pipe,
fun(Field@0) -> {sql_error, Field@0} end
),
gleam@result:'try'(_pipe@1, fun(Ino) -> case Ino of
[Id] ->
walk_path(Conn, Rest, Id, Original_path);
_ ->
{error, {not_found, Original_path}}
end end)
end.
-file("src/pig/workspace/vfs.gleam", 53).
?DOC(" Resolve full path → inode. Root (/) = ino 1.\n").
-spec resolve_path(sqlight:connection(), binary()) -> {ok, integer()} |
{error, error()}.
resolve_path(Conn, Path) ->
gleam@result:'try'(
validate_path(Path),
fun(_use0) ->
nil = _use0,
case split_path(Path) of
[] ->
{ok, 1};
Components ->
walk_path(Conn, Components, 1, Path)
end
end
).
-file("src/pig/workspace/vfs.gleam", 87).
?DOC(" Resolve all but the last component → #(parent_ino, filename).\n").
-spec resolve_parent(sqlight:connection(), binary()) -> {ok,
{integer(), binary()}} |
{error, error()}.
resolve_parent(Conn, Path) ->
gleam@result:'try'(
validate_path(Path),
fun(_use0) ->
nil = _use0,
Components = split_path(Path),
case Components of
[] ->
{error, {invalid_path, Path}};
_ ->
Filename@1 = case gleam@list:last(Components) of
{ok, Filename} -> Filename;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Pattern match failed, no pattern matched the value."/utf8>>,
file => <<?FILEPATH/utf8>>,
module => <<"pig/workspace/vfs"/utf8>>,
function => <<"resolve_parent"/utf8>>,
line => 96,
value => _assert_fail,
start => 2618,
'end' => 2665,
pattern_start => 2629,
pattern_end => 2641})
end,
Parent_components = gleam@list:take(
Components,
erlang:length(Components) - 1
),
case Parent_components of
[] ->
{ok, {1, Filename@1}};
_ ->
Parent_path = <<"/"/utf8,
(gleam@string:join(
Parent_components,
<<"/"/utf8>>
))/binary>>,
gleam@result:'try'(
resolve_path(Conn, Parent_path),
fun(Parent_ino) ->
{ok, {Parent_ino, Filename@1}}
end
)
end
end
end
).
-file("src/pig/workspace/vfs.gleam", 113).
?DOC(" Insert inode, return its ino via RETURNING.\n").
-spec insert_inode(sqlight:connection(), integer()) -> {ok, integer()} |
{error, error()}.
insert_inode(Conn, Mode) ->
_pipe = sqlight:'query'(
<<"INSERT INTO vfs_inode (mode, size, mtime) VALUES (?, 0, unixepoch()) RETURNING ino"/utf8>>,
Conn,
[sqlight:int(Mode)],
gleam@dynamic@decode:at(
[0],
{decoder, fun gleam@dynamic@decode:decode_int/1}
)
),
_pipe@1 = gleam@result:map_error(
_pipe,
fun(Field@0) -> {sql_error, Field@0} end
),
gleam@result:'try'(_pipe@1, fun(Rows) -> case Rows of
[Ino] ->
{ok, Ino};
_ ->
{error,
{sql_error,
{sqlight_error,
internal,
<<"unexpected RETURNING result"/utf8>>,
-1}}}
end end).
-file("src/pig/workspace/vfs.gleam", 137).
?DOC(" Insert dentry row.\n").
-spec insert_dentry(sqlight:connection(), binary(), integer(), integer()) -> {ok,
nil} |
{error, error()}.
insert_dentry(Conn, Name, Parent_ino, Ino) ->
_pipe = sqlight:'query'(
<<"INSERT INTO vfs_dentry (name, parent_ino, ino) VALUES (?, ?, ?) RETURNING ino"/utf8>>,
Conn,
[sqlight:text(Name), sqlight:int(Parent_ino), sqlight:int(Ino)],
gleam@dynamic@decode:at(
[0],
{decoder, fun gleam@dynamic@decode:decode_int/1}
)
),
_pipe@1 = gleam@result:map_error(
_pipe,
fun(Field@0) -> {sql_error, Field@0} end
),
gleam@result:map(_pipe@1, fun(_) -> nil end).
-file("src/pig/workspace/vfs.gleam", 154).
?DOC(" Look up inode for a name in a parent directory.\n").
-spec lookup_dentry(sqlight:connection(), integer(), binary()) -> {ok,
integer()} |
{error, error()}.
lookup_dentry(Conn, Parent_ino, Name) ->
_pipe = sqlight:'query'(
<<"SELECT ino FROM vfs_dentry WHERE parent_ino = ? AND name = ?"/utf8>>,
Conn,
[sqlight:int(Parent_ino), sqlight:text(Name)],
gleam@dynamic@decode:at(
[0],
{decoder, fun gleam@dynamic@decode:decode_int/1}
)
),
_pipe@1 = gleam@result:map_error(
_pipe,
fun(Field@0) -> {sql_error, Field@0} end
),
gleam@result:'try'(_pipe@1, fun(Rows) -> case Rows of
[Ino] ->
{ok, Ino};
_ ->
{error, {not_found, Name}}
end end).
-file("src/pig/workspace/vfs.gleam", 177).
?DOC(" Run a function inside a transaction. Commits on Ok, rolls back on Error.\n").
-spec transaction(sqlight:connection(), fun(() -> {ok, LDG} | {error, error()})) -> {ok,
LDG} |
{error, error()}.
transaction(Conn, Body) ->
gleam@result:'try'(
begin
_pipe = sqlight:exec(<<"BEGIN"/utf8>>, Conn),
gleam@result:map_error(
_pipe,
fun(Field@0) -> {sql_error, Field@0} end
)
end,
fun(_use0) ->
nil = _use0,
case Body() of
{ok, Value} ->
_pipe@1 = sqlight:exec(<<"COMMIT"/utf8>>, Conn),
_pipe@2 = gleam@result:map_error(
_pipe@1,
fun(Field@0) -> {sql_error, Field@0} end
),
gleam@result:map(_pipe@2, fun(_) -> Value end);
{error, E} ->
_ = sqlight:exec(<<"ROLLBACK"/utf8>>, Conn),
{error, E}
end
end
).
-file("src/pig/workspace/vfs.gleam", 231).
-spec insert_one_chunk(sqlight:connection(), integer(), bitstring(), integer()) -> {ok,
nil} |
{error, error()}.
insert_one_chunk(Conn, Ino, Data, Index) ->
_pipe = sqlight:'query'(
<<"INSERT INTO vfs_data (ino, chunk_index, data) VALUES (?, ?, ?) RETURNING chunk_index"/utf8>>,
Conn,
[sqlight:int(Ino), sqlight:int(Index), sqlight_ffi:coerce_blob(Data)],
gleam@dynamic@decode:at(
[0],
{decoder, fun gleam@dynamic@decode:decode_int/1}
)
),
_pipe@1 = gleam@result:map_error(
_pipe,
fun(Field@0) -> {sql_error, Field@0} end
),
gleam@result:map(_pipe@1, fun(_) -> nil end).
-file("src/pig/workspace/vfs.gleam", 208).
-spec insert_chunks_loop(
sqlight:connection(),
integer(),
bitstring(),
integer()
) -> {ok, nil} | {error, error()}.
insert_chunks_loop(Conn, Ino, Remaining, Index) ->
Remaining_size = erlang:byte_size(Remaining),
case Remaining_size of
0 ->
{ok, nil};
_ when Remaining_size =< 4096 ->
insert_one_chunk(Conn, Ino, Remaining, Index);
_ ->
Chunk@1 = case gleam_stdlib:bit_array_slice(Remaining, 0, 4096) of
{ok, Chunk} -> Chunk;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Pattern match failed, no pattern matched the value."/utf8>>,
file => <<?FILEPATH/utf8>>,
module => <<"pig/workspace/vfs"/utf8>>,
function => <<"insert_chunks_loop"/utf8>>,
line => 220,
value => _assert_fail,
start => 6207,
'end' => 6271,
pattern_start => 6218,
pattern_end => 6227})
end,
Rest@1 = case gleam_stdlib:bit_array_slice(
Remaining,
4096,
Remaining_size - 4096
) of
{ok, Rest} -> Rest;
_assert_fail@1 ->
erlang:error(#{gleam_error => let_assert,
message => <<"Pattern match failed, no pattern matched the value."/utf8>>,
file => <<?FILEPATH/utf8>>,
module => <<"pig/workspace/vfs"/utf8>>,
function => <<"insert_chunks_loop"/utf8>>,
line => 221,
value => _assert_fail@1,
start => 6278,
'end' => 6375,
pattern_start => 6289,
pattern_end => 6297})
end,
case insert_one_chunk(Conn, Ino, Chunk@1, Index) of
{ok, nil} ->
insert_chunks_loop(Conn, Ino, Rest@1, Index + 1);
{error, E} ->
{error, E}
end
end.
-file("src/pig/workspace/vfs.gleam", 199).
?DOC(" Insert file content as chunks. Tail-recursive.\n").
-spec insert_chunks(sqlight:connection(), integer(), bitstring(), integer()) -> {ok,
nil} |
{error, error()}.
insert_chunks(Conn, Ino, Remaining, Index) ->
insert_chunks_loop(Conn, Ino, Remaining, Index).
-file("src/pig/workspace/vfs.gleam", 250).
?DOC(" Create a directory at the given path.\n").
-spec mkdir(sqlight:connection(), binary()) -> {ok, nil} | {error, error()}.
mkdir(Conn, Path) ->
gleam@result:'try'(
resolve_parent(Conn, Path),
fun(_use0) ->
{Parent_ino, Dir_name} = _use0,
case lookup_dentry(Conn, Parent_ino, Dir_name) of
{ok, _} ->
{error, {already_exists, Path}};
{error, {not_found, _}} ->
gleam@result:'try'(
transaction(
Conn,
fun() ->
gleam@result:'try'(
insert_inode(Conn, 16877),
fun(New_ino) ->
insert_dentry(
Conn,
Dir_name,
Parent_ino,
New_ino
)
end
)
end
),
fun(_use0@1) ->
nil = _use0@1,
{ok, nil}
end
);
{error, E} ->
{error, E}
end
end
).
-file("src/pig/workspace/vfs.gleam", 269).
?DOC(" Write content to a file. Creates if missing, overwrites if exists.\n").
-spec write_file(sqlight:connection(), binary(), binary()) -> {ok, nil} |
{error, error()}.
write_file(Conn, Path, Content) ->
gleam@result:'try'(
resolve_parent(Conn, Path),
fun(_use0) ->
{Parent_ino, Filename} = _use0,
gleam@result:'try'(
transaction(
Conn,
fun() ->
gleam@result:'try'(
case lookup_dentry(Conn, Parent_ino, Filename) of
{ok, Existing_ino} ->
gleam@result:'try'(
begin
_pipe = sqlight:exec(
<<"DELETE FROM vfs_data WHERE ino = "/utf8,
(erlang:integer_to_binary(
Existing_ino
))/binary>>,
Conn
),
gleam@result:map_error(
_pipe,
fun(Field@0) -> {sql_error, Field@0} end
)
end,
fun(_use0@1) ->
nil = _use0@1,
{ok, Existing_ino}
end
);
{error, {not_found, _}} ->
gleam@result:'try'(
insert_inode(Conn, 33188),
fun(New_ino) ->
gleam@result:'try'(
insert_dentry(
Conn,
Filename,
Parent_ino,
New_ino
),
fun(_use0@2) ->
nil = _use0@2,
{ok, New_ino}
end
)
end
);
{error, E} ->
{error, E}
end,
fun(Ino) ->
Bytes = <<Content/binary>>,
Byte_size = erlang:byte_size(Bytes),
gleam@result:'try'(
begin
_pipe@1 = sqlight:exec(
<<<<<<"UPDATE vfs_inode SET size = "/utf8,
(erlang:integer_to_binary(
Byte_size
))/binary>>/binary,
", mtime = unixepoch() WHERE ino = "/utf8>>/binary,
(erlang:integer_to_binary(Ino))/binary>>,
Conn
),
gleam@result:map_error(
_pipe@1,
fun(Field@0) -> {sql_error, Field@0} end
)
end,
fun(_use0@3) ->
nil = _use0@3,
insert_chunks(Conn, Ino, Bytes, 0)
end
)
end
)
end
),
fun(_use0@4) ->
nil = _use0@4,
{ok, nil}
end
)
end
).
-file("src/pig/workspace/vfs.gleam", 327).
?DOC(" Read the full content of a file.\n").
-spec read_file(sqlight:connection(), binary()) -> {ok, binary()} |
{error, error()}.
read_file(Conn, Path) ->
gleam@result:'try'(
resolve_path(Conn, Path),
fun(Ino) ->
gleam@result:'try'(
begin
_pipe = sqlight:'query'(
<<"SELECT mode FROM vfs_inode WHERE ino = ?"/utf8>>,
Conn,
[sqlight:int(Ino)],
gleam@dynamic@decode:at(
[0],
{decoder, fun gleam@dynamic@decode:decode_int/1}
)
),
_pipe@1 = gleam@result:map_error(
_pipe,
fun(Field@0) -> {sql_error, Field@0} end
),
gleam@result:'try'(_pipe@1, fun(Rows) -> case Rows of
[] ->
{error, {not_found, Path}};
[M] when M =:= 16877 ->
{error, {invalid_path, Path}};
[_] ->
{ok, nil};
_ ->
{error, {not_found, Path}}
end end)
end,
fun(_) ->
_pipe@2 = sqlight:'query'(
<<"SELECT data FROM vfs_data WHERE ino = ? ORDER BY chunk_index ASC"/utf8>>,
Conn,
[sqlight:int(Ino)],
gleam@dynamic@decode:at(
[0],
{decoder,
fun gleam@dynamic@decode:decode_bit_array/1}
)
),
_pipe@3 = gleam@result:map_error(
_pipe@2,
fun(Field@0) -> {sql_error, Field@0} end
),
gleam@result:'try'(_pipe@3, fun(Chunks) -> case Chunks of
[] ->
{ok, <<""/utf8>>};
_ ->
Combined = gleam_stdlib:bit_array_concat(
Chunks
),
case gleam@bit_array:to_string(Combined) of
{ok, Content} ->
{ok, Content};
{error, _} ->
{error,
{sql_error,
{sqlight_error,
internal,
<<"failed to convert blob to string"/utf8>>,
-1}}}
end
end end)
end
)
end
).
-file("src/pig/workspace/vfs.gleam", 380).
?DOC(" Read lines with offset/limit, formatted as \"N\\\\tline_content\" (0-indexed).\n").
-spec read_file_lines(sqlight:connection(), binary(), integer(), integer()) -> {ok,
binary()} |
{error, error()}.
read_file_lines(Conn, Path, Offset, Limit) ->
gleam@result:'try'(
read_file(Conn, Path),
fun(Content) ->
Lines = begin
_pipe = Content,
_pipe@1 = gleam@string:split(_pipe, <<"\n"/utf8>>),
_pipe@2 = gleam@list:drop(_pipe@1, Offset),
_pipe@3 = gleam@list:take(_pipe@2, Limit),
gleam@list:index_map(
_pipe@3,
fun(Line, Index) ->
<<<<(erlang:integer_to_binary(Offset + Index))/binary,
"\t"/utf8>>/binary,
Line/binary>>
end
)
end,
{ok, gleam@string:join(Lines, <<"\n"/utf8>>)}
end
).
-file("src/pig/workspace/vfs.gleam", 399).
?DOC(" List entries in a directory, sorted alphabetically.\n").
-spec list_directory(sqlight:connection(), binary()) -> {ok, list(binary())} |
{error, error()}.
list_directory(Conn, Path) ->
gleam@result:'try'(
resolve_path(Conn, Path),
fun(Ino) ->
gleam@result:'try'(
begin
_pipe = sqlight:'query'(
<<"SELECT mode FROM vfs_inode WHERE ino = ?"/utf8>>,
Conn,
[sqlight:int(Ino)],
gleam@dynamic@decode:at(
[0],
{decoder, fun gleam@dynamic@decode:decode_int/1}
)
),
_pipe@1 = gleam@result:map_error(
_pipe,
fun(Field@0) -> {sql_error, Field@0} end
),
gleam@result:'try'(_pipe@1, fun(Rows) -> case Rows of
[M] when M =:= 16877 ->
{ok, nil};
[_] ->
{error, {invalid_path, Path}};
_ ->
{error, {not_found, Path}}
end end)
end,
fun(_) ->
_pipe@2 = sqlight:'query'(
<<"SELECT name FROM vfs_dentry WHERE parent_ino = ? ORDER BY name ASC"/utf8>>,
Conn,
[sqlight:int(Ino)],
gleam@dynamic@decode:at(
[0],
{decoder, fun gleam@dynamic@decode:decode_string/1}
)
),
gleam@result:map_error(
_pipe@2,
fun(Field@0) -> {sql_error, Field@0} end
)
end
)
end
).
-file("src/pig/workspace/vfs.gleam", 560).
-spec find_matching_lines(binary(), binary(), binary()) -> list(grep_match()).
find_matching_lines(Content, File_path, Pattern) ->
Pattern_lower = string:lowercase(Pattern),
_pipe = Content,
_pipe@1 = gleam@string:split(_pipe, <<"\n"/utf8>>),
_pipe@2 = gleam@list:index_map(
_pipe@1,
fun(Line, Index) -> {Line, Index} end
),
_pipe@3 = gleam@list:filter(
_pipe@2,
fun(Tuple) ->
{Line@1, _} = Tuple,
gleam_stdlib:contains_string(
string:lowercase(Line@1),
Pattern_lower
)
end
),
gleam@list:map(
_pipe@3,
fun(Tuple@1) ->
{Line@2, Index@1} = Tuple@1,
{grep_match, File_path, Index@1, Line@2}
end
).
-file("src/pig/workspace/vfs.gleam", 521).
?DOC(" Read each matching file and extract the lines that contain the pattern.\n").
-spec extract_matching_lines(
sqlight:connection(),
binary(),
list(binary()),
integer(),
list(grep_match()),
integer()
) -> {ok, list(grep_match())} | {error, error()}.
extract_matching_lines(Conn, Pattern, Paths, Max_results, Acc, Acc_len) ->
case Paths of
[] ->
{ok, Acc};
[Path | Rest] ->
case (Max_results > 0) andalso (Acc_len >= Max_results) of
true ->
{ok, Acc};
false ->
gleam@result:'try'(case read_file(Conn, Path) of
{ok, Content} ->
{ok,
find_matching_lines(Content, Path, Pattern)};
{error, {not_found, _}} ->
{ok, []};
{error, {invalid_path, _}} ->
{ok, []};
{error, E} ->
{error, E}
end, fun(New_matches) ->
Limited = case Max_results > 0 of
true ->
gleam@list:take(
New_matches,
Max_results - Acc_len
);
false ->
New_matches
end,
Added = erlang:length(Limited),
extract_matching_lines(
Conn,
Pattern,
Rest,
Max_results,
lists:append(Acc, Limited),
Acc_len + Added
)
end)
end
end.
-file("src/pig/workspace/vfs.gleam", 580).
?DOC(" Escape SQL LIKE wildcard characters (%, _, \\) for literal matching.\n").
-spec escape_like(binary()) -> binary().
escape_like(S) ->
_pipe = S,
_pipe@1 = gleam@string:replace(_pipe, <<"\\"/utf8>>, <<"\\\\"/utf8>>),
_pipe@2 = gleam@string:replace(_pipe@1, <<"%"/utf8>>, <<"\\%"/utf8>>),
gleam@string:replace(_pipe@2, <<"_"/utf8>>, <<"\\_"/utf8>>).
-file("src/pig/workspace/vfs.gleam", 447).
?DOC(
" Search file contents for a substring pattern.\n"
"\n"
" Returns matching lines with their file path and line number.\n"
"\n"
" The database does the heavy lifting: a single SQL query uses a\n"
" recursive CTE to walk the directory tree, reassembles file content\n"
" from chunks via `group_concat`, and filters with `LIKE`. Only files\n"
" that contain a match are read back into Gleam for line-level\n"
" extraction.\n"
"\n"
" Parameters:\n"
" - pattern: substring to search for\n"
" - path: directory to search under (empty or \"/\" for root, can be a file)\n"
" - include: GLOB pattern to filter file paths (e.g., \"*.py\")\n"
" - max_results: maximum number of matching lines (0 = unlimited)\n"
).
-spec grep(sqlight:connection(), binary(), binary(), binary(), integer()) -> {ok,
list(grep_match())} |
{error, error()}.
grep(Conn, Pattern, Path, Include, Max_results) ->
Path_filter = case Path of
<<""/utf8>> ->
<<"%"/utf8>>;
<<"/"/utf8>> ->
<<"%"/utf8>>;
P ->
Normalized = case gleam_stdlib:string_starts_with(P, <<"/"/utf8>>) of
true ->
P;
false ->
<<"/"/utf8, P/binary>>
end,
Escaped = escape_like(Normalized),
case gleam_stdlib:string_ends_with(Normalized, <<"/"/utf8>>) of
true ->
<<Escaped/binary, "%"/utf8>>;
false ->
<<Escaped/binary, "/%"/utf8>>
end
end,
Include_filter = case Include of
<<""/utf8>> ->
<<"*"/utf8>>;
Glob ->
Glob
end,
Like_pattern = <<<<"%"/utf8, (escape_like(Pattern))/binary>>/binary,
"%"/utf8>>,
gleam@result:'try'(
begin
_pipe = sqlight:'query'(
<<"
WITH RECURSIVE paths(path, ino) AS (
SELECT '/' || name, ino FROM vfs_dentry WHERE parent_ino = 1
UNION ALL
SELECT p.path || '/' || d.name, d.ino
FROM paths p JOIN vfs_dentry d ON d.parent_ino = p.ino
)
SELECT p.path
FROM paths p
JOIN vfs_inode i ON p.ino = i.ino
WHERE i.mode = ?
AND p.path LIKE ? ESCAPE '\\'
AND p.path GLOB ?
AND (
SELECT group_concat(CAST(data AS TEXT), '')
FROM (SELECT data FROM vfs_data WHERE ino = p.ino ORDER BY chunk_index)
) LIKE ? ESCAPE '\\'
ORDER BY p.path"/utf8>>,
Conn,
[sqlight:int(33188),
sqlight:text(Path_filter),
sqlight:text(Include_filter),
sqlight:text(Like_pattern)],
gleam@dynamic@decode:at(
[0],
{decoder, fun gleam@dynamic@decode:decode_string/1}
)
),
gleam@result:map_error(
_pipe,
fun(Field@0) -> {sql_error, Field@0} end
)
end,
fun(Matching_paths) ->
Targets = case {Matching_paths, Path} of
{[], <<""/utf8>>} ->
[];
{[], _} ->
[Path];
{Paths, _} ->
Paths
end,
extract_matching_lines(Conn, Pattern, Targets, Max_results, [], 0)
end
).
-file("src/pig/workspace/vfs.gleam", 588).
?DOC(" Delete a file or empty directory.\n").
-spec delete_file(sqlight:connection(), binary()) -> {ok, nil} |
{error, error()}.
delete_file(Conn, Path) ->
gleam@result:'try'(
resolve_path(Conn, Path),
fun(Ino) ->
gleam@result:'try'(
resolve_parent(Conn, Path),
fun(_use0) ->
{Parent_ino, Filename} = _use0,
gleam@result:'try'(
begin
_pipe = sqlight:'query'(
<<"SELECT mode FROM vfs_inode WHERE ino = ?"/utf8>>,
Conn,
[sqlight:int(Ino)],
gleam@dynamic@decode:at(
[0],
{decoder,
fun gleam@dynamic@decode:decode_int/1}
)
),
_pipe@1 = gleam@result:map_error(
_pipe,
fun(Field@0) -> {sql_error, Field@0} end
),
gleam@result:'try'(
_pipe@1,
fun(Rows) -> case Rows of
[] ->
{error, {not_found, Path}};
[Mode] ->
{ok, Mode};
_ ->
{error, {not_found, Path}}
end end
)
end,
fun(Mode@1) ->
gleam@result:'try'(case Mode@1 =:= 16877 of
true ->
gleam@result:'try'(
begin
_pipe@2 = sqlight:'query'(
<<"SELECT COUNT(*) FROM vfs_dentry WHERE parent_ino = ?"/utf8>>,
Conn,
[sqlight:int(Ino)],
gleam@dynamic@decode:at(
[0],
{decoder,
fun gleam@dynamic@decode:decode_int/1}
)
),
_pipe@3 = gleam@result:map_error(
_pipe@2,
fun(Field@0) -> {sql_error, Field@0} end
),
gleam@result:'try'(
_pipe@3,
fun(Rows@1) ->
case Rows@1 of
[0] ->
{ok, nil};
_ ->
{error,
{not_empty,
Path}}
end
end
)
end,
fun(_use0@1) ->
nil = _use0@1,
{ok, nil}
end
);
false ->
{ok, nil}
end, fun(_use0@2) ->
nil = _use0@2,
transaction(
Conn,
fun() ->
gleam@result:'try'(
begin
_pipe@4 = sqlight:'query'(
<<"DELETE FROM vfs_dentry WHERE parent_ino = ? AND name = ? RETURNING name"/utf8>>,
Conn,
[sqlight:int(Parent_ino),
sqlight:text(
Filename
)],
gleam@dynamic@decode:at(
[0],
{decoder,
fun gleam@dynamic@decode:decode_string/1}
)
),
_pipe@5 = gleam@result:map_error(
_pipe@4,
fun(Field@0) -> {sql_error, Field@0} end
),
gleam@result:map(
_pipe@5,
fun(_) -> nil end
)
end,
fun(_use0@3) ->
nil = _use0@3,
gleam@result:'try'(
begin
_pipe@6 = sqlight:exec(
<<"DELETE FROM vfs_data WHERE ino = "/utf8,
(erlang:integer_to_binary(
Ino
))/binary>>,
Conn
),
gleam@result:map_error(
_pipe@6,
fun(Field@0) -> {sql_error, Field@0} end
)
end,
fun(_use0@4) ->
nil = _use0@4,
gleam@result:'try'(
begin
_pipe@7 = sqlight:exec(
<<"DELETE FROM vfs_inode WHERE ino = "/utf8,
(erlang:integer_to_binary(
Ino
))/binary>>,
Conn
),
gleam@result:map_error(
_pipe@7,
fun(Field@0) -> {sql_error, Field@0} end
)
end,
fun(_use0@5) ->
nil = _use0@5,
{ok, nil}
end
)
end
)
end
)
end
)
end)
end
)
end
)
end
).