Packages

Prompt Runner SDK - packet-first prompt execution for Elixir and CLI workflows with verifier-owned completion, retry, repair, and git-aware repository orchestration.

Current section

Files

Jump to
prompt_runner_sdk lib prompt_runner git.ex
Raw

lib/prompt_runner/git.ex

defmodule PromptRunner.Git do
@moduledoc false
alias PromptRunner.CommitMessages
alias PromptRunner.UI
@spec commit_multi_repo(PromptRunner.Config.t(), String.t(), list({String.t(), String.t()})) ::
list({String.t(), term()})
def commit_multi_repo(config, num, target_repos) do
Enum.map(target_repos, fn {repo_name, repo_path} ->
msg = CommitMessages.get_message(config, num, repo_name)
unless msg do
raise "Commit message not found for prompt #{num}:#{repo_name}"
end
IO.puts("")
IO.puts("#{UI.yellow("Checking")} #{repo_name} (#{repo_path})...")
result = commit_repo(repo_path, msg, num, repo_name)
{repo_name, result}
end)
end
@spec commit_single_repo(PromptRunner.Config.t(), String.t(), String.t(), String.t() | nil) ::
{:ok, String.t()} | {:skip, atom()} | {:error, atom()}
def commit_single_repo(config, num, repo_name \\ "default", repo_path \\ nil) do
path = repo_path || config.project_dir
# Try repo-specific message first, fall back to generic
msg =
if repo_name != "default" do
CommitMessages.get_message(config, num, repo_name) ||
CommitMessages.get_message(config, num)
else
CommitMessages.get_message(config, num)
end
unless msg do
raise "Commit message not found for prompt #{num}"
end
commit_repo(path, msg, num, repo_name)
end
@spec commit_repo(String.t(), String.t(), String.t(), String.t()) ::
{:ok, String.t()} | {:skip, atom()} | {:error, atom()}
def commit_repo(project_dir, msg, num, repo_name) do
{status, exit_status} = System.cmd("git", ["status", "--porcelain"], cd: project_dir)
cond do
exit_status != 0 ->
IO.puts(UI.red("ERROR: git status failed for #{repo_name}"))
{:error, :git_status_failed}
String.trim(status) == "" ->
IO.puts(UI.dim("No changes in #{repo_name}"))
{:skip, :no_changes}
true ->
IO.puts(UI.yellow("Committing to #{repo_name}..."))
{_, 0} = System.cmd("git", ["add", "-A"], cd: project_dir)
tmp_dir = System.tmp_dir!()
tmp_id = System.unique_integer([:positive])
tmp_path = Path.join(tmp_dir, "prompt-#{num}-#{repo_name}-commit-msg-#{tmp_id}.txt")
File.write!(tmp_path, msg <> "\n")
{_, exit_code} = System.cmd("git", ["commit", "--file", tmp_path], cd: project_dir)
File.rm(tmp_path)
if exit_code == 0 do
{sha, 0} = System.cmd("git", ["rev-parse", "HEAD"], cd: project_dir)
short = sha |> String.trim() |> String.slice(0, 8)
IO.puts(UI.green("Committed to #{repo_name}: #{short}"))
{:ok, String.trim(sha)}
else
IO.puts(UI.red("ERROR: Git commit failed for #{repo_name}"))
{:error, :commit_failed}
end
end
end
end