##// END OF EJS Templates
patchbomb: add option to send intro email for a single patch (issue1120)
patchbomb: add option to send intro email for a single patch (issue1120)

File last commit:

r7066:865c5be0 default
r7360:42f1b8cb default
Show More
merge.py
500 lines | 17.9 KiB | text/x-python | PythonLexer
Matt Mackall
Move merge code to its own module...
r2775 # merge.py - directory-level update/merge handling for Mercurial
#
Thomas Arendsen Hein
Updated copyright notices and add "and others" to "hg version"
r4635 # Copyright 2006, 2007 Matt Mackall <mpm@selenic.com>
Matt Mackall
Move merge code to its own module...
r2775 #
# This software may be used and distributed according to the terms
# of the GNU General Public License, incorporated herein by reference.
Matt Mackall
resolve: new command...
r6518 from node import nullid, nullrev, hex, bin
Matt Mackall
Simplify i18n imports
r3891 from i18n import _
Dirkjan Ochtman
python-2.6: use sha wrapper from util for new merge code
r6517 import errno, util, os, filemerge, copies, shutil
Matt Mackall
merge: introduce mergestate
r6512
class mergestate(object):
'''track 3-way merge state of individual files'''
def __init__(self, repo):
self._repo = repo
Matt Mackall
resolve: new command...
r6518 self._read()
def reset(self, node):
Matt Mackall
merge: introduce mergestate
r6512 self._state = {}
self._local = node
shutil.rmtree(self._repo.join("merge"), True)
Matt Mackall
resolve: new command...
r6518 def _read(self):
self._state = {}
try:
Patrick Mezard
merge: replace readline() call, missing from posixfile_nt
r6530 localnode = None
Matt Mackall
resolve: new command...
r6518 f = self._repo.opener("merge/state")
Patrick Mezard
merge: replace readline() call, missing from posixfile_nt
r6530 for i, l in enumerate(f):
if i == 0:
localnode = l[:-1]
else:
bits = l[:-1].split("\0")
self._state[bits[0]] = bits[1:]
self._local = bin(localnode)
Matt Mackall
resolve: new command...
r6518 except IOError, err:
if err.errno != errno.ENOENT:
raise
def _write(self):
f = self._repo.opener("merge/state", "w")
f.write(hex(self._local) + "\n")
for d, v in self._state.items():
f.write("\0".join([d] + v) + "\n")
Matt Mackall
merge: introduce mergestate
r6512 def add(self, fcl, fco, fca, fd, flags):
Dirkjan Ochtman
python-2.6: use sha wrapper from util for new merge code
r6517 hash = util.sha1(fcl.path()).hexdigest()
Matt Mackall
merge: introduce mergestate
r6512 self._repo.opener("merge/" + hash, "w").write(fcl.data())
Matt Mackall
resolve: new command...
r6518 self._state[fd] = ['u', hash, fcl.path(), fca.path(),
hex(fca.filenode()), fco.path(), flags]
self._write()
Matt Mackall
merge: introduce mergestate
r6512 def __contains__(self, dfile):
return dfile in self._state
def __getitem__(self, dfile):
Matt Mackall
resolve: new command...
r6518 return self._state[dfile][0]
def __iter__(self):
l = self._state.keys()
l.sort()
for f in l:
yield f
Matt Mackall
merge: introduce mergestate
r6512 def mark(self, dfile, state):
Matt Mackall
resolve: new command...
r6518 self._state[dfile][0] = state
self._write()
Matt Mackall
merge: introduce mergestate
r6512 def resolve(self, dfile, wctx, octx):
if self[dfile] == 'r':
return 0
Matt Mackall
resolve: new command...
r6518 state, hash, lfile, afile, anode, ofile, flags = self._state[dfile]
Matt Mackall
merge: introduce mergestate
r6512 f = self._repo.opener("merge/" + hash)
self._repo.wwrite(dfile, f.read(), flags)
fcd = wctx[dfile]
fco = octx[ofile]
fca = self._repo.filectx(afile, fileid=anode)
r = filemerge.filemerge(self._repo, self._local, lfile, fcd, fco, fca)
if not r:
self.mark(dfile, 'r')
return r
Matt Mackall
Move merge code to its own module...
r2775
Matt Mackall
merge: privatize some functions, unnest some others
r6269 def _checkunknown(wctx, mctx):
Matt Mackall
merge: update some docstrings
r3315 "check for collisions between unknown files and files in mctx"
Matt Mackall
merge: use new working context object in update
r3218 for f in wctx.unknown():
Matt Mackall
merge: simplify some helpers
r6272 if f in mctx and mctx[f].cmp(wctx[f].data()):
raise util.Abort(_("untracked file in working directory differs"
" from file in requested revision: '%s'") % f)
Matt Mackall
merge: pull manifest checks and updates into separate functions
r3107
Matt Mackall
merge: privatize some functions, unnest some others
r6269 def _checkcollision(mctx):
Matt Mackall
imported patch collision
r3785 "check for case folding collisions in the destination context"
folded = {}
Matt Mackall
merge: simplify some helpers
r6272 for fn in mctx:
Matt Mackall
imported patch collision
r3785 fold = fn.lower()
if fold in folded:
raise util.Abort(_("case-folding collision between %s and %s")
% (fn, folded[fold]))
folded[fold] = fn
Matt Mackall
merge: privatize some functions, unnest some others
r6269 def _forgetremoved(wctx, mctx, branchmerge):
Matt Mackall
merge: pull manifest checks and updates into separate functions
r3107 """
Forget removed files
If we're jumping between revisions (as opposed to merging), and if
neither the working directory nor the target rev has the file,
then we need to remove it from the dirstate, to prevent the
dirstate from listing the file when it is no longer in the
manifest.
Alexis S. L. Carvalho
merge: fix handling of deleted files
r6242
If we're merging, and the other revision has removed a file
that is not present in the working directory, we need to mark it
as removed.
Matt Mackall
merge: pull manifest checks and updates into separate functions
r3107 """
action = []
Alexis S. L. Carvalho
merge: fix handling of deleted files
r6242 state = branchmerge and 'r' or 'f'
for f in wctx.deleted():
Matt Mackall
merge: simplify some helpers
r6272 if f not in mctx:
Alexis S. L. Carvalho
merge: fix handling of deleted files
r6242 action.append((f, state))
if not branchmerge:
for f in wctx.removed():
Matt Mackall
merge: simplify some helpers
r6272 if f not in mctx:
Alexis S. L. Carvalho
merge: fix handling of deleted files
r6242 action.append((f, "f"))
Matt Mackall
merge: pull manifest checks and updates into separate functions
r3107
return action
Matt Mackall
merge: use contexts for manifestmerge...
r3295 def manifestmerge(repo, p1, p2, pa, overwrite, partial):
Matt Mackall
merge: pull manifest comparison out into separate function
r3105 """
Matt Mackall
merge: update some docstrings
r3315 Merge p1 and p2 with ancestor ma and generate merge action list
overwrite = whether we clobber working files
partial = function to filter file lists
Matt Mackall
merge: pull manifest comparison out into separate function
r3105 """
Matt Mackall
merge: various tidying...
r3314 repo.ui.note(_("resolving manifests\n"))
repo.ui.debug(_(" overwrite %s partial %s\n") % (overwrite, bool(partial)))
repo.ui.debug(_(" ancestor %s local %s remote %s\n") % (pa, p1, p2))
Matt Mackall
merge: use contexts for manifestmerge...
r3295 m1 = p1.manifest()
m2 = p2.manifest()
ma = pa.manifest()
backwards = (pa == p2)
Matt Mackall
merge: various tidying...
r3314 action = []
Matt Mackall
copies: move findcopies code to its own module...
r6274 copy, copied, diverge = {}, {}, {}
Matt Mackall
merge: use contexts for manifestmerge...
r3295
Matt Mackall
merge: add rename following...
r3249 def fmerge(f, f2=None, fa=None):
Matt Mackall
symlinks: minimal support for symlinks in merge/update...
r4007 """merge flags"""
Matt Mackall
merge: add rename following...
r3249 if not f2:
f2 = f
fa = f
Matt Mackall
merge: add flag merging intelligence...
r5708 a, m, n = ma.flags(fa), m1.flags(f), m2.flags(f2)
if m == n: # flags agree
return m # unchanged
if m and n: # flags are set but don't agree
if not a: # both differ from parent
r = repo.ui.prompt(
_(" conflicting flags for %s\n"
"(n)one, e(x)ec or sym(l)ink?") % f, "[nxl]", "n")
return r != "n" and r or ''
if m == a:
return n # changed from m to n
return m # changed from n to m
if m and m != a: # changed from a to m
return m
if n and n != a: # changed from a to n
return n
return '' # flag was cleared
Matt Mackall
merge: simplify exec flag handling
r3118
Matt Mackall
merge: swap file and mode args for act()
r3307 def act(msg, m, f, *args):
Matt Mackall
merge: use contexts for manifestmerge...
r3295 repo.ui.debug(" %s: %s -> %s\n" % (f, msg, m))
Matt Mackall
merge: simplify actions with helper function
r3121 action.append((f, m) + args)
Matt Mackall
diff: use copy smarts from copies.py
r6275 if pa and not (backwards or overwrite):
Matt Mackall
copies: skip directory rename checks when not merging...
r6425 if repo.ui.configbool("merge", "followcopies", True):
dirs = repo.ui.configbool("merge", "followdirs", True)
copy, diverge = copies.copies(repo, p1, p2, pa, dirs)
Matt Mackall
copies: move findcopies code to its own module...
r6274 copied = dict.fromkeys(copy.values())
for of, fl in diverge.items():
act("divergent renames", "dr", of, fl)
Matt Mackall
merge: use contexts for manifestmerge...
r3295
Matt Mackall
merge: pull manifest comparison out into separate function
r3105 # Compare manifests
for f, n in m1.iteritems():
Matt Mackall
merge: reduce manifest copying
r3248 if partial and not partial(f):
continue
Matt Mackall
merge: pull manifest comparison out into separate function
r3105 if f in m2:
Matt Mackall
merge: add flag merging intelligence...
r5708 if overwrite or backwards:
rflags = m2.flags(f)
else:
rflags = fmerge(f)
Matt Mackall
merge: pull manifest comparison out into separate function
r3105 # are files different?
if n != m2[f]:
a = ma.get(f, nullid)
Matt Mackall
merge: simplify merge tests, fix exec flag bug...
r5700 # are we clobbering?
if overwrite:
Matt Mackall
merge: add flag merging intelligence...
r5708 act("clobbering", "g", f, rflags)
Matt Mackall
merge: simplify merge tests, fix exec flag bug...
r5700 # or are we going back in time and clean?
Matt Mackall
merge: fix bug going backwards for already reverted files (issue1303)
r7066 elif backwards:
if not n[20:] or not p2[f].cmp(p1[f].data()):
act("reverting", "g", f, rflags)
Matt Mackall
merge: pull manifest comparison out into separate function
r3105 # are both different from the ancestor?
Matt Mackall
merge: simplify merge tests, fix exec flag bug...
r5700 elif n != a and m2[f] != a:
Matt Mackall
merge: add flag merging intelligence...
r5708 act("versions differ", "m", f, f, f, rflags, False)
Matt Mackall
merge: pull manifest comparison out into separate function
r3105 # is remote's version newer?
Matt Mackall
merge: simplify merge tests, fix exec flag bug...
r5700 elif m2[f] != a:
Matt Mackall
merge: add flag merging intelligence...
r5708 act("remote is newer", "g", f, rflags)
Matt Mackall
merge: eliminate confusing queued variable
r3113 # local is newer, not overwrite, check mode bits
Matt Mackall
merge: add flag merging intelligence...
r5708 elif m1.flags(f) != rflags:
act("update permissions", "e", f, rflags)
Matt Mackall
merge: eliminate confusing queued variable
r3113 # contents same, check mode bits
Matt Mackall
merge: add flag merging intelligence...
r5708 elif m1.flags(f) != rflags:
act("update permissions", "e", f, rflags)
Matt Mackall
merge: only store one direction of copies in the copy map...
r3730 elif f in copied:
continue
Matt Mackall
merge: add rename following...
r3249 elif f in copy:
f2 = copy[f]
Matt Mackall
merge: handle directory renames...
r3733 if f2 not in m2: # directory rename
act("remote renamed directory to " + f2, "d",
Matt Mackall
symlinks: minimal support for symlinks in merge/update...
r4007 f, None, f2, m1.flags(f))
Matt Mackall
merge: handle directory renames...
r3733 elif f2 in m1: # case 2 A,B/B/B
Matt Mackall
merge: only store one direction of copies in the copy map...
r3730 act("local copied to " + f2, "m",
f, f2, f, fmerge(f, f2, f2), False)
else: # case 4,21 A/B/B
act("local moved to " + f2, "m",
f, f2, f, fmerge(f, f2, f2), False)
Matt Mackall
merge: pull manifest comparison out into separate function
r3105 elif f in ma:
Matt Mackall
merge: simplify tests for local changed/remote deleted
r3117 if n != ma[f] and not overwrite:
Matt Mackall
merge: use contexts for manifestmerge...
r3295 if repo.ui.prompt(
Thomas Arendsen Hein
Fix misleading error and prompts during update/merge (issue556)
r5670 _(" local changed %s which remote deleted\n"
"use (c)hanged version or (d)elete?") % f,
_("[cd]"), _("c")) == _("d"):
Matt Mackall
merge: swap file and mode args for act()
r3307 act("prompt delete", "r", f)
Matt Mackall
merge: pull manifest comparison out into separate function
r3105 else:
Matt Mackall
merge: swap file and mode args for act()
r3307 act("other deleted", "r", f)
Matt Mackall
merge: pull manifest comparison out into separate function
r3105 else:
# file is created on branch or in working directory
Matt Mackall
merge: simplify local created logic
r3120 if (overwrite and n[20:] != "u") or (backwards and not n[20:]):
Matt Mackall
merge: swap file and mode args for act()
r3307 act("remote deleted", "r", f)
Matt Mackall
merge: pull manifest comparison out into separate function
r3105
for f, n in m2.iteritems():
Matt Mackall
merge: reduce manifest copying
r3248 if partial and not partial(f):
continue
if f in m1:
continue
Matt Mackall
merge: add copied hash to simplify copy logic
r3729 if f in copied:
continue
Matt Mackall
merge: add rename following...
r3249 if f in copy:
f2 = copy[f]
Matt Mackall
merge: handle directory renames...
r3733 if f2 not in m1: # directory rename
act("local renamed directory to " + f2, "d",
Matt Mackall
symlinks: minimal support for symlinks in merge/update...
r4007 None, f, f2, m2.flags(f))
Matt Mackall
merge: handle directory renames...
r3733 elif f2 in m2: # rename case 1, A/A,B/A
Matt Mackall
merge: only store one direction of copies in the copy map...
r3730 act("remote copied to " + f, "m",
f2, f, f, fmerge(f2, f, f2), False)
else: # case 3,20 A/B/A
act("remote moved to " + f, "m",
f2, f, f, fmerge(f2, f, f2), True)
Matt Mackall
merge: add rename following...
r3249 elif f in ma:
Matt Mackall
merge: more simplification of m2 manifest scanning
r3116 if overwrite or backwards:
Matt Mackall
symlinks: minimal support for symlinks in merge/update...
r4007 act("recreating", "g", f, m2.flags(f))
Matt Mackall
merge: more simplification of m2 manifest scanning
r3116 elif n != ma[f]:
Matt Mackall
merge: use contexts for manifestmerge...
r3295 if repo.ui.prompt(
Thomas Arendsen Hein
Fix misleading error and prompts during update/merge (issue556)
r5670 _("remote changed %s which local deleted\n"
"use (c)hanged version or leave (d)eleted?") % f,
_("[cd]"), _("c")) == _("c"):
Matt Mackall
symlinks: minimal support for symlinks in merge/update...
r4007 act("prompt recreating", "g", f, m2.flags(f))
Matt Mackall
merge: reorder tests on m2 items in manifestmerge
r3115 else:
Matt Mackall
symlinks: minimal support for symlinks in merge/update...
r4007 act("remote created", "g", f, m2.flags(f))
Matt Mackall
merge: pull manifest comparison out into separate function
r3105
return action
Paul Moore
Sort removes first when applying updates (fixes issues 750 and 912)...
r6805 def actioncmp(a1, a2):
m1 = a1[1]
m2 = a2[1]
if m1 == m2:
return cmp(a1, a2)
if m1 == 'r':
return -1
if m2 == 'r':
return 1
return cmp(a1, a2)
Matt Mackall
merge: pass contexts to applyupdates
r3297 def applyupdates(repo, action, wctx, mctx):
Matt Mackall
merge: update some docstrings
r3315 "apply the merge action list to the working directory"
Matt Mackall
merge: move apply and dirstate code into separate functions
r3111 updated, merged, removed, unresolved = 0, 0, 0, 0
Matt Mackall
merge: introduce mergestate
r6512 ms = mergestate(repo)
ms.reset(wctx.parents()[0].node())
moves = []
Paul Moore
Sort removes first when applying updates (fixes issues 750 and 912)...
r6805 action.sort(actioncmp)
Matt Mackall
merge: introduce mergestate
r6512
# prescan for merges
Matt Mackall
merge: do early copy to deal with issue636...
r5042 for a in action:
f, m = a[:2]
if m == 'm': # merge
f2, fd, flags, move = a[2:]
Matt Mackall
merge: introduce mergestate
r6512 repo.ui.debug(_("preserving %s for resolve of %s\n") % (f, fd))
fcl = wctx[f]
fco = mctx[f2]
fca = fcl.ancestor(fco) or repo.filectx(f, fileid=nullrev)
ms.add(fcl, fco, fca, fd, flags)
if f != fd and move:
moves.append(f)
# remove renamed files after safely stored
for f in moves:
if util.lexists(repo.wjoin(f)):
repo.ui.debug(_("removing %s\n") % f)
os.unlink(repo.wjoin(f))
Matt Mackall
merge: do early copy to deal with issue636...
r5042
Bryan O'Sullivan
Make audit_path more stringent....
r5158 audit_path = util.path_auditor(repo.root)
Matt Mackall
merge: move apply and dirstate code into separate functions
r3111 for a in action:
f, m = a[:2]
Matt Mackall
merge: handle directory renames...
r3733 if f and f[0] == "/":
Matt Mackall
merge: move apply and dirstate code into separate functions
r3111 continue
if m == "r": # remove
repo.ui.note(_("removing %s\n") % f)
Bryan O'Sullivan
Make audit_path more stringent....
r5158 audit_path(f)
Matt Mackall
merge: move apply and dirstate code into separate functions
r3111 try:
util.unlink(repo.wjoin(f))
except OSError, inst:
if inst.errno != errno.ENOENT:
repo.ui.warn(_("update failed to remove %s: %s!\n") %
(f, inst.strerror))
Thomas Arendsen Hein
white space and line break cleanups
r3673 removed += 1
Matt Mackall
merge: unify merge and copy actions
r3308 elif m == "m": # merge
Matt Mackall
symlinks: minimal support for symlinks in merge/update...
r4007 f2, fd, flags, move = a[2:]
Matt Mackall
merge: introduce mergestate
r6512 r = ms.resolve(fd, wctx, mctx)
Matt Mackall
merge: if filemerge skips merge, report as updated
r3400 if r > 0:
Matt Mackall
merge: add rename following...
r3249 unresolved += 1
Matt Mackall
merge: pull file copy/move out of filemerge
r3309 else:
Matt Mackall
merge: if filemerge skips merge, report as updated
r3400 if r is None:
updated += 1
else:
merged += 1
Matt Mackall
util: set_flags shouldn't know about repo flag formats
r6877 util.set_flags(repo.wjoin(fd), 'l' in flags, 'x' in flags)
Matt Mackall
merge: avoid double deletion mentioned in issue636
r5059 if f != fd and move and util.lexists(repo.wjoin(f)):
Matt Mackall
merge: do early copy to deal with issue636...
r5042 repo.ui.debug(_("removing %s\n") % f)
os.unlink(repo.wjoin(f))
Matt Mackall
merge: move apply and dirstate code into separate functions
r3111 elif m == "g": # get
Matt Mackall
symlinks: minimal support for symlinks in merge/update...
r4007 flags = a[2]
Matt Mackall
merge: move apply and dirstate code into separate functions
r3111 repo.ui.note(_("getting %s\n") % f)
Matt Mackall
merge: eliminate nodes from action list...
r3303 t = mctx.filectx(f).data()
Matt Mackall
symlinks: minimal support for symlinks in merge/update...
r4007 repo.wwrite(f, t, flags)
Matt Mackall
merge: move apply and dirstate code into separate functions
r3111 updated += 1
Matt Mackall
merge: handle directory renames...
r3733 elif m == "d": # directory rename
Matt Mackall
symlinks: minimal support for symlinks in merge/update...
r4007 f2, fd, flags = a[2:]
Matt Mackall
merge: handle directory renames...
r3733 if f:
repo.ui.note(_("moving %s to %s\n") % (f, fd))
t = wctx.filectx(f).data()
Matt Mackall
symlinks: minimal support for symlinks in merge/update...
r4007 repo.wwrite(fd, t, flags)
Matt Mackall
merge: handle directory renames...
r3733 util.unlink(repo.wjoin(f))
if f2:
repo.ui.note(_("getting %s to %s\n") % (f2, fd))
t = mctx.filectx(f2).data()
Matt Mackall
symlinks: minimal support for symlinks in merge/update...
r4007 repo.wwrite(fd, t, flags)
Matt Mackall
merge: handle directory renames...
r3733 updated += 1
Matt Mackall
merge: warn user about divergent renames
r4674 elif m == "dr": # divergent renames
fl = a[2]
Martin Geisler
i18n: mark strings for translation in Mercurial
r6953 repo.ui.warn(_("warning: detected divergent renames of %s to:\n") % f)
Matt Mackall
merge: warn user about divergent renames
r4674 for nf in fl:
repo.ui.warn(" %s\n" % nf)
Matt Mackall
merge: move apply and dirstate code into separate functions
r3111 elif m == "e": # exec
Matt Mackall
symlinks: minimal support for symlinks in merge/update...
r4007 flags = a[2]
Matt Mackall
util: set_flags shouldn't know about repo flag formats
r6877 util.set_flags(repo.wjoin(f), 'l' in flags, 'x' in flags)
Matt Mackall
merge: move apply and dirstate code into separate functions
r3111
return updated, merged, removed, unresolved
Matt Mackall
merge: update dirstate correctly for non-branchmerge updates...
r3372 def recordupdates(repo, action, branchmerge):
Matt Mackall
merge: update some docstrings
r3315 "record merge actions to the dirstate"
Matt Mackall
merge: move apply and dirstate code into separate functions
r3111 for a in action:
f, m = a[:2]
if m == "r": # remove
if branchmerge:
Matt Mackall
dirstate: break update into separate functions
r4904 repo.dirstate.remove(f)
Matt Mackall
merge: move apply and dirstate code into separate functions
r3111 else:
Matt Mackall
dirstate: break update into separate functions
r4904 repo.dirstate.forget(f)
Matt Mackall
merge: move apply and dirstate code into separate functions
r3111 elif m == "f": # forget
Matt Mackall
dirstate: break update into separate functions
r4904 repo.dirstate.forget(f)
Matt Mackall
merge: don't forget to update the dirstate for exec bit changes
r4997 elif m in "ge": # get or exec change
Matt Mackall
merge: move apply and dirstate code into separate functions
r3111 if branchmerge:
Matt Mackall
dirstate: break update into separate functions
r4904 repo.dirstate.normaldirty(f)
Matt Mackall
merge: move apply and dirstate code into separate functions
r3111 else:
Matt Mackall
dirstate: break update into separate functions
r4904 repo.dirstate.normal(f)
Matt Mackall
merge: move apply and dirstate code into separate functions
r3111 elif m == "m": # merge
Matt Mackall
merge: eliminate nodes from action list...
r3303 f2, fd, flag, move = a[2:]
Matt Mackall
merge: fixes for merge+rename...
r3251 if branchmerge:
# We've done a branch merge, mark this file as merged
# so that we properly record the merger later
Matt Mackall
dirstate: break update into separate functions
r4904 repo.dirstate.merge(fd)
Matt Mackall
merge: update dirstate correctly for non-branchmerge updates...
r3372 if f != f2: # copy/rename
if move:
Matt Mackall
dirstate: break update into separate functions
r4904 repo.dirstate.remove(f)
Matt Mackall
merge: update dirstate correctly for non-branchmerge updates...
r3372 if f != fd:
repo.dirstate.copy(f, fd)
else:
repo.dirstate.copy(f2, fd)
Matt Mackall
merge: fixes for merge+rename...
r3251 else:
# We've update-merged a locally modified file, so
# we set the dirstate to emulate a normal checkout
# of that file some time in the past. Thus our
# merge will appear as a normal local file
# modification.
Alexis S. L. Carvalho
merge: forcefully mark files that we get from the second parent as dirty...
r5210 repo.dirstate.normallookup(fd)
Matt Mackall
merge: unify merge and copy actions
r3308 if move:
Matt Mackall
dirstate: break update into separate functions
r4904 repo.dirstate.forget(f)
Matt Mackall
merge: handle directory renames...
r3733 elif m == "d": # directory rename
f2, fd, flag = a[2:]
Matt Mackall
merge: fix adding untracked files on directory rename (issue612)...
r4819 if not f2 and f not in repo.dirstate:
# untracked file moved
continue
Matt Mackall
merge: handle directory renames...
r3733 if branchmerge:
Matt Mackall
dirstate: break update into separate functions
r4904 repo.dirstate.add(fd)
Matt Mackall
merge: handle directory renames...
r3733 if f:
Matt Mackall
dirstate: break update into separate functions
r4904 repo.dirstate.remove(f)
Matt Mackall
merge: handle directory renames...
r3733 repo.dirstate.copy(f, fd)
if f2:
repo.dirstate.copy(f2, fd)
else:
Matt Mackall
dirstate: break update into separate functions
r4904 repo.dirstate.normal(fd)
Matt Mackall
merge: handle directory renames...
r3733 if f:
Matt Mackall
dirstate: break update into separate functions
r4904 repo.dirstate.forget(f)
Matt Mackall
merge: move apply and dirstate code into separate functions
r3111
Matt Mackall
Make repo locks recursive, eliminate all passing of lock/wlock
r4917 def update(repo, node, branchmerge, force, partial):
Matt Mackall
merge: update some docstrings
r3315 """
Perform a merge between the working directory and the given node
branchmerge = whether to merge between branches
force = whether to force branch merging or file overwriting
partial = a function to filter file lists (dirstate not updated)
"""
Matt Mackall
Merge: combine force and forcemerge arguments
r2815
Matt Mackall
Make repo locks recursive, eliminate all passing of lock/wlock
r4917 wlock = repo.wlock()
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 try:
Matt Mackall
use repo[changeid] to get a changectx
r6747 wc = repo[None]
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 if node is None:
# tip of current branch
try:
node = repo.branchtags()[wc.branch()]
except KeyError:
Matt Mackall
update: default to tipmost branch if default branch doesn't exist
r5570 if wc.branch() == "default": # no default branch!
node = repo.lookup("tip") # update to tip
else:
raise util.Abort(_("branch %s not found") % wc.branch())
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 overwrite = force and not branchmerge
pl = wc.parents()
Matt Mackall
use repo[changeid] to get a changectx
r6747 p1, p2 = pl[0], repo[node]
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 pa = p1.ancestor(p2)
fp1, fp2, xp1, xp2 = p1.node(), p2.node(), str(p1), str(p2)
fastforward = False
Matt Mackall
merge: various tidying...
r3314
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 ### check phase
if not overwrite and len(pl) > 1:
raise util.Abort(_("outstanding uncommitted merges"))
Matt Mackall
update: better logic and messages for updates...
r6375 if branchmerge:
if pa == p2:
raise util.Abort(_("can't merge with ancestor"))
elif pa == p1:
if p1.branch() != p2.branch():
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 fastforward = True
else:
Matt Mackall
update: better logic and messages for updates...
r6375 raise util.Abort(_("nothing to merge (use 'hg update'"
" or check 'hg heads')"))
if not force and (wc.files() or wc.deleted()):
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 raise util.Abort(_("outstanding uncommitted changes"))
Matt Mackall
update: better logic and messages for updates...
r6375 elif not overwrite:
if pa == p1 or pa == p2: # linear
pass # all good
elif p1.branch() == p2.branch():
if wc.files() or wc.deleted():
raise util.Abort(_("crosses branches (use 'hg merge' or "
"'hg update -C' to discard changes)"))
Thomas Arendsen Hein
Fix missing space in one of the new update messages.
r6381 raise util.Abort(_("crosses branches (use 'hg merge' "
Matt Mackall
update: better logic and messages for updates...
r6375 "or 'hg update -C')"))
elif wc.files() or wc.deleted():
raise util.Abort(_("crosses named branches (use "
"'hg update -C' to discard changes)"))
else:
# Allow jumping branches if there are no changes
overwrite = True
Matt Mackall
Merge: move most tests to the beginning
r2814
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 ### calculate phase
action = []
if not force:
Matt Mackall
merge: privatize some functions, unnest some others
r6269 _checkunknown(wc, p2)
Matt Mackall
rename checkfolding to checkcase
r6746 if not util.checkcase(repo.path):
Matt Mackall
merge: privatize some functions, unnest some others
r6269 _checkcollision(p2)
action += _forgetremoved(wc, p2, branchmerge)
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 action += manifestmerge(repo, wc, p2, pa, overwrite, partial)
Matt Mackall
Move merge code to its own module...
r2775
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 ### apply phase
if not branchmerge: # just jump to the new rev
fp1, fp2, xp1, xp2 = fp2, nullid, xp2, ''
if not partial:
repo.hook('preupdate', throw=True, parent1=xp1, parent2=xp2)
Matt Mackall
Move merge code to its own module...
r2775
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 stats = applyupdates(repo, action, wc, p2)
Matt Mackall
merge: consolidate dirstate updates
r2899
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 if not partial:
recordupdates(repo, action, branchmerge)
repo.dirstate.setparents(fp1, fp2)
if not branchmerge and not fastforward:
repo.dirstate.setbranch(p2.branch())
repo.hook('update', parent1=xp1, parent2=xp2, error=stats[3])
Matt Mackall
merge: various tidying...
r3314
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 return stats
finally:
del wlock