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
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
//! **The pack-shaped values the protocol carries.** Vocabulary, not machinery.
//!
//! # Why these live here and not in `gunnar-pack`
//!
//! Every one of these types used to be `gunnar_pack::…`, and naming them was
//! the last edge `gunnar-wire` had into a pack *implementation*. It was a
//! **vocabulary** edge and never a call: nothing under `gunnar-wire/src` has
//! called `index_pack`, `PackWriter`, `write_pack_copy` or
//! `gix_pack::data::output::entry::iter_from_counts` since the engine seam
//! landed — [`crate::upload_pack`] emits through
//! [`GitServe::emit_pack`](gunnar_store::git_storage_trait::GitServe::emit_pack) and the
//! receive path takes the bytes through a caller-supplied
//! [`PackIngest`](crate::receive_pack::PackIngest) whose only shipping
//! implementation goes straight to `GitOps::put_pack`.
//!
//! But cargo links what a manifest names, not what a call graph reaches. One
//! `pub struct` field spelled `gix_pack::data::Version` was enough to put
//! `gix-pack` — and behind it `gix-diff`, `gix-traverse`, `gix-revwalk`,
//! `gix-commitgraph`, `gix-fs`, `gix-tempfile`, `gix-path`, `gix-chunk`,
//! `gix-zlib` and `gix-features/parallel` — into **every** build of the
//! appliance, including `--no-default-features --features server,engine-znippy`
//! whose whole point is that the pack pipeline is not there.
//!
//! So the vocabulary moved to the side that speaks it. These are the words
//! `receive-pack` and `upload-pack` use to *report* what an engine did; the
//! engine behind the contract is what actually did it, and which crate it used
//! is its own business. `gunnar-pack` remains a **dev-dependency** of this
//! crate, where it is what it always was for these tests: an outside oracle
//! that indexes a pack gunnar produced and disagrees when gunnar is wrong.
//!
//! # The residue, said out loud
//!
//! [`ObjectId`] and [`Kind`] are still `gix-hash`'s. They are cheap value types
//! — a 32-byte inline array and a two-variant enum — with no pipeline behind
//! them, and the contract's own `Oid<'a> = &'a [u8]` is a *borrow*, so it
//! cannot be what an owned id in a returned struct is spelled as. Replacing
//! them is a workspace-wide rename with no dependency payoff on its own, and it
//! is not what this module is for.
use PathBuf;
use ;
/// **A packfile's format version**, as the four bytes after `PACK` say it.
///
/// Local, and two variants wide, because the field below is the only thing
/// `gunnar-wire` and `gunnar-server` ever wanted out of `gix-pack` — see this
/// module's header for what naming it cost.
/// **What came out of taking a pushed pack into storage.**
///
/// A *receipt*, not a handle: every field is a fact read back off what was
/// stored, and nothing here reaches into the store to answer. The three
/// `Option<PathBuf>`s are `None` on every engine that does not keep git's
/// on-disk layout — which is the default one — and `None` there is the truth
/// rather than a degraded answer.
/// **What one packfile emission produced.**
///
/// Filled in from the engine's own `PackStats` on the way out of
/// [`GitServe::emit_pack`](gunnar_store::git_storage_trait::GitServe::emit_pack), so every
/// number is read back off what the engine reported rather than restated from
/// what was asked for.
///
/// **No `Default`**, and that is a property rather than an omission: `ObjectId`
/// has none, and an outcome with a zeroed pack id is one that claims a pack was
/// written and cannot name it. `gunnar-pack`'s own `WriteOutcome` refused the
/// same shape for the same reason.
/// Ceiling on a single entry's allocation while decoding an untrusted pack:
/// 1 GiB.
///
/// Chosen to be far above any object a real repository contains and far below
/// what hurts a server. The size being guarded is **read out of the pack**, so
/// it is attacker-controlled: a pack can claim an entry is enormous and,
/// without this, a decoder tries to allocate exactly that.
///
/// The same number `gunnar-pack` applies on its own receive path, and the
/// twinning is **checked** rather than asserted in prose:
/// `tests/pack_vocabulary.rs` compares the two. It lives out there and not in a
/// `#[cfg(test)]` block down this file because `xtask::engine_seam` reads
/// `crates/*/src` and does not read `#[cfg]`, deliberately — a rule with a
/// "but it is only a test" escape hatch inside a shipped file is a rule with a
/// hole in it, and the guard found this very line the first time it ran.
pub const DEFAULT_ALLOC_LIMIT_BYTES: usize = 1 << 30;