Mercurial > hg
comparison hgext/lfs/wrapper.py @ 38178:3790efb388ca stable
lfs: bypass wrapped functions when reposetup() hasn't been called (issue5902)
There are only a handful of methods that access repo attributes that are applied
in reposetup(). The `diff` test covers all of the commands that call
scmutil.prefetchfiles(). Along the way, I saw that adding files and upgrading
the repo format were also problems (also tested here).
I don't think running `hg serve` through the commandserver is sane, but I
conditionalized both the capabilities and the wsgirequest handler because it's
trivially correct. It doesn't look like there has ever been a caller of
candownload(), so there's no test for that path.
The upload case isn't testable, because uploadblobs() bails if there are no
pointers. The requirement should be added any time pointers are introduced, and
that would force the extension to be loaded specifically for the repo. This
covers `debuglfsupload`, the pre-push hook (which isn't set until the repo is
promoted to LFS), and uploadblobsfromrevs(), which can be called by other
extensions.
I think readfromstore() and writetostore() are only reachable as a flag
processor for revlog.REVIDX_EXTSTORED, and a requirement is added as soon as
that is seen, so I don't think those are a problem.
author | Matt Harbison <matt_harbison@yahoo.com> |
---|---|
date | Thu, 31 May 2018 09:19:09 -0400 |
parents | 7269b87f817c |
children | 37e56607cbb9 |
comparison
equal
deleted
inserted
replaced
38040:a3b4ccbec269 | 38178:3790efb388ca |
---|---|
35 return versions | 35 return versions |
36 | 36 |
37 def _capabilities(orig, repo, proto): | 37 def _capabilities(orig, repo, proto): |
38 '''Wrap server command to announce lfs server capability''' | 38 '''Wrap server command to announce lfs server capability''' |
39 caps = orig(repo, proto) | 39 caps = orig(repo, proto) |
40 # XXX: change to 'lfs=serve' when separate git server isn't required? | 40 if util.safehasattr(repo.svfs, 'lfslocalblobstore'): |
41 caps.append('lfs') | 41 # XXX: change to 'lfs=serve' when separate git server isn't required? |
42 caps.append('lfs') | |
42 return caps | 43 return caps |
43 | 44 |
44 def bypasscheckhash(self, text): | 45 def bypasscheckhash(self, text): |
45 return False | 46 return False |
46 | 47 |
116 return bool(flags & revlog.REVIDX_EXTSTORED) | 117 return bool(flags & revlog.REVIDX_EXTSTORED) |
117 | 118 |
118 def filelogaddrevision(orig, self, text, transaction, link, p1, p2, | 119 def filelogaddrevision(orig, self, text, transaction, link, p1, p2, |
119 cachedelta=None, node=None, | 120 cachedelta=None, node=None, |
120 flags=revlog.REVIDX_DEFAULT_FLAGS, **kwds): | 121 flags=revlog.REVIDX_DEFAULT_FLAGS, **kwds): |
121 textlen = len(text) | 122 # The matcher isn't available if reposetup() wasn't called. |
122 # exclude hg rename meta from file size | 123 lfstrack = self.opener.options.get('lfstrack') |
123 meta, offset = revlog.parsemeta(text) | 124 |
124 if offset: | 125 if lfstrack: |
125 textlen -= offset | 126 textlen = len(text) |
126 | 127 # exclude hg rename meta from file size |
127 lfstrack = self.opener.options['lfstrack'] | 128 meta, offset = revlog.parsemeta(text) |
128 | 129 if offset: |
129 if lfstrack(self.filename, textlen): | 130 textlen -= offset |
130 flags |= revlog.REVIDX_EXTSTORED | 131 |
132 if lfstrack(self.filename, textlen): | |
133 flags |= revlog.REVIDX_EXTSTORED | |
131 | 134 |
132 return orig(self, text, transaction, link, p1, p2, cachedelta=cachedelta, | 135 return orig(self, text, transaction, link, p1, p2, cachedelta=cachedelta, |
133 node=node, flags=flags, **kwds) | 136 node=node, flags=flags, **kwds) |
134 | 137 |
135 def filelogrenamed(orig, self, node): | 138 def filelogrenamed(orig, self, node): |
245 destrepo.vfs.append('hgrc', util.tonativeeol('\n[extensions]\nlfs=\n')) | 248 destrepo.vfs.append('hgrc', util.tonativeeol('\n[extensions]\nlfs=\n')) |
246 | 249 |
247 def _prefetchfiles(repo, revs, match): | 250 def _prefetchfiles(repo, revs, match): |
248 """Ensure that required LFS blobs are present, fetching them as a group if | 251 """Ensure that required LFS blobs are present, fetching them as a group if |
249 needed.""" | 252 needed.""" |
253 if not util.safehasattr(repo.svfs, 'lfslocalblobstore'): | |
254 return | |
255 | |
250 pointers = [] | 256 pointers = [] |
251 oids = set() | 257 oids = set() |
252 localstore = repo.svfs.lfslocalblobstore | 258 localstore = repo.svfs.lfslocalblobstore |
253 | 259 |
254 for rev in revs: | 260 for rev in revs: |
264 # Recalculating the repo store here allows 'paths.default' that is set | 270 # Recalculating the repo store here allows 'paths.default' that is set |
265 # on the repo by a clone command to be used for the update. | 271 # on the repo by a clone command to be used for the update. |
266 blobstore.remote(repo).readbatch(pointers, localstore) | 272 blobstore.remote(repo).readbatch(pointers, localstore) |
267 | 273 |
268 def _canskipupload(repo): | 274 def _canskipupload(repo): |
275 # Skip if this hasn't been passed to reposetup() | |
276 if not util.safehasattr(repo.svfs, 'lfsremoteblobstore'): | |
277 return True | |
278 | |
269 # if remotestore is a null store, upload is a no-op and can be skipped | 279 # if remotestore is a null store, upload is a no-op and can be skipped |
270 return isinstance(repo.svfs.lfsremoteblobstore, blobstore._nullremote) | 280 return isinstance(repo.svfs.lfsremoteblobstore, blobstore._nullremote) |
271 | 281 |
272 def candownload(repo): | 282 def candownload(repo): |
283 # Skip if this hasn't been passed to reposetup() | |
284 if not util.safehasattr(repo.svfs, 'lfsremoteblobstore'): | |
285 return False | |
286 | |
273 # if remotestore is a null store, downloads will lead to nothing | 287 # if remotestore is a null store, downloads will lead to nothing |
274 return not isinstance(repo.svfs.lfsremoteblobstore, blobstore._nullremote) | 288 return not isinstance(repo.svfs.lfsremoteblobstore, blobstore._nullremote) |
275 | 289 |
276 def uploadblobsfromrevs(repo, revs): | 290 def uploadblobsfromrevs(repo, revs): |
277 '''upload lfs blobs introduced by revs | 291 '''upload lfs blobs introduced by revs |
387 remoteblob.writebatch(pointers, repo.svfs.lfslocalblobstore) | 401 remoteblob.writebatch(pointers, repo.svfs.lfslocalblobstore) |
388 | 402 |
389 def upgradefinishdatamigration(orig, ui, srcrepo, dstrepo, requirements): | 403 def upgradefinishdatamigration(orig, ui, srcrepo, dstrepo, requirements): |
390 orig(ui, srcrepo, dstrepo, requirements) | 404 orig(ui, srcrepo, dstrepo, requirements) |
391 | 405 |
392 srclfsvfs = srcrepo.svfs.lfslocalblobstore.vfs | 406 # Skip if this hasn't been passed to reposetup() |
393 dstlfsvfs = dstrepo.svfs.lfslocalblobstore.vfs | 407 if (util.safehasattr(srcrepo.svfs, 'lfslocalblobstore') and |
394 | 408 util.safehasattr(dstrepo.svfs, 'lfslocalblobstore')): |
395 for dirpath, dirs, files in srclfsvfs.walk(): | 409 srclfsvfs = srcrepo.svfs.lfslocalblobstore.vfs |
396 for oid in files: | 410 dstlfsvfs = dstrepo.svfs.lfslocalblobstore.vfs |
397 ui.write(_('copying lfs blob %s\n') % oid) | 411 |
398 lfutil.link(srclfsvfs.join(oid), dstlfsvfs.join(oid)) | 412 for dirpath, dirs, files in srclfsvfs.walk(): |
413 for oid in files: | |
414 ui.write(_('copying lfs blob %s\n') % oid) | |
415 lfutil.link(srclfsvfs.join(oid), dstlfsvfs.join(oid)) | |
399 | 416 |
400 def upgraderequirements(orig, repo): | 417 def upgraderequirements(orig, repo): |
401 reqs = orig(repo) | 418 reqs = orig(repo) |
402 if 'lfs' in repo.requirements: | 419 if 'lfs' in repo.requirements: |
403 reqs.add('lfs') | 420 reqs.add('lfs') |