Parser and emitter for git-style INI configuration files.
parse/1 accepts arbitrary input — caller- or filesystem-supplied
text — and returns a tagged {:ok, _} | {:error, _} result. It
never raises on untrusted input.
Threat model
.git/config is treated as caller-controlled input, not
remote-controlled. Exgit does not fetch or persist config received
over the wire, and it does not act on any config value:
- no
core.sshCommand/core.fsmonitor/core.hookspath— there is no code path that executes a command out of config - no
http.proxy— Req's proxy comes from env or the explicit transport opts, not from config - no
insteadOf/pushInsteadOfURL rewriting - no
include/includeIfexpansion — config files are read as-is;[include] path=...entries are parsed but ignored - no
~/or${VAR}path expansion — paths in config values are treated as opaque strings
This keeps the blast radius of a hostile .git/config to "data
the caller reads back out of repo.config and uses themselves."
A consumer who reads e.g. Config.get(config, "core", "sshCommand")
and hands it to System.cmd/2 is outside exgit's trust boundary.
If submodule support is added, .gitmodules URLs become a
remote-controlled surface and will need separate validation —
refusing file://, ssh://user@host/…;command, and any URL
containing shell-metacharacters. Not currently present.
Summary
Functions
Append another value for key without replacing existing ones.
Types
@type t() :: %Exgit.Config{sections: [{section_key(), [{String.t(), String.t()}]}]}