[PATCH] detect conflicts between merged remote files and directories (issue29)
Matt Mackall
mpm at selenic.com
Wed Oct 24 17:04:39 CDT 2012
On Tue, 2012-10-23 at 10:09 -0700, Evgeniy Makeev wrote:
> # HG changeset patch
> # User Evgeniy Makeev <evgeniym at fb.com>
> # Date 1350964267 25200
> # Node ID 395b8469087e74e0ed98487217c9259e215ec479
> # Parent d51364b318eab1871af13f30be099799c04a43d1
> detect conflicts between merged remote files and directories (issue29)
>
> The fix checks for three kinds of conflicts:
> 1. Remote file conflicts with a local directory with identical name
> In this case user prompted to abort the merge (default) or to resolve
> the conflict by deleting the remote file
> 2. Remote directory conflicts with a local file with the same name
> In this case user prompted to abort (default) or to resolve the conflict
> by deleting all remote files which have the directory in their paths
> 3. Remote file conflicts with local empty directory
> This conflict is caught only during applyupdates when the IO already
> in progress. User prompted to resolve conflict by removing the empty
> local directory (default) or abort the merge
On the whole, this is a nice piece of work, but not yet in a form we can
accept. Seems like now is a good time to point you at:
http://mercurial.selenic.com/wiki/OneChangePerPatch
So, yes, I did mention there were case issues here. But, no, that was
not a request that you send a very large patch that tried to fixed
everything at once.
You should really structure this as:
patch 1: fix basic directory/file collision issues with a test
patch 2: add groundwork for doing case-insensitive version of the above
patch 3: add case-insensitive support in merge with corresponding test
(and possibly more parts)
Also, you should probably hold off on sending or even working on 2 and 3
further until 1 is accepted, which may take a couple round trips still.
But I will comment a bit on all three parts below anyway.
> diff -r d51364b318ea -r 395b8469087e mercurial/context.py
> --- a/mercurial/context.py Thu Jul 26 21:29:39 2012 +0200
> +++ b/mercurial/context.py Mon Oct 22 20:51:07 2012 -0700
> @@ -352,6 +352,23 @@
> def dirs(self):
> return self._dirs
>
> + @propertycache
> + def _normdirs(self):
One of these methods wants a docstring.
> + dirs = set()
> + for f in self._manifest:
> + pos = f.rfind('/')
> + while pos != -1:
> + f = f[:pos]
> + fnorm = util.normcase(f)
> + if fnorm in dirs:
> + break # dirs already contains this and above
> + dirs.add(fnorm)
> + pos = f.rfind('/')
> + return dirs
> +
> + def normdirs(self):
> + return self._normdirs
..and all of this should go in patch #1 of N.
> class filectx(object):
> """A filecontext object makes access to data related to a particular
> filerevision convenient."""
> diff -r d51364b318ea -r 395b8469087e mercurial/merge.py
> --- a/mercurial/merge.py Thu Jul 26 21:29:39 2012 +0200
> +++ b/mercurial/merge.py Mon Oct 22 20:51:07 2012 -0700
> @@ -190,6 +190,31 @@
> def act(msg, m, f, *args):
> repo.ui.debug(" %s: %s -> %s\n" % (f, msg, m))
> action.append((f, m) + args)
> +
> + def addremotedir(f):
> + # find all dirs from f's path
> + pathpos = f.rfind('/')
> + while pathpos != -1:
> + f = f[:pathpos]
> + if f in newdirset:
> + break # newdirset already contains this and above
> + newdirset.add(f)
> + pathpos = f.rfind('/')
Initialize newdirset immediately above this, please.
> + if util.checkcase(repo.path):
This is a bit unfortunate on two counts:
a) we already call checkcase and cache its result for future use in
several places
b) we'd like to minimize the the number of places that are directly
exposed to case-awareness.
> + def findirs(f):
> + return f in p1.dirs()
> + def addnormdir(fdir):
> + addremotedir(fdir)
> + def finnewdirs(f):
> + return f in newdirset
> + else:
> + def findirs(f):
> + return util.normcase(f) in p1.normdirs()
> + def addnormdir(fdir):
> + addremotedir(util.normcase(fdir))
> + def finnewdirs(f):
> + return util.normcase(f) in newdirset
> action, copy = [], {}
>
> @@ -259,6 +284,7 @@
> else:
> act("other deleted", "r", f)
>
> + newdirset = set()
> for f, n in m2.iteritems():
> if partial and not partial(f):
> continue
> @@ -282,7 +308,20 @@
> act("remote differs from untracked local",
> "m", f, f, f, rflags, False)
> else:
> - act("remote created", "g", f, m2.flags(f))
> + if findirs(f) and os.path.isdir(repo.wjoin(f)):
> + # check if the added remote file collides with existing dir
> + if 0 == repo.ui.promptchoice(
> + _(" remote %s conflicts with local directory %s\n"
> + "(a)bort operation or (d)elete remote file? [a]")
> + % (f, repo.wjoin(f)),
Here I'll refer you back to
http://markmail.org/message/ult635knza7kr45l
where I
a) suggested you not include an abort option
b) asked you to add an explicit choice between a file and a directory
c) gave you suggested wording
If you don't like my suggested wording, fine, but it's highly
inefficient to "argue by large patch". Better to just use normal email.
--
Mathematics is the supreme nostalgia of our time.
More information about the Mercurial-devel
mailing list