comparison tests/test-manifest.t @ 42377:0546ead39a7e stable

manifest: avoid corruption by dropping removed files with pure (issue5801) Previously, removed files would simply be marked by overwriting the first byte with NUL and dropping their entry in `self.position`. But no effort was made to ignore them when compacting the dictionary into text form. This allowed them to slip into the manifest revision, since the code seems to be trying to minimize the string operations by copying as large a chunk as possible. As part of this, compact() walks the existing text based on entries in the `positions` list, and consumed everything up to the next position entry. This typically resulted in a ValueError complaining about unsorted manifest entries. Sometimes it seems that files do get dropped in large repos- it seems to correspond to there being a new entry that would take the same slot. A much more trivial problem is that if the only changes were removals, `_compact()` didn't even run because `__delitem__` doesn't add anything to `self.extradata`. Now there's an explicit variable to flag this, both to allow `_compact()` to run, and to avoid searching the manifest in cases where there are no removals. In practice, this behavior was mostly obscured by the check in fastdelta() which takes a different path that explicitly drops removed files if there are fewer than 1000 changes. However, timeless has a repo where after rebasing tens of commits, a totally different path[1] is taken that bypasses the change count check and hits this problem. [1] https://www.mercurial-scm.org/repo/hg/file/2338bdea4474/mercurial/manifest.py#l1511
author Matt Harbison <matt_harbison@yahoo.com>
date Thu, 23 May 2019 21:54:24 -0400
parents 89c0c8edc9d4
children 8377570a36a9
comparison
equal deleted inserted replaced
42376:89c0c8edc9d4 42377:0546ead39a7e
217 $ cat >> $HGRCPATH <<EOF 217 $ cat >> $HGRCPATH <<EOF
218 > [extensions] 218 > [extensions]
219 > manifest = $TESTTMP/manifest.py 219 > manifest = $TESTTMP/manifest.py
220 > EOF 220 > EOF
221 221
222 BROKEN: Pure removes should actually remove all dropped entries 222 Pure removes should actually remove all dropped entries
223 223
224 $ hg init repo 224 $ hg init repo
225 $ cd repo 225 $ cd repo
226 $ echo a > a.txt 226 $ echo a > a.txt
227 $ echo aa > aa.txt 227 $ echo aa > aa.txt
237 $ hg ci -m 'remove b and d' 237 $ hg ci -m 'remove b and d'
238 238
239 $ hg debugdata -m 1 239 $ hg debugdata -m 1
240 a.txt\x00b789fdd96dc2f3bd229c1dd8eedf0fc60e2b68e3 (esc) 240 a.txt\x00b789fdd96dc2f3bd229c1dd8eedf0fc60e2b68e3 (esc)
241 aa.txt\x00a4bdc161c8fbb523c9a60409603f8710ff49a571 (esc) 241 aa.txt\x00a4bdc161c8fbb523c9a60409603f8710ff49a571 (esc)
242 \x00.txt\x001e88685f5ddec574a34c70af492f95b6debc8741 (esc) (pure !)
243 c.txt\x00149da44f2a4e14f488b7bd4157945a9837408c00 (esc) 242 c.txt\x00149da44f2a4e14f488b7bd4157945a9837408c00 (esc)
244 cc.txt\x00149da44f2a4e14f488b7bd4157945a9837408c00 (esc) 243 cc.txt\x00149da44f2a4e14f488b7bd4157945a9837408c00 (esc)
245 ccc.txt\x00149da44f2a4e14f488b7bd4157945a9837408c00 (esc) 244 ccc.txt\x00149da44f2a4e14f488b7bd4157945a9837408c00 (esc)
246 \x00.txt\x001e88685f5ddec574a34c70af492f95b6debc8741 (esc) (pure !)
247 e.txt\x00149da44f2a4e14f488b7bd4157945a9837408c00 (esc) 245 e.txt\x00149da44f2a4e14f488b7bd4157945a9837408c00 (esc)
248 246
249 $ hg up -C . 2>&1 | grep ValueError || true 247 $ hg up -qC .
250 raise ValueError("Manifest lines not in sorted order.") (pure !) 248
251 ValueError: Manifest lines not in sorted order. (pure !) 249 $ hg verify
252
253 $ hg verify || true
254 checking changesets 250 checking changesets
255 checking manifests 251 checking manifests
256 manifest@1: reading delta c1f6b2f803ac: Non-hexadecimal digit found (pure !)
257 crosschecking files in changesets and manifests 252 crosschecking files in changesets and manifests
258 checking files 253 checking files
259 checked 2 changesets with 8 changes to 8 files 254 checked 2 changesets with 8 changes to 8 files
260 1 integrity errors encountered! (pure !)
261 (first damaged changeset appears to be 1) (pure !)
262 255
263 $ hg rollback -q --config ui.rollback=True 256 $ hg rollback -q --config ui.rollback=True
264 $ hg rm b.txt d.txt 257 $ hg rm b.txt d.txt
265 $ echo bb > bb.txt 258 $ echo bb > bb.txt
266 259
267 BROKEN: A mix of adds and removes should remove all dropped entries. 260 A mix of adds and removes should remove all dropped entries.
268 261
269 $ hg ci -Aqm 'remove b and d; add bb' 262 $ hg ci -Aqm 'remove b and d; add bb'
270 263
271 $ hg debugdata -m 1 264 $ hg debugdata -m 1
272 a.txt\x00b789fdd96dc2f3bd229c1dd8eedf0fc60e2b68e3 (esc) 265 a.txt\x00b789fdd96dc2f3bd229c1dd8eedf0fc60e2b68e3 (esc)
273 aa.txt\x00a4bdc161c8fbb523c9a60409603f8710ff49a571 (esc) 266 aa.txt\x00a4bdc161c8fbb523c9a60409603f8710ff49a571 (esc)
274 bb.txt\x0004c6faf8a9fdd848a5304dfc1704749a374dff44 (esc) 267 bb.txt\x0004c6faf8a9fdd848a5304dfc1704749a374dff44 (esc)
275 c.txt\x00149da44f2a4e14f488b7bd4157945a9837408c00 (esc) 268 c.txt\x00149da44f2a4e14f488b7bd4157945a9837408c00 (esc)
276 cc.txt\x00149da44f2a4e14f488b7bd4157945a9837408c00 (esc) 269 cc.txt\x00149da44f2a4e14f488b7bd4157945a9837408c00 (esc)
277 ccc.txt\x00149da44f2a4e14f488b7bd4157945a9837408c00 (esc) 270 ccc.txt\x00149da44f2a4e14f488b7bd4157945a9837408c00 (esc)
278 \x00.txt\x001e88685f5ddec574a34c70af492f95b6debc8741 (esc) (pure !)
279 e.txt\x00149da44f2a4e14f488b7bd4157945a9837408c00 (esc) 271 e.txt\x00149da44f2a4e14f488b7bd4157945a9837408c00 (esc)
280 272
281 $ hg up -C . 2>&1 | grep ValueError || true 273 $ hg verify
282 raise ValueError("Manifest lines not in sorted order.") (pure !)
283 ValueError: Manifest lines not in sorted order. (pure !)
284
285 $ hg verify || true
286 checking changesets 274 checking changesets
287 checking manifests 275 checking manifests
288 manifest@1: reading delta 0a0385480090: Manifest lines not in sorted order. (pure !)
289 crosschecking files in changesets and manifests 276 crosschecking files in changesets and manifests
290 bb.txt@1: in changeset but not in manifest (pure !)
291 checking files 277 checking files
292 checked 2 changesets with 9 changes to 9 files 278 checked 2 changesets with 9 changes to 9 files
293 2 integrity errors encountered! (pure !)
294 (first damaged changeset appears to be 1) (pure !)