3400 finally: |
3402 finally: |
3401 s.close() |
3403 s.close() |
3402 |
3404 |
3403 |
3405 |
3404 @command( |
3406 @command( |
|
3407 b"debugbackupbundle", |
|
3408 [ |
|
3409 ( |
|
3410 b"", |
|
3411 b"recover", |
|
3412 b"", |
|
3413 b"brings the specified changeset back into the repository", |
|
3414 ) |
|
3415 ] |
|
3416 + cmdutil.logopts, |
|
3417 _(b"hg debugbackupbundle [--recover HASH]"), |
|
3418 ) |
|
3419 def debugbackupbundle(ui, repo, *pats, **opts): |
|
3420 """lists the changesets available in backup bundles |
|
3421 |
|
3422 Without any arguments, this command prints a list of the changesets in each |
|
3423 backup bundle. |
|
3424 |
|
3425 --recover takes a changeset hash and unbundles the first bundle that |
|
3426 contains that hash, which puts that changeset back in your repository. |
|
3427 |
|
3428 --verbose will print the entire commit message and the bundle path for that |
|
3429 backup. |
|
3430 """ |
|
3431 backups = list( |
|
3432 filter( |
|
3433 os.path.isfile, glob.glob(repo.vfs.join(b"strip-backup") + b"/*.hg") |
|
3434 ) |
|
3435 ) |
|
3436 backups.sort(key=lambda x: os.path.getmtime(x), reverse=True) |
|
3437 |
|
3438 opts = pycompat.byteskwargs(opts) |
|
3439 opts[b"bundle"] = b"" |
|
3440 opts[b"force"] = None |
|
3441 limit = logcmdutil.getlimit(opts) |
|
3442 |
|
3443 def display(other, chlist, displayer): |
|
3444 if opts.get(b"newest_first"): |
|
3445 chlist.reverse() |
|
3446 count = 0 |
|
3447 for n in chlist: |
|
3448 if limit is not None and count >= limit: |
|
3449 break |
|
3450 parents = [True for p in other.changelog.parents(n) if p != nullid] |
|
3451 if opts.get(b"no_merges") and len(parents) == 2: |
|
3452 continue |
|
3453 count += 1 |
|
3454 displayer.show(other[n]) |
|
3455 |
|
3456 recovernode = opts.get(b"recover") |
|
3457 if recovernode: |
|
3458 if scmutil.isrevsymbol(repo, recovernode): |
|
3459 ui.warn(_(b"%s already exists in the repo\n") % recovernode) |
|
3460 return |
|
3461 elif backups: |
|
3462 msg = _( |
|
3463 b"Recover changesets using: hg debugbackupbundle --recover " |
|
3464 b"<changeset hash>\n\nAvailable backup changesets:" |
|
3465 ) |
|
3466 ui.status(msg, label=b"status.removed") |
|
3467 else: |
|
3468 ui.status(_(b"no backup changesets found\n")) |
|
3469 return |
|
3470 |
|
3471 for backup in backups: |
|
3472 # Much of this is copied from the hg incoming logic |
|
3473 source = ui.expandpath(os.path.relpath(backup, encoding.getcwd())) |
|
3474 source, branches = hg.parseurl(source, opts.get(b"branch")) |
|
3475 try: |
|
3476 other = hg.peer(repo, opts, source) |
|
3477 except error.LookupError as ex: |
|
3478 msg = _(b"\nwarning: unable to open bundle %s") % source |
|
3479 hint = _(b"\n(missing parent rev %s)\n") % short(ex.name) |
|
3480 ui.warn(msg, hint=hint) |
|
3481 continue |
|
3482 revs, checkout = hg.addbranchrevs( |
|
3483 repo, other, branches, opts.get(b"rev") |
|
3484 ) |
|
3485 |
|
3486 if revs: |
|
3487 revs = [other.lookup(rev) for rev in revs] |
|
3488 |
|
3489 quiet = ui.quiet |
|
3490 try: |
|
3491 ui.quiet = True |
|
3492 other, chlist, cleanupfn = bundlerepo.getremotechanges( |
|
3493 ui, repo, other, revs, opts[b"bundle"], opts[b"force"] |
|
3494 ) |
|
3495 except error.LookupError: |
|
3496 continue |
|
3497 finally: |
|
3498 ui.quiet = quiet |
|
3499 |
|
3500 try: |
|
3501 if not chlist: |
|
3502 continue |
|
3503 if recovernode: |
|
3504 with repo.lock(), repo.transaction(b"unbundle") as tr: |
|
3505 if scmutil.isrevsymbol(other, recovernode): |
|
3506 ui.status(_(b"Unbundling %s\n") % (recovernode)) |
|
3507 f = hg.openpath(ui, source) |
|
3508 gen = exchange.readbundle(ui, f, source) |
|
3509 if isinstance(gen, bundle2.unbundle20): |
|
3510 bundle2.applybundle( |
|
3511 repo, |
|
3512 gen, |
|
3513 tr, |
|
3514 source=b"unbundle", |
|
3515 url=b"bundle:" + source, |
|
3516 ) |
|
3517 else: |
|
3518 gen.apply(repo, b"unbundle", b"bundle:" + source) |
|
3519 break |
|
3520 else: |
|
3521 backupdate = encoding.strtolocal( |
|
3522 time.strftime( |
|
3523 "%a %H:%M, %Y-%m-%d", |
|
3524 time.localtime(os.path.getmtime(source)), |
|
3525 ) |
|
3526 ) |
|
3527 ui.status(b"\n%s\n" % (backupdate.ljust(50))) |
|
3528 if ui.verbose: |
|
3529 ui.status(b"%s%s\n" % (b"bundle:".ljust(13), source)) |
|
3530 else: |
|
3531 opts[ |
|
3532 b"template" |
|
3533 ] = b"{label('status.modified', node|short)} {desc|firstline}\n" |
|
3534 displayer = logcmdutil.changesetdisplayer( |
|
3535 ui, other, opts, False |
|
3536 ) |
|
3537 display(other, chlist, displayer) |
|
3538 displayer.close() |
|
3539 finally: |
|
3540 cleanupfn() |
|
3541 |
|
3542 |
|
3543 @command( |
3405 b'debugsub', |
3544 b'debugsub', |
3406 [(b'r', b'rev', b'', _(b'revision to check'), _(b'REV'))], |
3545 [(b'r', b'rev', b'', _(b'revision to check'), _(b'REV'))], |
3407 _(b'[-r REV] [REV]'), |
3546 _(b'[-r REV] [REV]'), |
3408 ) |
3547 ) |
3409 def debugsub(ui, repo, rev=None): |
3548 def debugsub(ui, repo, rev=None): |