Details
Details
- Reviewers
- None
- Group Reviewers
hg-reviewers - Commits
- rHG44c2e80db985: rebase: fix dir/file conflict detection when using in-mem merge
Diff Detail
Diff Detail
- Repository
- rHG Mercurial
- Lint
Lint Skipped - Unit
Unit Tests Skipped
hg-reviewers |
Lint Skipped |
Unit Tests Skipped |
Path | Packages | |||
---|---|---|---|---|
M | mercurial/context.py (9 lines) | |||
M | tests/test-rebase-inmemory.t (16 lines) |
Commit | Parents | Author | Summary | Date |
---|---|---|---|---|
Martin von Zweigbergk | Dec 3 2018, 2:14 PM |
Status | Author | Revision | |
---|---|---|---|
Closed | martinvonz | ||
Closed | martinvonz |
if self._cache[path]['exists']: | if self._cache[path]['exists']: | ||||
return self._cache[path]['flags'] | return self._cache[path]['flags'] | ||||
else: | else: | ||||
raise error.ProgrammingError("No such file or directory: %s" % | raise error.ProgrammingError("No such file or directory: %s" % | ||||
self._path) | self._path) | ||||
else: | else: | ||||
return self._wrappedctx[path].flags() | return self._wrappedctx[path].flags() | ||||
def __contains__(self, key): | |||||
if key in self._cache: | |||||
return self._cache[key]['exists'] | |||||
return key in self.p1() | |||||
def _existsinparent(self, path): | def _existsinparent(self, path): | ||||
try: | try: | ||||
# ``commitctx` raises a ``ManifestLookupError`` if a path does not | # ``commitctx` raises a ``ManifestLookupError`` if a path does not | ||||
# exist, unlike ``workingctx``, which returns a ``workingfilectx`` | # exist, unlike ``workingctx``, which returns a ``workingfilectx`` | ||||
# with an ``exists()`` function. | # with an ``exists()`` function. | ||||
self._wrappedctx[path] | self._wrappedctx[path] | ||||
return True | return True | ||||
except error.ManifestLookupError: | except error.ManifestLookupError: | ||||
"%s." % (path, component, | "%s." % (path, component, | ||||
self.p1().rev())) | self.p1().rev())) | ||||
# Test that each new directory to be created to write this path from p2 | # Test that each new directory to be created to write this path from p2 | ||||
# is not a file in p1. | # is not a file in p1. | ||||
components = path.split('/') | components = path.split('/') | ||||
for i in pycompat.xrange(len(components)): | for i in pycompat.xrange(len(components)): | ||||
component = "/".join(components[0:i]) | component = "/".join(components[0:i]) | ||||
if component in self.p1() and self._cache[component]['exists']: | if component in self: | ||||
fail(path, component) | fail(path, component) | ||||
# Test the other direction -- that this path from p2 isn't a directory | # Test the other direction -- that this path from p2 isn't a directory | ||||
# in p1 (test that p1 doesn't any paths matching `path/*`). | # in p1 (test that p1 doesn't any paths matching `path/*`). | ||||
match = matchmod.match('/', '', [path + '/'], default=b'relpath') | match = matchmod.match('/', '', [path + '/'], default=b'relpath') | ||||
matches = self.p1().manifest().matches(match) | matches = self.p1().manifest().matches(match) | ||||
mfiles = matches.keys() | mfiles = matches.keys() | ||||
if len(mfiles) > 0: | if len(mfiles) > 0: | ||||
if len(mfiles) == 1 and mfiles[0] == path: | if len(mfiles) == 1 and mfiles[0] == path: | ||||
return | return | ||||
# omit the files which are deleted in current IMM wctx | # omit the files which are deleted in current IMM wctx | ||||
mfiles = [m for m in mfiles if self._cache[m]['exists']] | mfiles = [m for m in mfiles if m in self] | ||||
if not mfiles: | if not mfiles: | ||||
return | return | ||||
raise error.Abort("error: file '%s' cannot be written because " | raise error.Abort("error: file '%s' cannot be written because " | ||||
" '%s/' is a folder in %s (containing %d " | " '%s/' is a folder in %s (containing %d " | ||||
"entries: %s)" | "entries: %s)" | ||||
% (path, path, self.p1(), len(mfiles), | % (path, path, self.p1(), len(mfiles), | ||||
', '.join(mfiles))) | ', '.join(mfiles))) | ||||
o | 1: fc055c3b4d33 'b' | o | 1: fc055c3b4d33 'b' | ||||
|/ | |/ | ||||
o 0: b173517d0057 'a' | o 0: b173517d0057 'a' | ||||
$ mkdir c | $ mkdir c | ||||
$ echo c > c/c | $ echo c > c/c | ||||
$ hg add c/c | $ hg add c/c | ||||
$ hg ci -m 'c/c' | $ hg ci -m 'c/c' | ||||
BROKEN: This should be a conflict, should not crash | $ hg rebase -r . -d 3 -n | ||||
$ hg rebase -r . -d 3 -n 2>&1 | grep KeyError | starting dry-run rebase; repository will not be changed | ||||
KeyError: 'c' | rebasing 8:755f0104af9b "c/c" (tip) | ||||
BROKEN: This should be a conflict, should not crash | abort: error: 'c/c' conflicts with file 'c' in 3. | ||||
$ hg rebase -r 3 -d . -n 2>&1 | grep KeyError | [255] | ||||
KeyError: 'c/c' | $ hg rebase -r 3 -d . -n | ||||
starting dry-run rebase; repository will not be changed | |||||
rebasing 3:844a7de3e617 "c" | |||||
abort: error: file 'c' cannot be written because 'c/' is a folder in 755f0104af9b (containing 1 entries: c/c) | |||||
[255] | |||||
$ cd .. | $ cd .. | ||||
Test dry-run rebasing | Test dry-run rebasing | ||||
$ hg init repo3 | $ hg init repo3 | ||||
$ cd repo3 | $ cd repo3 | ||||
$ echo a>a | $ echo a>a |