185 pendingctx = nodemod.bin(fp.readline().strip()) |
188 pendingctx = nodemod.bin(fp.readline().strip()) |
186 parents = [nodemod.bin(h) for h in fp.readline().split()] |
189 parents = [nodemod.bin(h) for h in fp.readline().split()] |
187 nodestoprune = [nodemod.bin(h) for h in fp.readline().split()] |
190 nodestoprune = [nodemod.bin(h) for h in fp.readline().split()] |
188 branchtorestore = fp.readline().strip() |
191 branchtorestore = fp.readline().strip() |
189 keep = fp.readline().strip() == cls._keep |
192 keep = fp.readline().strip() == cls._keep |
|
193 activebook = fp.readline().strip() |
190 except (ValueError, TypeError) as err: |
194 except (ValueError, TypeError) as err: |
191 raise error.CorruptedState(str(err)) |
195 raise error.CorruptedState(str(err)) |
192 finally: |
196 finally: |
193 fp.close() |
197 fp.close() |
194 |
198 |
199 obj.pendingctx = repo[pendingctx] |
203 obj.pendingctx = repo[pendingctx] |
200 obj.parents = parents |
204 obj.parents = parents |
201 obj.nodestoprune = nodestoprune |
205 obj.nodestoprune = nodestoprune |
202 obj.branchtorestore = branchtorestore |
206 obj.branchtorestore = branchtorestore |
203 obj.keep = keep |
207 obj.keep = keep |
|
208 obj.activebookmark = '' |
|
209 if activebook != cls._noactivebook: |
|
210 obj.activebookmark = activebook |
204 except error.RepoLookupError as err: |
211 except error.RepoLookupError as err: |
205 raise error.CorruptedState(str(err)) |
212 raise error.CorruptedState(str(err)) |
206 |
213 |
207 return obj |
214 return obj |
208 |
215 |
209 @classmethod |
216 @classmethod |
210 def save(cls, repo, name, originalwctx, pendingctx, nodestoprune, |
217 def save(cls, repo, name, originalwctx, pendingctx, nodestoprune, |
211 branchtorestore, keep=False): |
218 branchtorestore, keep=False, activebook=''): |
212 fp = repo.vfs(cls._filename, 'wb') |
219 fp = repo.vfs(cls._filename, 'wb') |
213 fp.write('%i\n' % cls._version) |
220 fp.write('%i\n' % cls._version) |
214 fp.write('%s\n' % name) |
221 fp.write('%s\n' % name) |
215 fp.write('%s\n' % nodemod.hex(originalwctx.node())) |
222 fp.write('%s\n' % nodemod.hex(originalwctx.node())) |
216 fp.write('%s\n' % nodemod.hex(pendingctx.node())) |
223 fp.write('%s\n' % nodemod.hex(pendingctx.node())) |
218 ' '.join([nodemod.hex(p) for p in repo.dirstate.parents()])) |
225 ' '.join([nodemod.hex(p) for p in repo.dirstate.parents()])) |
219 fp.write('%s\n' % |
226 fp.write('%s\n' % |
220 ' '.join([nodemod.hex(n) for n in nodestoprune])) |
227 ' '.join([nodemod.hex(n) for n in nodestoprune])) |
221 fp.write('%s\n' % branchtorestore) |
228 fp.write('%s\n' % branchtorestore) |
222 fp.write('%s\n' % (cls._keep if keep else cls._nokeep)) |
229 fp.write('%s\n' % (cls._keep if keep else cls._nokeep)) |
|
230 fp.write('%s\n' % (activebook or cls._noactivebook)) |
223 fp.close() |
231 fp.close() |
224 |
232 |
225 @classmethod |
233 @classmethod |
226 def clear(cls, repo): |
234 def clear(cls, repo): |
227 repo.vfs.unlinkpath(cls._filename, ignoremissing=True) |
235 repo.vfs.unlinkpath(cls._filename, ignoremissing=True) |
242 continue |
250 continue |
243 base = f[:-(1 + len(patchextension))] |
251 base = f[:-(1 + len(patchextension))] |
244 for ext in shelvefileextensions: |
252 for ext in shelvefileextensions: |
245 vfs.tryunlink(base + '.' + ext) |
253 vfs.tryunlink(base + '.' + ext) |
246 |
254 |
|
255 def _backupactivebookmark(repo): |
|
256 activebookmark = repo._activebookmark |
|
257 if activebookmark: |
|
258 bookmarks.deactivate(repo) |
|
259 return activebookmark |
|
260 |
|
261 def _restoreactivebookmark(repo, mark): |
|
262 if mark: |
|
263 bookmarks.activate(repo, mark) |
|
264 |
247 def _aborttransaction(repo): |
265 def _aborttransaction(repo): |
248 '''Abort current transaction for shelve/unshelve, but keep dirstate |
266 '''Abort current transaction for shelve/unshelve, but keep dirstate |
249 ''' |
267 ''' |
250 tr = repo.currenttransaction() |
268 tr = repo.currenttransaction() |
251 repo.dirstate.savebackup(tr, suffix='.shelve') |
269 repo.dirstate.savebackup(tr, suffix='.shelve') |
375 desc = '(changes in empty repository)' |
393 desc = '(changes in empty repository)' |
376 |
394 |
377 if not opts.get('message'): |
395 if not opts.get('message'): |
378 opts['message'] = desc |
396 opts['message'] = desc |
379 |
397 |
380 lock = tr = None |
398 lock = tr = activebookmark = None |
381 try: |
399 try: |
382 lock = repo.lock() |
400 lock = repo.lock() |
383 |
401 |
384 # use an uncommitted transaction to generate the bundle to avoid |
402 # use an uncommitted transaction to generate the bundle to avoid |
385 # pull races. ensure we don't print the abort message to stderr. |
403 # pull races. ensure we don't print the abort message to stderr. |
388 interactive = opts.get('interactive', False) |
406 interactive = opts.get('interactive', False) |
389 includeunknown = (opts.get('unknown', False) and |
407 includeunknown = (opts.get('unknown', False) and |
390 not opts.get('addremove', False)) |
408 not opts.get('addremove', False)) |
391 |
409 |
392 name = getshelvename(repo, parent, opts) |
410 name = getshelvename(repo, parent, opts) |
|
411 activebookmark = _backupactivebookmark(repo) |
393 extra = {} |
412 extra = {} |
394 if includeunknown: |
413 if includeunknown: |
395 _includeunknownfiles(repo, pats, opts, extra) |
414 _includeunknownfiles(repo, pats, opts, extra) |
396 |
415 |
397 if _iswctxonnewbranch(repo) and not _isbareshelve(pats, opts): |
416 if _iswctxonnewbranch(repo) and not _isbareshelve(pats, opts): |
402 commitfunc = getcommitfunc(extra, interactive, editor=True) |
421 commitfunc = getcommitfunc(extra, interactive, editor=True) |
403 if not interactive: |
422 if not interactive: |
404 node = cmdutil.commit(ui, repo, commitfunc, pats, opts) |
423 node = cmdutil.commit(ui, repo, commitfunc, pats, opts) |
405 else: |
424 else: |
406 node = cmdutil.dorecord(ui, repo, commitfunc, None, |
425 node = cmdutil.dorecord(ui, repo, commitfunc, None, |
407 False, cmdutil.recordfilter, *pats, **opts) |
426 False, cmdutil.recordfilter, *pats, |
|
427 **opts) |
408 if not node: |
428 if not node: |
409 _nothingtoshelvemessaging(ui, repo, pats, opts) |
429 _nothingtoshelvemessaging(ui, repo, pats, opts) |
410 return 1 |
430 return 1 |
411 |
431 |
412 _shelvecreatedcommit(repo, node, name) |
432 _shelvecreatedcommit(repo, node, name) |
418 if origbranch != repo['.'].branch() and not _isbareshelve(pats, opts): |
438 if origbranch != repo['.'].branch() and not _isbareshelve(pats, opts): |
419 repo.dirstate.setbranch(origbranch) |
439 repo.dirstate.setbranch(origbranch) |
420 |
440 |
421 _finishshelve(repo) |
441 _finishshelve(repo) |
422 finally: |
442 finally: |
|
443 _restoreactivebookmark(repo, activebookmark) |
423 lockmod.release(tr, lock) |
444 lockmod.release(tr, lock) |
424 |
445 |
425 def _isbareshelve(pats, opts): |
446 def _isbareshelve(pats, opts): |
426 return (not pats |
447 return (not pats |
427 and not opts.get('interactive', False) |
448 and not opts.get('interactive', False) |
637 |
658 |
638 mergefiles(ui, repo, state.wctx, shelvectx) |
659 mergefiles(ui, repo, state.wctx, shelvectx) |
639 restorebranch(ui, repo, state.branchtorestore) |
660 restorebranch(ui, repo, state.branchtorestore) |
640 |
661 |
641 repair.strip(ui, repo, state.nodestoprune, backup=False, topic='shelve') |
662 repair.strip(ui, repo, state.nodestoprune, backup=False, topic='shelve') |
|
663 _restoreactivebookmark(repo, state.activebookmark) |
642 shelvedstate.clear(repo) |
664 shelvedstate.clear(repo) |
643 unshelvecleanup(ui, repo, state.name, opts) |
665 unshelvecleanup(ui, repo, state.name, opts) |
644 ui.status(_("unshelve of '%s' complete\n") % state.name) |
666 ui.status(_("unshelve of '%s' complete\n") % state.name) |
645 |
667 |
646 def _commitworkingcopychanges(ui, repo, opts, tmpwctx): |
668 def _commitworkingcopychanges(ui, repo, opts, tmpwctx): |
670 shelvectx = repo['tip'] |
692 shelvectx = repo['tip'] |
671 ui.quiet = oldquiet |
693 ui.quiet = oldquiet |
672 return repo, shelvectx |
694 return repo, shelvectx |
673 |
695 |
674 def _rebaserestoredcommit(ui, repo, opts, tr, oldtiprev, basename, pctx, |
696 def _rebaserestoredcommit(ui, repo, opts, tr, oldtiprev, basename, pctx, |
675 tmpwctx, shelvectx, branchtorestore): |
697 tmpwctx, shelvectx, branchtorestore, |
|
698 activebookmark): |
676 """Rebase restored commit from its original location to a destination""" |
699 """Rebase restored commit from its original location to a destination""" |
677 # If the shelve is not immediately on top of the commit |
700 # If the shelve is not immediately on top of the commit |
678 # we'll be merging with, rebase it to be on top. |
701 # we'll be merging with, rebase it to be on top. |
679 if tmpwctx.node() == shelvectx.parents()[0].node(): |
702 if tmpwctx.node() == shelvectx.parents()[0].node(): |
680 return shelvectx |
703 return shelvectx |
691 tr.close() |
714 tr.close() |
692 |
715 |
693 nodestoprune = [repo.changelog.node(rev) |
716 nodestoprune = [repo.changelog.node(rev) |
694 for rev in xrange(oldtiprev, len(repo))] |
717 for rev in xrange(oldtiprev, len(repo))] |
695 shelvedstate.save(repo, basename, pctx, tmpwctx, nodestoprune, |
718 shelvedstate.save(repo, basename, pctx, tmpwctx, nodestoprune, |
696 branchtorestore, opts.get('keep')) |
719 branchtorestore, opts.get('keep'), activebookmark) |
697 |
720 |
698 repo.vfs.rename('rebasestate', 'unshelverebasestate') |
721 repo.vfs.rename('rebasestate', 'unshelverebasestate') |
699 raise error.InterventionRequired( |
722 raise error.InterventionRequired( |
700 _("unresolved conflicts (see 'hg resolve', then " |
723 _("unresolved conflicts (see 'hg resolve', then " |
701 "'hg unshelve --continue')")) |
724 "'hg unshelve --continue')")) |
717 shelveunknown = frozenset(shelveunknown.split('\0')) |
740 shelveunknown = frozenset(shelveunknown.split('\0')) |
718 addedafter = frozenset(repo.status().added) |
741 addedafter = frozenset(repo.status().added) |
719 toforget = (addedafter & shelveunknown) - addedbefore |
742 toforget = (addedafter & shelveunknown) - addedbefore |
720 repo[None].forget(toforget) |
743 repo[None].forget(toforget) |
721 |
744 |
722 def _finishunshelve(repo, oldtiprev, tr): |
745 def _finishunshelve(repo, oldtiprev, tr, activebookmark): |
|
746 _restoreactivebookmark(repo, activebookmark) |
723 # The transaction aborting will strip all the commits for us, |
747 # The transaction aborting will strip all the commits for us, |
724 # but it doesn't update the inmemory structures, so addchangegroup |
748 # but it doesn't update the inmemory structures, so addchangegroup |
725 # hooks still fire and try to operate on the missing commits. |
749 # hooks still fire and try to operate on the missing commits. |
726 # Clean up manually to prevent this. |
750 # Clean up manually to prevent this. |
727 repo.unfiltered().changelog.strip(oldtiprev, tr) |
751 repo.unfiltered().changelog.strip(oldtiprev, tr) |
863 # ...-> pctx -> tmpwctx -> shelvectx |
887 # ...-> pctx -> tmpwctx -> shelvectx |
864 # where tmpwctx is an optional commit with the user's pending changes |
888 # where tmpwctx is an optional commit with the user's pending changes |
865 # and shelvectx is the unshelved changes. Then we merge it all down |
889 # and shelvectx is the unshelved changes. Then we merge it all down |
866 # to the original pctx. |
890 # to the original pctx. |
867 |
891 |
|
892 activebookmark = _backupactivebookmark(repo) |
868 overrides = {('ui', 'forcemerge'): opts.get('tool', '')} |
893 overrides = {('ui', 'forcemerge'): opts.get('tool', '')} |
869 with ui.configoverride(overrides, 'unshelve'): |
894 with ui.configoverride(overrides, 'unshelve'): |
870 tmpwctx, addedbefore = _commitworkingcopychanges(ui, repo, opts, |
895 tmpwctx, addedbefore = _commitworkingcopychanges(ui, repo, opts, |
871 tmpwctx) |
896 tmpwctx) |
872 |
897 |
877 if shelvectx.branch() != shelvectx.p1().branch(): |
902 if shelvectx.branch() != shelvectx.p1().branch(): |
878 branchtorestore = shelvectx.branch() |
903 branchtorestore = shelvectx.branch() |
879 |
904 |
880 shelvectx = _rebaserestoredcommit(ui, repo, opts, tr, oldtiprev, |
905 shelvectx = _rebaserestoredcommit(ui, repo, opts, tr, oldtiprev, |
881 basename, pctx, tmpwctx, |
906 basename, pctx, tmpwctx, |
882 shelvectx, branchtorestore) |
907 shelvectx, branchtorestore, |
|
908 activebookmark) |
883 mergefiles(ui, repo, pctx, shelvectx) |
909 mergefiles(ui, repo, pctx, shelvectx) |
884 restorebranch(ui, repo, branchtorestore) |
910 restorebranch(ui, repo, branchtorestore) |
885 _forgetunknownfiles(repo, shelvectx, addedbefore) |
911 _forgetunknownfiles(repo, shelvectx, addedbefore) |
886 |
912 |
887 shelvedstate.clear(repo) |
913 shelvedstate.clear(repo) |
888 _finishunshelve(repo, oldtiprev, tr) |
914 _finishunshelve(repo, oldtiprev, tr, activebookmark) |
889 unshelvecleanup(ui, repo, basename, opts) |
915 unshelvecleanup(ui, repo, basename, opts) |
890 finally: |
916 finally: |
891 ui.quiet = oldquiet |
917 ui.quiet = oldquiet |
892 if tr: |
918 if tr: |
893 tr.release() |
919 tr.release() |