Patchwork D6987: debugstrip: add debugstrip to core

login
register
mail settings
Submitter phabricator
Date Oct. 12, 2019, 10:01 p.m.
Message ID <d4c0684c02fb06ce076e09a4ccfe46e6@localhost.localdomain>
Download mbox | patch
Permalink /patch/42280/
State Not Applicable
Headers show

Comments

phabricator - Oct. 12, 2019, 10:01 p.m.
navaneeth.suresh retitled this revision from "strip: move strip extension to core as debugstrip" to "debugstrip: add debugstrip to core".
navaneeth.suresh updated this revision to Diff 17120.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D6987?vs=16914&id=17120

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

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

AFFECTED FILES
  mercurial/debugcommands.py
  tests/test-completion.t
  tests/test-debugstrip.t
  tests/test-help.t
  tests/test-strip.t

CHANGE DETAILS




To: navaneeth.suresh, durin42, #hg-reviewers
Cc: pulkit, marmoute, mjpieters, mercurial-devel

Patch

diff --git a/tests/test-help.t b/tests/test-help.t
--- a/tests/test-help.t
+++ b/tests/test-help.t
@@ -1051,6 +1051,7 @@ 
    debugsidedata
                  dump the side data for a cl/manifest/file revision
    debugssl      test a secure connection to a server
+   debugstrip    strip changesets and all their descendants from the repository
    debugsub      (no help text available)
    debugsuccessorssets
                  show set of successors for revision
diff --git a/tests/test-strip.t b/tests/test-debugstrip.t
copy from tests/test-strip.t
copy to tests/test-debugstrip.t
--- a/tests/test-strip.t
+++ b/tests/test-debugstrip.t
@@ -1,17 +1,16 @@ 
   $ echo "[extensions]" >> $HGRCPATH
-  $ echo "strip=" >> $HGRCPATH
   $ echo "drawdag=$TESTDIR/drawdag.py" >> $HGRCPATH
 
   $ restore() {
   >     hg unbundle -q .hg/strip-backup/*
   >     rm .hg/strip-backup/*
   > }
-  $ teststrip() {
+  $ testdebugstrip() {
   >     hg up -C $1
-  >     echo % before update $1, strip $2
+  >     echo % before update $1, debugstrip $2
   >     hg log -G -T '{rev}:{node}'
-  >     hg --traceback strip $2
-  >     echo % after update $1, strip $2
+  >     hg --traceback debugstrip $2
+  >     echo % after update $1, debugstrip $2
   >     hg log -G -T '{rev}:{node}'
   >     restore
   > }
@@ -67,9 +66,9 @@ 
   summary:     a
   
 
-  $ teststrip 4 4
+  $ testdebugstrip 4 4
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  % before update 4, strip 4
+  % before update 4, debugstrip 4
   @  4:443431ffac4f5b5a19b0b6c298a21b7ba736bcce
   |
   o  3:65bd5f99a4a376cdea23a1153f07856b0d881d64
@@ -82,7 +81,7 @@ 
   
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
-  % after update 4, strip 4
+  % after update 4, debugstrip 4
   @  3:65bd5f99a4a376cdea23a1153f07856b0d881d64
   |
   | o  2:264128213d290d868c54642d13aeaa3675551a78
@@ -91,9 +90,9 @@ 
   |
   o  0:9ab35a2d17cb64271241ea881efcc19dd953215b
   
-  $ teststrip 4 3
+  $ testdebugstrip 4 3
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  % before update 4, strip 3
+  % before update 4, debugstrip 3
   @  4:443431ffac4f5b5a19b0b6c298a21b7ba736bcce
   |
   o  3:65bd5f99a4a376cdea23a1153f07856b0d881d64
@@ -106,16 +105,16 @@ 
   
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
-  % after update 4, strip 3
+  % after update 4, debugstrip 3
   o  2:264128213d290d868c54642d13aeaa3675551a78
   |
   @  1:ef3a871183d7199c541cc140218298bbfcc6c28a
   |
   o  0:9ab35a2d17cb64271241ea881efcc19dd953215b
   
-  $ teststrip 1 4
+  $ testdebugstrip 1 4
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  % before update 1, strip 4
+  % before update 1, debugstrip 4
   o  4:443431ffac4f5b5a19b0b6c298a21b7ba736bcce
   |
   o  3:65bd5f99a4a376cdea23a1153f07856b0d881d64
@@ -127,7 +126,7 @@ 
   o  0:9ab35a2d17cb64271241ea881efcc19dd953215b
   
   saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
-  % after update 1, strip 4
+  % after update 1, debugstrip 4
   o  3:65bd5f99a4a376cdea23a1153f07856b0d881d64
   |
   | o  2:264128213d290d868c54642d13aeaa3675551a78
@@ -136,9 +135,9 @@ 
   |
   o  0:9ab35a2d17cb64271241ea881efcc19dd953215b
   
-  $ teststrip 4 2
+  $ testdebugstrip 4 2
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  % before update 4, strip 2
+  % before update 4, debugstrip 2
   @  4:443431ffac4f5b5a19b0b6c298a21b7ba736bcce
   |
   o  3:65bd5f99a4a376cdea23a1153f07856b0d881d64
@@ -150,7 +149,7 @@ 
   o  0:9ab35a2d17cb64271241ea881efcc19dd953215b
   
   saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
-  % after update 4, strip 2
+  % after update 4, debugstrip 2
   @  3:443431ffac4f5b5a19b0b6c298a21b7ba736bcce
   |
   o  2:65bd5f99a4a376cdea23a1153f07856b0d881d64
@@ -159,9 +158,9 @@ 
   |
   o  0:9ab35a2d17cb64271241ea881efcc19dd953215b
   
-  $ teststrip 4 1
+  $ testdebugstrip 4 1
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  % before update 4, strip 1
+  % before update 4, debugstrip 1
   @  4:264128213d290d868c54642d13aeaa3675551a78
   |
   | o  3:443431ffac4f5b5a19b0b6c298a21b7ba736bcce
@@ -174,12 +173,12 @@ 
   
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
-  % after update 4, strip 1
+  % after update 4, debugstrip 1
   @  0:9ab35a2d17cb64271241ea881efcc19dd953215b
   
-  $ teststrip null 4
+  $ testdebugstrip null 4
   0 files updated, 0 files merged, 1 files removed, 0 files unresolved
-  % before update null, strip 4
+  % before update null, debugstrip 4
   o  4:264128213d290d868c54642d13aeaa3675551a78
   |
   | o  3:443431ffac4f5b5a19b0b6c298a21b7ba736bcce
@@ -191,7 +190,7 @@ 
   o  0:9ab35a2d17cb64271241ea881efcc19dd953215b
   
   saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
-  % after update null, strip 4
+  % after update null, debugstrip 4
   o  3:443431ffac4f5b5a19b0b6c298a21b7ba736bcce
   |
   o  2:65bd5f99a4a376cdea23a1153f07856b0d881d64
@@ -240,7 +239,7 @@ 
   summary:     c
   
 
-  $ hg --traceback strip 4
+  $ hg --traceback debugstrip 4
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   saved backup bundle to $TESTTMP/test/.hg/strip-backup/264128213d29-0b39d6bf-backup.hg
   $ hg parents
@@ -298,7 +297,7 @@ 
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
   (branch merge, don't forget to commit)
 
-before strip of merge parent
+before debugstrip of merge parent
 
   $ hg parents
   changeset:   2:65bd5f99a4a3
@@ -313,17 +312,17 @@ 
   date:        Thu Jan 01 00:00:00 1970 +0000
   summary:     c
   
-##strip not allowed with merge in progress
-  $ hg strip 4
+##debugstrip not allowed with merge in progress
+  $ hg debugstrip 4
   abort: outstanding uncommitted merge
   (use 'hg commit' or 'hg merge --abort')
   [255]
-##strip allowed --force with merge in progress
-  $ hg strip 4 --force
+##debugstrip allowed --force with merge in progress
+  $ hg debugstrip 4 --force
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
 
-after strip of merge parent
+after debugstrip of merge parent
 
   $ hg parents
   changeset:   1:ef3a871183d7
@@ -366,9 +365,9 @@ 
      summary:     a
   
 
-2 is parent of 3, only one strip should happen
+2 is parent of 3, only one debugstrip should happen
 
-  $ hg strip "roots(2)" 3
+  $ hg debugstrip "roots(2)" 3
   saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
   $ hg log -G
   @  changeset:   2:264128213d29
@@ -418,13 +417,13 @@ 
   
 Failed hook while applying "saveheads" bundle.
 
-  $ hg strip 2 --config hooks.pretxnchangegroup.bad=false
+  $ hg debugstrip 2 --config hooks.pretxnchangegroup.bad=false
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
   transaction abort!
   rollback completed
-  strip failed, backup bundle stored in '$TESTTMP/test/.hg/strip-backup/*-backup.hg' (glob)
-  strip failed, unrecovered changes stored in '$TESTTMP/test/.hg/strip-backup/*-temp.hg' (glob)
+  strip failed, backup bundle stored in '$TESTTMP/test/.hg/strip-backup/264128213d29-0b39d6bf-backup.hg'
+  strip failed, unrecovered changes stored in '$TESTTMP/test/.hg/strip-backup/264128213d29-0eb9aae0-temp.hg'
   (fix the problem, then recover the changesets with "hg unbundle '$TESTTMP/test/.hg/strip-backup/*-temp.hg'") (glob)
   abort: pretxnchangegroup.bad hook exited with status 1
   [255]
@@ -458,9 +457,9 @@ 
      summary:     a
   
 
-2 different branches: 2 strips
+2 different branches: 2 debugstrips
 
-  $ hg strip 2 4
+  $ hg debugstrip 2 4
   saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
   $ hg log -G
   o  changeset:   2:65bd5f99a4a3
@@ -481,9 +480,9 @@ 
   
   $ restore
 
-2 different branches and a common ancestor: 1 strip
+2 different branches and a common ancestor: 1 debugstrip
 
-  $ hg strip 1 "2|4"
+  $ hg debugstrip 1 "2|4"
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
   $ restore
@@ -498,7 +497,7 @@ 
   data/bar.i
 #endif
 
-  $ hg strip tip
+  $ hg debugstrip tip
   0 files updated, 0 files merged, 1 files removed, 0 files unresolved
   saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
 #if repofncache
@@ -506,19 +505,19 @@ 
   data/bar.i
 #endif
 
-stripping an empty revset
+debugstripping an empty revset
 
-  $ hg strip "1 and not 1"
+  $ hg debugstrip "1 and not 1"
   abort: empty revision set
   [255]
 
 remove branchy history for qimport tests
 
-  $ hg strip 3
+  $ hg debugstrip 3
   saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
 
 
-strip of applied mq should cleanup status file
+debugstrip of applied mq should cleanup status file
 
   $ echo "mq=" >> $HGRCPATH
   $ hg up -C 3
@@ -527,35 +526,35 @@ 
   $ hg ci -mf
   $ hg qimport -r tip:2
 
-applied patches before strip
+applied patches before debugstrip
 
   $ hg qapplied
   d
   e
   f
 
-stripping revision in queue
+debugstripping revision in queue
 
-  $ hg strip 3
+  $ hg debugstrip 3
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
 
-applied patches after stripping rev in queue
+applied patches after debugstripping rev in queue
 
   $ hg qapplied
   d
 
-stripping ancestor of queue
+debugstripping ancestor of queue
 
-  $ hg strip 1
+  $ hg debugstrip 1
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
 
-applied patches after stripping ancestor of queue
+applied patches after debugstripping ancestor of queue
 
   $ hg qapplied
 
-Verify strip protects against stripping wc parent when there are uncommitted mods
+Verify debugstrip protects against debugstripping wc parent when there are uncommitted mods
 
   $ echo b > b
   $ echo bb > bar
@@ -592,10 +591,10 @@ 
   mq:     3 unapplied
 
   $ echo c > b
-  $ hg strip tip
+  $ hg debugstrip tip
   abort: uncommitted changes
   [255]
-  $ hg strip tip --keep
+  $ hg debugstrip tip --keep
   saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
   $ hg log --graph
   @  changeset:   0:9ab35a2d17cb
@@ -619,7 +618,7 @@ 
   phases: 1 draft
   mq:     3 unapplied
 
-Strip adds, removes, modifies with --keep
+debugstrip adds, removes, modifies with --keep
 
   $ touch b
   $ hg add b
@@ -632,7 +631,7 @@ 
   $ hg rm bar
   $ hg commit -mc
   $ hg status
-  $ hg strip --keep tip
+  $ hg debugstrip --keep tip
   saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
   $ hg status
   ! bar
@@ -646,7 +645,7 @@ 
   $ hg status
   $ echo b > b
   $ echo d > d
-  $ hg strip --keep tip
+  $ hg debugstrip --keep tip
   saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
   $ hg status
   M b
@@ -659,18 +658,18 @@ 
   $ hg commit -mc
   $ hg rm c
   $ hg commit -mc
-  $ hg strip --keep '.^' -q
+  $ hg debugstrip --keep '.^' -q
   $ cd ..
 
-stripping many nodes on a complex graph (issue3299)
+debugstripping many nodes on a complex graph (issue3299)
 
   $ hg init issue3299
   $ cd issue3299
   $ hg debugbuilddag '@a.:a@b.:b.:x<a@a.:a<b@b.:b<a@a.:a'
-  $ hg strip 'not ancestors(x)'
+  $ hg debugstrip 'not ancestors(x)'
   saved backup bundle to $TESTTMP/issue3299/.hg/strip-backup/*-backup.hg (glob)
 
-test hg strip -B bookmark
+test hg debugstrip -B bookmark
 
   $ cd ..
   $ hg init bookmarks
@@ -678,7 +677,7 @@ 
   $ hg debugbuilddag '..<2.*1/2:m<2+3:c<m+3:a<2.:b<m+2:d<2.:e<m+1:f'
   $ hg bookmark -r 'a' 'todelete'
   $ hg bookmark -r 'b' 'B'
-  $ hg bookmark -r 'b' 'nostrip'
+  $ hg bookmark -r 'b' 'nodebugstrip'
   $ hg bookmark -r 'c' 'delete'
   $ hg bookmark -r 'd' 'multipledelete1'
   $ hg bookmark -r 'e' 'multipledelete2'
@@ -687,11 +686,11 @@ 
   $ hg up -C todelete
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
   (activating bookmark todelete)
-  $ hg strip -B nostrip
-  bookmark 'nostrip' deleted
+  $ hg debugstrip -B nodebugstrip
+  bookmark 'nodebugstrip' deleted
   abort: empty revision set
   [255]
-  $ hg strip -B todelete
+  $ hg debugstrip -B todelete
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
   saved backup bundle to $TESTTMP/bookmarks/.hg/strip-backup/*-backup.hg (glob)
   bookmark 'todelete' deleted
@@ -707,7 +706,7 @@ 
      multipledelete2           12:b4594d867745
      singlenode1               13:43227190fef8
      singlenode2               13:43227190fef8
-  $ hg strip -B multipledelete1 -B multipledelete2
+  $ hg debugstrip -B multipledelete1 -B multipledelete2
   saved backup bundle to $TESTTMP/bookmarks/.hg/strip-backup/e46a4836065c-89ec65c2-backup.hg
   bookmark 'multipledelete1' deleted
   bookmark 'multipledelete2' deleted
@@ -717,23 +716,23 @@ 
   $ hg id -ir b4594d867745
   abort: unknown revision 'b4594d867745'!
   [255]
-  $ hg strip -B singlenode1 -B singlenode2
+  $ hg debugstrip -B singlenode1 -B singlenode2
   saved backup bundle to $TESTTMP/bookmarks/.hg/strip-backup/43227190fef8-8da858f2-backup.hg
   bookmark 'singlenode1' deleted
   bookmark 'singlenode2' deleted
   $ hg id -ir 43227190fef8
   abort: unknown revision '43227190fef8'!
   [255]
-  $ hg strip -B unknownbookmark
+  $ hg debugstrip -B unknownbookmark
   abort: bookmark 'unknownbookmark' not found
   [255]
-  $ hg strip -B unknownbookmark1 -B unknownbookmark2
+  $ hg debugstrip -B unknownbookmark1 -B unknownbookmark2
   abort: bookmark 'unknownbookmark1,unknownbookmark2' not found
   [255]
-  $ hg strip -B delete -B unknownbookmark
+  $ hg debugstrip -B delete -B unknownbookmark
   abort: bookmark 'unknownbookmark' not found
   [255]
-  $ hg strip -B delete
+  $ hg debugstrip -B delete
   saved backup bundle to $TESTTMP/bookmarks/.hg/strip-backup/*-backup.hg (glob)
   bookmark 'delete' deleted
   $ hg id -ir 6:2702dd0c91e7
@@ -744,7 +743,7 @@ 
   (activating bookmark B)
   $ echo a > a
   $ hg add a
-  $ hg strip -B B
+  $ hg debugstrip -B B
   abort: uncommitted changes
   [255]
   $ hg bookmarks
@@ -752,18 +751,16 @@ 
 
 Make sure no one adds back a -b option:
 
-  $ hg strip -b tip
-  hg strip: option -b not recognized
-  hg strip [-k] [-f] [-B bookmark] [-r] REV...
+  $ hg debugstrip -b tip
+  hg debugstrip: option -b not recognized
+  hg debugstrip [-k] [-f] [-B bookmark] [-r] REV...
   
   strip changesets and all their descendants from the repository
   
-  (use 'hg help -e strip' to show help for the strip extension)
-  
   options ([+] can be repeated):
   
    -r --rev REV [+]           strip specified revision (optional, can specify
-                              revisions without this option)
+                              revisions without this  option)
    -f --force                 force removal of changesets, discard uncommitted
                               changes (no backup)
       --no-backup             do not save backup bundle
@@ -771,7 +768,7 @@ 
    -B --bookmark BOOKMARK [+] remove revs only reachable from given bookmark
       --mq                    operate on patch repository
   
-  (use 'hg strip -h' to show more help)
+  (use 'hg debugstrip -h' to show more help)
   [255]
 
   $ cd ..
@@ -784,14 +781,14 @@ 
   $ hg commit -Aqm a
   $ touch b
   $ hg commit -Aqm b
-  $ hg strip -r 0
+  $ hg debugstrip -r 0
   0 files updated, 0 files merged, 2 files removed, 0 files unresolved
   saved backup bundle to $TESTTMP/doublebundle/.hg/strip-backup/3903775176ed-e68910bd-backup.hg
   $ ls .hg/strip-backup
   3903775176ed-e68910bd-backup.hg
 #if repobundlerepo
   $ hg pull -q -r 3903775176ed .hg/strip-backup/3903775176ed-e68910bd-backup.hg
-  $ hg strip -r 0
+  $ hg debugstrip -r 0
   saved backup bundle to $TESTTMP/doublebundle/.hg/strip-backup/3903775176ed-54390173-backup.hg
   $ ls .hg/strip-backup
   3903775176ed-54390173-backup.hg
@@ -799,7 +796,7 @@ 
 #endif
   $ cd ..
 
-Test that we only bundle the stripped changesets (issue4736)
+Test that we only bundle the debugstripped changesets (issue4736)
 ------------------------------------------------------------
 
 initialization (previous repo is empty anyway)
@@ -880,9 +877,9 @@ 
   
 #endif
 
-check strip behavior
+check debugdebugstrip behavior
 
-  $ hg --config extensions.strip= strip 'desc(commitD)' --debug
+  $ hg debugstrip 'desc(commitD)' --debug
   resolving manifests
    branchmerge: False, force: True, partial: False
    ancestor: d8db9d137221+, local: d8db9d137221+, remote: eca11cf91c71
@@ -921,7 +918,7 @@ 
      summary:     commitA
   
 
-strip backup content
+debugstrip backup content
 
 #if repobundlerepo
   $ hg log -r 'bundle()' -R .hg/strip-backup/6625a5168474-*-backup.hg
@@ -942,9 +939,9 @@ 
 
 #endif
 
-Check that the phase cache is properly invalidated after a strip with bookmark.
+Check that the phase cache is properly invalidated after a debugstrip with bookmark.
 
-  $ cat > ../stripstalephasecache.py << EOF
+  $ cat > ../debugstripstalephasecache.py << EOF
   > from mercurial import extensions, localrepo
   > def transactioncallback(orig, repo, desc, *args, **kwargs):
   >     def test(transaction):
@@ -956,7 +953,7 @@ 
   >     transaction = orig(repo, desc, *args, **kwargs)
   >     # warm up the phase cache
   >     list(repo.revs(b"not public()"))
-  >     if desc != b'strip':
+  >     if desc != b'debugstrip':
   >          transaction.addpostclose(b"phase invalidation test", test)
   >     return transaction
   > def extsetup(ui):
@@ -972,37 +969,35 @@ 
   $ hg add l
   $ hg commit -m commitL
   $ hg book -r tip blah
-  $ hg strip ".^" --config extensions.crash=$TESTTMP/stripstalephasecache.py
+  $ hg debugstrip ".^" --config extensions.crash=$TESTTMP/debugstripstalephasecache.py
   0 files updated, 0 files merged, 2 files removed, 0 files unresolved
   saved backup bundle to $TESTTMP/issue4736/.hg/strip-backup/8f0b4384875c-4fa10deb-backup.hg
   $ hg up -C 1
   0 files updated, 0 files merged, 1 files removed, 0 files unresolved
 
-Error during post-close callback of the strip transaction
+Error during post-close callback of the debugstrip transaction
 (They should be gracefully handled and reported)
 
-  $ cat > ../crashstrip.py << EOF
+  $ cat > ../crashdebugstrip.py << EOF
   > from mercurial import error
   > def reposetup(ui, repo):
-  >     class crashstriprepo(repo.__class__):
+  >     class crashdebugstriprepo(repo.__class__):
   >         def transaction(self, desc, *args, **kwargs):
-  >             tr = super(crashstriprepo, self).transaction(desc, *args, **kwargs)
-  >             if desc == b'strip':
+  >             tr = super(crashdebugstriprepo, self).transaction(desc, *args, **kwargs)
+  >             if desc == b'debugstrip':
   >                 def crash(tra): raise error.Abort(b'boom')
   >                 tr.addpostclose(b'crash', crash)
   >             return tr
-  >     repo.__class__ = crashstriprepo
+  >     repo.__class__ = crashdebugstriprepo
   > EOF
-  $ hg strip tip --config extensions.crash=$TESTTMP/crashstrip.py
+  $ hg debugstrip tip --config extensions.crash=$TESTTMP/crashdebugstrip.py
   saved backup bundle to $TESTTMP/issue4736/.hg/strip-backup/5c51d8d6557d-70daef06-backup.hg
-  strip failed, backup bundle stored in '$TESTTMP/issue4736/.hg/strip-backup/5c51d8d6557d-70daef06-backup.hg'
-  abort: boom
-  [255]
 
-test stripping a working directory parent doesn't switch named branches
+test debugstripping a working directory parent doesn't switch named branches
 
   $ hg log -G
   @  changeset:   1:eca11cf91c71
+  |  bookmark:    blah
   |  tag:         tip
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
@@ -1050,6 +1045,7 @@ 
   |    summary:     start new branch
   |
   o  changeset:   1:eca11cf91c71
+  |  bookmark:    blah
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
   |  summary:     commitB
@@ -1060,7 +1056,7 @@ 
      summary:     commitA
   
 
-  $ hg strip --force -r 35358f982181
+  $ hg debugstrip --force -r 35358f982181
   0 files updated, 0 files merged, 1 files removed, 0 files unresolved
   saved backup bundle to $TESTTMP/issue4736/.hg/strip-backup/35358f982181-50d992d4-backup.hg
   $ hg log -G
@@ -1078,6 +1074,7 @@ 
   |  summary:     start new branch
   |
   o  changeset:   1:eca11cf91c71
+  |  bookmark:    blah
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
   |  summary:     commitB
@@ -1127,6 +1124,7 @@ 
   |    summary:     start new branch
   |
   o  changeset:   1:eca11cf91c71
+  |  bookmark:    blah
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
   |  summary:     commitB
@@ -1137,7 +1135,7 @@ 
      summary:     commitA
   
 
-  $ hg strip -r 35358f982181
+  $ hg debugstrip -r 35358f982181
   0 files updated, 0 files merged, 1 files removed, 0 files unresolved
   saved backup bundle to $TESTTMP/issue4736/.hg/strip-backup/35358f982181-a6f020aa-backup.hg
   $ hg log -G
@@ -1155,6 +1153,7 @@ 
   |  summary:     start new branch
   |
   o  changeset:   1:eca11cf91c71
+  |  bookmark:    blah
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
   |  summary:     commitB
@@ -1173,7 +1172,7 @@ 
   new changesets 35358f982181:4cf5e92caec2 (2 drafts)
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
 
-  $ hg strip -k -r 35358f982181
+  $ hg debugstrip -k -r 35358f982181
   saved backup bundle to $TESTTMP/issue4736/.hg/strip-backup/35358f982181-a6f020aa-backup.hg
   $ hg log -G
   @  changeset:   3:f62c6c09b707
@@ -1190,6 +1189,7 @@ 
   |  summary:     start new branch
   |
   o  changeset:   1:eca11cf91c71
+  |  bookmark:    blah
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
   |  summary:     commitB
@@ -1206,7 +1206,7 @@ 
   @@ -0,0 +1,1 @@
   +bar
 
-Use delayedstrip to strip inside a transaction
+Use delayedstrip to debugstrip inside a transaction
 
   $ cd $TESTTMP
   $ hg init delayedstrip
@@ -1215,7 +1215,7 @@ 
   >   D
   >   |
   >   C F H    # Commit on top of "I",
-  >   | |/|    # Strip B+D+I+E+G+H+Z
+  >   | |/|    # debugstrip B+D+I+E+G+H+Z
   > I B E G
   >  \|/
   >   A   Z
@@ -1330,7 +1330,7 @@ 
      b-I                       0:426bada5c675
      b-Z                       -1:000000000000
 
-Test the above using obsstore "by the way". Not directly related to strip, but
+Test the above using obsstore "by the way". Not directly related to debugstrip, but
 we have reusable code here
 
   $ cd $TESTTMP/scmutilcleanup.obsstore
@@ -1386,7 +1386,7 @@ 
   $ hg ci --amend -m a2
   $ hg debugobsolete
   cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b 489bac576828490c0bb8d45eac9e5e172e4ec0a8 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '1', 'operation': 'amend', 'user': 'test'}
-  $ hg strip .
+  $ hg debugstrip .
   0 files updated, 0 files merged, 1 files removed, 0 files unresolved
   saved backup bundle to $TESTTMP/issue5678/.hg/strip-backup/489bac576828-bef27e14-backup.hg
   $ hg unbundle -q .hg/strip-backup/*
diff --git a/tests/test-completion.t b/tests/test-completion.t
--- a/tests/test-completion.t
+++ b/tests/test-completion.t
@@ -126,6 +126,7 @@ 
   debugsetparents
   debugsidedata
   debugssl
+  debugstrip
   debugsub
   debugsuccessorssets
   debugtemplate
@@ -308,6 +309,7 @@ 
   debugsetparents: 
   debugsidedata: changelog, manifest, dir
   debugssl: 
+  debugstrip: rev, force, no-backup, nobackup, , keep, bookmark, soft
   debugsub: rev
   debugsuccessorssets: closest
   debugtemplate: rev, define
diff --git a/mercurial/debugcommands.py b/mercurial/debugcommands.py
--- a/mercurial/debugcommands.py
+++ b/mercurial/debugcommands.py
@@ -92,6 +92,8 @@ 
     deltas as deltautil
 )
 
+from hgext import strip
+
 release = lockmod.release
 
 command = registrar.command()
@@ -2726,6 +2728,149 @@ 
     finally:
         s.close()
 
+@command('debugstrip', [
+    ('r', 'rev', [], _('strip specified revision (optional, '
+                       'can specify revisions without this  option)'),
+                       _('REV')),
+    ('f', 'force', None, _('force removal of changesets, discard '
+                           'uncommitted changes (no backup)')),
+    ('', 'no-backup', None, _('do not save backup bundle')),
+    ('', 'nobackup', None, _('do not save backup bundle (DEPRECATED)')),
+    ('n', '', None, _('ignored  (DEPRECATED)')),
+    ('k', 'keep', None, _('do not modify working directory during strip')),
+    ('B', 'bookmark', [], _('remove revs only reachable from given bookmark'), _('BOOKMARK')),
+    ('', 'soft', None,
+          _('simply drop changesets from visible history (EXPERIMENTAL)')),
+    ],
+    _('hg debugstrip [-k] [-f] [-B bookmark] [-r] REV...'),
+    helpcategory=command.CATEGORY_MAINTENANCE)
+def debugstrip(ui, repo, *revs, **opts):
+    """strip changesets and all their descendants from the repository
+
+    The strip command removes the specified changesets and all their
+    descendants. If the working directory has uncommitted changes, the
+    operation is aborted unless the --force flag is supplied, in which
+    case changes will be discarded.
+
+    If a parent of the working directory is stripped, then the working
+    directory will automatically be updated to the most recent
+    available ancestor of the stripped parent after the operation
+    completes.
+
+    Any stripped changesets are stored in ``.hg/strip-backup`` as a
+    bundle (see :hg:`help bundle` and :hg:`help unbundle`). They can
+    be restored by running :hg:`unbundle .hg/strip-backup/BUNDLE`,
+    where BUNDLE is the bundle file created by the strip. Note that
+    the local revision numbers will in general be different after the
+    restore.
+
+    Use the --no-backup option to discard the backup bundle once the
+    operation completes.
+
+    Strip is not a history-rewriting operation and can be used on
+    changesets in the public phase. But if the stripped changesets have
+    been pushed to a remote repository you will likely pull them again.
+
+    Return 0 on success.
+    """
+    opts = pycompat.byteskwargs(opts)
+    backup = True
+    if opts.get('no_backup') or opts.get('nobackup'):
+        backup = False
+
+    cl = repo.changelog
+    revs = list(revs) + opts.get('rev')
+    revs = set(scmutil.revrange(repo, revs))
+
+    with repo.wlock():
+        bookmarks = set(opts.get('bookmark'))
+        if bookmarks:
+            repomarks = repo._bookmarks
+            if not bookmarks.issubset(repomarks):
+                raise error.Abort(_("bookmark '%s' not found") %
+                    ','.join(sorted(bookmarks - set(repomarks.keys()))))
+
+            # If the requested bookmark is not the only one pointing to a
+            # a revision we have to only delete the bookmark and not strip
+            # anything. revsets cannot detect that case.
+            nodetobookmarks = {}
+            for mark, node in repomarks.iteritems():
+                nodetobookmarks.setdefault(node, []).append(mark)
+            for marks in nodetobookmarks.values():
+                if bookmarks.issuperset(marks):
+                    rsrevs = scmutil.bookmarkrevs(repo, marks[0])
+                    revs.update(set(rsrevs))
+            if not revs:
+                with repo.lock(), repo.transaction('bookmark') as tr:
+                    bmchanges = [(b, None) for b in bookmarks]
+                    repomarks.applychanges(repo, tr, bmchanges)
+                for bookmark in sorted(bookmarks):
+                    ui.write(_("bookmark '%s' deleted\n") % bookmark)
+
+        if not revs:
+            raise error.Abort(_('empty revision set'))
+
+        descendants = set(cl.descendants(revs))
+        strippedrevs = revs.union(descendants)
+        roots = revs.difference(descendants)
+
+        # if one of the wdir parent is stripped we'll need
+        # to update away to an earlier revision
+        update = any(p != nullid and cl.rev(p) in strippedrevs
+                     for p in repo.dirstate.parents())
+
+        rootnodes = set(cl.node(r) for r in roots)
+
+        q = getattr(repo, 'mq', None)
+        if q is not None and q.applied:
+            # refresh queue state if we're about to strip
+            # applied patches
+            if cl.rev(repo.lookup('qtip')) in strippedrevs:
+                q.applieddirty = True
+                start = 0
+                end = len(q.applied)
+                for i, statusentry in enumerate(q.applied):
+                    if statusentry.node in rootnodes:
+                        # if one of the stripped roots is an applied
+                        # patch, only part of the queue is stripped
+                        start = i
+                        break
+                del q.applied[start:end]
+                q.savedirty()
+
+        revs = sorted(rootnodes)
+        if update and opts.get('keep'):
+            urev = strip._findupdatetarget(repo, revs)
+            uctx = repo[urev]
+
+            # only reset the dirstate for files that would actually change
+            # between the working context and uctx
+            descendantrevs = repo.revs(b"%d::.", uctx.rev())
+            changedfiles = []
+            for rev in descendantrevs:
+                # blindly reset the files, regardless of what actually changed
+                changedfiles.extend(repo[rev].files())
+
+            # reset files that only changed in the dirstate too
+            dirstate = repo.dirstate
+            dirchanges = [f for f in dirstate if dirstate[f] != 'n']
+            changedfiles.extend(dirchanges)
+
+            repo.dirstate.rebuild(urev, uctx.manifest(), changedfiles)
+            repo.dirstate.write(repo.currenttransaction())
+
+            # clear resolve state
+            mergemod.mergestate.clean(repo, repo['.'].node())
+
+            update = False
+
+
+        strip.strip(ui, repo, revs, backup=backup, update=update,
+                    force=opts.get('force'), bookmarks=bookmarks,
+                    soft=opts['soft'])
+
+    return 0
+
 @command('debugsub',
     [('r', 'rev', '',
      _('revision to check'), _('REV'))],