D7932: debugstripbackups: introduce command to interact with strip backups

2020-02-12 Thread durin42 (Augie Fackler)
This revision now requires changes to proceed.
durin42 added a comment.
durin42 requested changes to this revision.


  I think I'd prefer debugbackupbundle per marmoute's suggestion.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST ACTION
  https://phab.mercurial-scm.org/D7932/new/

REVISION DETAIL
  https://phab.mercurial-scm.org/D7932

To: pulkit, #hg-reviewers, durin42
Cc: marmoute, durin42, mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D7932: debugstripbackups: introduce command to interact with strip backups

2020-02-04 Thread pulkit (Pulkit Goyal)
pulkit edited the summary of this revision.
pulkit retitled this revision from "[RFC]debugbackups: introduce command to 
interact with strip backups" to "debugstripbackups: introduce command to 
interact with strip backups".
pulkit updated this revision to Diff 19868.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D7932?vs=19436=19868

CHANGES SINCE LAST ACTION
  https://phab.mercurial-scm.org/D7932/new/

REVISION DETAIL
  https://phab.mercurial-scm.org/D7932

AFFECTED FILES
  mercurial/debugcommands.py
  tests/test-debugstripbackup.t

CHANGE DETAILS

diff --git a/tests/test-debugstripbackup.t b/tests/test-debugstripbackup.t
new file mode 100644
--- /dev/null
+++ b/tests/test-debugstripbackup.t
@@ -0,0 +1,39 @@
+  $ cat >> $HGRCPATH << EOF
+  > [extensions]
+  > strip=
+  > EOF
+
+Setup repo
+
+  $ hg init repo
+  $ cd repo
+
+Test backups list and recover
+
+  $ hg debugstripbackups
+  no backup changesets found
+
+  $ mkcommit() {
+  >echo "$1" > "$1"
+  >hg add "$1"
+  >hg ci -l $1
+  > }
+  $ mkcommit a
+  $ mkcommit b
+  $ hg strip .
+  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  saved backup bundle to 
$TESTTMP/repo/.hg/strip-backup/d2ae7f538514-2953539b-backup.hg (glob)
+  $ hg debugstripbackups
+  Recover changesets using: hg debugstripbackups --recover 
+  
+  Available backup changesets:
+  * (glob)
+  d2ae7f538514 b
+
+  $ hg debugstripbackups --recover d2ae7f538514
+  Unbundling d2ae7f538514
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 1 files
+  new changesets d2ae7f538514 (1 drafts)
diff --git a/mercurial/debugcommands.py b/mercurial/debugcommands.py
--- a/mercurial/debugcommands.py
+++ b/mercurial/debugcommands.py
@@ -11,6 +11,7 @@
 import collections
 import difflib
 import errno
+import glob
 import operator
 import os
 import platform
@@ -39,6 +40,7 @@
 )
 from . import (
 bundle2,
+bundlerepo,
 changegroup,
 cmdutil,
 color,
@@ -130,6 +132,7 @@
 gen.apply(repo)
 
 
+
 @command(
 b'debugbuilddag',
 [
@@ -3361,6 +3364,131 @@
 
 
 @command(
+"debugstripbackups",
+[
+(
+"",
+"recover",
+"",
+"brings the specified changeset back into the repository",
+)
+]
++ cmdutil.logopts,
+_("hg debugstripbackups [--recover HASH]"),
+)
+def debugstripbackups(ui, repo, *pats, **opts):
+"""lists the changesets available in backup bundles
+
+Without any arguments, this command prints a list of the changesets in each
+backup bundle.
+
+--recover takes a changeset hash and unbundles the first bundle that
+contains that hash, which puts that changeset back in your repository.
+
+--verbose will print the entire commit message and the bundle path for that
+backup.
+"""
+backups = filter(os.path.isfile, glob.glob(repo.vfs.join("strip-backup") + 
"/*.hg"))
+backups.sort(key=lambda x: os.path.getmtime(x), reverse=True)
+
+opts["bundle"] = ""
+opts["force"] = None
+limit = logcmdutil.getlimit(opts)
+
+def display(other, chlist, displayer):
+if opts.get("newest_first"):
+chlist.reverse()
+count = 0
+for n in chlist:
+if limit is not None and count >= limit:
+break
+parents = [True for p in other.changelog.parents(n) if p != nullid]
+if opts.get("no_merges") and len(parents) == 2:
+continue
+count += 1
+displayer.show(other[n])
+
+recovernode = opts.get("recover")
+if recovernode:
+if scmutil.isrevsymbol(repo, recovernode):
+ui.warn(_("%s already exists in the repo\n") % recovernode)
+return
+elif backups:
+msg = _(
+"Recover changesets using: hg debugstripbackups --recover "
+"\n\nAvailable backup changesets:"
+)
+ui.status(msg, label="status.removed")
+else:
+ui.status(_("no backup changesets found\n"))
+return
+
+for backup in backups:
+# Much of this is copied from the hg incoming logic
+source = ui.expandpath(os.path.relpath(backup, encoding.getcwd()))
+source, branches = hg.parseurl(source, opts.get("branch"))
+try:
+other = hg.peer(repo, opts, source)
+except error.LookupError as ex:
+msg = _("\nwarning: unable to open bundle %s") % source
+hint = _("\n(missing parent rev %s)\n") % short(ex.name)
+ui.warn(msg, hint=hint)
+continue
+revs, checkout = hg.addbranchrevs(
+repo, other, branches, opts.get("rev")
+)
+
+if revs:
+revs = [other.lookup(rev) for rev in revs]
+
+quiet = ui.quiet
+try:
+ui.quiet = True
+other, chlist, cleanupfn = bundlerepo.getremotechanges(
+ui,