diff -r 557c8522aec0 -r 384df4db6520 mercurial/merge.py --- a/mercurial/merge.py Tue Jan 15 01:05:12 2013 +0100 +++ b/mercurial/merge.py Wed Jan 09 02:02:45 2013 +0100 @@ -45,11 +45,11 @@ f.write("\0".join([d] + v) + "\n") f.close() self._dirty = False - def add(self, fcl, fco, fca, fd, flags): + def add(self, fcl, fco, fca, fd): hash = util.sha1(fcl.path()).hexdigest() self._repo.opener.write("merge/" + hash, fcl.data()) self._state[fd] = ['u', hash, fcl.path(), fca.path(), - hex(fca.filenode()), fco.path(), flags] + hex(fca.filenode()), fco.path(), fcl.flags()] self._dirty = True def __contains__(self, dfile): return dfile in self._state @@ -67,12 +67,22 @@ if self[dfile] == 'r': return 0 state, hash, lfile, afile, anode, ofile, flags = self._state[dfile] + 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 f = self._repo.opener("merge/" + hash) self._repo.wwrite(dfile, f.read(), flags) f.close() - 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 r is None: # no real conflict @@ -183,32 +193,6 @@ partial = function to filter file lists """ - def fmerge(f, f2, fa): - """merge flags""" - a, m, n = ma.flags(fa), m1.flags(f), m2.flags(f2) - if m == n: # flags agree - return m # unchanged - if m and n and not a: # flags set, don't agree, differ from parent - r = repo.ui.promptchoice( - _(" conflicting flags for %s\n" - "(n)one, e(x)ec or sym(l)ink?") % f, - (_("&None"), _("E&xec"), _("Sym&link")), 0) - if r == 1: - return "x" # Exec - if r == 2: - return "l" # Symlink - return "" - 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 - def act(msg, m, f, *args): repo.ui.debug(" %s: %s -> %s\n" % (f, msg, m)) actions.append((f, m) + args) @@ -248,17 +232,25 @@ if partial and not partial(f): continue if f in m2: - rflags = fmerge(f, f, f) + n2 = m2[f] + fl1, fl2, fla = m1.flags(f), m2.flags(f), ma.flags(f) + nol = 'l' not in fl1 + fl2 + fla a = ma.get(f, nullid) - if n == m2[f] or m2[f] == a: # same or local newer - # is file locally modified or flags need changing? - # dirstate flags may need to be made current - if m1.flags(f) != rflags or n[20:]: - act("update permissions", "e", f, rflags) - elif n == a: # remote newer - act("remote is newer", "g", f, rflags) - else: # both changed - act("versions differ", "m", f, f, f, rflags, False) + if n == n2 and fl1 == fl2: + pass # same - keep local + elif n2 == a and fl2 == fla: + pass # remote unchanged - keep local + elif n == a and fl1 == fla: # local unchanged - use remote + if n == n2: # optimization: keep local content + act("update permissions", "e", f, fl2) + else: + act("remote is newer", "g", f, fl2) + elif nol and n2 == a: # remote only changed 'x' + act("update permissions", "e", f, fl2) + elif nol and n == a: # local only changed 'x' + act("remote is newer", "g", f, fl) + else: # both changed something + act("versions differ", "m", f, f, f, False) elif f in copied: # files we'll deal with on m2 side pass elif f in movewithdir: # directory rename @@ -267,8 +259,7 @@ m1.flags(f)) elif f in copy: # case 2 A,B/B/B or case 4,21 A/B/B f2 = copy[f] - act("local copied/moved to " + f2, "m", f, f2, f, - fmerge(f, f2, f2), False) + act("local copied/moved to " + f2, "m", f, f2, f, False) elif f in ma: # clean, a different, no remote if n != ma[f]: if repo.ui.promptchoice( @@ -296,16 +287,15 @@ f2 = copy[f] if f2 in m2: # rename case 1, A/A,B/A act("remote copied to " + f, "m", - f2, f, f, fmerge(f2, f, f2), False) + f2, f, f, False) else: # case 3,20 A/B/A act("remote moved to " + f, "m", - f2, f, f, fmerge(f2, f, f2), True) + f2, f, f, 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) + "m", f, f, f, False) else: act("remote created", "g", f, m2.flags(f)) elif n != ma[f]: @@ -341,7 +331,7 @@ for a in actions: f, m = a[:2] if m == "m": # merge - f2, fd, flags, move = a[2:] + f2, fd, move = a[2:] if fd == '.hgsubstate': # merged internally continue repo.ui.debug("preserving %s for resolve of %s\n" % (f, fd)) @@ -356,7 +346,7 @@ fca = fcl.ancestor(fco, actx) if not fca: fca = repo.filectx(f, fileid=nullrev) - ms.add(fcl, fco, fca, fd, flags) + ms.add(fcl, fco, fca, fd) if f != fd and move: moves.append(f) @@ -390,7 +380,7 @@ subrepo.submerge(repo, wctx, mctx, wctx.ancestor(mctx), overwrite) continue - f2, fd, flags, move = a[2:] + f2, fd, move = a[2:] audit(fd) r = ms.resolve(fd, wctx, mctx) if r is not None and r > 0: @@ -484,7 +474,7 @@ else: repo.dirstate.normal(f) elif m == "m": # merge - f2, fd, flag, move = a[2:] + f2, fd, move = a[2:] if branchmerge: # We've done a branch merge, mark this file as merged # so that we properly record the merger later