##// END OF EJS Templates
obsolete: order of magnitude speedup in _computebumpedset...
obsolete: order of magnitude speedup in _computebumpedset Reminder: a changeset is said "bumped" if it tries to obsolete a immutable changeset. The previous algorithm for computing bumped changeset was: 1) Get all public changesets 2) Find all they successors 3) Search for stuff that are eligible for being "bumped" (mutable and non obsolete) The entry size of this algorithm is `O(len(public))` which is mostly the same as `O(len(repo))`. Even this this approach mean fewer obsolescence marker are traveled, this is not very scalable. The new algorithm is: 1) For each potential bumped changesets (non obsolete mutable) 2) iterate over precursors 3) if a precursors is public. changeset is bumped We travel more obsolescence marker, but the entry size is much smaller since the amount of potential bumped should remains mostly stable with time `O(1)`. On some confidential gigantic repo this move bumped computation from 15.19s to 0.46s (×33 speedup…). On "smaller" repo (mercurial, cubicweb's review) no significant gain were seen. The additional traversal of obsolescence marker is probably probably counter balance the advantage of it. Other optimisation could be done in the future (eg: sharing precursors cache for divergence detection)

File last commit:

r19987:ba648607 stable
r20207:cd62532c default
Show More
merge.py
781 lines | 28.7 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 #
Martin Geisler
updated license to be explicit about GPL version 2
r8225 # This software may be used and distributed according to the terms of the
Matt Mackall
Update license to GPLv2+
r10263 # GNU General Public License version 2 or any later version.
Matt Mackall
Move merge code to its own module...
r2775
Matt Mackall
resolve: new command...
r6518 from node import nullid, nullrev, hex, bin
Matt Mackall
Simplify i18n imports
r3891 from i18n import _
Pierre-Yves David
update: allow dirty update to foreground (successors)...
r18985 from mercurial import obsolete
Siddharth Agarwal
manifestmerge: use dicthelpers.diff and join...
r18822 import error, util, filemerge, copies, subrepo, worker, dicthelpers
Simon Heimberg
separate import lines from mercurial and general python modules
r8312 import errno, os, 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
Peter Arrenbrecht
merge: delay writing the mergestate during until commit is called...
r12369 self._dirty = False
Matt Mackall
resolve: new command...
r6518 self._read()
Matt Mackall
resolve: move reset to localrepo.commit...
r7848 def reset(self, node=None):
Matt Mackall
merge: introduce mergestate
r6512 self._state = {}
Matt Mackall
resolve: move reset to localrepo.commit...
r7848 if node:
self._local = node
Matt Mackall
merge: introduce mergestate
r6512 shutil.rmtree(self._repo.join("merge"), True)
Peter Arrenbrecht
merge: delay writing the mergestate during until commit is called...
r12369 self._dirty = False
Matt Mackall
resolve: new command...
r6518 def _read(self):
self._state = {}
try:
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:
Martin Geisler
resolve: do not crash on empty mergestate...
r11451 self._local = bin(l[:-1])
Patrick Mezard
merge: replace readline() call, missing from posixfile_nt
r6530 else:
bits = l[:-1].split("\0")
self._state[bits[0]] = bits[1:]
Dan Villiom Podlaski Christiansen
explicitly close files...
r13400 f.close()
Matt Mackall
resolve: new command...
r6518 except IOError, err:
if err.errno != errno.ENOENT:
raise
Peter Arrenbrecht
merge: delay writing the mergestate during until commit is called...
r12369 self._dirty = False
def commit(self):
if self._dirty:
f = self._repo.opener("merge/state", "w")
f.write(hex(self._local) + "\n")
for d, v in self._state.iteritems():
f.write("\0".join([d] + v) + "\n")
Dan Villiom Podlaski Christiansen
explicitly close files...
r13400 f.close()
Peter Arrenbrecht
merge: delay writing the mergestate during until commit is called...
r12369 self._dirty = False
Mads Kiilerich
merge: merge file flags together with file content...
r18338 def add(self, fcl, fco, fca, fd):
Dirkjan Ochtman
python-2.6: use sha wrapper from util for new merge code
r6517 hash = util.sha1(fcl.path()).hexdigest()
Dan Villiom Podlaski Christiansen
prevent transient leaks of file handle by using new helper functions...
r14168 self._repo.opener.write("merge/" + hash, fcl.data())
Matt Mackall
resolve: new command...
r6518 self._state[fd] = ['u', hash, fcl.path(), fca.path(),
Mads Kiilerich
merge: merge file flags together with file content...
r18338 hex(fca.filenode()), fco.path(), fcl.flags()]
Peter Arrenbrecht
merge: delay writing the mergestate during until commit is called...
r12369 self._dirty = True
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
Bryan O'Sullivan
merge: add a files method to the mergestate class...
r19285 def files(self):
return self._state.keys()
Matt Mackall
merge: introduce mergestate
r6512 def mark(self, dfile, state):
Matt Mackall
resolve: new command...
r6518 self._state[dfile][0] = state
Peter Arrenbrecht
merge: delay writing the mergestate during until commit is called...
r12369 self._dirty = True
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]
Mads Kiilerich
merge: merge file flags together with file content...
r18338 fcd = wctx[dfile]
fco = octx[ofile]
fca = self._repo.filectx(afile, fileid=anode)
# "premerge" x flags
flo = fco.flags()
fla = fca.flags()
if 'x' in flags + flo + fla and 'l' not in flags + flo + fla:
if fca.node() == nullid:
self._repo.ui.warn(_('warning: cannot merge flags for %s\n') %
afile)
elif flags == fla:
flags = flo
# restore local
Matt Mackall
merge: introduce mergestate
r6512 f = self._repo.opener("merge/" + hash)
self._repo.wwrite(dfile, f.read(), flags)
Dan Villiom Podlaski Christiansen
explicitly close files...
r13400 f.close()
Matt Mackall
merge: introduce mergestate
r6512 r = filemerge.filemerge(self._repo, self._local, lfile, fcd, fco, fca)
Matt Mackall
merge: drop resolve state for mergers with identical contents (issue2680)
r13536 if r is None:
# no real conflict
del self._state[dfile]
elif not r:
Matt Mackall
merge: introduce mergestate
r6512 self.mark(dfile, 'r')
return r
Matt Mackall
Move merge code to its own module...
r2775
Matt Mackall
merge: refactor unknown file conflict checking...
r16093 def _checkunknownfile(repo, wctx, mctx, f):
return (not repo.dirstate._ignore(f)
Matt Mackall
merge: check for untracked files more precisely (issue3400)...
r16534 and os.path.isfile(repo.wjoin(f))
Siddharth Agarwal
manifestmerge: local unknown, remote created: don't traverse symlinks...
r19157 and repo.wopener.audit.check(f)
Matt Mackall
merge: fix unknown file merge detection for case-folding systems...
r16284 and repo.dirstate.normalize(f) not in repo.dirstate
Matt Mackall
merge: refactor unknown file conflict checking...
r16093 and mctx[f].cmp(wctx[f]))
def _checkunknown(repo, wctx, mctx):
Matt Mackall
merge: update some docstrings
r3315 "check for collisions between unknown files and files in mctx"
Jordi Gutiérrez Hermoso
merge: report all files in _checkunknown...
r15894
error = False
Matt Mackall
merge: refactor unknown file conflict checking...
r16093 for f in mctx:
if f not in wctx and _checkunknownfile(repo, wctx, mctx, f):
Jordi Gutiérrez Hermoso
merge: report all files in _checkunknown...
r15894 error = True
Matt Mackall
merge: refactor unknown file conflict checking...
r16093 wctx._repo.ui.warn(_("%s: untracked file differs\n") % f)
Jordi Gutiérrez Hermoso
merge: report all files in _checkunknown...
r15894 if error:
raise util.Abort(_("untracked files in working directory differ "
"from files in requested revision"))
Matt Mackall
merge: pull manifest checks and updates into separate functions
r3107
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 """
Mads Kiilerich
merge: rename list of actions from action to actions
r18330 actions = []
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:
Mads Kiilerich
merge: delay debug messages for merge actions...
r18541 actions.append((f, state, None, "forget deleted"))
Alexis S. L. Carvalho
merge: fix handling of deleted files
r6242
if not branchmerge:
for f in wctx.removed():
Matt Mackall
merge: simplify some helpers
r6272 if f not in mctx:
Mads Kiilerich
merge: delay debug messages for merge actions...
r18541 actions.append((f, "f", None, "forget removed"))
Matt Mackall
merge: pull manifest checks and updates into separate functions
r3107
Mads Kiilerich
merge: rename list of actions from action to actions
r18330 return actions
Matt Mackall
merge: pull manifest checks and updates into separate functions
r3107
FUJIWARA Katsunori
icasefs: rewrite case-folding collision detection (issue3452)...
r19105 def _checkcollision(repo, wmf, actions, prompts):
# build provisional merged manifest up
pmmf = set(wmf)
def addop(f, args):
pmmf.add(f)
def removeop(f, args):
pmmf.discard(f)
def nop(f, args):
pass
def renameop(f, args):
f2, fd, flags = args
if f:
pmmf.discard(f)
pmmf.add(fd)
def mergeop(f, args):
f2, fd, move = args
if move:
pmmf.discard(f)
pmmf.add(fd)
opmap = {
"a": addop,
"d": renameop,
"dr": nop,
"e": nop,
"f": addop, # untracked file should be kept in working directory
"g": addop,
"m": mergeop,
"r": removeop,
"rd": nop,
}
for f, m, args, msg in actions:
op = opmap.get(m)
assert op, m
op(f, args)
opmap = {
"cd": addop,
"dc": addop,
}
for f, m in prompts:
op = opmap.get(m)
assert op, m
op(f, None)
# check case-folding collision in provisional merged manifest
foldmap = {}
for f in sorted(pmmf):
fold = util.normcase(f)
if fold in foldmap:
raise util.Abort(_("case-folding collision between %s and %s")
% (f, foldmap[fold]))
foldmap[fold] = f
Durham Goode
rebase: fix --collapse when a file was added then removed...
r18778 def manifestmerge(repo, wctx, p2, pa, branchmerge, force, partial,
acceptremote=False):
Matt Mackall
merge: pull manifest comparison out into separate function
r3105 """
Alecs King
merge: fix typo in docstring
r11817 Merge p1 and p2 with ancestor pa and generate merge action list
Matt Mackall
merge: update some docstrings
r3315
Siddharth Agarwal
manifestmerge: pass in branchmerge and force separately...
r18605 branchmerge and force are as passed in to update
Matt Mackall
merge: update some docstrings
r3315 partial = function to filter file lists
Durham Goode
rebase: fix --collapse when a file was added then removed...
r18778 acceptremote = accept the incoming changes without prompting
Matt Mackall
merge: pull manifest comparison out into separate function
r3105 """
Siddharth Agarwal
manifestmerge: pass in branchmerge and force separately...
r18605 overwrite = force and not branchmerge
Mads Kiilerich
merge: rename list of actions from action to actions
r18330 actions, copy, movewithdir = [], {}, {}
Matt Mackall
merge: refactor manifestmerge init to better report effective ancestor
r8753
Siddharth Agarwal
manifestmerge: fix order in which manifests are fetched...
r18651 followcopies = False
Matt Mackall
merge: refactor some initialization, drop backwards var
r8749 if overwrite:
Bryan O'Sullivan
merge: rename p1 to wctx in manifestmerge...
r18611 pa = wctx
Matt Mackall
merge: refactor manifestmerge init to better report effective ancestor
r8753 elif pa == p2: # backwards
Bryan O'Sullivan
merge: rename p1 to wctx in manifestmerge...
r18611 pa = wctx.p1()
Bryan O'Sullivan
merge: don't call copies.mergecopies unless we need to...
r18612 elif not branchmerge and not wctx.dirty(missing=True):
pass
Matt Mackall
merge: refactor manifestmerge init to better report effective ancestor
r8753 elif pa and repo.ui.configbool("merge", "followcopies", True):
Siddharth Agarwal
manifestmerge: fix order in which manifests are fetched...
r18651 followcopies = True
# manifests fetched in order are going to be faster, so prime the caches
[x.manifest() for x in
sorted(wctx.parents() + [p2, pa], key=lambda x: x.rev())]
if followcopies:
Bryan O'Sullivan
merge: rename p1 to wctx in manifestmerge...
r18611 ret = copies.mergecopies(repo, wctx, p2, pa)
Siddharth Agarwal
copies: separate moves via directory renames from explicit copies...
r18134 copy, movewithdir, diverge, renamedelete = ret
Matt Mackall
merge: refactor manifestmerge init to better report effective ancestor
r8753 for of, fl in diverge.iteritems():
Mads Kiilerich
merge: inline act()...
r18544 actions.append((of, "dr", (fl,), "divergent renames"))
Thomas Arendsen Hein
merge: warn about file deleted in one branch and renamed in other (issue3074)...
r16794 for of, fl in renamedelete.iteritems():
Mads Kiilerich
merge: inline act()...
r18544 actions.append((of, "rd", (fl,), "rename and delete"))
Matt Mackall
merge: refactor manifestmerge init to better report effective ancestor
r8753
repo.ui.note(_("resolving manifests\n"))
Siddharth Agarwal
manifestmerge: pass in branchmerge and force separately...
r18605 repo.ui.debug(" branchmerge: %s, force: %s, partial: %s\n"
% (bool(branchmerge), bool(force), bool(partial)))
Bryan O'Sullivan
merge: rename p1 to wctx in manifestmerge...
r18611 repo.ui.debug(" ancestor: %s, local: %s, remote: %s\n" % (pa, wctx, p2))
Matt Mackall
merge: refactor manifestmerge init to better report effective ancestor
r8753
Bryan O'Sullivan
merge: rename p1 to wctx in manifestmerge...
r18611 m1, m2, ma = wctx.manifest(), p2.manifest(), pa.manifest()
Matt Mackall
merge: refactor manifestmerge init to better report effective ancestor
r8753 copied = set(copy.values())
Siddharth Agarwal
copies: separate moves via directory renames from explicit copies...
r18134 copied.update(movewithdir.values())
Matt Mackall
merge: use contexts for manifestmerge...
r3295
Matt Mackall
subrepo: correctly handle update -C with modified subrepos (issue2022)...
r11470 if '.hgsubstate' in m1:
Matt Mackall
submerge: properly deal with overwrites...
r9783 # check whether sub state is modified
Bryan O'Sullivan
merge: rename p1 to wctx in manifestmerge...
r18611 for s in sorted(wctx.substate):
if wctx.sub(s).dirty():
Matt Mackall
submerge: properly deal with overwrites...
r9783 m1['.hgsubstate'] += "+"
break
Siddharth Agarwal
manifestmerge: handle abort on local unknown, remote created files...
r18606 aborts, prompts = [], []
Matt Mackall
merge: pull manifest comparison out into separate function
r3105 # Compare manifests
Siddharth Agarwal
manifestmerge: use dicthelpers.diff and join...
r18822 fdiff = dicthelpers.diff(m1, m2)
flagsdiff = m1.flagsdiff(m2)
diff12 = dicthelpers.join(fdiff, flagsdiff)
for f, (n12, fl12) in diff12.iteritems():
if n12:
n1, n2 = n12
else: # file contents didn't change, but flags did
Siddharth Agarwal
manifestmerge: handle workdir removed, remote removed with flags...
r18895 n1 = n2 = m1.get(f, None)
if n1 is None:
# Since n1 == n2, the file isn't present in m2 either. This
# means that the file was removed or deleted locally and
# removed remotely, but that residual entries remain in flags.
# This can happen in manifests generated by workingctx.
continue
Siddharth Agarwal
manifestmerge: use dicthelpers.diff and join...
r18822 if fl12:
fl1, fl2 = fl12
else: # flags didn't change, file contents did
fl1 = fl2 = m1.flags(f)
Matt Mackall
merge: reduce manifest copying
r3248 if partial and not partial(f):
continue
Siddharth Agarwal
manifestmerge: use dicthelpers.diff and join...
r18822 if n1 and n2:
fla = ma.flags(f)
Mads Kiilerich
merge: merge file flags together with file content...
r18338 nol = 'l' not in fl1 + fl2 + fla
Matt Mackall
merge: simplify file revision comparison logic
r8752 a = ma.get(f, nullid)
Siddharth Agarwal
manifestmerge: use dicthelpers.diff and join...
r18822 if n2 == a and fl2 == fla:
Mads Kiilerich
merge: merge file flags together with file content...
r18338 pass # remote unchanged - keep local
Siddharth Agarwal
manifestmerge: rename n to n1 and n2...
r18818 elif n1 == a and fl1 == fla: # local unchanged - use remote
if n1 == n2: # optimization: keep local content
Mads Kiilerich
merge: inline act()...
r18544 actions.append((f, "e", (fl2,), "update permissions"))
Mads Kiilerich
merge: merge file flags together with file content...
r18338 else:
Mads Kiilerich
merge: inline act()...
r18544 actions.append((f, "g", (fl2,), "remote is newer"))
Mads Kiilerich
merge: merge file flags together with file content...
r18338 elif nol and n2 == a: # remote only changed 'x'
Mads Kiilerich
merge: inline act()...
r18544 actions.append((f, "e", (fl2,), "update permissions"))
Siddharth Agarwal
manifestmerge: rename n to n1 and n2...
r18818 elif nol and n1 == a: # local only changed 'x'
Mads Kiilerich
merge: inline act()...
r18544 actions.append((f, "g", (fl1,), "remote is newer"))
Mads Kiilerich
merge: merge file flags together with file content...
r18338 else: # both changed something
Mads Kiilerich
merge: inline act()...
r18544 actions.append((f, "m", (f, f, False), "versions differ"))
Matt Mackall
merge: simplify file revision comparison logic
r8752 elif f in copied: # files we'll deal with on m2 side
pass
Siddharth Agarwal
manifestmerge: use dicthelpers.diff and join...
r18822 elif n1 and f in movewithdir: # directory rename
Siddharth Agarwal
copies: separate moves via directory renames from explicit copies...
r18134 f2 = movewithdir[f]
Siddharth Agarwal
manifestmerge: drop redundant flags calls
r18823 actions.append((f, "d", (None, f2, fl1),
Mads Kiilerich
merge: inline act()...
r18544 "remote renamed directory to " + f2))
Siddharth Agarwal
manifestmerge: use dicthelpers.diff and join...
r18822 elif n1 and f in copy:
Matt Mackall
merge: add rename following...
r3249 f2 = copy[f]
Mads Kiilerich
merge: inline act()...
r18544 actions.append((f, "m", (f2, f, False),
"local copied/moved to " + f2))
Siddharth Agarwal
manifestmerge: use dicthelpers.diff and join...
r18822 elif n1 and f in ma: # clean, a different, no remote
Siddharth Agarwal
manifestmerge: rename n to n1 and n2...
r18818 if n1 != ma[f]:
Mads Kiilerich
merge: delay prompts a bit and show them in (extra) sorted order...
r18539 prompts.append((f, "cd")) # prompt changed/deleted
Siddharth Agarwal
manifestmerge: rename n to n1 and n2...
r18818 elif n1[20:] == "a": # added, no remote
Mads Kiilerich
merge: inline act()...
r18544 actions.append((f, "f", None, "remote deleted"))
Matt Mackall
merge: don't use unknown()...
r16094 else:
Mads Kiilerich
merge: inline act()...
r18544 actions.append((f, "r", None, "other deleted"))
Siddharth Agarwal
manifestmerge: use dicthelpers.diff and join...
r18822 elif n2 and f in movewithdir:
Siddharth Agarwal
copies: separate moves via directory renames from explicit copies...
r18134 f2 = movewithdir[f]
Siddharth Agarwal
manifestmerge: drop redundant flags calls
r18823 actions.append((None, "d", (f, f2, fl2),
Mads Kiilerich
merge: inline act()...
r18544 "local renamed directory to " + f2))
Siddharth Agarwal
manifestmerge: use dicthelpers.diff and join...
r18822 elif n2 and f in copy:
Matt Mackall
merge: add rename following...
r3249 f2 = copy[f]
Mads Kiilerich
merge: remove "case" comments...
r18339 if f2 in m2:
Mads Kiilerich
merge: inline act()...
r18544 actions.append((f2, "m", (f, f, False),
"remote copied to " + f))
Mads Kiilerich
merge: remove "case" comments...
r18339 else:
Mads Kiilerich
merge: inline act()...
r18544 actions.append((f2, "m", (f, f, True),
"remote moved to " + f))
Siddharth Agarwal
manifestmerge: use dicthelpers.diff and join...
r18822 elif n2 and f not in ma:
Siddharth Agarwal
manifestmerge: handle abort on local unknown, remote created files...
r18606 # local unknown, remote created: the logic is described by the
# following table:
#
# force branchmerge different | action
# n * n | get
# n * y | abort
# y n * | get
# y y n | get
# y y y | merge
#
# Checking whether the files are different is expensive, so we
# don't do that when we can avoid it.
if force and not branchmerge:
Siddharth Agarwal
manifestmerge: drop redundant flags calls
r18823 actions.append((f, "g", (fl2,), "remote created"))
Mads Kiilerich
merge: remove "case" comments...
r18339 else:
Bryan O'Sullivan
merge: rename p1 to wctx in manifestmerge...
r18611 different = _checkunknownfile(repo, wctx, p2, f)
Siddharth Agarwal
manifestmerge: handle abort on local unknown, remote created files...
r18606 if force and branchmerge and different:
actions.append((f, "m", (f, f, False),
"remote differs from untracked local"))
elif not force and different:
aborts.append((f, "ud"))
else:
Siddharth Agarwal
manifestmerge: drop redundant flags calls
r18823 actions.append((f, "g", (fl2,), "remote created"))
Siddharth Agarwal
manifestmerge: use dicthelpers.diff and join...
r18822 elif n2 and n2 != ma[f]:
Mads Kiilerich
merge: delay prompts a bit and show them in (extra) sorted order...
r18539 prompts.append((f, "dc")) # prompt deleted/changed
Siddharth Agarwal
manifestmerge: handle abort on local unknown, remote created files...
r18606 for f, m in sorted(aborts):
if m == "ud":
repo.ui.warn(_("%s: untracked file differs\n") % f)
else: assert False, m
if aborts:
raise util.Abort(_("untracked files in working directory differ "
"from files in requested revision"))
FUJIWARA Katsunori
icasefs: rewrite case-folding collision detection (issue3452)...
r19105 if not util.checkcase(repo.path):
# check collision between files only in p2 for clean update
if (not branchmerge and
(force or not wctx.dirty(missing=True, branch=False))):
_checkcollision(repo, m2, [], [])
else:
_checkcollision(repo, m1, actions, prompts)
Mads Kiilerich
merge: delay prompts a bit and show them in (extra) sorted order...
r18539 for f, m in sorted(prompts):
if m == "cd":
Durham Goode
rebase: fix --collapse when a file was added then removed...
r18778 if acceptremote:
actions.append((f, "r", None, "remote delete"))
elif repo.ui.promptchoice(
Mads Kiilerich
merge: don't indent "local changed %s which remote deleted" prompt...
r18543 _("local changed %s which remote deleted\n"
Matt Mackall
ui: merge prompt text components into a singe string...
r19226 "use (c)hanged version or (d)elete?"
"$$ &Changed $$ &Delete") % f, 0):
Mads Kiilerich
merge: inline act()...
r18544 actions.append((f, "r", None, "prompt delete"))
Matt Mackall
merge: don't use unknown()...
r16094 else:
Mads Kiilerich
merge: inline act()...
r18544 actions.append((f, "a", None, "prompt keep"))
Mads Kiilerich
merge: delay prompts a bit and show them in (extra) sorted order...
r18539 elif m == "dc":
Durham Goode
rebase: fix --collapse when a file was added then removed...
r18778 if acceptremote:
actions.append((f, "g", (m2.flags(f),), "remote recreating"))
elif repo.ui.promptchoice(
Matt Mackall
merge: reorder remote creation tests
r8741 _("remote changed %s which local deleted\n"
Matt Mackall
ui: merge prompt text components into a singe string...
r19226 "use (c)hanged version or leave (d)eleted?"
"$$ &Changed $$ &Deleted") % f, 0) == 0:
Mads Kiilerich
merge: inline act()...
r18544 actions.append((f, "g", (m2.flags(f),), "prompt recreating"))
Mads Kiilerich
merge: delay prompts a bit and show them in (extra) sorted order...
r18539 else: assert False, m
Mads Kiilerich
merge: rename list of actions from action to actions
r18330 return actions
Matt Mackall
merge: pull manifest comparison out into separate function
r3105
Dirkjan Ochtman
some modernization cleanups, forward compatibility
r8366 def actionkey(a):
Siddharth Agarwal
merge: move forgets to the beginning of the action list...
r19987 return a[1] in "rf" and -1 or 0, a
Paul Moore
Sort removes first when applying updates (fixes issues 750 and 912)...
r6805
Bryan O'Sullivan
merge: handle subrepo merges and .hgsubstate specially...
r18632 def getremove(repo, mctx, overwrite, args):
Bryan O'Sullivan
merge: split out mostly-non-interactive working dir updates...
r18630 """apply usually-non-interactive updates to the working directory
mctx is the context to be merged into the working copy
yields tuples for progress updates
"""
Bryan O'Sullivan
merge: don't fiddle with name lookups or i18n in hot loops...
r18640 verbose = repo.ui.verbose
unlink = util.unlinkpath
wjoin = repo.wjoin
fctx = mctx.filectx
wwrite = repo.wwrite
Bryan O'Sullivan
merge: split out mostly-non-interactive working dir updates...
r18630 audit = repo.wopener.audit
Bryan O'Sullivan
merge: report non-interactive progress in chunks...
r18633 i = 0
for arg in args:
Bryan O'Sullivan
merge: split out mostly-non-interactive working dir updates...
r18630 f = arg[0]
if arg[1] == 'r':
Bryan O'Sullivan
merge: don't fiddle with name lookups or i18n in hot loops...
r18640 if verbose:
repo.ui.note(_("removing %s\n") % f)
Bryan O'Sullivan
merge: split out mostly-non-interactive working dir updates...
r18630 audit(f)
try:
Bryan O'Sullivan
merge: don't fiddle with name lookups or i18n in hot loops...
r18640 unlink(wjoin(f), ignoremissing=True)
Bryan O'Sullivan
merge: split out mostly-non-interactive working dir updates...
r18630 except OSError, inst:
repo.ui.warn(_("update failed to remove %s: %s!\n") %
(f, inst.strerror))
else:
Bryan O'Sullivan
merge: don't fiddle with name lookups or i18n in hot loops...
r18640 if verbose:
repo.ui.note(_("getting %s\n") % f)
wwrite(f, fctx(f).data(), arg[2][0])
Bryan O'Sullivan
merge: report non-interactive progress in chunks...
r18633 if i == 100:
yield i, f
i = 0
i += 1
if i > 0:
Bryan O'Sullivan
merge: split out mostly-non-interactive working dir updates...
r18630 yield i, f
Mads Kiilerich
merge: rename list of actions from action to actions
r18330 def applyupdates(repo, actions, wctx, mctx, actx, overwrite):
Peter Arrenbrecht
merge: pass constant cset ancestor to fctx.ancestor
r11454 """apply the merge action list to the working directory
wctx is the working copy context
mctx is the context to be merged into the working copy
actx is the context of the common ancestor
Greg Ward
merge: document some internal return values.
r13162
Return a tuple of counts (updated, merged, removed, unresolved) that
describes how many files were affected by the update.
Peter Arrenbrecht
merge: pass constant cset ancestor to fctx.ancestor
r11454 """
Matt Mackall
merge: update some docstrings
r3315
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)
Matt Mackall
misc: replace .parents()[0] with p1()
r13878 ms.reset(wctx.p1().node())
Matt Mackall
merge: introduce mergestate
r6512 moves = []
Mads Kiilerich
merge: rename list of actions from action to actions
r18330 actions.sort(key=actionkey)
Matt Mackall
merge: introduce mergestate
r6512
# prescan for merges
Mads Kiilerich
merge: rename list of actions from action to actions
r18330 for a in actions:
Mads Kiilerich
merge: delay debug messages for merge actions...
r18541 f, m, args, msg = a
repo.ui.debug(" %s: %s -> %s\n" % (f, msg, m))
Mads Kiilerich
merge: consistently use "x" instead of 'x' for internal action types...
r18329 if m == "m": # merge
Mads Kiilerich
merge: make all action tuples have the same length - keep args as tuple
r18540 f2, fd, move = args
Mads Kiilerich
merge: .hgsubstate is special as merge destination, not as merge source
r18332 if fd == '.hgsubstate': # merged internally
Matt Mackall
subrepo: add update/merge logic
r8814 continue
Mads Kiilerich
merge: delay debug messages for merge actions...
r18541 repo.ui.debug(" preserving %s for resolve of %s\n" % (f, fd))
Matt Mackall
merge: introduce mergestate
r6512 fcl = wctx[f]
fco = mctx[f2]
Matt Mackall
merge: move reverse-merge logic out of filemerge (issue2342)
r12008 if mctx == actx: # backwards, use working dir parent as ancestor
Matt Mackall
merge: handle no file parent in backwards merge (issue2364)
r12664 if fcl.parents():
Matt Mackall
misc: replace .parents()[0] with p1()
r13878 fca = fcl.p1()
Matt Mackall
merge: handle no file parent in backwards merge (issue2364)
r12664 else:
fca = repo.filectx(f, fileid=nullrev)
Matt Mackall
merge: move reverse-merge logic out of filemerge (issue2342)
r12008 else:
fca = fcl.ancestor(fco, actx)
if not fca:
fca = repo.filectx(f, fileid=nullrev)
Mads Kiilerich
merge: merge file flags together with file content...
r18338 ms.add(fcl, fco, fca, fd)
Matt Mackall
merge: introduce mergestate
r6512 if f != fd and move:
moves.append(f)
Mads Kiilerich
merge: consistently use repo.wopener.audit instead of creating a new auditor
r18328 audit = repo.wopener.audit
Adrian Buehlmann
applyupdates: audit unlinking of renamed files and directories
r14398
Matt Mackall
merge: introduce mergestate
r6512 # remove renamed files after safely stored
for f in moves:
Martin Geisler
util: remove lexists, Python 2.4 introduced os.path.lexists
r12032 if os.path.lexists(repo.wjoin(f)):
Martin Geisler
do not attempt to translate ui.debug output
r9467 repo.ui.debug("removing %s\n" % f)
Adrian Buehlmann
applyupdates: audit unlinking of renamed files and directories
r14398 audit(f)
Mads Kiilerich
merge: use util.unlinkpath for removing moved files...
r18333 util.unlinkpath(repo.wjoin(f))
Matt Mackall
merge: do early copy to deal with issue636...
r5042
Mads Kiilerich
merge: rename list of actions from action to actions
r18330 numupdates = len(actions)
Bryan O'Sullivan
merge: split out mostly-non-interactive working dir updates...
r18630 workeractions = [a for a in actions if a[1] in 'gr']
FUJIWARA Katsunori
merge: increase safety of parallel updating/removing on icasefs...
r19095 updateactions = [a for a in workeractions if a[1] == 'g']
updated = len(updateactions)
removeactions = [a for a in workeractions if a[1] == 'r']
removed = len(removeactions)
Bryan O'Sullivan
merge: split out mostly-non-interactive working dir updates...
r18630 actions = [a for a in actions if a[1] not in 'gr']
Bryan O'Sullivan
merge: handle subrepo merges and .hgsubstate specially...
r18632 hgsub = [a[1] for a in workeractions if a[0] == '.hgsubstate']
if hgsub and hgsub[0] == 'r':
subrepo.submerge(repo, wctx, mctx, wctx, overwrite)
Bryan O'Sullivan
merge: report non-interactive progress in chunks...
r18633 z = 0
Bryan O'Sullivan
merge: apply non-interactive working dir updates in parallel...
r18639 prog = worker.worker(repo.ui, 0.001, getremove, (repo, mctx, overwrite),
FUJIWARA Katsunori
merge: increase safety of parallel updating/removing on icasefs...
r19095 removeactions)
for i, item in prog:
z += i
repo.ui.progress(_('updating'), z, item=item, total=numupdates,
unit=_('files'))
prog = worker.worker(repo.ui, 0.001, getremove, (repo, mctx, overwrite),
updateactions)
Bryan O'Sullivan
merge: apply non-interactive working dir updates in parallel...
r18639 for i, item in prog:
Bryan O'Sullivan
merge: report non-interactive progress in chunks...
r18633 z += i
repo.ui.progress(_('updating'), z, item=item, total=numupdates,
Martin Geisler
merge: use repo.ui directly instead local variable...
r15041 unit=_('files'))
Bryan O'Sullivan
merge: split out mostly-non-interactive working dir updates...
r18630
Bryan O'Sullivan
merge: handle subrepo merges and .hgsubstate specially...
r18632 if hgsub and hgsub[0] == 'g':
subrepo.submerge(repo, wctx, mctx, wctx, overwrite)
Bryan O'Sullivan
merge: don't fiddle with name lookups or i18n in hot loops...
r18640 _updating = _('updating')
_files = _('files')
progress = repo.ui.progress
Mads Kiilerich
merge: rename list of actions from action to actions
r18330 for i, a in enumerate(actions):
Mads Kiilerich
merge: delay debug messages for merge actions...
r18541 f, m, args, msg = a
Bryan O'Sullivan
merge: don't fiddle with name lookups or i18n in hot loops...
r18640 progress(_updating, z + i + 1, item=f, total=numupdates, unit=_files)
Bryan O'Sullivan
merge: split out mostly-non-interactive working dir updates...
r18630 if m == "m": # merge
Kevin Bullock
applyupdates: assign variable before we try to use it (issue3855)...
r18780 f2, fd, move = args
Mads Kiilerich
merge: .hgsubstate is special as merge destination, not as merge source
r18332 if fd == '.hgsubstate': # subrepo states need updating
Brodie Rao
cleanup: eradicate long lines
r16683 subrepo.submerge(repo, wctx, mctx, wctx.ancestor(mctx),
overwrite)
Matt Mackall
subrepo: add update/merge logic
r8814 continue
Mads Kiilerich
merge: consistently use repo.wopener.audit instead of creating a new auditor
r18328 audit(fd)
Matt Mackall
merge: introduce mergestate
r6512 r = ms.resolve(fd, wctx, mctx)
Alejandro Santos
compat: can't compare two values of unequal datatypes
r9030 if r is not None and 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
merge: handle directory renames...
r3733 elif m == "d": # directory rename
Mads Kiilerich
merge: make all action tuples have the same length - keep args as tuple
r18540 f2, fd, flags = args
Matt Mackall
merge: handle directory renames...
r3733 if f:
repo.ui.note(_("moving %s to %s\n") % (f, fd))
Adrian Buehlmann
applyupdates: audit unlinking of renamed files and directories
r14398 audit(f)
Mads Kiilerich
merge: drop reference to file contents immediately after write...
r18335 repo.wwrite(fd, wctx.filectx(f).data(), flags)
Adrian Buehlmann
rename util.unlink to unlinkpath
r13235 util.unlinkpath(repo.wjoin(f))
Matt Mackall
merge: handle directory renames...
r3733 if f2:
repo.ui.note(_("getting %s to %s\n") % (f2, fd))
Mads Kiilerich
merge: drop reference to file contents immediately after write...
r18335 repo.wwrite(fd, mctx.filectx(f2).data(), flags)
Matt Mackall
merge: handle directory renames...
r3733 updated += 1
Matt Mackall
merge: warn user about divergent renames
r4674 elif m == "dr": # divergent renames
Mads Kiilerich
merge: make all action tuples have the same length - keep args as tuple
r18540 fl, = args
Dan Villiom Podlaski Christiansen
merge: make 'diverging renames' diagnostic a more helpful note....
r12757 repo.ui.warn(_("note: possible conflict - %s was renamed "
"multiple times to:\n") % f)
Matt Mackall
merge: warn user about divergent renames
r4674 for nf in fl:
repo.ui.warn(" %s\n" % nf)
Thomas Arendsen Hein
merge: warn about file deleted in one branch and renamed in other (issue3074)...
r16794 elif m == "rd": # rename and delete
Mads Kiilerich
merge: make all action tuples have the same length - keep args as tuple
r18540 fl, = args
Thomas Arendsen Hein
merge: warn about file deleted in one branch and renamed in other (issue3074)...
r16794 repo.ui.warn(_("note: possible conflict - %s was deleted "
"and renamed to:\n") % f)
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
Mads Kiilerich
merge: make all action tuples have the same length - keep args as tuple
r18540 flags, = args
Mads Kiilerich
merge: consistently use repo.wopener.audit instead of creating a new auditor
r18328 audit(f)
Adrian Buehlmann
rename util.set_flags to setflags
r14232 util.setflags(repo.wjoin(f), 'l' in flags, 'x' in flags)
Mads Kiilerich
merge: changing the mode of a file is also an update...
r18334 updated += 1
Peter Arrenbrecht
merge: delay writing the mergestate during until commit is called...
r12369 ms.commit()
Bryan O'Sullivan
merge: don't fiddle with name lookups or i18n in hot loops...
r18640 progress(_updating, None, total=numupdates, unit=_files)
Matt Mackall
merge: move apply and dirstate code into separate functions
r3111
return updated, merged, removed, unresolved
Durham Goode
rebase: fix --collapse when a file was added then removed...
r18778 def calculateupdates(repo, tctx, mctx, ancestor, branchmerge, force, partial,
acceptremote=False):
David Schleimer
merge: refactor action calculation into function...
r18035 "Calculate the actions needed to merge mctx into tctx"
Mads Kiilerich
merge: rename list of actions from action to actions
r18330 actions = []
actions += manifestmerge(repo, tctx, mctx,
ancestor,
Siddharth Agarwal
manifestmerge: pass in branchmerge and force separately...
r18605 branchmerge, force,
Durham Goode
rebase: fix --collapse when a file was added then removed...
r18778 partial, acceptremote)
David Schleimer
merge: support calculating merge actions against non-working contexts...
r18036 if tctx.rev() is None:
Mads Kiilerich
merge: rename list of actions from action to actions
r18330 actions += _forgetremoved(tctx, mctx, branchmerge)
return actions
David Schleimer
merge: refactor action calculation into function...
r18035
Mads Kiilerich
merge: rename list of actions from action to actions
r18330 def recordupdates(repo, actions, branchmerge):
Matt Mackall
merge: update some docstrings
r3315 "record merge actions to the dirstate"
Mads Kiilerich
merge: rename list of actions from action to actions
r18330 for a in actions:
Mads Kiilerich
merge: delay debug messages for merge actions...
r18541 f, m, args, msg = a
Matt Mackall
merge: move apply and dirstate code into separate functions
r3111 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: rename forget to drop...
r14434 repo.dirstate.drop(f)
Matt Mackall
merge: mark kept local files as readded on linear update (issue539)
r7768 elif m == "a": # re-add
if not branchmerge:
repo.dirstate.add(f)
Matt Mackall
merge: move apply and dirstate code into separate functions
r3111 elif m == "f": # forget
Matt Mackall
dirstate: rename forget to drop...
r14434 repo.dirstate.drop(f)
Benoit Boissinot
correctly update dirstate after update+mode change (issue1456)
r7569 elif m == "e": # exec change
Patrick Mezard
merge: fix execute bit update issue introduced by 89207edf3973
r7630 repo.dirstate.normallookup(f)
Benoit Boissinot
correctly update dirstate after update+mode change (issue1456)
r7569 elif m == "g": # get
Matt Mackall
merge: move apply and dirstate code into separate functions
r3111 if branchmerge:
Benoit Boissinot
dirstate: more explicit name, rename normaldirty() to otherparent()
r10968 repo.dirstate.otherparent(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
Mads Kiilerich
merge: make all action tuples have the same length - keep args as tuple
r18540 f2, fd, move = args
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.
Gilles Moris
merge: avoid to break the dirstate copy status on moved files...
r11178 if f2 == fd: # file not locally copied/moved
repo.dirstate.normallookup(fd)
Matt Mackall
merge: unify merge and copy actions
r3308 if move:
Matt Mackall
dirstate: rename forget to drop...
r14434 repo.dirstate.drop(f)
Matt Mackall
merge: handle directory renames...
r3733 elif m == "d": # directory rename
Mads Kiilerich
merge: make all action tuples have the same length - keep args as tuple
r18540 f2, fd, flag = args
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: rename forget to drop...
r14434 repo.dirstate.drop(f)
Matt Mackall
merge: move apply and dirstate code into separate functions
r3111
Patrick Mezard
rebase: allow collapsing branches in place (issue3111)...
r16696 def update(repo, node, branchmerge, force, partial, ancestor=None,
mergeancestor=False):
Matt Mackall
merge: update some docstrings
r3315 """
Perform a merge between the working directory and the given node
Stuart W Marks
update: add comments and test cases for updating across branches...
r9716 node = the node to update to, or None if unspecified
Matt Mackall
merge: update some docstrings
r3315 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)
Durham Goode
rebase: fix --collapse when a file was added then removed...
r18778 mergeancestor = whether it is merging with an ancestor. If true,
we should accept the incoming changes for any prompts that occur.
If false, merging with an ancestor (fast-forward) is only allowed
between different named branches. This flag is used by rebase extension
as a temporary fix and should be avoided in general.
Stuart W Marks
update: add comments and test cases for updating across branches...
r9716
The table below shows all the behaviors of the update command
given the -c and -C or no options, whether the working directory
is dirty, whether a revision is specified, and the relationship of
the parent rev to the target rev (linear, on the same named
branch, or on another named branch).
Adrian Buehlmann
combine tests
r12279 This logic is tested by test-update-branches.t.
Stuart W Marks
update: add comments and test cases for updating across branches...
r9716
-c -C dirty rev | linear same cross
n n n n | ok (1) x
Stuart W Marks
update: allow branch crossing without -c or -C, with no uncommitted changes...
r9717 n n n y | ok ok ok
Siddharth Agarwal
update: add error message for dirty non-linear update with no rev...
r19799 n n y n | merge (2) (2)
n n y y | merge (3) (3)
Stuart W Marks
update: add comments and test cases for updating across branches...
r9716 n y * * | --- discard ---
Siddharth Agarwal
update: add error message for dirty non-linear update with no rev...
r19799 y n y * | --- (4) ---
Stuart W Marks
update: add comments and test cases for updating across branches...
r9716 y n n * | --- ok ---
Siddharth Agarwal
update: add error message for dirty non-linear update with no rev...
r19799 y y * * | --- (5) ---
Stuart W Marks
update: add comments and test cases for updating across branches...
r9716
x = can't happen
* = don't-care
Siddharth Agarwal
update: improve error message for clean non-linear update
r19798 1 = abort: not a linear update (merge or update --check to force update)
Siddharth Agarwal
update: improve error message for dirty non-linear update with rev
r19800 2 = abort: uncommitted changes (commit and merge, or update --clean to
discard changes)
Siddharth Agarwal
update: add error message for dirty non-linear update with no rev...
r19799 3 = abort: uncommitted changes (commit or update --clean to discard changes)
Siddharth Agarwal
update: standardize error message for dirty update --check...
r19801 4 = abort: uncommitted changes (checked in commands.py)
Siddharth Agarwal
update: add error message for dirty non-linear update with no rev...
r19799 5 = incompatible options (checked in commands.py)
Greg Ward
merge: document some internal return values.
r13162
Return the same tuple as applyupdates().
Matt Mackall
merge: update some docstrings
r3315 """
Matt Mackall
Merge: combine force and forcemerge arguments
r2815
Stuart W Marks
update: allow branch crossing without -c or -C, with no uncommitted changes...
r9717 onode = node
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:
Brodie Rao
localrepo: add branchtip() method for faster single-branch lookups...
r16719 node = repo.branchtip(wc.branch())
except error.RepoLookupError:
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
merge: add ancestor to the update function...
r13874 if ancestor:
pa = repo[ancestor]
else:
pa = p1.ancestor(p2)
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 fp1, fp2, xp1, xp2 = p1.node(), p2.node(), str(p1), str(p2)
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:
Matt Mackall
merge: improve merge with ancestor message
r11417 raise util.Abort(_("merging with a working directory ancestor"
" has no effect"))
Matt Mackall
update: better logic and messages for updates...
r6375 elif pa == p1:
Patrick Mezard
rebase: allow collapsing branches in place (issue3111)...
r16696 if not mergeancestor and p1.branch() == p2.branch():
Kevin Bullock
merge: make 'nothing to merge' aborts consistent...
r15619 raise util.Abort(_("nothing to merge"),
hint=_("use 'hg update' "
"or check 'hg heads'"))
Matt Mackall
update: better logic and messages for updates...
r6375 if not force and (wc.files() or wc.deleted()):
Siddharth Agarwal
merge: standardize error message for dirty working dir
r19802 raise util.Abort(_("uncommitted changes"),
Kevin Bullock
merge: make 'nothing to merge' aborts consistent...
r15619 hint=_("use 'hg status' to list changes"))
Mads Kiilerich
subrepos: process subrepos in sorted order...
r18364 for s in sorted(wc.substate):
Oleg Stepanov
Do not allow merging with uncommitted changes in a subrepo
r13437 if wc.sub(s).dirty():
Siddharth Agarwal
merge: standardize error message for dirty subrepo
r19803 raise util.Abort(_("uncommitted changes in "
Oleg Stepanov
Do not allow merging with uncommitted changes in a subrepo
r13437 "subrepository '%s'") % s)
Matt Mackall
update: better logic and messages for updates...
r6375 elif not overwrite:
Siddharth Agarwal
merge: exit early during a no-op update (BC)...
r19929 if p1 == p2: # no-op update
# call the hooks and exit early
repo.hook('preupdate', throw=True, parent1=xp2, parent2='')
repo.hook('update', parent1=xp2, parent2='', error=0)
return 0, 0, 0, 0
Mads Kiilerich
spelling: random spell checker fixes
r19951 if pa not in (p1, p2): # nonlinear
Pierre-Yves David
update: allow dirty update to foreground (successors)...
r18985 dirty = wc.dirty(missing=True)
if dirty or onode is None:
# Branching is a bit strange to ensure we do the minimal
# amount of call to obsolete.background.
foreground = obsolete.foreground(repo, [p1.node()])
# note: the <node> variable contains a random identifier
if repo[node].node() in foreground:
pa = p1 # allow updating to successors
Siddharth Agarwal
update: add error message for dirty non-linear update with no rev...
r19799 elif dirty:
msg = _("uncommitted changes")
Siddharth Agarwal
update: improve error message for dirty non-linear update with rev
r19800 if onode is None:
hint = _("commit and merge, or update --clean to"
" discard changes")
else:
hint = _("commit or update --clean to discard"
" changes")
Siddharth Agarwal
update: add error message for dirty non-linear update with no rev...
r19799 raise util.Abort(msg, hint=hint)
Pierre-Yves David
update: allow dirty update to foreground (successors)...
r18985 else: # node is none
Siddharth Agarwal
update: improve error message for clean non-linear update
r19798 msg = _("not a linear update")
hint = _("merge or update --check to force update")
raise util.Abort(msg, hint=hint)
Pierre-Yves David
update: allow dirty update to foreground (successors)...
r18985 else:
# Allow jumping branches if clean and specific rev given
pa = p1
Matt Mackall
Merge: move most tests to the beginning
r2814
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 ### calculate phase
Mads Kiilerich
merge: rename list of actions from action to actions
r18330 actions = calculateupdates(repo, wc, p2, pa,
Durham Goode
rebase: fix --collapse when a file was added then removed...
r18778 branchmerge, force, partial, mergeancestor)
Matt Mackall
Move merge code to its own module...
r2775
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 ### apply phase
Matt Mackall
merge: back out single-parent fast-forward merge...
r13550 if not branchmerge: # just jump to the new rev
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 fp1, fp2, xp1, xp2 = fp2, nullid, xp2, ''
if not partial:
repo.hook('preupdate', throw=True, parent1=xp1, parent2=xp2)
Matt Mackall
update: add tracking of interrupted updates (issue3113)...
r19482 # note that we're in the middle of an update
repo.vfs.write('updatestate', p2.hex())
Matt Mackall
Move merge code to its own module...
r2775
Mads Kiilerich
merge: rename list of actions from action to actions
r18330 stats = applyupdates(repo, actions, wc, p2, pa, overwrite)
Matt Mackall
merge: consolidate dirstate updates
r2899
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 if not partial:
Patrick Mezard
localrepo: add setparents() to adjust dirstate copies (issue3407)...
r16551 repo.setparents(fp1, fp2)
Mads Kiilerich
merge: rename list of actions from action to actions
r18330 recordupdates(repo, actions, branchmerge)
Matt Mackall
update: add tracking of interrupted updates (issue3113)...
r19482 # update completed, clear state
util.unlink(repo.join('updatestate'))
Mads Kiilerich
merge: remove last traces of fastforward merging...
r13561 if not branchmerge:
Matt Mackall
Use try/finally pattern to cleanup locks and transactions
r4915 repo.dirstate.setbranch(p2.branch())
finally:
Ronny Pfannschmidt
switch lock releasing in the core from gc to explicit
r8109 wlock.release()
Sune Foldager
run commit and update hooks after command completion (issue1827)...
r10492
if not partial:
repo.hook('update', parent1=xp1, parent2=xp2, error=stats[3])
return stats