comparison mercurial/hg.py @ 49683:d9791643aab7

peer-or-repo: make sure object in "scheme" have a `instance` object The previous form of having heterogeneous object in the dictionnary makes things more complicated than they needed to be. I am not super happy about the current (especially around 'islocal', that most item do not have), but this is already much better.
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Tue, 29 Nov 2022 19:54:55 +0100
parents 1e6c37360527
children 229e0ed88895
comparison
equal deleted inserted replaced
49682:1e6c37360527 49683:d9791643aab7
63 63
64 # shared features 64 # shared features
65 sharedbookmarks = b'bookmarks' 65 sharedbookmarks = b'bookmarks'
66 66
67 67
68 def _local(path):
69 path = util.expandpath(urlutil.urllocalpath(path))
70
71 try:
72 # we use os.stat() directly here instead of os.path.isfile()
73 # because the latter started returning `False` on invalid path
74 # exceptions starting in 3.8 and we care about handling
75 # invalid paths specially here.
76 st = os.stat(path)
77 isfile = stat.S_ISREG(st.st_mode)
78 except ValueError as e:
79 raise error.Abort(
80 _(b'invalid path %s: %s') % (path, stringutil.forcebytestr(e))
81 )
82 except OSError:
83 isfile = False
84
85 return isfile and bundlerepo or localrepo
86
87
88 def addbranchrevs(lrepo, other, branches, revs): 68 def addbranchrevs(lrepo, other, branches, revs):
89 peer = other.peer() # a courtesy to callers using a localrepo for other 69 peer = other.peer() # a courtesy to callers using a localrepo for other
90 hashbranch, branches = branches 70 hashbranch, branches = branches
91 if not hashbranch and not branches: 71 if not hashbranch and not branches:
92 x = revs or None 72 x = revs or None
127 if not primary(hashbranch): 107 if not primary(hashbranch):
128 revs.append(hashbranch) 108 revs.append(hashbranch)
129 return revs, revs[0] 109 return revs, revs[0]
130 110
131 111
112 def _isfile(path):
113 try:
114 # we use os.stat() directly here instead of os.path.isfile()
115 # because the latter started returning `False` on invalid path
116 # exceptions starting in 3.8 and we care about handling
117 # invalid paths specially here.
118 st = os.stat(path)
119 except ValueError as e:
120 msg = stringutil.forcebytestr(e)
121 raise error.Abort(_(b'invalid path %s: %s') % (path, msg))
122 except OSError:
123 return False
124 else:
125 return stat.S_ISREG(st.st_mode)
126
127
128 class LocalFactory:
129 """thin wrapper to dispatch between localrepo and bundle repo"""
130
131 @staticmethod
132 def islocal(path: bytes) -> bool:
133 path = util.expandpath(urlutil.urllocalpath(path))
134 return not _isfile(path)
135
136 @staticmethod
137 def instance(ui, path, *args, **kwargs):
138 path = util.expandpath(urlutil.urllocalpath(path))
139 if _isfile(path):
140 cls = bundlerepo
141 else:
142 cls = localrepo
143 return cls.instance(ui, path, *args, **kwargs)
144
145
132 schemes = { 146 schemes = {
133 b'bundle': bundlerepo, 147 b'bundle': bundlerepo,
134 b'union': unionrepo, 148 b'union': unionrepo,
135 b'file': _local, 149 b'file': LocalFactory,
136 b'http': httppeer, 150 b'http': httppeer,
137 b'https': httppeer, 151 b'https': httppeer,
138 b'ssh': sshpeer, 152 b'ssh': sshpeer,
139 b'static-http': statichttprepo, 153 b'static-http': statichttprepo,
140 } 154 }
142 156
143 def _peerlookup(path): 157 def _peerlookup(path):
144 u = urlutil.url(path) 158 u = urlutil.url(path)
145 scheme = u.scheme or b'file' 159 scheme = u.scheme or b'file'
146 thing = schemes.get(scheme) or schemes[b'file'] 160 thing = schemes.get(scheme) or schemes[b'file']
147 try: 161 return thing
148 return thing(path)
149 except TypeError:
150 # we can't test callable(thing) because 'thing' can be an unloaded
151 # module that implements __call__
152 if not util.safehasattr(thing, b'instance'):
153 raise
154 return thing
155 162
156 163
157 def islocal(repo): 164 def islocal(repo):
158 '''return true if repo (or path pointing to repo) is local''' 165 '''return true if repo (or path pointing to repo) is local'''
159 if isinstance(repo, bytes): 166 if isinstance(repo, bytes):