Answers from a file¶
--answers-from <path> supplies answers from a TOML, JSON or YAML file, on
both git tpl init and git tpl update.
It exists because four unrelated things need the same thing:
- migrating from Copier, Cruft, or anything else that recorded its answers
- creating many projects from one set of house values
- rendering in CI, where there is no terminal to prompt at
- checking a template's fixtures in, so the template can have tests
A tool-specific importer would have bought only the first, and would have put someone else's file format in the CLI surface permanently.
The file¶
Either a flat table of name = value:
…or those same pairs under an answers key, so a template's fixture file can
carry other tables beside them:
Nothing else is a valid shape. A document that is not a table is refused
(tpl::answers::shape) rather than silently supplying nothing.
Formats¶
The same three the data sources take, read by the same parsers, chosen by the file extension:
| Extension | Format |
|---|---|
.toml, anything else |
TOML |
.json |
JSON |
.yaml, .yml |
YAML 1.2 |
YAML matters here specifically: .copier-answers.yml and most hand-written
house-defaults files are YAML, and requiring a yq step first would have
undercut the point of the flag. It is YAML 1.2, so no is the string "no" —
see About YAML.
Types are preserved¶
This is the difference between the file and --answer. A flag can only carry
text, so --answer port=8080 is a string that the question's declared type
turns into an integer. A file carries the type it was written with.
A value that does not match the question's declared type is an error
(tpl::eval::wrong_type), never a silent coercion. port = "eighty" for an
integer question fails; it does not become 0.
Unknown keys are ignored, and reported¶
A key naming no question in the template is skipped, and named on stderr:
Both halves are deliberate. Erroring would make the flag useless for the case
that motivated it — a .copier-answers.yml carries _src_path and _commit,
and any long-lived template has dropped a question at some point. Staying silent
would make a typo'd key look exactly like an answer that had no effect.
Nothing about the ignored keys is recorded: .config/git.tpl.toml holds the
answers to questions the template actually asked.
A Copier answers file works unedited¶
This is not Copier compatibility, and is not meant to grow into it. The flag maps names to names: a template whose questions were renamed between tools needs its answers edited. Shipping a mapping language to avoid that would cost more than the editing does.
Precedence¶
--answers-from is repeatable, and later files win over earlier ones — house
defaults first, the specific file on top:
$ git tpl init <template> \
--answers-from house-defaults.toml \
--answers-from this-project.toml \
--answer project_name=thing
The whole chain, highest first:
--answer
> the last --answers-from
> earlier --answers-from
> answers recorded in .config/git.tpl.toml (update only)
> the question's default
A question covered by none of them is asked as usual, unless --defaults or
tpl.interactive false is in force — in which case its default is taken, and a
question with no default is an error (tpl::eval::unanswered).
Failures¶
| Code | Meaning |
|---|---|
tpl::answers::read |
The file could not be read. The path is in the help. |
tpl::answers::parse |
It is not valid TOML, JSON or YAML. |
tpl::answers::shape |
It is not a table of answers. |
tpl::eval::wrong_type |
A value does not match the question's declared type. |
The path is resolved relative to your working directory, and is used as given. It is deliberately not restricted to the project — you named it yourself, unlike a local data source path, which comes out of a template repository and is therefore untrusted input.