Show More
@@ -590,12 +590,12 def reposetup(ui, repo): | |||||
590 | kwt.restrict = restrict |
|
590 | kwt.restrict = restrict | |
591 | return n |
|
591 | return n | |
592 |
|
592 | |||
593 | def rollback(self, dryrun=False): |
|
593 | def rollback(self, dryrun=False, force=False): | |
594 | wlock = self.wlock() |
|
594 | wlock = self.wlock() | |
595 | try: |
|
595 | try: | |
596 | if not dryrun: |
|
596 | if not dryrun: | |
597 | changed = self['.'].files() |
|
597 | changed = self['.'].files() | |
598 | ret = super(kwrepo, self).rollback(dryrun) |
|
598 | ret = super(kwrepo, self).rollback(dryrun, force) | |
599 | if not dryrun: |
|
599 | if not dryrun: | |
600 | ctx = self['.'] |
|
600 | ctx = self['.'] | |
601 | modified, added = _preselect(self[None].status(), changed) |
|
601 | modified, added = _preselect(self[None].status(), changed) |
@@ -4612,7 +4612,8 def revert(ui, repo, *pats, **opts): | |||||
4612 | finally: |
|
4612 | finally: | |
4613 | wlock.release() |
|
4613 | wlock.release() | |
4614 |
|
4614 | |||
4615 |
@command('rollback', dryrunopts |
|
4615 | @command('rollback', dryrunopts + | |
|
4616 | [('f', 'force', False, _('ignore safety measures'))]) | |||
4616 | def rollback(ui, repo, **opts): |
|
4617 | def rollback(ui, repo, **opts): | |
4617 | """roll back the last transaction (dangerous) |
|
4618 | """roll back the last transaction (dangerous) | |
4618 |
|
4619 | |||
@@ -4633,6 +4634,12 def rollback(ui, repo, **opts): | |||||
4633 | - push (with this repository as the destination) |
|
4634 | - push (with this repository as the destination) | |
4634 | - unbundle |
|
4635 | - unbundle | |
4635 |
|
4636 | |||
|
4637 | It's possible to lose data with rollback: commit, update back to | |||
|
4638 | an older changeset, and then rollback. The update removes the | |||
|
4639 | changes you committed from the working directory, and rollback | |||
|
4640 | removes them from history. To avoid data loss, you must pass | |||
|
4641 | --force in this case. | |||
|
4642 | ||||
4636 | This command is not intended for use on public repositories. Once |
|
4643 | This command is not intended for use on public repositories. Once | |
4637 | changes are visible for pull by other users, rolling a transaction |
|
4644 | changes are visible for pull by other users, rolling a transaction | |
4638 | back locally is ineffective (someone else may already have pulled |
|
4645 | back locally is ineffective (someone else may already have pulled | |
@@ -4642,7 +4649,8 def rollback(ui, repo, **opts): | |||||
4642 |
|
4649 | |||
4643 | Returns 0 on success, 1 if no rollback data is available. |
|
4650 | Returns 0 on success, 1 if no rollback data is available. | |
4644 | """ |
|
4651 | """ | |
4645 |
return repo.rollback(opts.get('dry_run') |
|
4652 | return repo.rollback(dryrun=opts.get('dry_run'), | |
|
4653 | force=opts.get('force')) | |||
4646 |
|
4654 | |||
4647 | @command('root', []) |
|
4655 | @command('root', []) | |
4648 | def root(ui, repo): |
|
4656 | def root(ui, repo): |
@@ -754,20 +754,20 class localrepository(repo.repository): | |||||
754 | finally: |
|
754 | finally: | |
755 | lock.release() |
|
755 | lock.release() | |
756 |
|
756 | |||
757 | def rollback(self, dryrun=False): |
|
757 | def rollback(self, dryrun=False, force=False): | |
758 | wlock = lock = None |
|
758 | wlock = lock = None | |
759 | try: |
|
759 | try: | |
760 | wlock = self.wlock() |
|
760 | wlock = self.wlock() | |
761 | lock = self.lock() |
|
761 | lock = self.lock() | |
762 | if os.path.exists(self.sjoin("undo")): |
|
762 | if os.path.exists(self.sjoin("undo")): | |
763 | return self._rollback(dryrun) |
|
763 | return self._rollback(dryrun, force) | |
764 | else: |
|
764 | else: | |
765 | self.ui.warn(_("no rollback information available\n")) |
|
765 | self.ui.warn(_("no rollback information available\n")) | |
766 | return 1 |
|
766 | return 1 | |
767 | finally: |
|
767 | finally: | |
768 | release(lock, wlock) |
|
768 | release(lock, wlock) | |
769 |
|
769 | |||
770 | def _rollback(self, dryrun): |
|
770 | def _rollback(self, dryrun, force): | |
771 | ui = self.ui |
|
771 | ui = self.ui | |
772 | try: |
|
772 | try: | |
773 | args = self.opener.read('undo.desc').splitlines() |
|
773 | args = self.opener.read('undo.desc').splitlines() | |
@@ -786,6 +786,13 class localrepository(repo.repository): | |||||
786 | % (oldtip, desc)) |
|
786 | % (oldtip, desc)) | |
787 | except IOError: |
|
787 | except IOError: | |
788 | msg = _('rolling back unknown transaction\n') |
|
788 | msg = _('rolling back unknown transaction\n') | |
|
789 | desc = None | |||
|
790 | ||||
|
791 | if not force and self['.'] != self['tip'] and desc == 'commit': | |||
|
792 | raise util.Abort( | |||
|
793 | _('rollback of last commit while not checked out ' | |||
|
794 | 'may lose data (use -f to force)')) | |||
|
795 | ||||
789 | ui.status(msg) |
|
796 | ui.status(msg) | |
790 | if dryrun: |
|
797 | if dryrun: | |
791 | return 0 |
|
798 | return 0 |
@@ -257,7 +257,7 Show all commands + options | |||||
257 | rename: after, force, include, exclude, dry-run |
|
257 | rename: after, force, include, exclude, dry-run | |
258 | resolve: all, list, mark, unmark, no-status, tool, include, exclude |
|
258 | resolve: all, list, mark, unmark, no-status, tool, include, exclude | |
259 | revert: all, date, rev, no-backup, include, exclude, dry-run |
|
259 | revert: all, date, rev, no-backup, include, exclude, dry-run | |
260 | rollback: dry-run |
|
260 | rollback: dry-run, force | |
261 | root: |
|
261 | root: | |
262 | showconfig: untrusted |
|
262 | showconfig: untrusted | |
263 | tag: force, local, rev, remove, edit, message, date, user |
|
263 | tag: force, local, rev, remove, edit, message, date, user |
@@ -60,7 +60,7 Test --user, --date and --message | |||||
60 | |/ |
|
60 | |/ | |
61 | @ 0:07f494440405 test 0 0 - default - adda |
|
61 | @ 0:07f494440405 test 0 0 - default - adda | |
62 |
|
62 | |||
63 | $ hg rollback |
|
63 | $ hg rollback -f | |
64 | repository tip rolled back to revision 1 (undo commit) |
|
64 | repository tip rolled back to revision 1 (undo commit) | |
65 |
|
65 | |||
66 | Test --import-branch |
|
66 | Test --import-branch | |
@@ -72,7 +72,7 Test --import-branch | |||||
72 | | |
|
72 | | | |
73 | @ 0:07f494440405 test 0 0 - default - adda |
|
73 | @ 0:07f494440405 test 0 0 - default - adda | |
74 |
|
74 | |||
75 | $ hg rollback |
|
75 | $ hg rollback -f | |
76 | repository tip rolled back to revision 1 (undo commit) |
|
76 | repository tip rolled back to revision 1 (undo commit) | |
77 |
|
77 | |||
78 | Test --strip |
|
78 | Test --strip | |
@@ -94,7 +94,7 Test --strip | |||||
94 | > +a |
|
94 | > +a | |
95 | > EOF |
|
95 | > EOF | |
96 | applying patch from stdin |
|
96 | applying patch from stdin | |
97 | $ hg rollback |
|
97 | $ hg rollback -f | |
98 | repository tip rolled back to revision 1 (undo commit) |
|
98 | repository tip rolled back to revision 1 (undo commit) | |
99 |
|
99 | |||
100 | Test unsupported combinations |
|
100 | Test unsupported combinations |
@@ -83,7 +83,7 working dir unaffected by rollback: do n | |||||
83 | $ hg bookmark bar |
|
83 | $ hg bookmark bar | |
84 | $ cat .hg/undo.branch ; echo |
|
84 | $ cat .hg/undo.branch ; echo | |
85 | test |
|
85 | test | |
86 | $ hg rollback |
|
86 | $ hg rollback -f | |
87 | repository tip rolled back to revision 1 (undo commit) |
|
87 | repository tip rolled back to revision 1 (undo commit) | |
88 | $ hg id -n |
|
88 | $ hg id -n | |
89 | 0 |
|
89 | 0 | |
@@ -146,3 +146,37 presents the correct tip changeset: | |||||
146 | working directory now based on revision 0 |
|
146 | working directory now based on revision 0 | |
147 | $ hg id default |
|
147 | $ hg id default | |
148 | 791dd2169706 |
|
148 | 791dd2169706 | |
|
149 | ||||
|
150 | update to older changeset and then refuse rollback, because | |||
|
151 | that would lose data (issue2998) | |||
|
152 | $ cd ../t | |||
|
153 | $ hg -q update | |||
|
154 | $ rm `hg status -un` | |||
|
155 | $ template='{rev}:{node|short} [{branch}] {desc|firstline}\n' | |||
|
156 | $ echo 'valuable new file' > b | |||
|
157 | $ echo 'valuable modification' >> a | |||
|
158 | $ hg commit -A -m'a valuable change' | |||
|
159 | adding b | |||
|
160 | $ hg update 0 | |||
|
161 | 1 files updated, 0 files merged, 1 files removed, 0 files unresolved | |||
|
162 | $ hg rollback | |||
|
163 | abort: rollback of last commit while not checked out may lose data (use -f to force) | |||
|
164 | [255] | |||
|
165 | $ hg tip -q | |||
|
166 | 2:4d9cd3795eea | |||
|
167 | $ hg rollback -f | |||
|
168 | repository tip rolled back to revision 1 (undo commit) | |||
|
169 | $ hg status | |||
|
170 | $ hg log --removed b # yep, it's gone | |||
|
171 | ||||
|
172 | same again, but emulate an old client that doesn't write undo.desc | |||
|
173 | $ hg -q update | |||
|
174 | $ echo 'valuable modification redux' >> a | |||
|
175 | $ hg commit -m'a valuable change redux' | |||
|
176 | $ rm .hg/undo.desc | |||
|
177 | $ hg update 0 | |||
|
178 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |||
|
179 | $ hg rollback | |||
|
180 | rolling back unknown transaction | |||
|
181 | $ cat a | |||
|
182 | a |
General Comments 0
You need to be logged in to leave comments.
Login now