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 | ||||