Mercurial > public > mercurial-scm > hg
comparison mercurial/context.py @ 35324:72fbdd373de8
overlayworkingctx: add _auditconflicts to write()
Alas, part of Mercurial's conflict detection (for file<->folder conflicts,
for example) depends on the filesystem. We don't have the filesystem with IMM,
so we have to run these checks ourselves.
Differential Revision: https://phab.mercurial-scm.org/D1241
author | Phil Cohen <phillco@fb.com> |
---|---|
date | Thu, 07 Dec 2017 16:07:06 -0800 |
parents | 8e1386b342f7 |
children | 71edd38c4bb4 |
comparison
equal
deleted
inserted
replaced
35323:8e1386b342f7 | 35324:72fbdd373de8 |
---|---|
2090 self._wrappedctx[path] | 2090 self._wrappedctx[path] |
2091 return True | 2091 return True |
2092 except error.ManifestLookupError: | 2092 except error.ManifestLookupError: |
2093 return False | 2093 return False |
2094 | 2094 |
2095 def _auditconflicts(self, path): | |
2096 """Replicates conflict checks done by wvfs.write(). | |
2097 | |
2098 Since we never write to the filesystem and never call `applyupdates` in | |
2099 IMM, we'll never check that a path is actually writable -- e.g., because | |
2100 it adds `a/foo`, but `a` is actually a file in the other commit. | |
2101 """ | |
2102 def fail(path, component): | |
2103 # p1() is the base and we're receiving "writes" for p2()'s | |
2104 # files. | |
2105 if 'l' in self.p1()[component].flags(): | |
2106 raise error.Abort("error: %s conflicts with symlink %s " | |
2107 "in %s." % (path, component, | |
2108 self.p1().rev())) | |
2109 else: | |
2110 raise error.Abort("error: '%s' conflicts with file '%s' in " | |
2111 "%s." % (path, component, | |
2112 self.p1().rev())) | |
2113 | |
2114 # Test that each new directory to be created to write this path from p2 | |
2115 # is not a file in p1. | |
2116 components = path.split('/') | |
2117 for i in xrange(len(components)): | |
2118 component = "/".join(components[0:i]) | |
2119 if component in self.p1(): | |
2120 fail(path, component) | |
2121 | |
2122 # Test the other direction -- that this path from p2 isn't a directory | |
2123 # in p1 (test that p1 doesn't any paths matching `path/*`). | |
2124 match = matchmod.match('/', '', [path + '/'], default=b'relpath') | |
2125 matches = self.p1().manifest().matches(match) | |
2126 if len(matches) > 0: | |
2127 if len(matches) == 1 and matches.keys()[0] == path: | |
2128 return | |
2129 raise error.Abort("error: file '%s' cannot be written because " | |
2130 " '%s/' is a folder in %s (containing %d " | |
2131 "entries: %s)" | |
2132 % (path, path, self.p1(), len(matches), | |
2133 ', '.join(matches.keys()))) | |
2134 | |
2095 def write(self, path, data, flags=''): | 2135 def write(self, path, data, flags=''): |
2096 if data is None: | 2136 if data is None: |
2097 raise error.ProgrammingError("data must be non-None") | 2137 raise error.ProgrammingError("data must be non-None") |
2138 self._auditconflicts(path) | |
2098 self._markdirty(path, exists=True, data=data, date=util.makedate(), | 2139 self._markdirty(path, exists=True, data=data, date=util.makedate(), |
2099 flags=flags) | 2140 flags=flags) |
2100 | 2141 |
2101 def setflags(self, path, l, x): | 2142 def setflags(self, path, l, x): |
2102 self._markdirty(path, exists=True, date=util.makedate(), | 2143 self._markdirty(path, exists=True, date=util.makedate(), |