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): |