comparison hg @ 87:b2b3fdbd79f4

Verify improvements: Check existence of parents of changesets and manifests Count errors Use ui for display Catch and count unpack exceptions Print error count and exit with non-zero status on error
author mpm@selenic.com
date Tue, 17 May 2005 12:23:53 -0800
parents 9fd5b35cfc45
children d9913355961d
comparison
equal deleted inserted replaced
86:1b945e8ba67b 87:b2b3fdbd79f4
371 elif cmd == "verify": 371 elif cmd == "verify":
372 filelinkrevs = {} 372 filelinkrevs = {}
373 filenodes = {} 373 filenodes = {}
374 manifestchangeset = {} 374 manifestchangeset = {}
375 changesets = revisions = files = 0 375 changesets = revisions = files = 0
376 376 errors = 0
377 print "checking changesets" 377
378 ui.status("checking changesets\n")
378 for i in range(repo.changelog.count()): 379 for i in range(repo.changelog.count()):
379 changesets += 1 380 changesets += 1
380 n = repo.changelog.node(i) 381 n = repo.changelog.node(i)
381 changes = repo.changelog.read(n) 382 for p in repo.changelog.parents(n):
383 if p not in repo.changelog.nodemap:
384 ui.warn("changeset %s has unknown parent %s\n" %
385 (hg.short(n), hg.short(p)))
386 errors += 1
387 try:
388 changes = repo.changelog.read(n)
389 except Error, inst:
390 ui.warn("unpacking changeset %s: %s\n" % (short(n), inst))
391 errors += 1
392
382 manifestchangeset[changes[0]] = n 393 manifestchangeset[changes[0]] = n
383 for f in changes[3]: 394 for f in changes[3]:
384 revisions += 1 395 revisions += 1
385 filelinkrevs.setdefault(f, []).append(i) 396 filelinkrevs.setdefault(f, []).append(i)
386 397
387 print "checking manifests" 398 ui.status("checking manifests\n")
388 for i in range(repo.manifest.count()): 399 for i in range(repo.manifest.count()):
389 n = repo.manifest.node(i) 400 n = repo.manifest.node(i)
401 for p in repo.manifest.parents(n):
402 if p not in repo.manifest.nodemap:
403 ui.warn("manifest %s has unknown parent %s\n" %
404 (hg.short(n), hg.short(p)))
405 errors += 1
390 ca = repo.changelog.node(repo.manifest.linkrev(n)) 406 ca = repo.changelog.node(repo.manifest.linkrev(n))
391 cc = manifestchangeset[n] 407 cc = manifestchangeset[n]
392 if ca != cc: 408 if ca != cc:
393 print "manifest %s points to %s, not %s" % \ 409 ui.warn("manifest %s points to %s, not %s\n" %
394 (hg.hex(n), hg.hex(ca), hg.hex(cc)) 410 (hg.hex(n), hg.hex(ca), hg.hex(cc)))
395 m = repo.manifest.read(n) 411 errors += 1
412
413 try:
414 m = repo.manifest.read(n)
415 except Error, inst:
416 ui.warn("unpacking manifest %s: %s\n" % (hg.short(n), inst))
417 errors += 1
418
396 for f, fn in m.items(): 419 for f, fn in m.items():
397 filenodes.setdefault(f, {})[fn] = 1 420 filenodes.setdefault(f, {})[fn] = 1
398 421
399 print "crosschecking files in changesets and manifests" 422 ui.status("crosschecking files in changesets and manifests\n")
400 for f in filenodes: 423 for f in filenodes:
401 if f not in filelinkrevs: 424 if f not in filelinkrevs:
402 print "file %s in manifest but not in changesets" 425 ui.warn("file %s in manifest but not in changesets\n" % f)
426 errors += 1
403 427
404 for f in filelinkrevs: 428 for f in filelinkrevs:
405 if f not in filenodes: 429 if f not in filenodes:
406 print "file %s in changeset but not in manifest" 430 ui.warn("file %s in changeset but not in manifest" % f)
407 431 errors += 1
408 print "checking files" 432
433 ui.status("checking files\n")
409 for f in filenodes: 434 for f in filenodes:
410 files += 1 435 files += 1
411 fl = repo.file(f) 436 fl = repo.file(f)
412 nodes = {"\0"*20: 1} 437 nodes = { hg.nullid: 1 }
413 for i in range(fl.count()): 438 for i in range(fl.count()):
414 n = fl.node(i) 439 n = fl.node(i)
415 440
416 if n not in filenodes[f]: 441 if n not in filenodes[f]:
417 print "%s:%s not in manifests" % (f, hg.hex(n)) 442 ui.warn("%s:%s not in manifests\n" % (f, hg.short(n)))
443 errors += 1
418 else: 444 else:
419 del filenodes[f][n] 445 del filenodes[f][n]
420 446
421 flr = fl.linkrev(n) 447 flr = fl.linkrev(n)
422 if flr not in filelinkrevs[f]: 448 if flr not in filelinkrevs[f]:
423 print "%s:%s points to unexpected changeset rev %d" \ 449 ui.warn("%s:%s points to unexpected changeset rev %d\n"
424 % (f, hg.hex(n), fl.linkrev(n)) 450 % (f, hg.short(n), fl.linkrev(n)))
451 errors += 1
425 else: 452 else:
426 filelinkrevs[f].remove(flr) 453 filelinkrevs[f].remove(flr)
427 454
428 # verify contents 455 # verify contents
429 t = fl.read(n) 456 try:
430 457 t = fl.read(n)
458 except Error, inst:
459 ui.warn("unpacking file %s %s: %s\n" % (f, short(n), inst))
460 errors += 1
461
431 # verify parents 462 # verify parents
432 (p1, p2) = fl.parents(n) 463 (p1, p2) = fl.parents(n)
433 if p1 not in nodes: 464 if p1 not in nodes:
434 print "%s:%s unknown parent 1 %s" % (f, hg.hex(n), hg.hex(p1)) 465 ui.warn("file %s:%s unknown parent 1 %s" %
466 (f, hg.short(n), hg.short(p1)))
467 errors += 1
435 if p2 not in nodes: 468 if p2 not in nodes:
436 print "file %s:%s unknown parent %s" % (f, hg.hex(n), hg.hex(p1)) 469 ui.warn("file %s:%s unknown parent 2 %s" %
470 (f, hg.short(n), hg.short(p1)))
471 errors += 1
437 nodes[n] = 1 472 nodes[n] = 1
438 473
439 # cross-check 474 # cross-check
440 for flr in filelinkrevs[f]: 475 for flr in filelinkrevs[f]:
441 print "changeset rev %d not in %s" % (flr, f) 476 ui.warn("changeset rev %d not in %s\n" % (flr, f))
477 errors += 1
442 478
443 for node in filenodes[f]: 479 for node in filenodes[f]:
444 print "node %s in manifests not in %s" % (hg.hex(n), f) 480 ui.warn("node %s in manifests not in %s\n" % (hg.hex(n), f))
445 481 errors += 1
446 482
447 print "%d files, %d changesets, %d total revisions" % (files, changesets, 483 ui.status("%d files, %d changesets, %d total revisions\n" %
448 revisions) 484 (files, changesets, revisions))
485
486 if errors:
487 ui.warn("%d integrity errors encountered!\n")
488 sys.exit(1)
449 489
450 else: 490 else:
451 print "unknown command\n" 491 print "unknown command\n"
452 help() 492 help()
453 sys.exit(1) 493 sys.exit(1)