Show More
@@ -1661,6 +1661,9 class workingctx(committablectx): | |||||
1661 | listsubrepos=listsubrepos, badfn=badfn, |
|
1661 | listsubrepos=listsubrepos, badfn=badfn, | |
1662 | icasefs=icasefs) |
|
1662 | icasefs=icasefs) | |
1663 |
|
1663 | |||
|
1664 | def flushall(self): | |||
|
1665 | pass # For overlayworkingfilectx compatibility. | |||
|
1666 | ||||
1664 | def _filtersuspectsymlink(self, files): |
|
1667 | def _filtersuspectsymlink(self, files): | |
1665 | if not files or self._repo.dirstate._checklink: |
|
1668 | if not files or self._repo.dirstate._checklink: | |
1666 | return files |
|
1669 | return files | |
@@ -1974,6 +1977,191 class workingfilectx(committablefilectx) | |||||
1974 | def setflags(self, l, x): |
|
1977 | def setflags(self, l, x): | |
1975 | self._repo.wvfs.setflags(self._path, l, x) |
|
1978 | self._repo.wvfs.setflags(self._path, l, x) | |
1976 |
|
1979 | |||
|
1980 | class overlayworkingctx(workingctx): | |||
|
1981 | """Wraps another mutable context with a write-back cache that can be flushed | |||
|
1982 | at a later time. | |||
|
1983 | ||||
|
1984 | self._cache[path] maps to a dict with keys: { | |||
|
1985 | 'exists': bool? | |||
|
1986 | 'date': date? | |||
|
1987 | 'data': str? | |||
|
1988 | 'flags': str? | |||
|
1989 | } | |||
|
1990 | If `exists` is True, `flags` must be non-None and 'date' is non-None. If it | |||
|
1991 | is `False`, the file was deleted. | |||
|
1992 | """ | |||
|
1993 | ||||
|
1994 | def __init__(self, repo, wrappedctx): | |||
|
1995 | super(overlayworkingctx, self).__init__(repo) | |||
|
1996 | self._repo = repo | |||
|
1997 | self._wrappedctx = wrappedctx | |||
|
1998 | self._clean() | |||
|
1999 | ||||
|
2000 | def data(self, path): | |||
|
2001 | if self.isdirty(path): | |||
|
2002 | if self._cache[path]['exists']: | |||
|
2003 | if self._cache[path]['data']: | |||
|
2004 | return self._cache[path]['data'] | |||
|
2005 | else: | |||
|
2006 | # Must fallback here, too, because we only set flags. | |||
|
2007 | return self._wrappedctx[path].data() | |||
|
2008 | else: | |||
|
2009 | raise error.ProgrammingError("No such file or directory: %s" % | |||
|
2010 | self._path) | |||
|
2011 | else: | |||
|
2012 | return self._wrappedctx[path].data() | |||
|
2013 | ||||
|
2014 | def filedate(self, path): | |||
|
2015 | if self.isdirty(path): | |||
|
2016 | return self._cache[path]['date'] | |||
|
2017 | else: | |||
|
2018 | return self._wrappedctx[path].date() | |||
|
2019 | ||||
|
2020 | def flags(self, path): | |||
|
2021 | if self.isdirty(path): | |||
|
2022 | if self._cache[path]['exists']: | |||
|
2023 | return self._cache[path]['flags'] | |||
|
2024 | else: | |||
|
2025 | raise error.ProgrammingError("No such file or directory: %s" % | |||
|
2026 | self._path) | |||
|
2027 | else: | |||
|
2028 | return self._wrappedctx[path].flags() | |||
|
2029 | ||||
|
2030 | def write(self, path, data, flags=''): | |||
|
2031 | if data is None: | |||
|
2032 | raise error.ProgrammingError("data must be non-None") | |||
|
2033 | self._markdirty(path, exists=True, data=data, date=util.makedate(), | |||
|
2034 | flags=flags) | |||
|
2035 | ||||
|
2036 | def setflags(self, path, l, x): | |||
|
2037 | self._markdirty(path, exists=True, date=util.makedate(), | |||
|
2038 | flags=(l and 'l' or '') + (x and 'x' or '')) | |||
|
2039 | ||||
|
2040 | def remove(self, path): | |||
|
2041 | self._markdirty(path, exists=False) | |||
|
2042 | ||||
|
2043 | def exists(self, path): | |||
|
2044 | """exists behaves like `lexists`, but needs to follow symlinks and | |||
|
2045 | return False if they are broken. | |||
|
2046 | """ | |||
|
2047 | if self.isdirty(path): | |||
|
2048 | # If this path exists and is a symlink, "follow" it by calling | |||
|
2049 | # exists on the destination path. | |||
|
2050 | if (self._cache[path]['exists'] and | |||
|
2051 | 'l' in self._cache[path]['flags']): | |||
|
2052 | return self.exists(self._cache[path]['data'].strip()) | |||
|
2053 | else: | |||
|
2054 | return self._cache[path]['exists'] | |||
|
2055 | return self._wrappedctx[path].exists() | |||
|
2056 | ||||
|
2057 | def lexists(self, path): | |||
|
2058 | """lexists returns True if the path exists""" | |||
|
2059 | if self.isdirty(path): | |||
|
2060 | return self._cache[path]['exists'] | |||
|
2061 | return self._wrappedctx[path].lexists() | |||
|
2062 | ||||
|
2063 | def size(self, path): | |||
|
2064 | if self.isdirty(path): | |||
|
2065 | if self._cache[path]['exists']: | |||
|
2066 | return len(self._cache[path]['data']) | |||
|
2067 | else: | |||
|
2068 | raise error.ProgrammingError("No such file or directory: %s" % | |||
|
2069 | self._path) | |||
|
2070 | return self._wrappedctx[path].size() | |||
|
2071 | ||||
|
2072 | def flushall(self): | |||
|
2073 | for path in self._writeorder: | |||
|
2074 | entry = self._cache[path] | |||
|
2075 | if entry['exists']: | |||
|
2076 | self._wrappedctx[path].clearunknown() | |||
|
2077 | if entry['data'] is not None: | |||
|
2078 | if entry['flags'] is None: | |||
|
2079 | raise error.ProgrammingError('data set but not flags') | |||
|
2080 | self._wrappedctx[path].write( | |||
|
2081 | entry['data'], | |||
|
2082 | entry['flags']) | |||
|
2083 | else: | |||
|
2084 | self._wrappedctx[path].setflags( | |||
|
2085 | 'l' in entry['flags'], | |||
|
2086 | 'x' in entry['flags']) | |||
|
2087 | else: | |||
|
2088 | self._wrappedctx[path].remove(path) | |||
|
2089 | self._clean() | |||
|
2090 | ||||
|
2091 | def isdirty(self, path): | |||
|
2092 | return path in self._cache | |||
|
2093 | ||||
|
2094 | def _clean(self): | |||
|
2095 | self._cache = {} | |||
|
2096 | self._writeorder = [] | |||
|
2097 | ||||
|
2098 | def _markdirty(self, path, exists, data=None, date=None, flags=''): | |||
|
2099 | if path not in self._cache: | |||
|
2100 | self._writeorder.append(path) | |||
|
2101 | ||||
|
2102 | self._cache[path] = { | |||
|
2103 | 'exists': exists, | |||
|
2104 | 'data': data, | |||
|
2105 | 'date': date, | |||
|
2106 | 'flags': flags, | |||
|
2107 | } | |||
|
2108 | ||||
|
2109 | def filectx(self, path, filelog=None): | |||
|
2110 | return overlayworkingfilectx(self._repo, path, parent=self, | |||
|
2111 | filelog=filelog) | |||
|
2112 | ||||
|
2113 | class overlayworkingfilectx(workingfilectx): | |||
|
2114 | """Wrap a ``workingfilectx`` but intercepts all writes into an in-memory | |||
|
2115 | cache, which can be flushed through later by calling ``flush()``.""" | |||
|
2116 | ||||
|
2117 | def __init__(self, repo, path, filelog=None, parent=None): | |||
|
2118 | super(overlayworkingfilectx, self).__init__(repo, path, filelog, | |||
|
2119 | parent) | |||
|
2120 | self._repo = repo | |||
|
2121 | self._parent = parent | |||
|
2122 | self._path = path | |||
|
2123 | ||||
|
2124 | def ctx(self): | |||
|
2125 | return self._parent | |||
|
2126 | ||||
|
2127 | def data(self): | |||
|
2128 | return self._parent.data(self._path) | |||
|
2129 | ||||
|
2130 | def date(self): | |||
|
2131 | return self._parent.filedate(self._path) | |||
|
2132 | ||||
|
2133 | def exists(self): | |||
|
2134 | return self.lexists() | |||
|
2135 | ||||
|
2136 | def lexists(self): | |||
|
2137 | return self._parent.exists(self._path) | |||
|
2138 | ||||
|
2139 | def renamed(self): | |||
|
2140 | # Copies are currently tracked in the dirstate as before. Straight copy | |||
|
2141 | # from workingfilectx. | |||
|
2142 | rp = self._repo.dirstate.copied(self._path) | |||
|
2143 | if not rp: | |||
|
2144 | return None | |||
|
2145 | return rp, self._changectx._parents[0]._manifest.get(rp, nullid) | |||
|
2146 | ||||
|
2147 | def size(self): | |||
|
2148 | return self._parent.size(self._path) | |||
|
2149 | ||||
|
2150 | def audit(self): | |||
|
2151 | pass | |||
|
2152 | ||||
|
2153 | def flags(self): | |||
|
2154 | return self._parent.flags(self._path) | |||
|
2155 | ||||
|
2156 | def setflags(self, islink, isexec): | |||
|
2157 | return self._parent.setflags(self._path, islink, isexec) | |||
|
2158 | ||||
|
2159 | def write(self, data, flags, backgroundclose=False): | |||
|
2160 | return self._parent.write(self._path, data, flags) | |||
|
2161 | ||||
|
2162 | def remove(self, ignoremissing=False): | |||
|
2163 | return self._parent.remove(self._path) | |||
|
2164 | ||||
1977 | class workingcommitctx(workingctx): |
|
2165 | class workingcommitctx(workingctx): | |
1978 | """A workingcommitctx object makes access to data related to |
|
2166 | """A workingcommitctx object makes access to data related to | |
1979 | the revision being committed convenient. |
|
2167 | the revision being committed convenient. |
General Comments 0
You need to be logged in to leave comments.
Login now