Packages
fnord
0.8.45
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/cmd/config/approvals.ex
defmodule Cmd.Config.Approvals do
@moduledoc false
alias Cmd.Config.Utils
@spec run(map(), list(), list()) :: :ok
def run(opts, [:approvals], _unknown) do
cond do
opts[:global] && opts[:project] ->
build_list()
|> Jason.encode!(pretty: true)
|> UI.puts()
opts[:global] ->
build_list(:global)
|> Jason.encode!(pretty: true)
|> UI.puts()
true ->
case Settings.get_selected_project() do
{:ok, _proj} ->
build_list(:project)
|> Jason.encode!(pretty: true)
|> UI.puts()
{:error, _} ->
UI.error("Project not specified or not found")
end
end
end
# Unified approve entry
def run(opts, [:approve], args) do
cond do
opts[:global] && opts[:project] ->
UI.error("Cannot use both --global and --project.")
is_nil(opts[:kind]) ->
UI.error("Missing --kind option.")
true ->
case Utils.require_key(opts, args, :pattern, "Pattern") do
{:error, msg} ->
UI.error(msg)
{:ok, pattern} ->
case normalize_pattern(opts[:kind], pattern) do
{:error, msg} ->
UI.error(msg)
{kind, pattern} ->
# determine scope from --global flag or default to project
scope = if opts[:global], do: :global, else: :project
if scope == :project && opts[:project], do: Settings.set_project(opts[:project])
settings = Settings.new()
case build_approve(settings, scope, kind, pattern) do
{:ok, data} ->
data
|> Jason.encode!(pretty: true)
|> UI.puts()
{:error, err} ->
UI.error(err)
end
end
end
end
end
# Helpers
# ----------------------------------------------------------------------------
defp build_list(:global) do
Settings.new()
|> Settings.Approvals.get_approvals(:global)
end
defp build_list(:project) do
Settings.new()
|> Settings.Approvals.get_approvals(:project)
end
defp build_list() do
global = build_list(:global)
project = build_list(:project)
Enum.concat([
Map.keys(global),
Map.keys(project)
])
|> Enum.uniq()
|> Enum.map(fn kind ->
{
kind,
%{
global: Map.get(global, kind, []),
project: Map.get(project, kind, [])
}
}
end)
|> Enum.into(%{})
end
# Interpret /pattern/ under --kind shell as full-command regex
defp normalize_pattern("shell", pat) when is_binary(pat) do
if String.starts_with?(pat, "/") and String.ends_with?(pat, "/") do
# Strip leading and trailing slash; use explicit step to avoid negative step warning
inner = String.slice(pat, 1..-2//1)
# Return error for empty inner regex
if inner == "" do
{:error, "Empty regex is not allowed"}
else
{"shell_full", inner}
end
else
{"shell", pat}
end
end
defp normalize_pattern(kind, pat), do: {kind, pat}
defp build_approve(settings, scope, kind, pattern) do
if kind == "shell_full" and pattern == "" do
{:error, "Empty regex is not allowed"}
else
# validate that the pattern is a valid regex
case Regex.compile(pattern, "u") do
{:error, reason} ->
# reason is a tuple {message, position}
msg = elem(reason, 0)
msg_str = to_string(msg)
{:error, "Invalid regex: #{msg_str}"}
{:ok, _regex} ->
# add the approved prefix and output updated patterns
new_settings = Settings.Approvals.approve(settings, scope, kind, pattern)
patterns = Settings.Approvals.get_approvals(new_settings, scope, kind)
{:ok, %{kind => patterns}}
end
end
end
end