Mercurial > public > mercurial-scm > hg
comparison mercurial/localrepo.py @ 49571:8fa3f7c3a9ad
typing: add basic type hints to localrepo.py
There's a lot more that could be done, but this sticks to the obviously correct
stuff that is either related to existing imports or primitives. Hopefully this
helps smoke out more path related bytes vs str issues in TortoiseHg.
I'm avoiding the interfaces for now, because they seem to confuse pytype and/or
PyCharm. It might be worth typing the return of `makelocalrepository` to
`localrepository`, but that leaks an implementation detail, so that can be
revisited later.
author | Matt Harbison <matt_harbison@yahoo.com> |
---|---|
date | Wed, 02 Nov 2022 16:43:01 -0400 |
parents | 4367c46a89ee |
children | 18282cf18aa2 |
comparison
equal
deleted
inserted
replaced
49570:3a2b6158374a | 49571:8fa3f7c3a9ad |
---|---|
13 import sys | 13 import sys |
14 import time | 14 import time |
15 import weakref | 15 import weakref |
16 | 16 |
17 from concurrent import futures | 17 from concurrent import futures |
18 from typing import ( | |
19 Optional, | |
20 ) | |
21 | |
18 from .i18n import _ | 22 from .i18n import _ |
19 from .node import ( | 23 from .node import ( |
20 bin, | 24 bin, |
21 hex, | 25 hex, |
22 nullrev, | 26 nullrev, |
524 # a missing file translates to no requirements. | 528 # a missing file translates to no requirements. |
525 read = vfs.tryread if allowmissing else vfs.read | 529 read = vfs.tryread if allowmissing else vfs.read |
526 return set(read(b'requires').splitlines()) | 530 return set(read(b'requires').splitlines()) |
527 | 531 |
528 | 532 |
529 def makelocalrepository(baseui, path, intents=None): | 533 def makelocalrepository(baseui, path: bytes, intents=None): |
530 """Create a local repository object. | 534 """Create a local repository object. |
531 | 535 |
532 Given arguments needed to construct a local repository, this function | 536 Given arguments needed to construct a local repository, this function |
533 performs various early repository loading functionality (such as | 537 performs various early repository loading functionality (such as |
534 reading the ``.hg/requires`` and ``.hg/hgrc`` files), validates that | 538 reading the ``.hg/requires`` and ``.hg/hgrc`` files), validates that |
843 features=features, | 847 features=features, |
844 intents=intents, | 848 intents=intents, |
845 ) | 849 ) |
846 | 850 |
847 | 851 |
848 def loadhgrc(ui, wdirvfs, hgvfs, requirements, sharedvfs=None): | 852 def loadhgrc( |
853 ui, | |
854 wdirvfs: vfsmod.vfs, | |
855 hgvfs: vfsmod.vfs, | |
856 requirements, | |
857 sharedvfs: Optional[vfsmod.vfs] = None, | |
858 ): | |
849 """Load hgrc files/content into a ui instance. | 859 """Load hgrc files/content into a ui instance. |
850 | 860 |
851 This is called during repository opening to load any additional | 861 This is called during repository opening to load any additional |
852 config files or settings relevant to the current repository. | 862 config files or settings relevant to the current repository. |
853 | 863 |
1321 | 1331 |
1322 def __init__( | 1332 def __init__( |
1323 self, | 1333 self, |
1324 baseui, | 1334 baseui, |
1325 ui, | 1335 ui, |
1326 origroot, | 1336 origroot: bytes, |
1327 wdirvfs, | 1337 wdirvfs: vfsmod.vfs, |
1328 hgvfs, | 1338 hgvfs: vfsmod.vfs, |
1329 requirements, | 1339 requirements, |
1330 supportedrequirements, | 1340 supportedrequirements, |
1331 sharedpath, | 1341 sharedpath: bytes, |
1332 store, | 1342 store, |
1333 cachevfs, | 1343 cachevfs: vfsmod.vfs, |
1334 wcachevfs, | 1344 wcachevfs: vfsmod.vfs, |
1335 features, | 1345 features, |
1336 intents=None, | 1346 intents=None, |
1337 ): | 1347 ): |
1338 """Create a new local repository instance. | 1348 """Create a new local repository instance. |
1339 | 1349 |
1975 return len(unfi.changelog) | 1985 return len(unfi.changelog) |
1976 | 1986 |
1977 def __iter__(self): | 1987 def __iter__(self): |
1978 return iter(self.changelog) | 1988 return iter(self.changelog) |
1979 | 1989 |
1980 def revs(self, expr, *args): | 1990 def revs(self, expr: bytes, *args): |
1981 """Find revisions matching a revset. | 1991 """Find revisions matching a revset. |
1982 | 1992 |
1983 The revset is specified as a string ``expr`` that may contain | 1993 The revset is specified as a string ``expr`` that may contain |
1984 %-formatting to escape certain types. See ``revsetlang.formatspec``. | 1994 %-formatting to escape certain types. See ``revsetlang.formatspec``. |
1985 | 1995 |
1991 that contains integer revisions. | 2001 that contains integer revisions. |
1992 """ | 2002 """ |
1993 tree = revsetlang.spectree(expr, *args) | 2003 tree = revsetlang.spectree(expr, *args) |
1994 return revset.makematcher(tree)(self) | 2004 return revset.makematcher(tree)(self) |
1995 | 2005 |
1996 def set(self, expr, *args): | 2006 def set(self, expr: bytes, *args): |
1997 """Find revisions matching a revset and emit changectx instances. | 2007 """Find revisions matching a revset and emit changectx instances. |
1998 | 2008 |
1999 This is a convenience wrapper around ``revs()`` that iterates the | 2009 This is a convenience wrapper around ``revs()`` that iterates the |
2000 result and is a generator of changectx instances. | 2010 result and is a generator of changectx instances. |
2001 | 2011 |
2003 user aliases, consider calling ``scmutil.revrange()``. | 2013 user aliases, consider calling ``scmutil.revrange()``. |
2004 """ | 2014 """ |
2005 for r in self.revs(expr, *args): | 2015 for r in self.revs(expr, *args): |
2006 yield self[r] | 2016 yield self[r] |
2007 | 2017 |
2008 def anyrevs(self, specs, user=False, localalias=None): | 2018 def anyrevs(self, specs: bytes, user=False, localalias=None): |
2009 """Find revisions matching one of the given revsets. | 2019 """Find revisions matching one of the given revsets. |
2010 | 2020 |
2011 Revset aliases from the configuration are not expanded by default. To | 2021 Revset aliases from the configuration are not expanded by default. To |
2012 expand user aliases, specify ``user=True``. To provide some local | 2022 expand user aliases, specify ``user=True``. To provide some local |
2013 definitions overriding user aliases, set ``localalias`` to | 2023 definitions overriding user aliases, set ``localalias`` to |
2028 ) | 2038 ) |
2029 else: | 2039 else: |
2030 m = revset.matchany(None, specs, localalias=localalias) | 2040 m = revset.matchany(None, specs, localalias=localalias) |
2031 return m(self) | 2041 return m(self) |
2032 | 2042 |
2033 def url(self): | 2043 def url(self) -> bytes: |
2034 return b'file:' + self.root | 2044 return b'file:' + self.root |
2035 | 2045 |
2036 def hook(self, name, throw=False, **args): | 2046 def hook(self, name, throw=False, **args): |
2037 """Call a hook, passing this repo instance. | 2047 """Call a hook, passing this repo instance. |
2038 | 2048 |
2227 '''the type of shared repository (None if not shared)''' | 2237 '''the type of shared repository (None if not shared)''' |
2228 if self.sharedpath != self.path: | 2238 if self.sharedpath != self.path: |
2229 return b'store' | 2239 return b'store' |
2230 return None | 2240 return None |
2231 | 2241 |
2232 def wjoin(self, f, *insidef): | 2242 def wjoin(self, f: bytes, *insidef: bytes) -> bytes: |
2233 return self.vfs.reljoin(self.root, f, *insidef) | 2243 return self.vfs.reljoin(self.root, f, *insidef) |
2234 | 2244 |
2235 def setparents(self, p1, p2=None): | 2245 def setparents(self, p1, p2=None): |
2236 if p2 is None: | 2246 if p2 is None: |
2237 p2 = self.nullid | 2247 p2 = self.nullid |
2238 self[None].setparents(p1, p2) | 2248 self[None].setparents(p1, p2) |
2239 self._quick_access_changeid_invalidate() | 2249 self._quick_access_changeid_invalidate() |
2240 | 2250 |
2241 def filectx(self, path, changeid=None, fileid=None, changectx=None): | 2251 def filectx(self, path: bytes, changeid=None, fileid=None, changectx=None): |
2242 """changeid must be a changeset revision, if specified. | 2252 """changeid must be a changeset revision, if specified. |
2243 fileid can be a file revision or node.""" | 2253 fileid can be a file revision or node.""" |
2244 return context.filectx( | 2254 return context.filectx( |
2245 self, path, changeid, fileid, changectx=changectx | 2255 self, path, changeid, fileid, changectx=changectx |
2246 ) | 2256 ) |
2247 | 2257 |
2248 def getcwd(self): | 2258 def getcwd(self) -> bytes: |
2249 return self.dirstate.getcwd() | 2259 return self.dirstate.getcwd() |
2250 | 2260 |
2251 def pathto(self, f, cwd=None): | 2261 def pathto(self, f: bytes, cwd: Optional[bytes] = None) -> bytes: |
2252 return self.dirstate.pathto(f, cwd) | 2262 return self.dirstate.pathto(f, cwd) |
2253 | 2263 |
2254 def _loadfilter(self, filter): | 2264 def _loadfilter(self, filter): |
2255 if filter not in self._filterpats: | 2265 if filter not in self._filterpats: |
2256 l = [] | 2266 l = [] |
2298 return self._loadfilter(b'decode') | 2308 return self._loadfilter(b'decode') |
2299 | 2309 |
2300 def adddatafilter(self, name, filter): | 2310 def adddatafilter(self, name, filter): |
2301 self._datafilters[name] = filter | 2311 self._datafilters[name] = filter |
2302 | 2312 |
2303 def wread(self, filename): | 2313 def wread(self, filename: bytes) -> bytes: |
2304 if self.wvfs.islink(filename): | 2314 if self.wvfs.islink(filename): |
2305 data = self.wvfs.readlink(filename) | 2315 data = self.wvfs.readlink(filename) |
2306 else: | 2316 else: |
2307 data = self.wvfs.read(filename) | 2317 data = self.wvfs.read(filename) |
2308 return self._filter(self._encodefilterpats, filename, data) | 2318 return self._filter(self._encodefilterpats, filename, data) |
2309 | 2319 |
2310 def wwrite(self, filename, data, flags, backgroundclose=False, **kwargs): | 2320 def wwrite( |
2321 self, | |
2322 filename: bytes, | |
2323 data: bytes, | |
2324 flags: bytes, | |
2325 backgroundclose=False, | |
2326 **kwargs | |
2327 ) -> int: | |
2311 """write ``data`` into ``filename`` in the working directory | 2328 """write ``data`` into ``filename`` in the working directory |
2312 | 2329 |
2313 This returns length of written (maybe decoded) data. | 2330 This returns length of written (maybe decoded) data. |
2314 """ | 2331 """ |
2315 data = self._filter(self._decodefilterpats, filename, data) | 2332 data = self._filter(self._decodefilterpats, filename, data) |
2323 self.wvfs.setflags(filename, False, True) | 2340 self.wvfs.setflags(filename, False, True) |
2324 else: | 2341 else: |
2325 self.wvfs.setflags(filename, False, False) | 2342 self.wvfs.setflags(filename, False, False) |
2326 return len(data) | 2343 return len(data) |
2327 | 2344 |
2328 def wwritedata(self, filename, data): | 2345 def wwritedata(self, filename: bytes, data: bytes) -> bytes: |
2329 return self._filter(self._decodefilterpats, filename, data) | 2346 return self._filter(self._decodefilterpats, filename, data) |
2330 | 2347 |
2331 def currenttransaction(self): | 2348 def currenttransaction(self): |
2332 """return the current transaction or None if non exists""" | 2349 """return the current transaction or None if non exists""" |
2333 if self._transref: | 2350 if self._transref: |
3518 pass | 3535 pass |
3519 | 3536 |
3520 return a | 3537 return a |
3521 | 3538 |
3522 | 3539 |
3523 def undoname(fn): | 3540 def undoname(fn: bytes) -> bytes: |
3524 base, name = os.path.split(fn) | 3541 base, name = os.path.split(fn) |
3525 assert name.startswith(b'journal') | 3542 assert name.startswith(b'journal') |
3526 return os.path.join(base, name.replace(b'journal', b'undo', 1)) | 3543 return os.path.join(base, name.replace(b'journal', b'undo', 1)) |
3527 | 3544 |
3528 | 3545 |
3529 def instance(ui, path, create, intents=None, createopts=None): | 3546 def instance(ui, path: bytes, create, intents=None, createopts=None): |
3530 | 3547 |
3531 # prevent cyclic import localrepo -> upgrade -> localrepo | 3548 # prevent cyclic import localrepo -> upgrade -> localrepo |
3532 from . import upgrade | 3549 from . import upgrade |
3533 | 3550 |
3534 localpath = urlutil.urllocalpath(path) | 3551 localpath = urlutil.urllocalpath(path) |
3541 repo = repo_maker() | 3558 repo = repo_maker() |
3542 repo = upgrade.may_auto_upgrade(repo, repo_maker) | 3559 repo = upgrade.may_auto_upgrade(repo, repo_maker) |
3543 return repo | 3560 return repo |
3544 | 3561 |
3545 | 3562 |
3546 def islocal(path): | 3563 def islocal(path: bytes) -> bool: |
3547 return True | 3564 return True |
3548 | 3565 |
3549 | 3566 |
3550 def defaultcreateopts(ui, createopts=None): | 3567 def defaultcreateopts(ui, createopts=None): |
3551 """Populate the default creation options for a repository. | 3568 """Populate the default creation options for a repository. |
3799 } | 3816 } |
3800 | 3817 |
3801 return {k: v for k, v in createopts.items() if k not in known} | 3818 return {k: v for k, v in createopts.items() if k not in known} |
3802 | 3819 |
3803 | 3820 |
3804 def createrepository(ui, path, createopts=None, requirements=None): | 3821 def createrepository(ui, path: bytes, createopts=None, requirements=None): |
3805 """Create a new repository in a vfs. | 3822 """Create a new repository in a vfs. |
3806 | 3823 |
3807 ``path`` path to the new repo's working directory. | 3824 ``path`` path to the new repo's working directory. |
3808 ``createopts`` options for the new repository. | 3825 ``createopts`` options for the new repository. |
3809 ``requirement`` predefined set of requirements. | 3826 ``requirement`` predefined set of requirements. |