diff options
author | Lorry Tar Creator <lorry-tar-importer@baserock.org> | 2011-10-01 20:49:36 +0000 |
---|---|---|
committer | Lorry <lorry@roadtrain.codethink.co.uk> | 2012-09-27 13:27:51 +0000 |
commit | 921ced43c48c1d170452a7b251b94cc96ec8dd44 (patch) | |
tree | 3c4a89176ea67fe4c7bf7b375488361a823c95fa /mercurial/merge.py | |
parent | 9039c805b0a7e36220101323f82735f08a104b37 (diff) | |
download | mercurial-tarball-master.tar.gz |
Imported from /srv/lorry/lorry-area/mercurial-tarball/mercurial-1.9.3.tar.gz.HEADmercurial-1.9.3master
Diffstat (limited to 'mercurial/merge.py')
-rw-r--r-- | mercurial/merge.py | 124 |
1 files changed, 34 insertions, 90 deletions
diff --git a/mercurial/merge.py b/mercurial/merge.py index 19ffb28..240081f 100644 --- a/mercurial/merge.py +++ b/mercurial/merge.py @@ -7,7 +7,7 @@ from node import nullid, nullrev, hex, bin from i18n import _ -import error, scmutil, util, filemerge, copies, subrepo +import scmutil, util, filemerge, copies, subrepo, encoding import errno, os, shutil class mergestate(object): @@ -81,50 +81,23 @@ class mergestate(object): self.mark(dfile, 'r') return r -def _checkunknownfile(repo, wctx, mctx, f): - return (not repo.dirstate._ignore(f) - and os.path.isfile(repo.wjoin(f)) - and repo.dirstate.normalize(f) not in repo.dirstate - and mctx[f].cmp(wctx[f])) - -def _checkunknown(repo, wctx, mctx): +def _checkunknown(wctx, mctx): "check for collisions between unknown files and files in mctx" + for f in wctx.unknown(): + if f in mctx and mctx[f].cmp(wctx[f]): + raise util.Abort(_("untracked file in working directory differs" + " from file in requested revision: '%s'") % f) - error = False - for f in mctx: - if f not in wctx and _checkunknownfile(repo, wctx, mctx, f): - error = True - wctx._repo.ui.warn(_("%s: untracked file differs\n") % f) - if error: - raise util.Abort(_("untracked files in working directory differ " - "from files in requested revision")) - -def _checkcollision(mctx, wctx): +def _checkcollision(mctx): "check for case folding collisions in the destination context" folded = {} for fn in mctx: - fold = util.normcase(fn) + fold = encoding.lower(fn) if fold in folded: raise util.Abort(_("case-folding collision between %s and %s") % (fn, folded[fold])) folded[fold] = fn - if wctx: - # class to delay looking up copy mapping - class pathcopies(object): - @util.propertycache - def map(self): - # {dst@mctx: src@wctx} copy mapping - return copies.pathcopies(wctx, mctx) - pc = pathcopies() - - for fn in wctx: - fold = util.normcase(fn) - mfn = folded.get(fold, None) - if mfn and mfn != fn and pc.map.get(mfn) != fn: - raise util.Abort(_("case-folding collision between %s and %s") - % (mfn, fn)) - def _forgetremoved(wctx, mctx, branchmerge): """ Forget removed files @@ -179,11 +152,6 @@ def manifestmerge(repo, p1, p2, pa, overwrite, partial): if m and m != a: # changed from a to m return m if n and n != a: # changed from a to n - if (n == 'l' or a == 'l') and m1.get(f) != ma.get(f): - # can't automatically merge symlink flag when there - # are file-level conflicts here, let filemerge take - # care of it - return m return n return '' # flag was cleared @@ -198,16 +166,14 @@ def manifestmerge(repo, p1, p2, pa, overwrite, partial): elif pa == p2: # backwards pa = p1.p1() elif pa and repo.ui.configbool("merge", "followcopies", True): - copy, diverge, renamedelete = copies.mergecopies(repo, p1, p2, pa) + dirs = repo.ui.configbool("merge", "followdirs", True) + copy, diverge = copies.copies(repo, p1, p2, pa, dirs) for of, fl in diverge.iteritems(): act("divergent renames", "dr", of, fl) - for of, fl in renamedelete.iteritems(): - act("rename and delete", "rd", of, fl) repo.ui.note(_("resolving manifests\n")) - repo.ui.debug(" overwrite: %s, partial: %s\n" - % (bool(overwrite), bool(partial))) - repo.ui.debug(" ancestor: %s, local: %s, remote: %s\n" % (pa, p1, p2)) + repo.ui.debug(" overwrite %s partial %s\n" % (overwrite, bool(partial))) + repo.ui.debug(" ancestor %s local %s remote %s\n" % (pa, p1, p2)) m1, m2, ma = p1.manifest(), p2.manifest(), pa.manifest() copied = set(copy.values()) @@ -256,7 +222,7 @@ def manifestmerge(repo, p1, p2, pa, overwrite, partial): act("prompt keep", "a", f) elif n[20:] == "a": # added, no remote act("remote deleted", "f", f) - else: + elif n[20:] != "u": act("other deleted", "r", f) for f, n in m2.iteritems(): @@ -276,13 +242,7 @@ def manifestmerge(repo, p1, p2, pa, overwrite, partial): act("remote moved to " + f, "m", f2, f, f, fmerge(f2, f, f2), True) elif f not in ma: - if (not overwrite - and _checkunknownfile(repo, p1, p2, f)): - rflags = fmerge(f, f, f) - act("remote differs from untracked local", - "m", f, f, f, rflags, False) - else: - act("remote created", "g", f, m2.flags(f)) + act("remote created", "g", f, m2.flags(f)) elif n != ma[f]: if repo.ui.promptchoice( _("remote changed %s which local deleted\n" @@ -313,6 +273,7 @@ def applyupdates(repo, action, wctx, mctx, actx, overwrite): action.sort(key=actionkey) # prescan for merges + u = repo.ui for a in action: f, m = a[:2] if m == 'm': # merge @@ -347,8 +308,8 @@ def applyupdates(repo, action, wctx, mctx, actx, overwrite): numupdates = len(action) for i, a in enumerate(action): f, m = a[:2] - repo.ui.progress(_('updating'), i + 1, item=f, total=numupdates, - unit=_('files')) + u.progress(_('updating'), i + 1, item=f, total=numupdates, + unit=_('files')) if f and f[0] == "/": continue if m == "r": # remove @@ -365,8 +326,7 @@ def applyupdates(repo, action, wctx, mctx, actx, overwrite): removed += 1 elif m == "m": # merge if f == '.hgsubstate': # subrepo states need updating - subrepo.submerge(repo, wctx, mctx, wctx.ancestor(mctx), - overwrite) + subrepo.submerge(repo, wctx, mctx, wctx.ancestor(mctx), overwrite) continue f2, fd, flags, move = a[2:] repo.wopener.audit(fd) @@ -378,6 +338,7 @@ def applyupdates(repo, action, wctx, mctx, actx, overwrite): updated += 1 else: merged += 1 + util.setflags(repo.wjoin(fd), 'l' in flags, 'x' in flags) if (move and repo.dirstate.normalize(fd) != f and os.path.lexists(repo.wjoin(f))): repo.ui.debug("removing %s\n" % f) @@ -411,18 +372,12 @@ def applyupdates(repo, action, wctx, mctx, actx, overwrite): "multiple times to:\n") % f) for nf in fl: repo.ui.warn(" %s\n" % nf) - elif m == "rd": # rename and delete - fl = a[2] - repo.ui.warn(_("note: possible conflict - %s was deleted " - "and renamed to:\n") % f) - for nf in fl: - repo.ui.warn(" %s\n" % nf) elif m == "e": # exec flags = a[2] repo.wopener.audit(f) util.setflags(repo.wjoin(f), 'l' in flags, 'x' in flags) ms.commit() - repo.ui.progress(_('updating'), None, total=numupdates, unit=_('files')) + u.progress(_('updating'), None, total=numupdates, unit=_('files')) return updated, merged, removed, unresolved @@ -488,8 +443,7 @@ def recordupdates(repo, action, branchmerge): if f: repo.dirstate.drop(f) -def update(repo, node, branchmerge, force, partial, ancestor=None, - mergeancestor=False): +def update(repo, node, branchmerge, force, partial, ancestor=None): """ Perform a merge between the working directory and the given node @@ -497,10 +451,6 @@ def update(repo, node, branchmerge, force, partial, ancestor=None, 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) - mergeancestor = 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. The table below shows all the behaviors of the update command given the -c and -C or no options, whether the working directory @@ -537,8 +487,8 @@ def update(repo, node, branchmerge, force, partial, ancestor=None, if node is None: # tip of current branch try: - node = repo.branchtip(wc.branch()) - except error.RepoLookupError: + node = repo.branchtags()[wc.branch()] + except KeyError: if wc.branch() == "default": # no default branch! node = repo.lookup("tip") # update to tip else: @@ -561,13 +511,12 @@ def update(repo, node, branchmerge, force, partial, ancestor=None, raise util.Abort(_("merging with a working directory ancestor" " has no effect")) elif pa == p1: - if not mergeancestor and p1.branch() == p2.branch(): - raise util.Abort(_("nothing to merge"), - hint=_("use 'hg update' " - "or check 'hg heads'")) + if p1.branch() == p2.branch(): + raise util.Abort(_("nothing to merge (use 'hg update'" + " or check 'hg heads')")) if not force and (wc.files() or wc.deleted()): - raise util.Abort(_("outstanding uncommitted changes"), - hint=_("use 'hg status' to list changes")) + raise util.Abort(_("outstanding uncommitted changes " + "(use 'hg status' to list changes)")) for s in wc.substate: if wc.sub(s).dirty(): raise util.Abort(_("outstanding uncommitted changes in " @@ -584,20 +533,15 @@ def update(repo, node, branchmerge, force, partial, ancestor=None, " --check to force update)")) else: # Allow jumping branches if clean and specific rev given - pa = p1 + overwrite = True ### calculate phase action = [] - folding = not util.checkcase(repo.path) - if folding: - # collision check is not needed for clean update - if (not branchmerge and - (force or not wc.dirty(missing=True, branch=False))): - _checkcollision(p2, None) - else: - _checkcollision(p2, wc) + wc.status(unknown=True) # prime cache if not force: - _checkunknown(repo, wc, p2) + _checkunknown(wc, p2) + if not util.checkcase(repo.path): + _checkcollision(p2) action += _forgetremoved(wc, p2, branchmerge) action += manifestmerge(repo, wc, p2, pa, overwrite, partial) @@ -610,7 +554,7 @@ def update(repo, node, branchmerge, force, partial, ancestor=None, stats = applyupdates(repo, action, wc, p2, pa, overwrite) if not partial: - repo.setparents(fp1, fp2) + repo.dirstate.setparents(fp1, fp2) recordupdates(repo, action, branchmerge) if not branchmerge: repo.dirstate.setbranch(p2.branch()) |