550 _(b"(deprecated '%%' in path %s=%s from %s)\n") |
557 _(b"(deprecated '%%' in path %s=%s from %s)\n") |
551 % (n, p, s) |
558 % (n, p, s) |
552 ) |
559 ) |
553 p = p.replace(b'%%', b'%') |
560 p = p.replace(b'%%', b'%') |
554 p = util.expandpath(p) |
561 p = util.expandpath(p) |
555 if not util.hasscheme(p) and not os.path.isabs(p): |
562 if not urlutil.hasscheme(p) and not os.path.isabs(p): |
556 p = os.path.normpath(os.path.join(root, p)) |
563 p = os.path.normpath(os.path.join(root, p)) |
557 c.set(b"paths", n, p) |
564 c.alter(b"paths", n, p) |
558 |
565 |
559 if section in (None, b'ui'): |
566 if section in (None, b'ui'): |
560 # update ui options |
567 # update ui options |
561 self._fmsgout, self._fmsgerr = _selectmsgdests(self) |
568 self._fmsgout, self._fmsgerr = _selectmsgdests(self) |
562 self.debugflag = self.configbool(b'ui', b'debug') |
569 self.debugflag = self.configbool(b'ui', b'debug') |
653 b"config item: '%s.%s' '%s'" |
660 b"config item: '%s.%s' '%s'" |
654 ) |
661 ) |
655 msg %= (section, name, pycompat.bytestr(default)) |
662 msg %= (section, name, pycompat.bytestr(default)) |
656 self.develwarn(msg, 2, b'warn-config-default') |
663 self.develwarn(msg, 2, b'warn-config-default') |
657 |
664 |
|
665 candidates = [] |
|
666 config = self._data(untrusted) |
658 for s, n in alternates: |
667 for s, n in alternates: |
659 candidate = self._data(untrusted).get(s, n, None) |
668 candidate = config.get(s, n, None) |
660 if candidate is not None: |
669 if candidate is not None: |
661 value = candidate |
670 candidates.append((s, n, candidate)) |
662 break |
671 if candidates: |
|
672 |
|
673 def level(x): |
|
674 return config.level(x[0], x[1]) |
|
675 |
|
676 value = max(candidates, key=level)[2] |
663 |
677 |
664 if self.debugflag and not untrusted and self._reportuntrusted: |
678 if self.debugflag and not untrusted and self._reportuntrusted: |
665 for s, n in alternates: |
679 for s, n in alternates: |
666 uvalue = self._ucfg.get(s, n) |
680 uvalue = self._ucfg.get(s, n) |
667 if uvalue is not None and uvalue != value: |
681 if uvalue is not None and uvalue != value: |
1014 user = stringutil.shortuser(user) |
1028 user = stringutil.shortuser(user) |
1015 return user |
1029 return user |
1016 |
1030 |
1017 def expandpath(self, loc, default=None): |
1031 def expandpath(self, loc, default=None): |
1018 """Return repository location relative to cwd or from [paths]""" |
1032 """Return repository location relative to cwd or from [paths]""" |
|
1033 msg = b'ui.expandpath is deprecated, use `get_*` functions from urlutil' |
|
1034 self.deprecwarn(msg, b'6.0') |
1019 try: |
1035 try: |
1020 p = self.paths.getpath(loc) |
1036 p = self.getpath(loc) |
1021 if p: |
1037 if p: |
1022 return p.rawloc |
1038 return p.rawloc |
1023 except error.RepoError: |
1039 except error.RepoError: |
1024 pass |
1040 pass |
1025 |
1041 |
1026 if default: |
1042 if default: |
1027 try: |
1043 try: |
1028 p = self.paths.getpath(default) |
1044 p = self.getpath(default) |
1029 if p: |
1045 if p: |
1030 return p.rawloc |
1046 return p.rawloc |
1031 except error.RepoError: |
1047 except error.RepoError: |
1032 pass |
1048 pass |
1033 |
1049 |
1034 return loc |
1050 return loc |
1035 |
1051 |
1036 @util.propertycache |
1052 @util.propertycache |
1037 def paths(self): |
1053 def paths(self): |
1038 return paths(self) |
1054 return urlutil.paths(self) |
|
1055 |
|
1056 def getpath(self, *args, **kwargs): |
|
1057 """see paths.getpath for details |
|
1058 |
|
1059 This method exist as `getpath` need a ui for potential warning message. |
|
1060 """ |
|
1061 return self.paths.getpath(self, *args, **kwargs) |
1039 |
1062 |
1040 @property |
1063 @property |
1041 def fout(self): |
1064 def fout(self): |
1042 return self._fout |
1065 return self._fout |
1043 |
1066 |
2157 _(b"ui.available-memory value is invalid ('%s')") % value |
2180 _(b"ui.available-memory value is invalid ('%s')") % value |
2158 ) |
2181 ) |
2159 return util._estimatememory() |
2182 return util._estimatememory() |
2160 |
2183 |
2161 |
2184 |
2162 class paths(dict): |
|
2163 """Represents a collection of paths and their configs. |
|
2164 |
|
2165 Data is initially derived from ui instances and the config files they have |
|
2166 loaded. |
|
2167 """ |
|
2168 |
|
2169 def __init__(self, ui): |
|
2170 dict.__init__(self) |
|
2171 |
|
2172 for name, loc in ui.configitems(b'paths', ignoresub=True): |
|
2173 # No location is the same as not existing. |
|
2174 if not loc: |
|
2175 continue |
|
2176 loc, sub = ui.configsuboptions(b'paths', name) |
|
2177 self[name] = path(ui, name, rawloc=loc, suboptions=sub) |
|
2178 |
|
2179 def getpath(self, name, default=None): |
|
2180 """Return a ``path`` from a string, falling back to default. |
|
2181 |
|
2182 ``name`` can be a named path or locations. Locations are filesystem |
|
2183 paths or URIs. |
|
2184 |
|
2185 Returns None if ``name`` is not a registered path, a URI, or a local |
|
2186 path to a repo. |
|
2187 """ |
|
2188 # Only fall back to default if no path was requested. |
|
2189 if name is None: |
|
2190 if not default: |
|
2191 default = () |
|
2192 elif not isinstance(default, (tuple, list)): |
|
2193 default = (default,) |
|
2194 for k in default: |
|
2195 try: |
|
2196 return self[k] |
|
2197 except KeyError: |
|
2198 continue |
|
2199 return None |
|
2200 |
|
2201 # Most likely empty string. |
|
2202 # This may need to raise in the future. |
|
2203 if not name: |
|
2204 return None |
|
2205 |
|
2206 try: |
|
2207 return self[name] |
|
2208 except KeyError: |
|
2209 # Try to resolve as a local path or URI. |
|
2210 try: |
|
2211 # We don't pass sub-options in, so no need to pass ui instance. |
|
2212 return path(None, None, rawloc=name) |
|
2213 except ValueError: |
|
2214 raise error.RepoError(_(b'repository %s does not exist') % name) |
|
2215 |
|
2216 |
|
2217 _pathsuboptions = {} |
|
2218 |
|
2219 |
|
2220 def pathsuboption(option, attr): |
|
2221 """Decorator used to declare a path sub-option. |
|
2222 |
|
2223 Arguments are the sub-option name and the attribute it should set on |
|
2224 ``path`` instances. |
|
2225 |
|
2226 The decorated function will receive as arguments a ``ui`` instance, |
|
2227 ``path`` instance, and the string value of this option from the config. |
|
2228 The function should return the value that will be set on the ``path`` |
|
2229 instance. |
|
2230 |
|
2231 This decorator can be used to perform additional verification of |
|
2232 sub-options and to change the type of sub-options. |
|
2233 """ |
|
2234 |
|
2235 def register(func): |
|
2236 _pathsuboptions[option] = (attr, func) |
|
2237 return func |
|
2238 |
|
2239 return register |
|
2240 |
|
2241 |
|
2242 @pathsuboption(b'pushurl', b'pushloc') |
|
2243 def pushurlpathoption(ui, path, value): |
|
2244 u = util.url(value) |
|
2245 # Actually require a URL. |
|
2246 if not u.scheme: |
|
2247 ui.warn(_(b'(paths.%s:pushurl not a URL; ignoring)\n') % path.name) |
|
2248 return None |
|
2249 |
|
2250 # Don't support the #foo syntax in the push URL to declare branch to |
|
2251 # push. |
|
2252 if u.fragment: |
|
2253 ui.warn( |
|
2254 _( |
|
2255 b'("#fragment" in paths.%s:pushurl not supported; ' |
|
2256 b'ignoring)\n' |
|
2257 ) |
|
2258 % path.name |
|
2259 ) |
|
2260 u.fragment = None |
|
2261 |
|
2262 return bytes(u) |
|
2263 |
|
2264 |
|
2265 @pathsuboption(b'pushrev', b'pushrev') |
|
2266 def pushrevpathoption(ui, path, value): |
|
2267 return value |
|
2268 |
|
2269 |
|
2270 class path(object): |
|
2271 """Represents an individual path and its configuration.""" |
|
2272 |
|
2273 def __init__(self, ui, name, rawloc=None, suboptions=None): |
|
2274 """Construct a path from its config options. |
|
2275 |
|
2276 ``ui`` is the ``ui`` instance the path is coming from. |
|
2277 ``name`` is the symbolic name of the path. |
|
2278 ``rawloc`` is the raw location, as defined in the config. |
|
2279 ``pushloc`` is the raw locations pushes should be made to. |
|
2280 |
|
2281 If ``name`` is not defined, we require that the location be a) a local |
|
2282 filesystem path with a .hg directory or b) a URL. If not, |
|
2283 ``ValueError`` is raised. |
|
2284 """ |
|
2285 if not rawloc: |
|
2286 raise ValueError(b'rawloc must be defined') |
|
2287 |
|
2288 # Locations may define branches via syntax <base>#<branch>. |
|
2289 u = util.url(rawloc) |
|
2290 branch = None |
|
2291 if u.fragment: |
|
2292 branch = u.fragment |
|
2293 u.fragment = None |
|
2294 |
|
2295 self.url = u |
|
2296 self.branch = branch |
|
2297 |
|
2298 self.name = name |
|
2299 self.rawloc = rawloc |
|
2300 self.loc = b'%s' % u |
|
2301 |
|
2302 # When given a raw location but not a symbolic name, validate the |
|
2303 # location is valid. |
|
2304 if not name and not u.scheme and not self._isvalidlocalpath(self.loc): |
|
2305 raise ValueError( |
|
2306 b'location is not a URL or path to a local ' |
|
2307 b'repo: %s' % rawloc |
|
2308 ) |
|
2309 |
|
2310 suboptions = suboptions or {} |
|
2311 |
|
2312 # Now process the sub-options. If a sub-option is registered, its |
|
2313 # attribute will always be present. The value will be None if there |
|
2314 # was no valid sub-option. |
|
2315 for suboption, (attr, func) in pycompat.iteritems(_pathsuboptions): |
|
2316 if suboption not in suboptions: |
|
2317 setattr(self, attr, None) |
|
2318 continue |
|
2319 |
|
2320 value = func(ui, self, suboptions[suboption]) |
|
2321 setattr(self, attr, value) |
|
2322 |
|
2323 def _isvalidlocalpath(self, path): |
|
2324 """Returns True if the given path is a potentially valid repository. |
|
2325 This is its own function so that extensions can change the definition of |
|
2326 'valid' in this case (like when pulling from a git repo into a hg |
|
2327 one).""" |
|
2328 try: |
|
2329 return os.path.isdir(os.path.join(path, b'.hg')) |
|
2330 # Python 2 may return TypeError. Python 3, ValueError. |
|
2331 except (TypeError, ValueError): |
|
2332 return False |
|
2333 |
|
2334 @property |
|
2335 def suboptions(self): |
|
2336 """Return sub-options and their values for this path. |
|
2337 |
|
2338 This is intended to be used for presentation purposes. |
|
2339 """ |
|
2340 d = {} |
|
2341 for subopt, (attr, _func) in pycompat.iteritems(_pathsuboptions): |
|
2342 value = getattr(self, attr) |
|
2343 if value is not None: |
|
2344 d[subopt] = value |
|
2345 return d |
|
2346 |
|
2347 |
|
2348 # we instantiate one globally shared progress bar to avoid |
2185 # we instantiate one globally shared progress bar to avoid |
2349 # competing progress bars when multiple UI objects get created |
2186 # competing progress bars when multiple UI objects get created |
2350 _progresssingleton = None |
2187 _progresssingleton = None |
2351 |
2188 |
2352 |
2189 |