-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathCargo.toml
More file actions
223 lines (204 loc) · 10.7 KB
/
Copy pathCargo.toml
File metadata and controls
223 lines (204 loc) · 10.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
# git-tpl — Git-native project templates.
#
# Single crate, `[lib]` + `[[bin]]`, matching the convention of the sibling
# projects (gh-ship, gh-settings). The library holds the whole engine; the
# binary is a thin CLI over it, so integration tests can exercise either.
# See docs/adr/004-single-crate.md.
[package]
name = "git-tpl"
version = "0.13.0"
edition = "2024"
# The MSRV. Checked by a dedicated CI job, which greps this very line — keep it
# a plain literal. `rust-toolchain.toml` separately pins the channel to develop
# against; the two answer different questions.
rust-version = "1.96"
license = "MIT"
authors = ["Axel H. <noirbizarre@gmail.com>"]
description = "Git-native project templates"
repository = "https://github.com/noirbizarre/git-tpl"
homepage = "https://noirbizarre.github.io/git-tpl/"
documentation = "https://noirbizarre.github.io/git-tpl/"
readme = "README.md"
keywords = ["git", "template", "scaffolding", "minijinja", "project"]
categories = ["command-line-utilities", "development-tools"]
# cargo-binstall otherwise derives an asset name from the target triple, and
# our assets carry short platform suffixes instead. A wrong guess is not an
# error: binstall silently falls back to building from source, which is the
# slow path this exists to avoid. So every published target is mapped by hand.
#
# `{ version }` and not `v{ version }`: this project tags without a prefix.
[package.metadata.binstall]
pkg-fmt = "tgz"
# The archives hold the binary at their root, so there is no directory to
# descend into.
bin-dir = "git-tpl{ binary-ext }"
[package.metadata.binstall.overrides.x86_64-unknown-linux-gnu]
pkg-url = "{ repo }/releases/download/{ version }/git-tpl_{ version }_linux-amd64.tar.gz"
[package.metadata.binstall.overrides.aarch64-unknown-linux-gnu]
pkg-url = "{ repo }/releases/download/{ version }/git-tpl_{ version }_linux-arm64.tar.gz"
[package.metadata.binstall.overrides.x86_64-unknown-linux-musl]
pkg-url = "{ repo }/releases/download/{ version }/git-tpl_{ version }_linux-amd64-musl.tar.gz"
[package.metadata.binstall.overrides.x86_64-apple-darwin]
pkg-url = "{ repo }/releases/download/{ version }/git-tpl_{ version }_darwin-amd64.tar.gz"
[package.metadata.binstall.overrides.aarch64-apple-darwin]
pkg-url = "{ repo }/releases/download/{ version }/git-tpl_{ version }_darwin-arm64.tar.gz"
[package.metadata.binstall.overrides.x86_64-pc-windows-msvc]
pkg-url = "{ repo }/releases/download/{ version }/git-tpl_{ version }_windows-amd64.zip"
pkg-fmt = "zip"
# The binary name is mandated by Git: `git tpl ...` resolves to an executable
# named `git-tpl` on PATH. It is not a stylistic choice, and renaming it breaks
# the only invocation the project is named after.
[[bin]]
name = "git-tpl"
path = "src/main.rs"
# The engine is a library first. The binary is one frontend; `gh-tpl` will be
# another. Integration tests use both — the library for engine-level assertions,
# the binary for output snapshots.
[lib]
name = "tpl"
path = "src/lib.rs"
[dependencies]
# Errors & diagnostics
thiserror = "2"
miette = { version = "7", features = ["fancy"] }
# Git. libgit2 bindings. `vendored-libgit2` builds libgit2 from source rather
# than linking whatever the host happens to ship, so the six release targets and
# every developer machine get identical Git semantics.
# `cred` is what git2 0.21 gates `Cred::credential_helper` behind; without it a
# private HTTPS template silently loses the credential-helper fallback.
# `https` and `ssh` are git2 defaults that `default-features = false` removes,
# and the vendored build then has no TLS backend and no libssh2: *every* remote
# becomes unreachable, with "there is no TLS stream available" for https and
# "unsupported URL protocol" for ssh. They are listed explicitly so that turning
# defaults off again cannot silently take the transports with them.
# `vendored-openssl` compiles OpenSSL from source next to libgit2, so the Linux
# and musl binaries carry their own TLS rather than the host's. It is inert on
# Windows (WinHTTP) and macOS (SecureTransport), where `https` pulls no
# openssl-sys at all.
git2 = { version = "0.21", default-features = false, features = [
"vendored-libgit2",
"vendored-openssl",
"https",
"ssh",
"cred",
] }
# The `.gitignore` evaluator for `--dirty`, and deliberately not libgit2's.
# libgit2 will not let a repository `.gitignore` negation override a rule that
# came from `core.excludesFile`, so a template shipping `!mise.toml` against the
# common global rule that hides mise configuration loses the file from a
# `--dirty` render while `git add -A` stages it (#51). libgit2 does not report
# which rule matched, so there is nothing to post-correct — the stack has to be
# evaluated here. See ADR-017.
#
# Only `gitignore::GitignoreBuilder` is used. The crate's parallel walker is
# not: it reports nothing about what it skipped, and `--dirty` must name the
# files a global rule removed. The walk stays ours.
#
# This is the one place full `regex-automata` enters the tree. `regex-lite`,
# chosen below for question patterns, is not a substitute: gitignore globs are
# not regexes, and hand-translating them is the failure this dependency buys
# out of.
ignore = "0.4"
# Templating. The only rendering engine, deliberately.
# `builtins` provides the filters templates actually reach for (lower, replace,
# trim). `loader` lets the renderer resolve `{% include %}` within the template
# tree rather than the filesystem.
minijinja = { version = "2", features = ["builtins", "loader"] }
# Transliteration for the `slugify` filter. A pure lookup table: no locale, no
# I/O, no allocation of behaviour that varies by machine, so it cannot break
# determinism. It is here rather than a hand-rolled ASCII fold because folding
# drops non-Latin scripts entirely — `Москва` would slug to the empty string.
deunicode = "1.6"
# CLI
clap = { version = "4", features = ["derive", "env", "wrap_help", "string"] }
# Completions and the man page are generated from the live `clap::Command` at
# runtime rather than from a checked-in script or a `build.rs`. A generator that
# reads the same definition the parser uses cannot advertise a flag that no
# longer exists — and the man page is not a nicety: Git intercepts
# `git tpl --help` and runs `man git-tpl`, which fails without one.
clap_complete = "4"
clap_mangen = "0.3"
console = "0.16"
demand = "2"
# The `git tpl test` spinner. Pairs with `console` (same author): both decide
# from the same terminal-detection primitives, so the two never disagree
# about whether a spinner belongs on screen.
indicatif = "0.18"
# Configuration & data
serde = { version = "1", features = ["derive"] }
# `preserve_order` keeps JSON object key order stable. Data files feed
# `choices_from`, and a choice list whose order changes between runs would make
# rendering non-deterministic for no reason. See ADR-006.
serde_json = { version = "1", features = ["preserve_order"] }
toml = { version = "1.1", features = ["preserve_order"] }
# Question declaration order breaks ties in the dependency sort (ADR-007), so
# it is the only ordering a template author controls and must survive parsing.
# A plain map would lose it.
indexmap = { version = "2", features = ["serde"] }
# YAML 1.2, which is the only kind worth accepting: the 1.1 scalar rules are
# what gave YAML its reputation, resolving `no` to false and `12:30:00` to a
# sexagesimal integer. `noyalib` is a pure-Rust, actively maintained YAML
# engine (the recommended successor once `serde_yaml` was archived). Its
# defaults are looser than this project needs — duplicate keys and multi-
# document streams are accepted, and `<<` auto-merges — so `format.rs` builds
# an explicit `ParserConfig` to restore the strict, bounded behavior a remote
# data source requires.
noyalib = "0.0.28"
# The answers digest recorded in the provenance trailers. `sha2` rather than a
# faster non-cryptographic hash because the digest is written into Git history
# and read back to decide whether a re-render is needed.
sha2 = "0.11"
hex = "0.4"
# The unified diff shown when a rendering no longer matches its recorded
# snapshot. Only the diff engine: the snapshots live in the *user's* template
# repository and must stay readable without a Rust toolchain, so nothing here
# owns their format. `GitBackend::diff_patch` was the alternative and needs two
# trees — using it would mean writing objects into the template repository to
# answer a question that reads nothing.
# `unicode` is on for `backport`'s un-substitution, which diffs *within* a line:
# the default byte/char granularity would split a `\r\n` or a combining sequence
# and hand back a byte range that is not a character boundary.
similar = { version = "3.2", features = ["unicode"] }
# A remote template is cloned into a fresh temporary directory per run.
# Caching between runs would be faster, but a stale cache silently rendering an
# old template is a far worse failure than a slow fetch — in a tool whose whole
# premise is reproducibility.
tempfile = "3"
# Word-splitting for a `git tpl test` case's `[commands]` entries — quotes and
# backslash escapes honoured, nothing else: no pipe, no glob, no redirection,
# no `$VAR` expansion, and no shell process runs. Already present transitively
# through `cc`'s build script; promoted to a direct dependency because a
# case's commands are parsed by the library itself, at runtime. See ADR-027.
shlex = "2"
# The remote data source client. Blocking, because everything below `ops` is
# synchronous and an async runtime would exist solely to be blocked on. Default
# features give rustls plus the platform verifier, so no release target needs a
# system TLS library. `ureq` also bounds the response body on the read itself,
# which is the only trustworthy way to enforce a size limit — `Content-Length`
# is a claim made by the server.
ureq = "3"
# Question `pattern` validation. The pattern comes from a template, which is
# untrusted input, and `regex-lite` has no backtracking — a hostile pattern
# costs time linear in the subject rather than exponential. It also carries no
# Unicode tables, so it adds neither a build-time cost nor an MSRV risk.
regex-lite = "0.1.9"
[dev-dependencies]
assert_cmd = "2"
predicates = "3"
insta = { version = "1", features = ["filters"] }
# The integration harness fingerprints the worktree to prove `update` does not
# touch it. Already a runtime dependency; listed for the tests' own use.
sha2 = "0.11"
hex = "0.4"
rstest = "0.26"
pretty_assertions = "1"
# `regex::escape`, for the snapshot filter that redacts the tests' temporary
# directory. Already in the dev tree via `insta`'s `filters`, so it costs no
# extra compilation; the runtime `regex-lite` is deliberately not reused here,
# because the pattern is consumed by `insta`'s `regex` and the two crates'
# syntaxes are only incidentally the same.
regex = "1"
[profile.release]
lto = true
codegen-units = 1
strip = true