shelve: add a shelve extension to save/restore working changes
This extension saves shelved changes using a temporary draft commit,
and bundles the temporary commit and its draft ancestors, then
strips them.
This strategy makes it possible to use Mercurial's bundle and merge
machinery to resolve conflicts if necessary when unshelving, even
when the destination commit or its ancestors have been amended,
squashed, or evolved. (Once a change has been unshelved, its
associated unbundled commits are either rolled back or stripped.)
Storing the shelved change as a bundle also avoids the difficulty
that hidden commits would cause, of making it impossible to amend
the parent if it is a draft commits (a common scenario).
Although this extension shares its name and some functionality with
the third party hgshelve extension, it has little else in common.
Notably, the hgshelve extension shelves changes as unified diffs,
which makes conflict resolution a matter of finding .rej files and
conflict markers, and cleaning up the mess by hand.
We do not yet allow hunk-level choosing of changes to record.
Compared to the hgshelve extension, this is a small regression in
usability, but we hope to integrate that at a later point, once the
record machinery becomes more reusable and robust.
2013-08-29 20:22:13 +04:00
|
|
|
# shelve.py - save/restore working directory state
|
|
|
|
#
|
|
|
|
# Copyright 2013 Facebook, Inc.
|
|
|
|
#
|
|
|
|
# This software may be used and distributed according to the terms of the
|
|
|
|
# GNU General Public License version 2 or any later version.
|
|
|
|
|
|
|
|
"""save and restore changes to the working directory
|
|
|
|
|
|
|
|
The "hg shelve" command saves changes made to the working directory
|
|
|
|
and reverts those changes, resetting the working directory to a clean
|
|
|
|
state.
|
|
|
|
|
|
|
|
Later on, the "hg unshelve" command restores the changes saved by "hg
|
|
|
|
shelve". Changes can be restored even after updating to a different
|
|
|
|
parent, in which case Mercurial's merge machinery will resolve any
|
|
|
|
conflicts if necessary.
|
|
|
|
|
|
|
|
You can have more than one shelved change outstanding at a time; each
|
|
|
|
shelved change has a distinct name. For details, see the help for "hg
|
|
|
|
shelve".
|
|
|
|
"""
|
|
|
|
|
|
|
|
from mercurial.i18n import _
|
2014-02-10 03:52:46 +04:00
|
|
|
from mercurial.node import nullid, nullrev, bin, hex
|
2014-02-10 03:53:25 +04:00
|
|
|
from mercurial import changegroup, cmdutil, scmutil, phases, commands
|
shelve: add a shelve extension to save/restore working changes
This extension saves shelved changes using a temporary draft commit,
and bundles the temporary commit and its draft ancestors, then
strips them.
This strategy makes it possible to use Mercurial's bundle and merge
machinery to resolve conflicts if necessary when unshelving, even
when the destination commit or its ancestors have been amended,
squashed, or evolved. (Once a change has been unshelved, its
associated unbundled commits are either rolled back or stripped.)
Storing the shelved change as a bundle also avoids the difficulty
that hidden commits would cause, of making it impossible to amend
the parent if it is a draft commits (a common scenario).
Although this extension shares its name and some functionality with
the third party hgshelve extension, it has little else in common.
Notably, the hgshelve extension shelves changes as unified diffs,
which makes conflict resolution a matter of finding .rej files and
conflict markers, and cleaning up the mess by hand.
We do not yet allow hunk-level choosing of changes to record.
Compared to the hgshelve extension, this is a small regression in
usability, but we hope to integrate that at a later point, once the
record machinery becomes more reusable and robust.
2013-08-29 20:22:13 +04:00
|
|
|
from mercurial import error, hg, mdiff, merge, patch, repair, util
|
2014-04-02 01:25:03 +04:00
|
|
|
from mercurial import templatefilters, changegroup
|
shelve: add a shelve extension to save/restore working changes
This extension saves shelved changes using a temporary draft commit,
and bundles the temporary commit and its draft ancestors, then
strips them.
This strategy makes it possible to use Mercurial's bundle and merge
machinery to resolve conflicts if necessary when unshelving, even
when the destination commit or its ancestors have been amended,
squashed, or evolved. (Once a change has been unshelved, its
associated unbundled commits are either rolled back or stripped.)
Storing the shelved change as a bundle also avoids the difficulty
that hidden commits would cause, of making it impossible to amend
the parent if it is a draft commits (a common scenario).
Although this extension shares its name and some functionality with
the third party hgshelve extension, it has little else in common.
Notably, the hgshelve extension shelves changes as unified diffs,
which makes conflict resolution a matter of finding .rej files and
conflict markers, and cleaning up the mess by hand.
We do not yet allow hunk-level choosing of changes to record.
Compared to the hgshelve extension, this is a small regression in
usability, but we hope to integrate that at a later point, once the
record machinery becomes more reusable and robust.
2013-08-29 20:22:13 +04:00
|
|
|
from mercurial import lock as lockmod
|
2013-10-24 00:12:48 +04:00
|
|
|
from hgext import rebase
|
shelve: add a shelve extension to save/restore working changes
This extension saves shelved changes using a temporary draft commit,
and bundles the temporary commit and its draft ancestors, then
strips them.
This strategy makes it possible to use Mercurial's bundle and merge
machinery to resolve conflicts if necessary when unshelving, even
when the destination commit or its ancestors have been amended,
squashed, or evolved. (Once a change has been unshelved, its
associated unbundled commits are either rolled back or stripped.)
Storing the shelved change as a bundle also avoids the difficulty
that hidden commits would cause, of making it impossible to amend
the parent if it is a draft commits (a common scenario).
Although this extension shares its name and some functionality with
the third party hgshelve extension, it has little else in common.
Notably, the hgshelve extension shelves changes as unified diffs,
which makes conflict resolution a matter of finding .rej files and
conflict markers, and cleaning up the mess by hand.
We do not yet allow hunk-level choosing of changes to record.
Compared to the hgshelve extension, this is a small regression in
usability, but we hope to integrate that at a later point, once the
record machinery becomes more reusable and robust.
2013-08-29 20:22:13 +04:00
|
|
|
import errno
|
|
|
|
|
|
|
|
cmdtable = {}
|
|
|
|
command = cmdutil.command(cmdtable)
|
|
|
|
testedwith = 'internal'
|
|
|
|
|
|
|
|
class shelvedfile(object):
|
2013-10-14 20:29:56 +04:00
|
|
|
"""Helper for the file storing a single shelve
|
|
|
|
|
|
|
|
Handles common functions on shelve files (.hg/.files/.patch) using
|
shelve: add a shelve extension to save/restore working changes
This extension saves shelved changes using a temporary draft commit,
and bundles the temporary commit and its draft ancestors, then
strips them.
This strategy makes it possible to use Mercurial's bundle and merge
machinery to resolve conflicts if necessary when unshelving, even
when the destination commit or its ancestors have been amended,
squashed, or evolved. (Once a change has been unshelved, its
associated unbundled commits are either rolled back or stripped.)
Storing the shelved change as a bundle also avoids the difficulty
that hidden commits would cause, of making it impossible to amend
the parent if it is a draft commits (a common scenario).
Although this extension shares its name and some functionality with
the third party hgshelve extension, it has little else in common.
Notably, the hgshelve extension shelves changes as unified diffs,
which makes conflict resolution a matter of finding .rej files and
conflict markers, and cleaning up the mess by hand.
We do not yet allow hunk-level choosing of changes to record.
Compared to the hgshelve extension, this is a small regression in
usability, but we hope to integrate that at a later point, once the
record machinery becomes more reusable and robust.
2013-08-29 20:22:13 +04:00
|
|
|
the vfs layer"""
|
|
|
|
def __init__(self, repo, name, filetype=None):
|
|
|
|
self.repo = repo
|
|
|
|
self.name = name
|
|
|
|
self.vfs = scmutil.vfs(repo.join('shelved'))
|
|
|
|
if filetype:
|
|
|
|
self.fname = name + '.' + filetype
|
|
|
|
else:
|
|
|
|
self.fname = name
|
|
|
|
|
|
|
|
def exists(self):
|
|
|
|
return self.vfs.exists(self.fname)
|
|
|
|
|
|
|
|
def filename(self):
|
|
|
|
return self.vfs.join(self.fname)
|
|
|
|
|
|
|
|
def unlink(self):
|
|
|
|
util.unlink(self.filename())
|
|
|
|
|
|
|
|
def stat(self):
|
|
|
|
return self.vfs.stat(self.fname)
|
|
|
|
|
|
|
|
def opener(self, mode='rb'):
|
|
|
|
try:
|
|
|
|
return self.vfs(self.fname, mode)
|
|
|
|
except IOError, err:
|
|
|
|
if err.errno != errno.ENOENT:
|
|
|
|
raise
|
2013-10-28 20:03:43 +04:00
|
|
|
raise util.Abort(_("shelved change '%s' not found") % self.name)
|
shelve: add a shelve extension to save/restore working changes
This extension saves shelved changes using a temporary draft commit,
and bundles the temporary commit and its draft ancestors, then
strips them.
This strategy makes it possible to use Mercurial's bundle and merge
machinery to resolve conflicts if necessary when unshelving, even
when the destination commit or its ancestors have been amended,
squashed, or evolved. (Once a change has been unshelved, its
associated unbundled commits are either rolled back or stripped.)
Storing the shelved change as a bundle also avoids the difficulty
that hidden commits would cause, of making it impossible to amend
the parent if it is a draft commits (a common scenario).
Although this extension shares its name and some functionality with
the third party hgshelve extension, it has little else in common.
Notably, the hgshelve extension shelves changes as unified diffs,
which makes conflict resolution a matter of finding .rej files and
conflict markers, and cleaning up the mess by hand.
We do not yet allow hunk-level choosing of changes to record.
Compared to the hgshelve extension, this is a small regression in
usability, but we hope to integrate that at a later point, once the
record machinery becomes more reusable and robust.
2013-08-29 20:22:13 +04:00
|
|
|
|
2014-03-08 20:03:28 +04:00
|
|
|
def applybundle(self):
|
|
|
|
fp = self.opener()
|
|
|
|
try:
|
|
|
|
gen = changegroup.readbundle(fp, self.fname, self.vfs)
|
|
|
|
changegroup.addchangegroup(self.repo, gen, 'unshelve',
|
|
|
|
'bundle:' + self.vfs.join(self.fname))
|
|
|
|
finally:
|
|
|
|
fp.close()
|
|
|
|
|
2014-03-08 20:03:28 +04:00
|
|
|
def writebundle(self, cg):
|
|
|
|
changegroup.writebundle(cg, self.fname, 'HG10UN', self.vfs)
|
|
|
|
|
shelve: add a shelve extension to save/restore working changes
This extension saves shelved changes using a temporary draft commit,
and bundles the temporary commit and its draft ancestors, then
strips them.
This strategy makes it possible to use Mercurial's bundle and merge
machinery to resolve conflicts if necessary when unshelving, even
when the destination commit or its ancestors have been amended,
squashed, or evolved. (Once a change has been unshelved, its
associated unbundled commits are either rolled back or stripped.)
Storing the shelved change as a bundle also avoids the difficulty
that hidden commits would cause, of making it impossible to amend
the parent if it is a draft commits (a common scenario).
Although this extension shares its name and some functionality with
the third party hgshelve extension, it has little else in common.
Notably, the hgshelve extension shelves changes as unified diffs,
which makes conflict resolution a matter of finding .rej files and
conflict markers, and cleaning up the mess by hand.
We do not yet allow hunk-level choosing of changes to record.
Compared to the hgshelve extension, this is a small regression in
usability, but we hope to integrate that at a later point, once the
record machinery becomes more reusable and robust.
2013-08-29 20:22:13 +04:00
|
|
|
class shelvedstate(object):
|
2013-10-16 18:36:58 +04:00
|
|
|
"""Handle persistence during unshelving operations.
|
2013-10-14 20:29:56 +04:00
|
|
|
|
|
|
|
Handles saving and restoring a shelved state. Ensures that different
|
2013-10-16 18:36:58 +04:00
|
|
|
versions of a shelved state are possible and handles them appropriately.
|
|
|
|
"""
|
shelve: add a shelve extension to save/restore working changes
This extension saves shelved changes using a temporary draft commit,
and bundles the temporary commit and its draft ancestors, then
strips them.
This strategy makes it possible to use Mercurial's bundle and merge
machinery to resolve conflicts if necessary when unshelving, even
when the destination commit or its ancestors have been amended,
squashed, or evolved. (Once a change has been unshelved, its
associated unbundled commits are either rolled back or stripped.)
Storing the shelved change as a bundle also avoids the difficulty
that hidden commits would cause, of making it impossible to amend
the parent if it is a draft commits (a common scenario).
Although this extension shares its name and some functionality with
the third party hgshelve extension, it has little else in common.
Notably, the hgshelve extension shelves changes as unified diffs,
which makes conflict resolution a matter of finding .rej files and
conflict markers, and cleaning up the mess by hand.
We do not yet allow hunk-level choosing of changes to record.
Compared to the hgshelve extension, this is a small regression in
usability, but we hope to integrate that at a later point, once the
record machinery becomes more reusable and robust.
2013-08-29 20:22:13 +04:00
|
|
|
_version = 1
|
|
|
|
_filename = 'shelvedstate'
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def load(cls, repo):
|
|
|
|
fp = repo.opener(cls._filename)
|
2013-10-14 20:59:12 +04:00
|
|
|
try:
|
|
|
|
version = int(fp.readline().strip())
|
shelve: add a shelve extension to save/restore working changes
This extension saves shelved changes using a temporary draft commit,
and bundles the temporary commit and its draft ancestors, then
strips them.
This strategy makes it possible to use Mercurial's bundle and merge
machinery to resolve conflicts if necessary when unshelving, even
when the destination commit or its ancestors have been amended,
squashed, or evolved. (Once a change has been unshelved, its
associated unbundled commits are either rolled back or stripped.)
Storing the shelved change as a bundle also avoids the difficulty
that hidden commits would cause, of making it impossible to amend
the parent if it is a draft commits (a common scenario).
Although this extension shares its name and some functionality with
the third party hgshelve extension, it has little else in common.
Notably, the hgshelve extension shelves changes as unified diffs,
which makes conflict resolution a matter of finding .rej files and
conflict markers, and cleaning up the mess by hand.
We do not yet allow hunk-level choosing of changes to record.
Compared to the hgshelve extension, this is a small regression in
usability, but we hope to integrate that at a later point, once the
record machinery becomes more reusable and robust.
2013-08-29 20:22:13 +04:00
|
|
|
|
2013-10-14 20:59:12 +04:00
|
|
|
if version != cls._version:
|
|
|
|
raise util.Abort(_('this version of shelve is incompatible '
|
|
|
|
'with the version used in this repo'))
|
|
|
|
name = fp.readline().strip()
|
2013-10-24 00:12:48 +04:00
|
|
|
wctx = fp.readline().strip()
|
|
|
|
pendingctx = fp.readline().strip()
|
2013-10-14 20:59:12 +04:00
|
|
|
parents = [bin(h) for h in fp.readline().split()]
|
|
|
|
stripnodes = [bin(h) for h in fp.readline().split()]
|
|
|
|
finally:
|
|
|
|
fp.close()
|
shelve: add a shelve extension to save/restore working changes
This extension saves shelved changes using a temporary draft commit,
and bundles the temporary commit and its draft ancestors, then
strips them.
This strategy makes it possible to use Mercurial's bundle and merge
machinery to resolve conflicts if necessary when unshelving, even
when the destination commit or its ancestors have been amended,
squashed, or evolved. (Once a change has been unshelved, its
associated unbundled commits are either rolled back or stripped.)
Storing the shelved change as a bundle also avoids the difficulty
that hidden commits would cause, of making it impossible to amend
the parent if it is a draft commits (a common scenario).
Although this extension shares its name and some functionality with
the third party hgshelve extension, it has little else in common.
Notably, the hgshelve extension shelves changes as unified diffs,
which makes conflict resolution a matter of finding .rej files and
conflict markers, and cleaning up the mess by hand.
We do not yet allow hunk-level choosing of changes to record.
Compared to the hgshelve extension, this is a small regression in
usability, but we hope to integrate that at a later point, once the
record machinery becomes more reusable and robust.
2013-08-29 20:22:13 +04:00
|
|
|
|
|
|
|
obj = cls()
|
|
|
|
obj.name = name
|
2013-10-24 00:12:48 +04:00
|
|
|
obj.wctx = repo[bin(wctx)]
|
|
|
|
obj.pendingctx = repo[bin(pendingctx)]
|
shelve: add a shelve extension to save/restore working changes
This extension saves shelved changes using a temporary draft commit,
and bundles the temporary commit and its draft ancestors, then
strips them.
This strategy makes it possible to use Mercurial's bundle and merge
machinery to resolve conflicts if necessary when unshelving, even
when the destination commit or its ancestors have been amended,
squashed, or evolved. (Once a change has been unshelved, its
associated unbundled commits are either rolled back or stripped.)
Storing the shelved change as a bundle also avoids the difficulty
that hidden commits would cause, of making it impossible to amend
the parent if it is a draft commits (a common scenario).
Although this extension shares its name and some functionality with
the third party hgshelve extension, it has little else in common.
Notably, the hgshelve extension shelves changes as unified diffs,
which makes conflict resolution a matter of finding .rej files and
conflict markers, and cleaning up the mess by hand.
We do not yet allow hunk-level choosing of changes to record.
Compared to the hgshelve extension, this is a small regression in
usability, but we hope to integrate that at a later point, once the
record machinery becomes more reusable and robust.
2013-08-29 20:22:13 +04:00
|
|
|
obj.parents = parents
|
|
|
|
obj.stripnodes = stripnodes
|
|
|
|
|
|
|
|
return obj
|
|
|
|
|
|
|
|
@classmethod
|
2013-11-27 04:23:05 +04:00
|
|
|
def save(cls, repo, name, originalwctx, pendingctx, stripnodes):
|
shelve: add a shelve extension to save/restore working changes
This extension saves shelved changes using a temporary draft commit,
and bundles the temporary commit and its draft ancestors, then
strips them.
This strategy makes it possible to use Mercurial's bundle and merge
machinery to resolve conflicts if necessary when unshelving, even
when the destination commit or its ancestors have been amended,
squashed, or evolved. (Once a change has been unshelved, its
associated unbundled commits are either rolled back or stripped.)
Storing the shelved change as a bundle also avoids the difficulty
that hidden commits would cause, of making it impossible to amend
the parent if it is a draft commits (a common scenario).
Although this extension shares its name and some functionality with
the third party hgshelve extension, it has little else in common.
Notably, the hgshelve extension shelves changes as unified diffs,
which makes conflict resolution a matter of finding .rej files and
conflict markers, and cleaning up the mess by hand.
We do not yet allow hunk-level choosing of changes to record.
Compared to the hgshelve extension, this is a small regression in
usability, but we hope to integrate that at a later point, once the
record machinery becomes more reusable and robust.
2013-08-29 20:22:13 +04:00
|
|
|
fp = repo.opener(cls._filename, 'wb')
|
2013-10-14 20:59:12 +04:00
|
|
|
fp.write('%i\n' % cls._version)
|
|
|
|
fp.write('%s\n' % name)
|
2013-10-24 00:12:48 +04:00
|
|
|
fp.write('%s\n' % hex(originalwctx.node()))
|
|
|
|
fp.write('%s\n' % hex(pendingctx.node()))
|
2013-10-14 20:59:12 +04:00
|
|
|
fp.write('%s\n' % ' '.join([hex(p) for p in repo.dirstate.parents()]))
|
|
|
|
fp.write('%s\n' % ' '.join([hex(n) for n in stripnodes]))
|
shelve: add a shelve extension to save/restore working changes
This extension saves shelved changes using a temporary draft commit,
and bundles the temporary commit and its draft ancestors, then
strips them.
This strategy makes it possible to use Mercurial's bundle and merge
machinery to resolve conflicts if necessary when unshelving, even
when the destination commit or its ancestors have been amended,
squashed, or evolved. (Once a change has been unshelved, its
associated unbundled commits are either rolled back or stripped.)
Storing the shelved change as a bundle also avoids the difficulty
that hidden commits would cause, of making it impossible to amend
the parent if it is a draft commits (a common scenario).
Although this extension shares its name and some functionality with
the third party hgshelve extension, it has little else in common.
Notably, the hgshelve extension shelves changes as unified diffs,
which makes conflict resolution a matter of finding .rej files and
conflict markers, and cleaning up the mess by hand.
We do not yet allow hunk-level choosing of changes to record.
Compared to the hgshelve extension, this is a small regression in
usability, but we hope to integrate that at a later point, once the
record machinery becomes more reusable and robust.
2013-08-29 20:22:13 +04:00
|
|
|
fp.close()
|
|
|
|
|
2013-10-14 19:46:47 +04:00
|
|
|
@classmethod
|
|
|
|
def clear(cls, repo):
|
|
|
|
util.unlinkpath(repo.join(cls._filename), ignoremissing=True)
|
shelve: add a shelve extension to save/restore working changes
This extension saves shelved changes using a temporary draft commit,
and bundles the temporary commit and its draft ancestors, then
strips them.
This strategy makes it possible to use Mercurial's bundle and merge
machinery to resolve conflicts if necessary when unshelving, even
when the destination commit or its ancestors have been amended,
squashed, or evolved. (Once a change has been unshelved, its
associated unbundled commits are either rolled back or stripped.)
Storing the shelved change as a bundle also avoids the difficulty
that hidden commits would cause, of making it impossible to amend
the parent if it is a draft commits (a common scenario).
Although this extension shares its name and some functionality with
the third party hgshelve extension, it has little else in common.
Notably, the hgshelve extension shelves changes as unified diffs,
which makes conflict resolution a matter of finding .rej files and
conflict markers, and cleaning up the mess by hand.
We do not yet allow hunk-level choosing of changes to record.
Compared to the hgshelve extension, this is a small regression in
usability, but we hope to integrate that at a later point, once the
record machinery becomes more reusable and robust.
2013-08-29 20:22:13 +04:00
|
|
|
|
|
|
|
def createcmd(ui, repo, pats, opts):
|
2013-10-16 18:36:58 +04:00
|
|
|
"""subcommand that creates a new shelve"""
|
2013-10-14 20:29:56 +04:00
|
|
|
|
shelve: add a shelve extension to save/restore working changes
This extension saves shelved changes using a temporary draft commit,
and bundles the temporary commit and its draft ancestors, then
strips them.
This strategy makes it possible to use Mercurial's bundle and merge
machinery to resolve conflicts if necessary when unshelving, even
when the destination commit or its ancestors have been amended,
squashed, or evolved. (Once a change has been unshelved, its
associated unbundled commits are either rolled back or stripped.)
Storing the shelved change as a bundle also avoids the difficulty
that hidden commits would cause, of making it impossible to amend
the parent if it is a draft commits (a common scenario).
Although this extension shares its name and some functionality with
the third party hgshelve extension, it has little else in common.
Notably, the hgshelve extension shelves changes as unified diffs,
which makes conflict resolution a matter of finding .rej files and
conflict markers, and cleaning up the mess by hand.
We do not yet allow hunk-level choosing of changes to record.
Compared to the hgshelve extension, this is a small regression in
usability, but we hope to integrate that at a later point, once the
record machinery becomes more reusable and robust.
2013-08-29 20:22:13 +04:00
|
|
|
def publicancestors(ctx):
|
2014-02-10 03:52:56 +04:00
|
|
|
"""Compute the public ancestors of a commit.
|
shelve: add a shelve extension to save/restore working changes
This extension saves shelved changes using a temporary draft commit,
and bundles the temporary commit and its draft ancestors, then
strips them.
This strategy makes it possible to use Mercurial's bundle and merge
machinery to resolve conflicts if necessary when unshelving, even
when the destination commit or its ancestors have been amended,
squashed, or evolved. (Once a change has been unshelved, its
associated unbundled commits are either rolled back or stripped.)
Storing the shelved change as a bundle also avoids the difficulty
that hidden commits would cause, of making it impossible to amend
the parent if it is a draft commits (a common scenario).
Although this extension shares its name and some functionality with
the third party hgshelve extension, it has little else in common.
Notably, the hgshelve extension shelves changes as unified diffs,
which makes conflict resolution a matter of finding .rej files and
conflict markers, and cleaning up the mess by hand.
We do not yet allow hunk-level choosing of changes to record.
Compared to the hgshelve extension, this is a small regression in
usability, but we hope to integrate that at a later point, once the
record machinery becomes more reusable and robust.
2013-08-29 20:22:13 +04:00
|
|
|
|
2014-02-10 03:52:56 +04:00
|
|
|
Much faster than the revset ancestors(ctx) & draft()"""
|
2014-02-10 03:52:46 +04:00
|
|
|
seen = set([nullrev])
|
shelve: add a shelve extension to save/restore working changes
This extension saves shelved changes using a temporary draft commit,
and bundles the temporary commit and its draft ancestors, then
strips them.
This strategy makes it possible to use Mercurial's bundle and merge
machinery to resolve conflicts if necessary when unshelving, even
when the destination commit or its ancestors have been amended,
squashed, or evolved. (Once a change has been unshelved, its
associated unbundled commits are either rolled back or stripped.)
Storing the shelved change as a bundle also avoids the difficulty
that hidden commits would cause, of making it impossible to amend
the parent if it is a draft commits (a common scenario).
Although this extension shares its name and some functionality with
the third party hgshelve extension, it has little else in common.
Notably, the hgshelve extension shelves changes as unified diffs,
which makes conflict resolution a matter of finding .rej files and
conflict markers, and cleaning up the mess by hand.
We do not yet allow hunk-level choosing of changes to record.
Compared to the hgshelve extension, this is a small regression in
usability, but we hope to integrate that at a later point, once the
record machinery becomes more reusable and robust.
2013-08-29 20:22:13 +04:00
|
|
|
visit = util.deque()
|
|
|
|
visit.append(ctx)
|
|
|
|
while visit:
|
|
|
|
ctx = visit.popleft()
|
2014-02-10 03:52:56 +04:00
|
|
|
yield ctx.node()
|
shelve: add a shelve extension to save/restore working changes
This extension saves shelved changes using a temporary draft commit,
and bundles the temporary commit and its draft ancestors, then
strips them.
This strategy makes it possible to use Mercurial's bundle and merge
machinery to resolve conflicts if necessary when unshelving, even
when the destination commit or its ancestors have been amended,
squashed, or evolved. (Once a change has been unshelved, its
associated unbundled commits are either rolled back or stripped.)
Storing the shelved change as a bundle also avoids the difficulty
that hidden commits would cause, of making it impossible to amend
the parent if it is a draft commits (a common scenario).
Although this extension shares its name and some functionality with
the third party hgshelve extension, it has little else in common.
Notably, the hgshelve extension shelves changes as unified diffs,
which makes conflict resolution a matter of finding .rej files and
conflict markers, and cleaning up the mess by hand.
We do not yet allow hunk-level choosing of changes to record.
Compared to the hgshelve extension, this is a small regression in
usability, but we hope to integrate that at a later point, once the
record machinery becomes more reusable and robust.
2013-08-29 20:22:13 +04:00
|
|
|
for parent in ctx.parents():
|
|
|
|
rev = parent.rev()
|
|
|
|
if rev not in seen:
|
|
|
|
seen.add(rev)
|
|
|
|
if parent.mutable():
|
|
|
|
visit.append(parent)
|
|
|
|
|
|
|
|
wctx = repo[None]
|
|
|
|
parents = wctx.parents()
|
|
|
|
if len(parents) > 1:
|
|
|
|
raise util.Abort(_('cannot shelve while merging'))
|
|
|
|
parent = parents[0]
|
|
|
|
|
|
|
|
# we never need the user, so we use a generic user for all shelve operations
|
|
|
|
user = 'shelve@localhost'
|
|
|
|
label = repo._bookmarkcurrent or parent.branch() or 'default'
|
|
|
|
|
|
|
|
# slashes aren't allowed in filenames, therefore we rename it
|
2014-04-04 05:32:56 +04:00
|
|
|
label = label.replace('/', '_')
|
shelve: add a shelve extension to save/restore working changes
This extension saves shelved changes using a temporary draft commit,
and bundles the temporary commit and its draft ancestors, then
strips them.
This strategy makes it possible to use Mercurial's bundle and merge
machinery to resolve conflicts if necessary when unshelving, even
when the destination commit or its ancestors have been amended,
squashed, or evolved. (Once a change has been unshelved, its
associated unbundled commits are either rolled back or stripped.)
Storing the shelved change as a bundle also avoids the difficulty
that hidden commits would cause, of making it impossible to amend
the parent if it is a draft commits (a common scenario).
Although this extension shares its name and some functionality with
the third party hgshelve extension, it has little else in common.
Notably, the hgshelve extension shelves changes as unified diffs,
which makes conflict resolution a matter of finding .rej files and
conflict markers, and cleaning up the mess by hand.
We do not yet allow hunk-level choosing of changes to record.
Compared to the hgshelve extension, this is a small regression in
usability, but we hope to integrate that at a later point, once the
record machinery becomes more reusable and robust.
2013-08-29 20:22:13 +04:00
|
|
|
|
|
|
|
def gennames():
|
|
|
|
yield label
|
|
|
|
for i in xrange(1, 100):
|
|
|
|
yield '%s-%02d' % (label, i)
|
|
|
|
|
|
|
|
shelvedfiles = []
|
|
|
|
|
|
|
|
def commitfunc(ui, repo, message, match, opts):
|
|
|
|
# check modified, added, removed, deleted only
|
|
|
|
for flist in repo.status(match=match)[:4]:
|
|
|
|
shelvedfiles.extend(flist)
|
2013-10-10 01:15:20 +04:00
|
|
|
hasmq = util.safehasattr(repo, 'mq')
|
|
|
|
if hasmq:
|
|
|
|
saved, repo.mq.checkapplied = repo.mq.checkapplied, False
|
2013-08-29 20:22:15 +04:00
|
|
|
try:
|
|
|
|
return repo.commit(message, user, opts.get('date'), match)
|
|
|
|
finally:
|
2013-10-10 01:15:20 +04:00
|
|
|
if hasmq:
|
|
|
|
repo.mq.checkapplied = saved
|
shelve: add a shelve extension to save/restore working changes
This extension saves shelved changes using a temporary draft commit,
and bundles the temporary commit and its draft ancestors, then
strips them.
This strategy makes it possible to use Mercurial's bundle and merge
machinery to resolve conflicts if necessary when unshelving, even
when the destination commit or its ancestors have been amended,
squashed, or evolved. (Once a change has been unshelved, its
associated unbundled commits are either rolled back or stripped.)
Storing the shelved change as a bundle also avoids the difficulty
that hidden commits would cause, of making it impossible to amend
the parent if it is a draft commits (a common scenario).
Although this extension shares its name and some functionality with
the third party hgshelve extension, it has little else in common.
Notably, the hgshelve extension shelves changes as unified diffs,
which makes conflict resolution a matter of finding .rej files and
conflict markers, and cleaning up the mess by hand.
We do not yet allow hunk-level choosing of changes to record.
Compared to the hgshelve extension, this is a small regression in
usability, but we hope to integrate that at a later point, once the
record machinery becomes more reusable and robust.
2013-08-29 20:22:13 +04:00
|
|
|
|
|
|
|
if parent.node() != nullid:
|
2014-02-10 03:53:27 +04:00
|
|
|
desc = "changes to '%s'" % parent.description().split('\n', 1)[0]
|
shelve: add a shelve extension to save/restore working changes
This extension saves shelved changes using a temporary draft commit,
and bundles the temporary commit and its draft ancestors, then
strips them.
This strategy makes it possible to use Mercurial's bundle and merge
machinery to resolve conflicts if necessary when unshelving, even
when the destination commit or its ancestors have been amended,
squashed, or evolved. (Once a change has been unshelved, its
associated unbundled commits are either rolled back or stripped.)
Storing the shelved change as a bundle also avoids the difficulty
that hidden commits would cause, of making it impossible to amend
the parent if it is a draft commits (a common scenario).
Although this extension shares its name and some functionality with
the third party hgshelve extension, it has little else in common.
Notably, the hgshelve extension shelves changes as unified diffs,
which makes conflict resolution a matter of finding .rej files and
conflict markers, and cleaning up the mess by hand.
We do not yet allow hunk-level choosing of changes to record.
Compared to the hgshelve extension, this is a small regression in
usability, but we hope to integrate that at a later point, once the
record machinery becomes more reusable and robust.
2013-08-29 20:22:13 +04:00
|
|
|
else:
|
2014-02-10 03:53:27 +04:00
|
|
|
desc = '(changes in empty repository)'
|
shelve: add a shelve extension to save/restore working changes
This extension saves shelved changes using a temporary draft commit,
and bundles the temporary commit and its draft ancestors, then
strips them.
This strategy makes it possible to use Mercurial's bundle and merge
machinery to resolve conflicts if necessary when unshelving, even
when the destination commit or its ancestors have been amended,
squashed, or evolved. (Once a change has been unshelved, its
associated unbundled commits are either rolled back or stripped.)
Storing the shelved change as a bundle also avoids the difficulty
that hidden commits would cause, of making it impossible to amend
the parent if it is a draft commits (a common scenario).
Although this extension shares its name and some functionality with
the third party hgshelve extension, it has little else in common.
Notably, the hgshelve extension shelves changes as unified diffs,
which makes conflict resolution a matter of finding .rej files and
conflict markers, and cleaning up the mess by hand.
We do not yet allow hunk-level choosing of changes to record.
Compared to the hgshelve extension, this is a small regression in
usability, but we hope to integrate that at a later point, once the
record machinery becomes more reusable and robust.
2013-08-29 20:22:13 +04:00
|
|
|
|
|
|
|
if not opts['message']:
|
|
|
|
opts['message'] = desc
|
|
|
|
|
|
|
|
name = opts['name']
|
|
|
|
|
2013-10-03 21:41:25 +04:00
|
|
|
wlock = lock = tr = bms = None
|
shelve: add a shelve extension to save/restore working changes
This extension saves shelved changes using a temporary draft commit,
and bundles the temporary commit and its draft ancestors, then
strips them.
This strategy makes it possible to use Mercurial's bundle and merge
machinery to resolve conflicts if necessary when unshelving, even
when the destination commit or its ancestors have been amended,
squashed, or evolved. (Once a change has been unshelved, its
associated unbundled commits are either rolled back or stripped.)
Storing the shelved change as a bundle also avoids the difficulty
that hidden commits would cause, of making it impossible to amend
the parent if it is a draft commits (a common scenario).
Although this extension shares its name and some functionality with
the third party hgshelve extension, it has little else in common.
Notably, the hgshelve extension shelves changes as unified diffs,
which makes conflict resolution a matter of finding .rej files and
conflict markers, and cleaning up the mess by hand.
We do not yet allow hunk-level choosing of changes to record.
Compared to the hgshelve extension, this is a small regression in
usability, but we hope to integrate that at a later point, once the
record machinery becomes more reusable and robust.
2013-08-29 20:22:13 +04:00
|
|
|
try:
|
|
|
|
wlock = repo.wlock()
|
|
|
|
lock = repo.lock()
|
|
|
|
|
2013-10-03 21:41:25 +04:00
|
|
|
bms = repo._bookmarks.copy()
|
2013-10-23 21:49:56 +04:00
|
|
|
# use an uncommitted transaction to generate the bundle to avoid
|
shelve: add a shelve extension to save/restore working changes
This extension saves shelved changes using a temporary draft commit,
and bundles the temporary commit and its draft ancestors, then
strips them.
This strategy makes it possible to use Mercurial's bundle and merge
machinery to resolve conflicts if necessary when unshelving, even
when the destination commit or its ancestors have been amended,
squashed, or evolved. (Once a change has been unshelved, its
associated unbundled commits are either rolled back or stripped.)
Storing the shelved change as a bundle also avoids the difficulty
that hidden commits would cause, of making it impossible to amend
the parent if it is a draft commits (a common scenario).
Although this extension shares its name and some functionality with
the third party hgshelve extension, it has little else in common.
Notably, the hgshelve extension shelves changes as unified diffs,
which makes conflict resolution a matter of finding .rej files and
conflict markers, and cleaning up the mess by hand.
We do not yet allow hunk-level choosing of changes to record.
Compared to the hgshelve extension, this is a small regression in
usability, but we hope to integrate that at a later point, once the
record machinery becomes more reusable and robust.
2013-08-29 20:22:13 +04:00
|
|
|
# pull races. ensure we don't print the abort message to stderr.
|
|
|
|
tr = repo.transaction('commit', report=lambda x: None)
|
|
|
|
|
|
|
|
if name:
|
|
|
|
if shelvedfile(repo, name, 'hg').exists():
|
|
|
|
raise util.Abort(_("a shelved change named '%s' already exists")
|
|
|
|
% name)
|
|
|
|
else:
|
|
|
|
for n in gennames():
|
|
|
|
if not shelvedfile(repo, n, 'hg').exists():
|
|
|
|
name = n
|
|
|
|
break
|
|
|
|
else:
|
|
|
|
raise util.Abort(_("too many shelved changes named '%s'") %
|
|
|
|
label)
|
|
|
|
|
|
|
|
# ensure we are not creating a subdirectory or a hidden file
|
|
|
|
if '/' in name or '\\' in name:
|
|
|
|
raise util.Abort(_('shelved change names may not contain slashes'))
|
|
|
|
if name.startswith('.'):
|
|
|
|
raise util.Abort(_("shelved change names may not start with '.'"))
|
|
|
|
|
|
|
|
node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
|
|
|
|
|
|
|
|
if not node:
|
|
|
|
stat = repo.status(match=scmutil.match(repo[None], pats, opts))
|
|
|
|
if stat[3]:
|
|
|
|
ui.status(_("nothing changed (%d missing files, see "
|
|
|
|
"'hg status')\n") % len(stat[3]))
|
|
|
|
else:
|
|
|
|
ui.status(_("nothing changed\n"))
|
|
|
|
return 1
|
|
|
|
|
|
|
|
phases.retractboundary(repo, phases.secret, [node])
|
|
|
|
|
|
|
|
fp = shelvedfile(repo, name, 'files').opener('wb')
|
|
|
|
fp.write('\0'.join(shelvedfiles))
|
|
|
|
|
|
|
|
bases = list(publicancestors(repo[node]))
|
2014-04-02 01:25:03 +04:00
|
|
|
cg = changegroup.changegroupsubset(repo, bases, [node], 'shelve')
|
2014-03-08 20:03:28 +04:00
|
|
|
shelvedfile(repo, name, 'hg').writebundle(cg)
|
shelve: add a shelve extension to save/restore working changes
This extension saves shelved changes using a temporary draft commit,
and bundles the temporary commit and its draft ancestors, then
strips them.
This strategy makes it possible to use Mercurial's bundle and merge
machinery to resolve conflicts if necessary when unshelving, even
when the destination commit or its ancestors have been amended,
squashed, or evolved. (Once a change has been unshelved, its
associated unbundled commits are either rolled back or stripped.)
Storing the shelved change as a bundle also avoids the difficulty
that hidden commits would cause, of making it impossible to amend
the parent if it is a draft commits (a common scenario).
Although this extension shares its name and some functionality with
the third party hgshelve extension, it has little else in common.
Notably, the hgshelve extension shelves changes as unified diffs,
which makes conflict resolution a matter of finding .rej files and
conflict markers, and cleaning up the mess by hand.
We do not yet allow hunk-level choosing of changes to record.
Compared to the hgshelve extension, this is a small regression in
usability, but we hope to integrate that at a later point, once the
record machinery becomes more reusable and robust.
2013-08-29 20:22:13 +04:00
|
|
|
cmdutil.export(repo, [node],
|
|
|
|
fp=shelvedfile(repo, name, 'patch').opener('wb'),
|
|
|
|
opts=mdiff.diffopts(git=True))
|
|
|
|
|
2013-10-03 21:41:25 +04:00
|
|
|
|
shelve: add a shelve extension to save/restore working changes
This extension saves shelved changes using a temporary draft commit,
and bundles the temporary commit and its draft ancestors, then
strips them.
This strategy makes it possible to use Mercurial's bundle and merge
machinery to resolve conflicts if necessary when unshelving, even
when the destination commit or its ancestors have been amended,
squashed, or evolved. (Once a change has been unshelved, its
associated unbundled commits are either rolled back or stripped.)
Storing the shelved change as a bundle also avoids the difficulty
that hidden commits would cause, of making it impossible to amend
the parent if it is a draft commits (a common scenario).
Although this extension shares its name and some functionality with
the third party hgshelve extension, it has little else in common.
Notably, the hgshelve extension shelves changes as unified diffs,
which makes conflict resolution a matter of finding .rej files and
conflict markers, and cleaning up the mess by hand.
We do not yet allow hunk-level choosing of changes to record.
Compared to the hgshelve extension, this is a small regression in
usability, but we hope to integrate that at a later point, once the
record machinery becomes more reusable and robust.
2013-08-29 20:22:13 +04:00
|
|
|
if ui.formatted():
|
|
|
|
desc = util.ellipsis(desc, ui.termwidth())
|
|
|
|
ui.status(_('shelved as %s\n') % name)
|
|
|
|
hg.update(repo, parent.node())
|
|
|
|
finally:
|
2013-10-03 21:41:25 +04:00
|
|
|
if bms:
|
|
|
|
# restore old bookmarks
|
|
|
|
repo._bookmarks.update(bms)
|
|
|
|
repo._bookmarks.write()
|
shelve: add a shelve extension to save/restore working changes
This extension saves shelved changes using a temporary draft commit,
and bundles the temporary commit and its draft ancestors, then
strips them.
This strategy makes it possible to use Mercurial's bundle and merge
machinery to resolve conflicts if necessary when unshelving, even
when the destination commit or its ancestors have been amended,
squashed, or evolved. (Once a change has been unshelved, its
associated unbundled commits are either rolled back or stripped.)
Storing the shelved change as a bundle also avoids the difficulty
that hidden commits would cause, of making it impossible to amend
the parent if it is a draft commits (a common scenario).
Although this extension shares its name and some functionality with
the third party hgshelve extension, it has little else in common.
Notably, the hgshelve extension shelves changes as unified diffs,
which makes conflict resolution a matter of finding .rej files and
conflict markers, and cleaning up the mess by hand.
We do not yet allow hunk-level choosing of changes to record.
Compared to the hgshelve extension, this is a small regression in
usability, but we hope to integrate that at a later point, once the
record machinery becomes more reusable and robust.
2013-08-29 20:22:13 +04:00
|
|
|
if tr:
|
|
|
|
tr.abort()
|
|
|
|
lockmod.release(lock, wlock)
|
|
|
|
|
|
|
|
def cleanupcmd(ui, repo):
|
2013-10-16 18:36:58 +04:00
|
|
|
"""subcommand that deletes all shelves"""
|
2013-10-14 20:29:56 +04:00
|
|
|
|
shelve: add a shelve extension to save/restore working changes
This extension saves shelved changes using a temporary draft commit,
and bundles the temporary commit and its draft ancestors, then
strips them.
This strategy makes it possible to use Mercurial's bundle and merge
machinery to resolve conflicts if necessary when unshelving, even
when the destination commit or its ancestors have been amended,
squashed, or evolved. (Once a change has been unshelved, its
associated unbundled commits are either rolled back or stripped.)
Storing the shelved change as a bundle also avoids the difficulty
that hidden commits would cause, of making it impossible to amend
the parent if it is a draft commits (a common scenario).
Although this extension shares its name and some functionality with
the third party hgshelve extension, it has little else in common.
Notably, the hgshelve extension shelves changes as unified diffs,
which makes conflict resolution a matter of finding .rej files and
conflict markers, and cleaning up the mess by hand.
We do not yet allow hunk-level choosing of changes to record.
Compared to the hgshelve extension, this is a small regression in
usability, but we hope to integrate that at a later point, once the
record machinery becomes more reusable and robust.
2013-08-29 20:22:13 +04:00
|
|
|
wlock = None
|
|
|
|
try:
|
|
|
|
wlock = repo.wlock()
|
|
|
|
for (name, _) in repo.vfs.readdir('shelved'):
|
|
|
|
suffix = name.rsplit('.', 1)[-1]
|
|
|
|
if suffix in ('hg', 'files', 'patch'):
|
|
|
|
shelvedfile(repo, name).unlink()
|
|
|
|
finally:
|
|
|
|
lockmod.release(wlock)
|
|
|
|
|
|
|
|
def deletecmd(ui, repo, pats):
|
2013-10-16 18:36:58 +04:00
|
|
|
"""subcommand that deletes a specific shelve"""
|
shelve: add a shelve extension to save/restore working changes
This extension saves shelved changes using a temporary draft commit,
and bundles the temporary commit and its draft ancestors, then
strips them.
This strategy makes it possible to use Mercurial's bundle and merge
machinery to resolve conflicts if necessary when unshelving, even
when the destination commit or its ancestors have been amended,
squashed, or evolved. (Once a change has been unshelved, its
associated unbundled commits are either rolled back or stripped.)
Storing the shelved change as a bundle also avoids the difficulty
that hidden commits would cause, of making it impossible to amend
the parent if it is a draft commits (a common scenario).
Although this extension shares its name and some functionality with
the third party hgshelve extension, it has little else in common.
Notably, the hgshelve extension shelves changes as unified diffs,
which makes conflict resolution a matter of finding .rej files and
conflict markers, and cleaning up the mess by hand.
We do not yet allow hunk-level choosing of changes to record.
Compared to the hgshelve extension, this is a small regression in
usability, but we hope to integrate that at a later point, once the
record machinery becomes more reusable and robust.
2013-08-29 20:22:13 +04:00
|
|
|
if not pats:
|
|
|
|
raise util.Abort(_('no shelved changes specified!'))
|
|
|
|
wlock = None
|
|
|
|
try:
|
|
|
|
wlock = repo.wlock()
|
|
|
|
try:
|
|
|
|
for name in pats:
|
|
|
|
for suffix in 'hg files patch'.split():
|
|
|
|
shelvedfile(repo, name, suffix).unlink()
|
|
|
|
except OSError, err:
|
|
|
|
if err.errno != errno.ENOENT:
|
|
|
|
raise
|
|
|
|
raise util.Abort(_("shelved change '%s' not found") % name)
|
|
|
|
finally:
|
|
|
|
lockmod.release(wlock)
|
|
|
|
|
|
|
|
def listshelves(repo):
|
2013-10-16 18:36:58 +04:00
|
|
|
"""return all shelves in repo as list of (time, filename)"""
|
shelve: add a shelve extension to save/restore working changes
This extension saves shelved changes using a temporary draft commit,
and bundles the temporary commit and its draft ancestors, then
strips them.
This strategy makes it possible to use Mercurial's bundle and merge
machinery to resolve conflicts if necessary when unshelving, even
when the destination commit or its ancestors have been amended,
squashed, or evolved. (Once a change has been unshelved, its
associated unbundled commits are either rolled back or stripped.)
Storing the shelved change as a bundle also avoids the difficulty
that hidden commits would cause, of making it impossible to amend
the parent if it is a draft commits (a common scenario).
Although this extension shares its name and some functionality with
the third party hgshelve extension, it has little else in common.
Notably, the hgshelve extension shelves changes as unified diffs,
which makes conflict resolution a matter of finding .rej files and
conflict markers, and cleaning up the mess by hand.
We do not yet allow hunk-level choosing of changes to record.
Compared to the hgshelve extension, this is a small regression in
usability, but we hope to integrate that at a later point, once the
record machinery becomes more reusable and robust.
2013-08-29 20:22:13 +04:00
|
|
|
try:
|
|
|
|
names = repo.vfs.readdir('shelved')
|
|
|
|
except OSError, err:
|
|
|
|
if err.errno != errno.ENOENT:
|
|
|
|
raise
|
|
|
|
return []
|
|
|
|
info = []
|
|
|
|
for (name, _) in names:
|
|
|
|
pfx, sfx = name.rsplit('.', 1)
|
|
|
|
if not pfx or sfx != 'patch':
|
|
|
|
continue
|
|
|
|
st = shelvedfile(repo, name).stat()
|
|
|
|
info.append((st.st_mtime, shelvedfile(repo, pfx).filename()))
|
|
|
|
return sorted(info, reverse=True)
|
|
|
|
|
|
|
|
def listcmd(ui, repo, pats, opts):
|
2013-10-16 18:36:58 +04:00
|
|
|
"""subcommand that displays the list of shelves"""
|
shelve: add a shelve extension to save/restore working changes
This extension saves shelved changes using a temporary draft commit,
and bundles the temporary commit and its draft ancestors, then
strips them.
This strategy makes it possible to use Mercurial's bundle and merge
machinery to resolve conflicts if necessary when unshelving, even
when the destination commit or its ancestors have been amended,
squashed, or evolved. (Once a change has been unshelved, its
associated unbundled commits are either rolled back or stripped.)
Storing the shelved change as a bundle also avoids the difficulty
that hidden commits would cause, of making it impossible to amend
the parent if it is a draft commits (a common scenario).
Although this extension shares its name and some functionality with
the third party hgshelve extension, it has little else in common.
Notably, the hgshelve extension shelves changes as unified diffs,
which makes conflict resolution a matter of finding .rej files and
conflict markers, and cleaning up the mess by hand.
We do not yet allow hunk-level choosing of changes to record.
Compared to the hgshelve extension, this is a small regression in
usability, but we hope to integrate that at a later point, once the
record machinery becomes more reusable and robust.
2013-08-29 20:22:13 +04:00
|
|
|
pats = set(pats)
|
|
|
|
width = 80
|
|
|
|
if not ui.plain():
|
|
|
|
width = ui.termwidth()
|
|
|
|
namelabel = 'shelve.newest'
|
|
|
|
for mtime, name in listshelves(repo):
|
|
|
|
sname = util.split(name)[1]
|
|
|
|
if pats and sname not in pats:
|
|
|
|
continue
|
|
|
|
ui.write(sname, label=namelabel)
|
|
|
|
namelabel = 'shelve.name'
|
|
|
|
if ui.quiet:
|
|
|
|
ui.write('\n')
|
|
|
|
continue
|
|
|
|
ui.write(' ' * (16 - len(sname)))
|
|
|
|
used = 16
|
2013-10-01 14:20:31 +04:00
|
|
|
age = '(%s)' % templatefilters.age(util.makedate(mtime), abbrev=True)
|
shelve: add a shelve extension to save/restore working changes
This extension saves shelved changes using a temporary draft commit,
and bundles the temporary commit and its draft ancestors, then
strips them.
This strategy makes it possible to use Mercurial's bundle and merge
machinery to resolve conflicts if necessary when unshelving, even
when the destination commit or its ancestors have been amended,
squashed, or evolved. (Once a change has been unshelved, its
associated unbundled commits are either rolled back or stripped.)
Storing the shelved change as a bundle also avoids the difficulty
that hidden commits would cause, of making it impossible to amend
the parent if it is a draft commits (a common scenario).
Although this extension shares its name and some functionality with
the third party hgshelve extension, it has little else in common.
Notably, the hgshelve extension shelves changes as unified diffs,
which makes conflict resolution a matter of finding .rej files and
conflict markers, and cleaning up the mess by hand.
We do not yet allow hunk-level choosing of changes to record.
Compared to the hgshelve extension, this is a small regression in
usability, but we hope to integrate that at a later point, once the
record machinery becomes more reusable and robust.
2013-08-29 20:22:13 +04:00
|
|
|
ui.write(age, label='shelve.age')
|
2013-10-01 14:20:31 +04:00
|
|
|
ui.write(' ' * (12 - len(age)))
|
|
|
|
used += 12
|
shelve: add a shelve extension to save/restore working changes
This extension saves shelved changes using a temporary draft commit,
and bundles the temporary commit and its draft ancestors, then
strips them.
This strategy makes it possible to use Mercurial's bundle and merge
machinery to resolve conflicts if necessary when unshelving, even
when the destination commit or its ancestors have been amended,
squashed, or evolved. (Once a change has been unshelved, its
associated unbundled commits are either rolled back or stripped.)
Storing the shelved change as a bundle also avoids the difficulty
that hidden commits would cause, of making it impossible to amend
the parent if it is a draft commits (a common scenario).
Although this extension shares its name and some functionality with
the third party hgshelve extension, it has little else in common.
Notably, the hgshelve extension shelves changes as unified diffs,
which makes conflict resolution a matter of finding .rej files and
conflict markers, and cleaning up the mess by hand.
We do not yet allow hunk-level choosing of changes to record.
Compared to the hgshelve extension, this is a small regression in
usability, but we hope to integrate that at a later point, once the
record machinery becomes more reusable and robust.
2013-08-29 20:22:13 +04:00
|
|
|
fp = open(name + '.patch', 'rb')
|
|
|
|
try:
|
|
|
|
while True:
|
|
|
|
line = fp.readline()
|
|
|
|
if not line:
|
|
|
|
break
|
|
|
|
if not line.startswith('#'):
|
|
|
|
desc = line.rstrip()
|
|
|
|
if ui.formatted():
|
|
|
|
desc = util.ellipsis(desc, width - used)
|
|
|
|
ui.write(desc)
|
|
|
|
break
|
|
|
|
ui.write('\n')
|
|
|
|
if not (opts['patch'] or opts['stat']):
|
|
|
|
continue
|
|
|
|
difflines = fp.readlines()
|
|
|
|
if opts['patch']:
|
|
|
|
for chunk, label in patch.difflabel(iter, difflines):
|
|
|
|
ui.write(chunk, label=label)
|
|
|
|
if opts['stat']:
|
|
|
|
for chunk, label in patch.diffstatui(difflines, width=width,
|
|
|
|
git=True):
|
|
|
|
ui.write(chunk, label=label)
|
|
|
|
finally:
|
|
|
|
fp.close()
|
|
|
|
|
|
|
|
def checkparents(repo, state):
|
2013-10-14 20:29:56 +04:00
|
|
|
"""check parent while resuming an unshelve"""
|
shelve: add a shelve extension to save/restore working changes
This extension saves shelved changes using a temporary draft commit,
and bundles the temporary commit and its draft ancestors, then
strips them.
This strategy makes it possible to use Mercurial's bundle and merge
machinery to resolve conflicts if necessary when unshelving, even
when the destination commit or its ancestors have been amended,
squashed, or evolved. (Once a change has been unshelved, its
associated unbundled commits are either rolled back or stripped.)
Storing the shelved change as a bundle also avoids the difficulty
that hidden commits would cause, of making it impossible to amend
the parent if it is a draft commits (a common scenario).
Although this extension shares its name and some functionality with
the third party hgshelve extension, it has little else in common.
Notably, the hgshelve extension shelves changes as unified diffs,
which makes conflict resolution a matter of finding .rej files and
conflict markers, and cleaning up the mess by hand.
We do not yet allow hunk-level choosing of changes to record.
Compared to the hgshelve extension, this is a small regression in
usability, but we hope to integrate that at a later point, once the
record machinery becomes more reusable and robust.
2013-08-29 20:22:13 +04:00
|
|
|
if state.parents != repo.dirstate.parents():
|
|
|
|
raise util.Abort(_('working directory parents do not match unshelve '
|
|
|
|
'state'))
|
|
|
|
|
2013-10-22 07:41:05 +04:00
|
|
|
def pathtofiles(repo, files):
|
|
|
|
cwd = repo.getcwd()
|
|
|
|
return [repo.pathto(f, cwd) for f in files]
|
|
|
|
|
shelve: add a shelve extension to save/restore working changes
This extension saves shelved changes using a temporary draft commit,
and bundles the temporary commit and its draft ancestors, then
strips them.
This strategy makes it possible to use Mercurial's bundle and merge
machinery to resolve conflicts if necessary when unshelving, even
when the destination commit or its ancestors have been amended,
squashed, or evolved. (Once a change has been unshelved, its
associated unbundled commits are either rolled back or stripped.)
Storing the shelved change as a bundle also avoids the difficulty
that hidden commits would cause, of making it impossible to amend
the parent if it is a draft commits (a common scenario).
Although this extension shares its name and some functionality with
the third party hgshelve extension, it has little else in common.
Notably, the hgshelve extension shelves changes as unified diffs,
which makes conflict resolution a matter of finding .rej files and
conflict markers, and cleaning up the mess by hand.
We do not yet allow hunk-level choosing of changes to record.
Compared to the hgshelve extension, this is a small regression in
usability, but we hope to integrate that at a later point, once the
record machinery becomes more reusable and robust.
2013-08-29 20:22:13 +04:00
|
|
|
def unshelveabort(ui, repo, state, opts):
|
2013-10-14 20:29:56 +04:00
|
|
|
"""subcommand that abort an in-progress unshelve"""
|
shelve: add a shelve extension to save/restore working changes
This extension saves shelved changes using a temporary draft commit,
and bundles the temporary commit and its draft ancestors, then
strips them.
This strategy makes it possible to use Mercurial's bundle and merge
machinery to resolve conflicts if necessary when unshelving, even
when the destination commit or its ancestors have been amended,
squashed, or evolved. (Once a change has been unshelved, its
associated unbundled commits are either rolled back or stripped.)
Storing the shelved change as a bundle also avoids the difficulty
that hidden commits would cause, of making it impossible to amend
the parent if it is a draft commits (a common scenario).
Although this extension shares its name and some functionality with
the third party hgshelve extension, it has little else in common.
Notably, the hgshelve extension shelves changes as unified diffs,
which makes conflict resolution a matter of finding .rej files and
conflict markers, and cleaning up the mess by hand.
We do not yet allow hunk-level choosing of changes to record.
Compared to the hgshelve extension, this is a small regression in
usability, but we hope to integrate that at a later point, once the
record machinery becomes more reusable and robust.
2013-08-29 20:22:13 +04:00
|
|
|
wlock = repo.wlock()
|
|
|
|
lock = None
|
|
|
|
try:
|
|
|
|
checkparents(repo, state)
|
2013-10-24 00:12:48 +04:00
|
|
|
|
|
|
|
util.rename(repo.join('unshelverebasestate'),
|
|
|
|
repo.join('rebasestate'))
|
|
|
|
try:
|
|
|
|
rebase.rebase(ui, repo, **{
|
|
|
|
'abort' : True
|
|
|
|
})
|
|
|
|
except Exception:
|
|
|
|
util.rename(repo.join('rebasestate'),
|
|
|
|
repo.join('unshelverebasestate'))
|
|
|
|
raise
|
|
|
|
|
shelve: add a shelve extension to save/restore working changes
This extension saves shelved changes using a temporary draft commit,
and bundles the temporary commit and its draft ancestors, then
strips them.
This strategy makes it possible to use Mercurial's bundle and merge
machinery to resolve conflicts if necessary when unshelving, even
when the destination commit or its ancestors have been amended,
squashed, or evolved. (Once a change has been unshelved, its
associated unbundled commits are either rolled back or stripped.)
Storing the shelved change as a bundle also avoids the difficulty
that hidden commits would cause, of making it impossible to amend
the parent if it is a draft commits (a common scenario).
Although this extension shares its name and some functionality with
the third party hgshelve extension, it has little else in common.
Notably, the hgshelve extension shelves changes as unified diffs,
which makes conflict resolution a matter of finding .rej files and
conflict markers, and cleaning up the mess by hand.
We do not yet allow hunk-level choosing of changes to record.
Compared to the hgshelve extension, this is a small regression in
usability, but we hope to integrate that at a later point, once the
record machinery becomes more reusable and robust.
2013-08-29 20:22:13 +04:00
|
|
|
lock = repo.lock()
|
2013-10-24 00:12:48 +04:00
|
|
|
|
2013-11-27 04:23:05 +04:00
|
|
|
mergefiles(ui, repo, state.wctx, state.pendingctx)
|
2013-10-24 00:12:48 +04:00
|
|
|
|
shelve: add a shelve extension to save/restore working changes
This extension saves shelved changes using a temporary draft commit,
and bundles the temporary commit and its draft ancestors, then
strips them.
This strategy makes it possible to use Mercurial's bundle and merge
machinery to resolve conflicts if necessary when unshelving, even
when the destination commit or its ancestors have been amended,
squashed, or evolved. (Once a change has been unshelved, its
associated unbundled commits are either rolled back or stripped.)
Storing the shelved change as a bundle also avoids the difficulty
that hidden commits would cause, of making it impossible to amend
the parent if it is a draft commits (a common scenario).
Although this extension shares its name and some functionality with
the third party hgshelve extension, it has little else in common.
Notably, the hgshelve extension shelves changes as unified diffs,
which makes conflict resolution a matter of finding .rej files and
conflict markers, and cleaning up the mess by hand.
We do not yet allow hunk-level choosing of changes to record.
Compared to the hgshelve extension, this is a small regression in
usability, but we hope to integrate that at a later point, once the
record machinery becomes more reusable and robust.
2013-08-29 20:22:13 +04:00
|
|
|
repair.strip(ui, repo, state.stripnodes, backup='none', topic='shelve')
|
|
|
|
shelvedstate.clear(repo)
|
|
|
|
ui.warn(_("unshelve of '%s' aborted\n") % state.name)
|
|
|
|
finally:
|
|
|
|
lockmod.release(lock, wlock)
|
|
|
|
|
2013-11-27 04:23:05 +04:00
|
|
|
def mergefiles(ui, repo, wctx, shelvectx):
|
2013-10-24 00:12:48 +04:00
|
|
|
"""updates to wctx and merges the changes from shelvectx into the
|
2013-11-27 04:23:05 +04:00
|
|
|
dirstate."""
|
2013-10-24 00:12:48 +04:00
|
|
|
oldquiet = ui.quiet
|
|
|
|
try:
|
|
|
|
ui.quiet = True
|
|
|
|
hg.update(repo, wctx.node())
|
|
|
|
files = []
|
|
|
|
files.extend(shelvectx.files())
|
|
|
|
files.extend(shelvectx.parents()[0].files())
|
2013-11-27 04:23:05 +04:00
|
|
|
|
|
|
|
# revert will overwrite unknown files, so move them out of the way
|
|
|
|
m, a, r, d, u = repo.status(unknown=True)[:5]
|
|
|
|
for file in u:
|
|
|
|
if file in files:
|
|
|
|
util.rename(file, file + ".orig")
|
2013-10-24 00:12:48 +04:00
|
|
|
cmdutil.revert(ui, repo, shelvectx, repo.dirstate.parents(),
|
|
|
|
*pathtofiles(repo, files),
|
|
|
|
**{'no_backup': True})
|
|
|
|
finally:
|
|
|
|
ui.quiet = oldquiet
|
|
|
|
|
shelve: add a shelve extension to save/restore working changes
This extension saves shelved changes using a temporary draft commit,
and bundles the temporary commit and its draft ancestors, then
strips them.
This strategy makes it possible to use Mercurial's bundle and merge
machinery to resolve conflicts if necessary when unshelving, even
when the destination commit or its ancestors have been amended,
squashed, or evolved. (Once a change has been unshelved, its
associated unbundled commits are either rolled back or stripped.)
Storing the shelved change as a bundle also avoids the difficulty
that hidden commits would cause, of making it impossible to amend
the parent if it is a draft commits (a common scenario).
Although this extension shares its name and some functionality with
the third party hgshelve extension, it has little else in common.
Notably, the hgshelve extension shelves changes as unified diffs,
which makes conflict resolution a matter of finding .rej files and
conflict markers, and cleaning up the mess by hand.
We do not yet allow hunk-level choosing of changes to record.
Compared to the hgshelve extension, this is a small regression in
usability, but we hope to integrate that at a later point, once the
record machinery becomes more reusable and robust.
2013-08-29 20:22:13 +04:00
|
|
|
def unshelvecleanup(ui, repo, name, opts):
|
2013-10-16 18:36:58 +04:00
|
|
|
"""remove related files after an unshelve"""
|
shelve: add a shelve extension to save/restore working changes
This extension saves shelved changes using a temporary draft commit,
and bundles the temporary commit and its draft ancestors, then
strips them.
This strategy makes it possible to use Mercurial's bundle and merge
machinery to resolve conflicts if necessary when unshelving, even
when the destination commit or its ancestors have been amended,
squashed, or evolved. (Once a change has been unshelved, its
associated unbundled commits are either rolled back or stripped.)
Storing the shelved change as a bundle also avoids the difficulty
that hidden commits would cause, of making it impossible to amend
the parent if it is a draft commits (a common scenario).
Although this extension shares its name and some functionality with
the third party hgshelve extension, it has little else in common.
Notably, the hgshelve extension shelves changes as unified diffs,
which makes conflict resolution a matter of finding .rej files and
conflict markers, and cleaning up the mess by hand.
We do not yet allow hunk-level choosing of changes to record.
Compared to the hgshelve extension, this is a small regression in
usability, but we hope to integrate that at a later point, once the
record machinery becomes more reusable and robust.
2013-08-29 20:22:13 +04:00
|
|
|
if not opts['keep']:
|
|
|
|
for filetype in 'hg files patch'.split():
|
|
|
|
shelvedfile(repo, name, filetype).unlink()
|
|
|
|
|
|
|
|
def unshelvecontinue(ui, repo, state, opts):
|
2013-10-14 20:29:56 +04:00
|
|
|
"""subcommand to continue an in-progress unshelve"""
|
shelve: add a shelve extension to save/restore working changes
This extension saves shelved changes using a temporary draft commit,
and bundles the temporary commit and its draft ancestors, then
strips them.
This strategy makes it possible to use Mercurial's bundle and merge
machinery to resolve conflicts if necessary when unshelving, even
when the destination commit or its ancestors have been amended,
squashed, or evolved. (Once a change has been unshelved, its
associated unbundled commits are either rolled back or stripped.)
Storing the shelved change as a bundle also avoids the difficulty
that hidden commits would cause, of making it impossible to amend
the parent if it is a draft commits (a common scenario).
Although this extension shares its name and some functionality with
the third party hgshelve extension, it has little else in common.
Notably, the hgshelve extension shelves changes as unified diffs,
which makes conflict resolution a matter of finding .rej files and
conflict markers, and cleaning up the mess by hand.
We do not yet allow hunk-level choosing of changes to record.
Compared to the hgshelve extension, this is a small regression in
usability, but we hope to integrate that at a later point, once the
record machinery becomes more reusable and robust.
2013-08-29 20:22:13 +04:00
|
|
|
# We're finishing off a merge. First parent is our original
|
|
|
|
# parent, second is the temporary "fake" commit we're unshelving.
|
|
|
|
wlock = repo.wlock()
|
|
|
|
lock = None
|
|
|
|
try:
|
|
|
|
checkparents(repo, state)
|
|
|
|
ms = merge.mergestate(repo)
|
|
|
|
if [f for f in ms if ms[f] == 'u']:
|
|
|
|
raise util.Abort(
|
|
|
|
_("unresolved conflicts, can't continue"),
|
|
|
|
hint=_("see 'hg resolve', then 'hg unshelve --continue'"))
|
2013-10-24 00:12:48 +04:00
|
|
|
|
shelve: add a shelve extension to save/restore working changes
This extension saves shelved changes using a temporary draft commit,
and bundles the temporary commit and its draft ancestors, then
strips them.
This strategy makes it possible to use Mercurial's bundle and merge
machinery to resolve conflicts if necessary when unshelving, even
when the destination commit or its ancestors have been amended,
squashed, or evolved. (Once a change has been unshelved, its
associated unbundled commits are either rolled back or stripped.)
Storing the shelved change as a bundle also avoids the difficulty
that hidden commits would cause, of making it impossible to amend
the parent if it is a draft commits (a common scenario).
Although this extension shares its name and some functionality with
the third party hgshelve extension, it has little else in common.
Notably, the hgshelve extension shelves changes as unified diffs,
which makes conflict resolution a matter of finding .rej files and
conflict markers, and cleaning up the mess by hand.
We do not yet allow hunk-level choosing of changes to record.
Compared to the hgshelve extension, this is a small regression in
usability, but we hope to integrate that at a later point, once the
record machinery becomes more reusable and robust.
2013-08-29 20:22:13 +04:00
|
|
|
lock = repo.lock()
|
2013-10-24 00:12:48 +04:00
|
|
|
|
|
|
|
util.rename(repo.join('unshelverebasestate'),
|
|
|
|
repo.join('rebasestate'))
|
|
|
|
try:
|
|
|
|
rebase.rebase(ui, repo, **{
|
|
|
|
'continue' : True
|
|
|
|
})
|
|
|
|
except Exception:
|
|
|
|
util.rename(repo.join('rebasestate'),
|
|
|
|
repo.join('unshelverebasestate'))
|
|
|
|
raise
|
|
|
|
|
|
|
|
shelvectx = repo['tip']
|
|
|
|
if not shelvectx in state.pendingctx.children():
|
|
|
|
# rebase was a no-op, so it produced no child commit
|
|
|
|
shelvectx = state.pendingctx
|
|
|
|
|
2013-11-27 04:23:05 +04:00
|
|
|
mergefiles(ui, repo, state.wctx, shelvectx)
|
2013-10-24 00:12:48 +04:00
|
|
|
|
|
|
|
state.stripnodes.append(shelvectx.node())
|
shelve: add a shelve extension to save/restore working changes
This extension saves shelved changes using a temporary draft commit,
and bundles the temporary commit and its draft ancestors, then
strips them.
This strategy makes it possible to use Mercurial's bundle and merge
machinery to resolve conflicts if necessary when unshelving, even
when the destination commit or its ancestors have been amended,
squashed, or evolved. (Once a change has been unshelved, its
associated unbundled commits are either rolled back or stripped.)
Storing the shelved change as a bundle also avoids the difficulty
that hidden commits would cause, of making it impossible to amend
the parent if it is a draft commits (a common scenario).
Although this extension shares its name and some functionality with
the third party hgshelve extension, it has little else in common.
Notably, the hgshelve extension shelves changes as unified diffs,
which makes conflict resolution a matter of finding .rej files and
conflict markers, and cleaning up the mess by hand.
We do not yet allow hunk-level choosing of changes to record.
Compared to the hgshelve extension, this is a small regression in
usability, but we hope to integrate that at a later point, once the
record machinery becomes more reusable and robust.
2013-08-29 20:22:13 +04:00
|
|
|
repair.strip(ui, repo, state.stripnodes, backup='none', topic='shelve')
|
2013-10-24 00:12:48 +04:00
|
|
|
shelvedstate.clear(repo)
|
shelve: add a shelve extension to save/restore working changes
This extension saves shelved changes using a temporary draft commit,
and bundles the temporary commit and its draft ancestors, then
strips them.
This strategy makes it possible to use Mercurial's bundle and merge
machinery to resolve conflicts if necessary when unshelving, even
when the destination commit or its ancestors have been amended,
squashed, or evolved. (Once a change has been unshelved, its
associated unbundled commits are either rolled back or stripped.)
Storing the shelved change as a bundle also avoids the difficulty
that hidden commits would cause, of making it impossible to amend
the parent if it is a draft commits (a common scenario).
Although this extension shares its name and some functionality with
the third party hgshelve extension, it has little else in common.
Notably, the hgshelve extension shelves changes as unified diffs,
which makes conflict resolution a matter of finding .rej files and
conflict markers, and cleaning up the mess by hand.
We do not yet allow hunk-level choosing of changes to record.
Compared to the hgshelve extension, this is a small regression in
usability, but we hope to integrate that at a later point, once the
record machinery becomes more reusable and robust.
2013-08-29 20:22:13 +04:00
|
|
|
unshelvecleanup(ui, repo, state.name, opts)
|
|
|
|
ui.status(_("unshelve of '%s' complete\n") % state.name)
|
|
|
|
finally:
|
|
|
|
lockmod.release(lock, wlock)
|
|
|
|
|
|
|
|
@command('unshelve',
|
|
|
|
[('a', 'abort', None,
|
|
|
|
_('abort an incomplete unshelve operation')),
|
|
|
|
('c', 'continue', None,
|
|
|
|
_('continue an incomplete unshelve operation')),
|
|
|
|
('', 'keep', None,
|
2014-04-08 01:10:20 +04:00
|
|
|
_('keep shelve after unshelving')),
|
|
|
|
('', 'date', '',
|
|
|
|
_('set date for temporary commits (DEPRECATED)'), _('DATE'))],
|
shelve: add a shelve extension to save/restore working changes
This extension saves shelved changes using a temporary draft commit,
and bundles the temporary commit and its draft ancestors, then
strips them.
This strategy makes it possible to use Mercurial's bundle and merge
machinery to resolve conflicts if necessary when unshelving, even
when the destination commit or its ancestors have been amended,
squashed, or evolved. (Once a change has been unshelved, its
associated unbundled commits are either rolled back or stripped.)
Storing the shelved change as a bundle also avoids the difficulty
that hidden commits would cause, of making it impossible to amend
the parent if it is a draft commits (a common scenario).
Although this extension shares its name and some functionality with
the third party hgshelve extension, it has little else in common.
Notably, the hgshelve extension shelves changes as unified diffs,
which makes conflict resolution a matter of finding .rej files and
conflict markers, and cleaning up the mess by hand.
We do not yet allow hunk-level choosing of changes to record.
Compared to the hgshelve extension, this is a small regression in
usability, but we hope to integrate that at a later point, once the
record machinery becomes more reusable and robust.
2013-08-29 20:22:13 +04:00
|
|
|
_('hg unshelve [SHELVED]'))
|
|
|
|
def unshelve(ui, repo, *shelved, **opts):
|
|
|
|
"""restore a shelved change to the working directory
|
|
|
|
|
|
|
|
This command accepts an optional name of a shelved change to
|
|
|
|
restore. If none is given, the most recent shelved change is used.
|
|
|
|
|
|
|
|
If a shelved change is applied successfully, the bundle that
|
|
|
|
contains the shelved changes is deleted afterwards.
|
|
|
|
|
|
|
|
Since you can restore a shelved change on top of an arbitrary
|
|
|
|
commit, it is possible that unshelving will result in a conflict
|
|
|
|
between your changes and the commits you are unshelving onto. If
|
|
|
|
this occurs, you must resolve the conflict, then use
|
|
|
|
``--continue`` to complete the unshelve operation. (The bundle
|
|
|
|
will not be deleted until you successfully complete the unshelve.)
|
|
|
|
|
|
|
|
(Alternatively, you can use ``--abort`` to abandon an unshelve
|
|
|
|
that causes a conflict. This reverts the unshelved changes, and
|
|
|
|
does not delete the bundle.)
|
|
|
|
"""
|
|
|
|
abortf = opts['abort']
|
|
|
|
continuef = opts['continue']
|
|
|
|
if not abortf and not continuef:
|
|
|
|
cmdutil.checkunfinished(repo)
|
|
|
|
|
|
|
|
if abortf or continuef:
|
|
|
|
if abortf and continuef:
|
|
|
|
raise util.Abort(_('cannot use both abort and continue'))
|
|
|
|
if shelved:
|
|
|
|
raise util.Abort(_('cannot combine abort/continue with '
|
|
|
|
'naming a shelved change'))
|
|
|
|
|
|
|
|
try:
|
|
|
|
state = shelvedstate.load(repo)
|
|
|
|
except IOError, err:
|
|
|
|
if err.errno != errno.ENOENT:
|
|
|
|
raise
|
|
|
|
raise util.Abort(_('no unshelve operation underway'))
|
|
|
|
|
|
|
|
if abortf:
|
|
|
|
return unshelveabort(ui, repo, state, opts)
|
|
|
|
elif continuef:
|
|
|
|
return unshelvecontinue(ui, repo, state, opts)
|
|
|
|
elif len(shelved) > 1:
|
|
|
|
raise util.Abort(_('can only unshelve one change at a time'))
|
|
|
|
elif not shelved:
|
|
|
|
shelved = listshelves(repo)
|
|
|
|
if not shelved:
|
|
|
|
raise util.Abort(_('no shelved changes to apply!'))
|
|
|
|
basename = util.split(shelved[0][1])[1]
|
|
|
|
ui.status(_("unshelving change '%s'\n") % basename)
|
|
|
|
else:
|
|
|
|
basename = shelved[0]
|
|
|
|
|
2013-11-01 23:49:42 +04:00
|
|
|
if not shelvedfile(repo, basename, 'files').exists():
|
|
|
|
raise util.Abort(_("shelved change '%s' not found") % basename)
|
shelve: add a shelve extension to save/restore working changes
This extension saves shelved changes using a temporary draft commit,
and bundles the temporary commit and its draft ancestors, then
strips them.
This strategy makes it possible to use Mercurial's bundle and merge
machinery to resolve conflicts if necessary when unshelving, even
when the destination commit or its ancestors have been amended,
squashed, or evolved. (Once a change has been unshelved, its
associated unbundled commits are either rolled back or stripped.)
Storing the shelved change as a bundle also avoids the difficulty
that hidden commits would cause, of making it impossible to amend
the parent if it is a draft commits (a common scenario).
Although this extension shares its name and some functionality with
the third party hgshelve extension, it has little else in common.
Notably, the hgshelve extension shelves changes as unified diffs,
which makes conflict resolution a matter of finding .rej files and
conflict markers, and cleaning up the mess by hand.
We do not yet allow hunk-level choosing of changes to record.
Compared to the hgshelve extension, this is a small regression in
usability, but we hope to integrate that at a later point, once the
record machinery becomes more reusable and robust.
2013-08-29 20:22:13 +04:00
|
|
|
|
2014-02-10 03:54:12 +04:00
|
|
|
oldquiet = ui.quiet
|
shelve: add a shelve extension to save/restore working changes
This extension saves shelved changes using a temporary draft commit,
and bundles the temporary commit and its draft ancestors, then
strips them.
This strategy makes it possible to use Mercurial's bundle and merge
machinery to resolve conflicts if necessary when unshelving, even
when the destination commit or its ancestors have been amended,
squashed, or evolved. (Once a change has been unshelved, its
associated unbundled commits are either rolled back or stripped.)
Storing the shelved change as a bundle also avoids the difficulty
that hidden commits would cause, of making it impossible to amend
the parent if it is a draft commits (a common scenario).
Although this extension shares its name and some functionality with
the third party hgshelve extension, it has little else in common.
Notably, the hgshelve extension shelves changes as unified diffs,
which makes conflict resolution a matter of finding .rej files and
conflict markers, and cleaning up the mess by hand.
We do not yet allow hunk-level choosing of changes to record.
Compared to the hgshelve extension, this is a small regression in
usability, but we hope to integrate that at a later point, once the
record machinery becomes more reusable and robust.
2013-08-29 20:22:13 +04:00
|
|
|
wlock = lock = tr = None
|
|
|
|
try:
|
|
|
|
lock = repo.lock()
|
2013-10-24 00:12:48 +04:00
|
|
|
wlock = repo.wlock()
|
shelve: add a shelve extension to save/restore working changes
This extension saves shelved changes using a temporary draft commit,
and bundles the temporary commit and its draft ancestors, then
strips them.
This strategy makes it possible to use Mercurial's bundle and merge
machinery to resolve conflicts if necessary when unshelving, even
when the destination commit or its ancestors have been amended,
squashed, or evolved. (Once a change has been unshelved, its
associated unbundled commits are either rolled back or stripped.)
Storing the shelved change as a bundle also avoids the difficulty
that hidden commits would cause, of making it impossible to amend
the parent if it is a draft commits (a common scenario).
Although this extension shares its name and some functionality with
the third party hgshelve extension, it has little else in common.
Notably, the hgshelve extension shelves changes as unified diffs,
which makes conflict resolution a matter of finding .rej files and
conflict markers, and cleaning up the mess by hand.
We do not yet allow hunk-level choosing of changes to record.
Compared to the hgshelve extension, this is a small regression in
usability, but we hope to integrate that at a later point, once the
record machinery becomes more reusable and robust.
2013-08-29 20:22:13 +04:00
|
|
|
|
|
|
|
tr = repo.transaction('unshelve', report=lambda x: None)
|
|
|
|
oldtiprev = len(repo)
|
2013-10-24 00:12:48 +04:00
|
|
|
|
2014-04-08 01:10:20 +04:00
|
|
|
pctx = repo['.']
|
|
|
|
tmpwctx = pctx
|
2013-10-24 00:12:48 +04:00
|
|
|
# The goal is to have a commit structure like so:
|
2014-04-08 01:10:20 +04:00
|
|
|
# ...-> pctx -> tmpwctx -> shelvectx
|
2013-10-24 00:12:48 +04:00
|
|
|
# where tmpwctx is an optional commit with the user's pending changes
|
|
|
|
# and shelvectx is the unshelved changes. Then we merge it all down
|
2014-04-08 01:10:20 +04:00
|
|
|
# to the original pctx.
|
2013-10-24 00:12:48 +04:00
|
|
|
|
|
|
|
# Store pending changes in a commit
|
2013-11-27 04:23:05 +04:00
|
|
|
m, a, r, d = repo.status()[:4]
|
|
|
|
if m or a or r or d:
|
2014-02-10 03:54:27 +04:00
|
|
|
ui.status(_("temporarily committing pending changes "
|
|
|
|
"(restore with 'hg unshelve --abort')\n"))
|
2013-10-24 00:12:48 +04:00
|
|
|
def commitfunc(ui, repo, message, match, opts):
|
|
|
|
hasmq = util.safehasattr(repo, 'mq')
|
|
|
|
if hasmq:
|
|
|
|
saved, repo.mq.checkapplied = repo.mq.checkapplied, False
|
|
|
|
|
|
|
|
try:
|
|
|
|
return repo.commit(message, 'shelve@localhost',
|
|
|
|
opts.get('date'), match)
|
|
|
|
finally:
|
|
|
|
if hasmq:
|
|
|
|
repo.mq.checkapplied = saved
|
|
|
|
|
|
|
|
tempopts = {}
|
|
|
|
tempopts['message'] = "pending changes temporary commit"
|
2014-04-08 01:10:20 +04:00
|
|
|
tempopts['date'] = opts.get('date')
|
2014-02-10 03:54:12 +04:00
|
|
|
ui.quiet = True
|
|
|
|
node = cmdutil.commit(ui, repo, commitfunc, [], tempopts)
|
2013-10-24 00:12:48 +04:00
|
|
|
tmpwctx = repo[node]
|
|
|
|
|
2014-03-08 20:03:28 +04:00
|
|
|
ui.quiet = True
|
|
|
|
shelvedfile(repo, basename, 'hg').applybundle()
|
|
|
|
nodes = [ctx.node() for ctx in repo.set('%d:', oldtiprev)]
|
|
|
|
phases.retractboundary(repo, phases.secret, nodes)
|
shelve: add a shelve extension to save/restore working changes
This extension saves shelved changes using a temporary draft commit,
and bundles the temporary commit and its draft ancestors, then
strips them.
This strategy makes it possible to use Mercurial's bundle and merge
machinery to resolve conflicts if necessary when unshelving, even
when the destination commit or its ancestors have been amended,
squashed, or evolved. (Once a change has been unshelved, its
associated unbundled commits are either rolled back or stripped.)
Storing the shelved change as a bundle also avoids the difficulty
that hidden commits would cause, of making it impossible to amend
the parent if it is a draft commits (a common scenario).
Although this extension shares its name and some functionality with
the third party hgshelve extension, it has little else in common.
Notably, the hgshelve extension shelves changes as unified diffs,
which makes conflict resolution a matter of finding .rej files and
conflict markers, and cleaning up the mess by hand.
We do not yet allow hunk-level choosing of changes to record.
Compared to the hgshelve extension, this is a small regression in
usability, but we hope to integrate that at a later point, once the
record machinery becomes more reusable and robust.
2013-08-29 20:22:13 +04:00
|
|
|
|
2014-02-10 03:54:12 +04:00
|
|
|
ui.quiet = oldquiet
|
|
|
|
|
2013-10-24 00:12:48 +04:00
|
|
|
shelvectx = repo['tip']
|
|
|
|
|
|
|
|
# If the shelve is not immediately on top of the commit
|
|
|
|
# we'll be merging with, rebase it to be on top.
|
|
|
|
if tmpwctx.node() != shelvectx.parents()[0].node():
|
2014-02-10 03:54:27 +04:00
|
|
|
ui.status(_('rebasing shelved changes\n'))
|
2013-10-24 00:12:48 +04:00
|
|
|
try:
|
|
|
|
rebase.rebase(ui, repo, **{
|
|
|
|
'rev' : [shelvectx.rev()],
|
|
|
|
'dest' : str(tmpwctx.rev()),
|
|
|
|
'keep' : True,
|
|
|
|
})
|
|
|
|
except error.InterventionRequired:
|
|
|
|
tr.close()
|
|
|
|
|
|
|
|
stripnodes = [repo.changelog.node(rev)
|
|
|
|
for rev in xrange(oldtiprev, len(repo))]
|
2014-04-08 01:10:20 +04:00
|
|
|
shelvedstate.save(repo, basename, pctx, tmpwctx, stripnodes)
|
2013-10-24 00:12:48 +04:00
|
|
|
|
|
|
|
util.rename(repo.join('rebasestate'),
|
|
|
|
repo.join('unshelverebasestate'))
|
shelve: add a shelve extension to save/restore working changes
This extension saves shelved changes using a temporary draft commit,
and bundles the temporary commit and its draft ancestors, then
strips them.
This strategy makes it possible to use Mercurial's bundle and merge
machinery to resolve conflicts if necessary when unshelving, even
when the destination commit or its ancestors have been amended,
squashed, or evolved. (Once a change has been unshelved, its
associated unbundled commits are either rolled back or stripped.)
Storing the shelved change as a bundle also avoids the difficulty
that hidden commits would cause, of making it impossible to amend
the parent if it is a draft commits (a common scenario).
Although this extension shares its name and some functionality with
the third party hgshelve extension, it has little else in common.
Notably, the hgshelve extension shelves changes as unified diffs,
which makes conflict resolution a matter of finding .rej files and
conflict markers, and cleaning up the mess by hand.
We do not yet allow hunk-level choosing of changes to record.
Compared to the hgshelve extension, this is a small regression in
usability, but we hope to integrate that at a later point, once the
record machinery becomes more reusable and robust.
2013-08-29 20:22:13 +04:00
|
|
|
raise error.InterventionRequired(
|
|
|
|
_("unresolved conflicts (see 'hg resolve', then "
|
|
|
|
"'hg unshelve --continue')"))
|
|
|
|
|
2013-10-24 00:12:48 +04:00
|
|
|
# refresh ctx after rebase completes
|
|
|
|
shelvectx = repo['tip']
|
|
|
|
|
|
|
|
if not shelvectx in tmpwctx.children():
|
|
|
|
# rebase was a no-op, so it produced no child commit
|
|
|
|
shelvectx = tmpwctx
|
|
|
|
|
2014-04-08 01:10:20 +04:00
|
|
|
mergefiles(ui, repo, pctx, shelvectx)
|
2013-10-24 00:12:48 +04:00
|
|
|
shelvedstate.clear(repo)
|
|
|
|
|
|
|
|
# The transaction aborting will strip all the commits for us,
|
|
|
|
# but it doesn't update the inmemory structures, so addchangegroup
|
|
|
|
# hooks still fire and try to operate on the missing commits.
|
|
|
|
# Clean up manually to prevent this.
|
2013-11-08 08:36:26 +04:00
|
|
|
repo.unfiltered().changelog.strip(oldtiprev, tr)
|
shelve: add a shelve extension to save/restore working changes
This extension saves shelved changes using a temporary draft commit,
and bundles the temporary commit and its draft ancestors, then
strips them.
This strategy makes it possible to use Mercurial's bundle and merge
machinery to resolve conflicts if necessary when unshelving, even
when the destination commit or its ancestors have been amended,
squashed, or evolved. (Once a change has been unshelved, its
associated unbundled commits are either rolled back or stripped.)
Storing the shelved change as a bundle also avoids the difficulty
that hidden commits would cause, of making it impossible to amend
the parent if it is a draft commits (a common scenario).
Although this extension shares its name and some functionality with
the third party hgshelve extension, it has little else in common.
Notably, the hgshelve extension shelves changes as unified diffs,
which makes conflict resolution a matter of finding .rej files and
conflict markers, and cleaning up the mess by hand.
We do not yet allow hunk-level choosing of changes to record.
Compared to the hgshelve extension, this is a small regression in
usability, but we hope to integrate that at a later point, once the
record machinery becomes more reusable and robust.
2013-08-29 20:22:13 +04:00
|
|
|
|
|
|
|
unshelvecleanup(ui, repo, basename, opts)
|
|
|
|
finally:
|
2014-02-10 03:54:12 +04:00
|
|
|
ui.quiet = oldquiet
|
shelve: add a shelve extension to save/restore working changes
This extension saves shelved changes using a temporary draft commit,
and bundles the temporary commit and its draft ancestors, then
strips them.
This strategy makes it possible to use Mercurial's bundle and merge
machinery to resolve conflicts if necessary when unshelving, even
when the destination commit or its ancestors have been amended,
squashed, or evolved. (Once a change has been unshelved, its
associated unbundled commits are either rolled back or stripped.)
Storing the shelved change as a bundle also avoids the difficulty
that hidden commits would cause, of making it impossible to amend
the parent if it is a draft commits (a common scenario).
Although this extension shares its name and some functionality with
the third party hgshelve extension, it has little else in common.
Notably, the hgshelve extension shelves changes as unified diffs,
which makes conflict resolution a matter of finding .rej files and
conflict markers, and cleaning up the mess by hand.
We do not yet allow hunk-level choosing of changes to record.
Compared to the hgshelve extension, this is a small regression in
usability, but we hope to integrate that at a later point, once the
record machinery becomes more reusable and robust.
2013-08-29 20:22:13 +04:00
|
|
|
if tr:
|
|
|
|
tr.release()
|
|
|
|
lockmod.release(lock, wlock)
|
|
|
|
|
|
|
|
@command('shelve',
|
|
|
|
[('A', 'addremove', None,
|
|
|
|
_('mark new/missing files as added/removed before shelving')),
|
|
|
|
('', 'cleanup', None,
|
|
|
|
_('delete all shelved changes')),
|
|
|
|
('', 'date', '',
|
|
|
|
_('shelve with the specified commit date'), _('DATE')),
|
|
|
|
('d', 'delete', None,
|
|
|
|
_('delete the named shelved change(s)')),
|
|
|
|
('l', 'list', None,
|
|
|
|
_('list current shelves')),
|
|
|
|
('m', 'message', '',
|
|
|
|
_('use text as shelve message'), _('TEXT')),
|
|
|
|
('n', 'name', '',
|
|
|
|
_('use the given name for the shelved commit'), _('NAME')),
|
|
|
|
('p', 'patch', None,
|
|
|
|
_('show patch')),
|
|
|
|
('', 'stat', None,
|
2014-02-10 03:53:25 +04:00
|
|
|
_('output diffstat-style summary of changes'))] + commands.walkopts,
|
2014-02-10 03:53:27 +04:00
|
|
|
_('hg shelve [OPTION]... [FILE]...'))
|
shelve: add a shelve extension to save/restore working changes
This extension saves shelved changes using a temporary draft commit,
and bundles the temporary commit and its draft ancestors, then
strips them.
This strategy makes it possible to use Mercurial's bundle and merge
machinery to resolve conflicts if necessary when unshelving, even
when the destination commit or its ancestors have been amended,
squashed, or evolved. (Once a change has been unshelved, its
associated unbundled commits are either rolled back or stripped.)
Storing the shelved change as a bundle also avoids the difficulty
that hidden commits would cause, of making it impossible to amend
the parent if it is a draft commits (a common scenario).
Although this extension shares its name and some functionality with
the third party hgshelve extension, it has little else in common.
Notably, the hgshelve extension shelves changes as unified diffs,
which makes conflict resolution a matter of finding .rej files and
conflict markers, and cleaning up the mess by hand.
We do not yet allow hunk-level choosing of changes to record.
Compared to the hgshelve extension, this is a small regression in
usability, but we hope to integrate that at a later point, once the
record machinery becomes more reusable and robust.
2013-08-29 20:22:13 +04:00
|
|
|
def shelvecmd(ui, repo, *pats, **opts):
|
|
|
|
'''save and set aside changes from the working directory
|
|
|
|
|
|
|
|
Shelving takes files that "hg status" reports as not clean, saves
|
|
|
|
the modifications to a bundle (a shelved change), and reverts the
|
|
|
|
files so that their state in the working directory becomes clean.
|
|
|
|
|
|
|
|
To restore these changes to the working directory, using "hg
|
|
|
|
unshelve"; this will work even if you switch to a different
|
|
|
|
commit.
|
|
|
|
|
|
|
|
When no files are specified, "hg shelve" saves all not-clean
|
|
|
|
files. If specific files or directories are named, only changes to
|
|
|
|
those files are shelved.
|
|
|
|
|
|
|
|
Each shelved change has a name that makes it easier to find later.
|
|
|
|
The name of a shelved change defaults to being based on the active
|
|
|
|
bookmark, or if there is no active bookmark, the current named
|
|
|
|
branch. To specify a different name, use ``--name``.
|
|
|
|
|
|
|
|
To see a list of existing shelved changes, use the ``--list``
|
|
|
|
option. For each shelved change, this will print its name, age,
|
|
|
|
and description; use ``--patch`` or ``--stat`` for more details.
|
|
|
|
|
|
|
|
To delete specific shelved changes, use ``--delete``. To delete
|
|
|
|
all shelved changes, use ``--cleanup``.
|
|
|
|
'''
|
|
|
|
cmdutil.checkunfinished(repo)
|
|
|
|
|
|
|
|
def checkopt(opt, incompatible):
|
|
|
|
if opts[opt]:
|
|
|
|
for i in incompatible.split():
|
|
|
|
if opts[i]:
|
|
|
|
raise util.Abort(_("options '--%s' and '--%s' may not be "
|
|
|
|
"used together") % (opt, i))
|
|
|
|
return True
|
|
|
|
if checkopt('cleanup', 'addremove delete list message name patch stat'):
|
|
|
|
if pats:
|
|
|
|
raise util.Abort(_("cannot specify names when using '--cleanup'"))
|
|
|
|
return cleanupcmd(ui, repo)
|
|
|
|
elif checkopt('delete', 'addremove cleanup list message name patch stat'):
|
|
|
|
return deletecmd(ui, repo, pats)
|
|
|
|
elif checkopt('list', 'addremove cleanup delete message name'):
|
|
|
|
return listcmd(ui, repo, pats, opts)
|
|
|
|
else:
|
|
|
|
for i in ('patch', 'stat'):
|
|
|
|
if opts[i]:
|
|
|
|
raise util.Abort(_("option '--%s' may not be "
|
|
|
|
"used when shelving a change") % (i,))
|
|
|
|
return createcmd(ui, repo, pats, opts)
|
|
|
|
|
|
|
|
def extsetup(ui):
|
|
|
|
cmdutil.unfinishedstates.append(
|
2013-10-28 20:03:43 +04:00
|
|
|
[shelvedstate._filename, False, False,
|
|
|
|
_('unshelve already in progress'),
|
shelve: add a shelve extension to save/restore working changes
This extension saves shelved changes using a temporary draft commit,
and bundles the temporary commit and its draft ancestors, then
strips them.
This strategy makes it possible to use Mercurial's bundle and merge
machinery to resolve conflicts if necessary when unshelving, even
when the destination commit or its ancestors have been amended,
squashed, or evolved. (Once a change has been unshelved, its
associated unbundled commits are either rolled back or stripped.)
Storing the shelved change as a bundle also avoids the difficulty
that hidden commits would cause, of making it impossible to amend
the parent if it is a draft commits (a common scenario).
Although this extension shares its name and some functionality with
the third party hgshelve extension, it has little else in common.
Notably, the hgshelve extension shelves changes as unified diffs,
which makes conflict resolution a matter of finding .rej files and
conflict markers, and cleaning up the mess by hand.
We do not yet allow hunk-level choosing of changes to record.
Compared to the hgshelve extension, this is a small regression in
usability, but we hope to integrate that at a later point, once the
record machinery becomes more reusable and robust.
2013-08-29 20:22:13 +04:00
|
|
|
_("use 'hg unshelve --continue' or 'hg unshelve --abort'")])
|