hgext/uncommit.py
changeset 35183 9dadcb99cc17
parent 35182 867990238dc6
child 35200 9e339c97fabb
equal deleted inserted replaced
35182:867990238dc6 35183:9dadcb99cc17
    96     overrides = {('phases', 'new-commit'): commitphase}
    96     overrides = {('phases', 'new-commit'): commitphase}
    97     with repo.ui.configoverride(overrides, 'uncommit'):
    97     with repo.ui.configoverride(overrides, 'uncommit'):
    98         newid = repo.commitctx(new)
    98         newid = repo.commitctx(new)
    99     return newid
    99     return newid
   100 
   100 
   101 def _uncommitdirstate(repo, oldctx, match):
   101 def _fixdirstate(repo, oldctx, newctx, status):
   102     """Fix the dirstate after switching the working directory from
   102     """ fix the dirstate after switching the working directory from oldctx to
   103     oldctx to a copy of oldctx not containing changed files matched by
   103     newctx which can be result of either unamend or uncommit.
   104     match.
   104     """
   105     """
       
   106     ctx = repo['.']
       
   107     ds = repo.dirstate
   105     ds = repo.dirstate
   108     copies = dict(ds.copies())
   106     copies = dict(ds.copies())
   109     s = repo.status(oldctx.p1(), oldctx, match=match)
   107     s = status
   110     for f in s.modified:
   108     for f in s.modified:
   111         if ds[f] == 'r':
   109         if ds[f] == 'r':
   112             # modified + removed -> removed
   110             # modified + removed -> removed
   113             continue
   111             continue
   114         ds.normallookup(f)
   112         ds.normallookup(f)
   136     oldcopies.update(copies)
   134     oldcopies.update(copies)
   137     copies = dict((dst, oldcopies.get(src, src))
   135     copies = dict((dst, oldcopies.get(src, src))
   138                   for dst, src in oldcopies.iteritems())
   136                   for dst, src in oldcopies.iteritems())
   139     # Adjust the dirstate copies
   137     # Adjust the dirstate copies
   140     for dst, src in copies.iteritems():
   138     for dst, src in copies.iteritems():
   141         if (src not in ctx or dst in ctx or ds[dst] != 'a'):
   139         if (src not in newctx or dst in newctx or ds[dst] != 'a'):
   142             src = None
   140             src = None
   143         ds.copy(src, dst)
   141         ds.copy(src, dst)
   144 
   142 
   145 @command('uncommit',
   143 @command('uncommit',
   146     [('', 'keep', False, _('allow an empty commit after uncommiting')),
   144     [('', 'keep', False, _('allow an empty commit after uncommiting')),
   192 
   190 
   193             scmutil.cleanupnodes(repo, mapping, 'uncommit')
   191             scmutil.cleanupnodes(repo, mapping, 'uncommit')
   194 
   192 
   195             with repo.dirstate.parentchange():
   193             with repo.dirstate.parentchange():
   196                 repo.dirstate.setparents(newid, node.nullid)
   194                 repo.dirstate.setparents(newid, node.nullid)
   197                 _uncommitdirstate(repo, old, match)
   195                 s = repo.status(old.p1(), old, match=match)
       
   196                 _fixdirstate(repo, old, repo[newid], s)
   198 
   197 
   199 def predecessormarkers(ctx):
   198 def predecessormarkers(ctx):
   200     """yields the obsolete markers marking the given changeset as a successor"""
   199     """yields the obsolete markers marking the given changeset as a successor"""
   201     for data in ctx.repo().obsstore.predecessors.get(ctx.node(), ()):
   200     for data in ctx.repo().obsstore.predecessors.get(ctx.node(), ()):
   202         yield obsutil.marker(ctx.repo(), data)
   201         yield obsutil.marker(ctx.repo(), data)
   203 
       
   204 def _unamenddirstate(repo, predctx, curctx):
       
   205     """"""
       
   206 
       
   207     s = repo.status(predctx, curctx)
       
   208     ds = repo.dirstate
       
   209     copies = dict(ds.copies())
       
   210     for f in s.modified:
       
   211         if ds[f] == 'r':
       
   212             # modified + removed -> removed
       
   213             continue
       
   214         ds.normallookup(f)
       
   215 
       
   216     for f in s.added:
       
   217         if ds[f] == 'r':
       
   218             # added + removed -> unknown
       
   219             ds.drop(f)
       
   220         elif ds[f] != 'a':
       
   221             ds.add(f)
       
   222 
       
   223     for f in s.removed:
       
   224         if ds[f] == 'a':
       
   225             # removed + added -> normal
       
   226             ds.normallookup(f)
       
   227         elif ds[f] != 'r':
       
   228             ds.remove(f)
       
   229 
       
   230     # Merge old parent and old working dir copies
       
   231     oldcopies = {}
       
   232     for f in (s.modified + s.added):
       
   233         src = curctx[f].renamed()
       
   234         if src:
       
   235             oldcopies[f] = src[0]
       
   236     oldcopies.update(copies)
       
   237     copies = dict((dst, oldcopies.get(src, src))
       
   238                   for dst, src in oldcopies.iteritems())
       
   239     # Adjust the dirstate copies
       
   240     for dst, src in copies.iteritems():
       
   241         if (src not in predctx or dst in predctx or ds[dst] != 'a'):
       
   242             src = None
       
   243         ds.copy(src, dst)
       
   244 
   202 
   245 @command('^unamend', [])
   203 @command('^unamend', [])
   246 def unamend(ui, repo, **opts):
   204 def unamend(ui, repo, **opts):
   247     """
   205     """
   248     undo the most recent amend operation on a current changeset
   206     undo the most recent amend operation on a current changeset
   310         diff = cm.diff(wm)
   268         diff = cm.diff(wm)
   311         changedfiles.extend(diff.iterkeys())
   269         changedfiles.extend(diff.iterkeys())
   312 
   270 
   313         with dirstate.parentchange():
   271         with dirstate.parentchange():
   314             dirstate.setparents(newprednode, node.nullid)
   272             dirstate.setparents(newprednode, node.nullid)
   315             _unamenddirstate(repo, newpredctx, curctx)
   273             s = repo.status(predctx, curctx)
       
   274             _fixdirstate(repo, curctx, newpredctx, s)
   316 
   275 
   317         mapping = {curctx.node(): (newprednode,)}
   276         mapping = {curctx.node(): (newprednode,)}
   318         scmutil.cleanupnodes(repo, mapping, 'unamend')
   277         scmutil.cleanupnodes(repo, mapping, 'unamend')