Resolves the priv/ggen/<pack-name>/ convention (or an explicit --pack-dir)
into sane defaults for --ontology/--query/--template, per the pack
convention design:
priv/ggen/<pack-name>/
├── pack.toml # optional, not read here
├── ontology.ttl # default --ontology
├── gates/*.rq # default --query source, one query per file
└── templates/*.{eex,tmpl} # default --template source (single-file case)Pure helper, no Igniter dependency, so both ggen_igniter.sync and
ggen_igniter.doctor (and tests) can call it directly.
Marketplace fetch (fetch_pack!/2)
Modeled on the real Rust ggen's ggen pack add <registry>:<id>
(crates/ggen-marketplace/src/marketplace/install.rs): resolve a package
spec, download a real archive over HTTP, verify it, extract it into a local
cache directory so resolve_dir!/1-style discovery works against it.
Two real, simple registry sources are implemented -- their verification strength is genuinely different, and this moduledoc says so honestly:
"github:owner/repo"(optionally"@ref", default"main") -- fetcheshttps://github.com/<owner>/<repo>/archive/refs/heads/<ref>.tar.gz. GitHub's archive endpoint publishes no checksum to verify against, so this path is print-only: the real SHA-256 of the downloaded archive is printed so the caller can pin/verify it manually (e.g. against a value they've recorded from a prior trusted fetch). This is not fail-closed verification -- there is nothing to fail closed against."hex:name@version"(or"hex:name"to resolve the latest stable version via the Hex API) -- fetches the real Hex package tarball fromhttps://repo.hex.pm/tarballs/<name>-<version>.tarand compares its real SHA-256 against thechecksumfield hex.pm's own API (https://hex.pm/api/packages/<name>/releases/<version>) publishes for that release. This path is fail-closed: a mismatch raises before anything is extracted.
Neither source is fabricated -- both are real public HTTP endpoints exercised
by the test suite (tagged :requires_network, see
test/ggen_igniter_pack_fetch_test.exs).
Summary
Functions
Default --ontology path for pack_dir: <pack_dir>/ontology.ttl.
Discovers every <pack_dir>/gates/*.rq file, sorted lexically (so the
NNN_ numeric-prefix convention controls ordering), mapped to
{name, path} where name is the filename stem with any leading
^\d+_ digit-prefix stripped: 010_spec.rq -> "spec", entities.rq ->
"entities" (no prefix, no change).
Discovers the --template under <pack_dir>/templates/.
Fetches a real marketplace pack over HTTP and extracts it into a local
cache directory, returning the extracted pack directory (usable directly
with resolve_dir!/1 via pack_dir:).
Resolves the pack directory from opts[:pack_dir] (explicit override) or
opts[:pack] (looked up under priv/ggen/<name>/). Raises ArgumentError
if neither is given.
Functions
Default --ontology path for pack_dir: <pack_dir>/ontology.ttl.
Discovers every <pack_dir>/gates/*.rq file, sorted lexically (so the
NNN_ numeric-prefix convention controls ordering), mapped to
{name, path} where name is the filename stem with any leading
^\d+_ digit-prefix stripped: 010_spec.rq -> "spec", entities.rq ->
"entities" (no prefix, no change).
@spec discover_template(String.t(), String.t() | nil) :: {:ok, String.t()} | {:error, :none} | {:error, {:ambiguous, [String.t()]}} | {:error, {:stem_not_found, String.t(), [String.t()]}}
Discovers the --template under <pack_dir>/templates/.
With stem omitted (or nil) -- the plain --pack NAME case -- returns
{:ok, path} when exactly one *.eex or *.tmpl file exists,
{:error, :none} when there are zero, or {:error, {:ambiguous, paths}}
when there is more than one (no guessing which of N templates is "the" one).
With stem given -- the --pack NAME:TEMPLATE_STEM case (see
Mix.Tasks.GgenIgniter.Sync's moduledoc) -- selects the one template file
whose basename up to its first . equals stem ("resource.ex.eex" ->
stem "resource", "domain.ex.eex" -> stem "domain"), bypassing the
ambiguity error entirely even when the pack has multiple templates:
{:ok, path} on a unique match, {:error, {:stem_not_found, stem, paths}}
when no template's stem matches (paths lists every template actually
found, for a helpful error), or {:error, {:ambiguous, paths}} in the
degenerate case of two templates sharing the same stem with different
extensions (e.g. both resource.eex and resource.tmpl present).
Fetches a real marketplace pack over HTTP and extracts it into a local
cache directory, returning the extracted pack directory (usable directly
with resolve_dir!/1 via pack_dir:).
spec is one of:
"github:owner/repo"or"github:owner/repo@ref"(ref defaults to"main") -- see the moduledoc for what verification this gives you (print-only SHA-256, no source-supplied checksum to compare against)."hex:name"or"hex:name@version"(version defaults to the latest stable release per the Hex API) -- fail-closed SHA-256 verification against hex.pm's own published release checksum.
Options:
:cache_dir-- override the cache root (default~/.cache/ggen_igniter/packs). Each pack is extracted to a spec-derived subdirectory under this root and is safe to re-fetch (previous contents at that path are replaced).
Raises ArgumentError for an unrecognized spec, and RuntimeError for any
HTTP failure or (hex only) checksum mismatch.
Resolves the pack directory from opts[:pack_dir] (explicit override) or
opts[:pack] (looked up under priv/ggen/<name>/). Raises ArgumentError
if neither is given.