##// END OF EJS Templates
lfs: don't skip locally available blobs when verifying...
lfs: don't skip locally available blobs when verifying The `skipflags` config was introduced in a2ab9ebcd85b, which specifically calls out downloading and storing all blobs as potentially too expensive. But I don't see any reason to skip blobs that are already available locally. Hashing the blob is the only way to indirectly verify the rawdata content stored in the revlog. (The note in that commit about skipping renamed is still correct, but the reason given about needing fulltext isn't.) Differential Revision: https://phab.mercurial-scm.org/D7712

File last commit:

r43812:2fe6121c default
r44529:1a6dd50c default
Show More
proto.py
221 lines | 7.6 KiB | text/x-python | PythonLexer
various
hgext: add largefiles extension...
r15168 # Copyright 2011 Fog Creek Software
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
liscju
py3: make largefiles/proto.py use absolute_import
r29312 from __future__ import absolute_import
various
hgext: add largefiles extension...
r15168
import os
Mads Kiilerich
largefiles: make the protocol hack for replacing heads with lheads more precise...
r19917 import re
various
hgext: add largefiles extension...
r15168
from mercurial.i18n import _
Gregory Szorc
py3: manually import pycompat.open into files that need it...
r43355 from mercurial.pycompat import open
various
hgext: add largefiles extension...
r15168
liscju
py3: make largefiles/proto.py use absolute_import
r29312 from mercurial import (
error,
Matt Harbison
largefiles: port wrapped functions to exthelper...
r41092 exthelper,
liscju
py3: make largefiles/proto.py use absolute_import
r29312 httppeer,
util,
Gregory Szorc
wireproto: introduce type for raw byte responses (API)...
r36091 wireprototypes,
Gregory Szorc
wireproto: move version 1 peer functionality to standalone module (API)...
r37632 wireprotov1peer,
Matt Harbison
largefiles: port wrapped functions to exthelper...
r41092 wireprotov1server,
liscju
py3: make largefiles/proto.py use absolute_import
r29312 )
Augie Fackler
formatting: blacken the codebase...
r43346 from . import lfutil
liscju
py3: make largefiles/proto.py use absolute_import
r29312
timeless
pycompat: switch to util.urlreq/util.urlerr for py3 compat
r28883 urlerr = util.urlerr
urlreq = util.urlreq
Augie Fackler
formatting: blacken the codebase...
r43346 LARGEFILES_REQUIRED_MSG = (
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'\nThis repository uses the largefiles extension.'
b'\n\nPlease enable it in your Mercurial config '
b'file.\n'
Augie Fackler
formatting: blacken the codebase...
r43346 )
various
hgext: add largefiles extension...
r15168
Matt Harbison
largefiles: port wrapped functions to exthelper...
r41092 eh = exthelper.exthelper()
Bryan O'Sullivan
largefiles: quiet (and document) undefined name errors (issue3886)...
r18922 # these will all be replaced by largefiles.uisetup
ssholdcallstream = None
httpoldcallstream = None
Augie Fackler
formatting: blacken the codebase...
r43346
various
hgext: add largefiles extension...
r15168 def putlfile(repo, proto, sha):
Mads Kiilerich
largefiles: add some docstrings
r28576 '''Server command for putting a largefile into a repository's local store
and into the user cache.'''
Gregory Szorc
wireproto: use maybecapturestdio() for push responses (API)...
r36084 with proto.mayberedirectstdio() as output:
path = lfutil.storepath(repo, sha)
util.makedirs(os.path.dirname(path))
tmpfp = util.atomictempfile(path, createmode=repo.store.createmode)
hlian
largefiles: in putlfile, ensure tempfile's directory exists prior to creation...
r16594
Gregory Szorc
wireproto: use maybecapturestdio() for push responses (API)...
r36084 try:
Joerg Sonnenberger
wireproto: allow direct stream processing for unbundle...
r37432 for p in proto.getpayload():
tmpfp.write(p)
Gregory Szorc
wireproto: use maybecapturestdio() for push responses (API)...
r36084 tmpfp._fp.seek(0)
if sha != lfutil.hexsha1(tmpfp._fp):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise IOError(0, _(b'largefile contents do not match hash'))
Gregory Szorc
wireproto: use maybecapturestdio() for push responses (API)...
r36084 tmpfp.close()
lfutil.linktousercache(repo, sha)
except IOError as e:
Augie Fackler
formatting: blacken the codebase...
r43346 repo.ui.warn(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b'largefiles: failed to put %s into store: %s\n')
Augie Fackler
formatting: blacken the codebase...
r43346 % (sha, e.strerror)
)
Gregory Szorc
wireproto: stop aliasing wire protocol types (API)...
r37309 return wireprototypes.pushres(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 1, output.getvalue() if output else b''
Augie Fackler
formatting: blacken the codebase...
r43346 )
Gregory Szorc
wireproto: use maybecapturestdio() for push responses (API)...
r36084 finally:
tmpfp.discard()
various
hgext: add largefiles extension...
r15168
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return wireprototypes.pushres(0, output.getvalue() if output else b'')
various
hgext: add largefiles extension...
r15168
Augie Fackler
formatting: blacken the codebase...
r43346
various
hgext: add largefiles extension...
r15168 def getlfile(repo, proto, sha):
Mads Kiilerich
largefiles: add some docstrings
r28576 '''Server command for retrieving a largefile from the repository-local
cache or user cache.'''
various
hgext: add largefiles extension...
r15168 filename = lfutil.findfile(repo, sha)
if not filename:
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.Abort(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b'requested largefile %s not present in cache') % sha
Augie Fackler
formatting: blacken the codebase...
r43346 )
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 f = open(filename, b'rb')
various
hgext: add largefiles extension...
r15168 length = os.fstat(f.fileno())[6]
Greg Ward
largefiles: improve comments, internal docstrings...
r15252
# Since we can't set an HTTP content-length header here, and
# Mercurial core provides no way to give the length of a streamres
# (and reading the entire file into RAM would be ill-advised), we
# just send the length on the first line of the response, like the
# ssh proto does for string responses.
various
hgext: add largefiles extension...
r15168 def generator():
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 yield b'%d\n' % length
Mads Kiilerich
largefiles: use filechunkiter for iterating largefile when serving getlfile...
r19009 for chunk in util.filechunkiter(f):
various
hgext: add largefiles extension...
r15168 yield chunk
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
wireproto: stop aliasing wire protocol types (API)...
r37309 return wireprototypes.streamreslegacy(gen=generator())
various
hgext: add largefiles extension...
r15168
Augie Fackler
formatting: blacken the codebase...
r43346
various
hgext: add largefiles extension...
r15168 def statlfile(repo, proto, sha):
Mads Kiilerich
largefiles: add some docstrings
r28576 '''Server command for checking if a largefile is present - returns '2\n' if
the largefile is missing, '0\n' if it seems to be in good condition.
Mads Kiilerich
largefiles: don't verify largefile hashes on servers when processing statlfile...
r18488
The value 1 is reserved for mismatched checksum, but that is too expensive
to be verified on every stat and must be caught be running 'hg verify'
server side.'''
various
hgext: add largefiles extension...
r15168 filename = lfutil.findfile(repo, sha)
if not filename:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return wireprototypes.bytesresponse(b'2\n')
return wireprototypes.bytesresponse(b'0\n')
various
hgext: add largefiles extension...
r15168
Augie Fackler
formatting: blacken the codebase...
r43346
various
hgext: add largefiles extension...
r15168 def wirereposetup(ui, repo):
class lfileswirerepository(repo.__class__):
def putlfile(self, sha, fd):
# unfortunately, httprepository._callpush tries to convert its
# input file-like into a bundle before sending it, so we can't use
# it ...
Peter Arrenbrecht
peer: introduce real peer classes...
r17192 if issubclass(self.__class__, httppeer.httppeer):
Augie Fackler
formatting: blacken the codebase...
r43346 res = self._call(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'putlfile',
Augie Fackler
formatting: blacken the codebase...
r43346 data=fd,
sha=sha,
Augie Fackler
cleanup: remove pointless r-prefixes on single-quoted strings...
r43906 headers={'content-type': 'application/mercurial-0.1'},
Augie Fackler
formatting: blacken the codebase...
r43346 )
various
hgext: add largefiles extension...
r15168 try:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 d, output = res.split(b'\n', 1)
Kevin Gessner
largefiles: display remote errors from putlfile (issue3123) (issue3149)
r15778 for l in output.splitlines(True):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.ui.warn(_(b'remote: '), l) # assume l ends with \n
Kevin Gessner
largefiles: display remote errors from putlfile (issue3123) (issue3149)
r15778 return int(d)
Mads Kiilerich
largefiles: don't mute and obfuscate http errors when putlfile fails...
r26825 except ValueError:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.ui.warn(_(b'unexpected putlfile response: %r\n') % res)
various
hgext: add largefiles extension...
r15168 return 1
# ... but we can't use sshrepository._call because the data=
# argument won't get sent, and _callpush does exactly what we want
# in this case: send the data straight through
else:
try:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ret, output = self._callpush(b"putlfile", fd, sha=sha)
if ret == b"":
raise error.ResponseError(
_(b'putlfile failed:'), output
)
various
hgext: add largefiles extension...
r15168 return int(ret)
except IOError:
return 1
except ValueError:
raise error.ResponseError(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b'putlfile failed (unexpected response):'), ret
Augie Fackler
formatting: blacken the codebase...
r43346 )
various
hgext: add largefiles extension...
r15168
def getlfile(self, sha):
Mads Kiilerich
largefiles: move protocol conversion into getlfile and make it an iterable...
r19004 """returns an iterable with the chunks of the file with sha sha"""
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 stream = self._callstream(b"getlfile", sha=sha)
various
hgext: add largefiles extension...
r15168 length = stream.readline()
try:
length = int(length)
except ValueError:
Augie Fackler
formatting: blacken the codebase...
r43346 self._abort(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 error.ResponseError(_(b"unexpected response:"), length)
Augie Fackler
formatting: blacken the codebase...
r43346 )
Mads Kiilerich
largefiles: move protocol conversion into getlfile and make it an iterable...
r19004
Mads Kiilerich
largefiles: drop limitreader, use filechunkiter limit...
r19005 # SSH streams will block if reading more than length
Mads Kiilerich
util: increase filechunkiter size to 128k...
r30181 for chunk in util.filechunkiter(stream, limit=length):
Mads Kiilerich
largefiles: move protocol conversion into getlfile and make it an iterable...
r19004 yield chunk
Mads Kiilerich
largefiles: getlfile must hit end of HTTP chunked streams to reuse connections...
r19006 # HTTP streams must hit the end to process the last empty
# chunk of Chunked-Encoding so the connection can be reused.
if issubclass(self.__class__, httppeer.httppeer):
chunk = stream.read(1)
if chunk:
Augie Fackler
formatting: blacken the codebase...
r43346 self._abort(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 error.ResponseError(_(b"unexpected response:"), chunk)
Augie Fackler
formatting: blacken the codebase...
r43346 )
various
hgext: add largefiles extension...
r15168
Gregory Szorc
wireproto: move version 1 peer functionality to standalone module (API)...
r37632 @wireprotov1peer.batchable
various
hgext: add largefiles extension...
r15168 def statlfile(self, sha):
Gregory Szorc
wireproto: move version 1 peer functionality to standalone module (API)...
r37632 f = wireprotov1peer.future()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 result = {b'sha': sha}
Na'Tosha Bard
largefiles: batch statlfile requests when pushing a largefiles repo (issue3386)...
r17127 yield result, f
various
hgext: add largefiles extension...
r15168 try:
Na'Tosha Bard
largefiles: batch statlfile requests when pushing a largefiles repo (issue3386)...
r17127 yield int(f.value)
timeless
pycompat: switch to util.urlreq/util.urlerr for py3 compat
r28883 except (ValueError, urlerr.httperror):
Greg Ward
largefiles: improve comments, internal docstrings...
r15252 # If the server returns anything but an integer followed by a
various
hgext: add largefiles extension...
r15168 # newline, newline, it's not speaking our language; if we get
# an HTTP error, we can't be sure the largefile is present;
Greg Ward
largefiles: improve comments, internal docstrings...
r15252 # either way, consider it missing.
Na'Tosha Bard
largefiles: batch statlfile requests when pushing a largefiles repo (issue3386)...
r17127 yield 2
various
hgext: add largefiles extension...
r15168
repo.__class__ = lfileswirerepository
Augie Fackler
formatting: blacken the codebase...
r43346
various
hgext: add largefiles extension...
r15168 # advertise the largefiles=serve capability
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 @eh.wrapfunction(wireprotov1server, b'_capabilities')
Matt Harbison
largefiles: modernize how capabilities are added to the wire protocol...
r35523 def _capabilities(orig, repo, proto):
'''announce largefile server capability'''
caps = orig(repo, proto)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 caps.append(b'largefiles=serve')
Matt Harbison
largefiles: modernize how capabilities are added to the wire protocol...
r35523 return caps
various
hgext: add largefiles extension...
r15168
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
largefiles: wrap heads command handler more directly...
r37502 def heads(orig, repo, proto):
Mads Kiilerich
largefiles: add some docstrings
r28576 '''Wrap server command - largefile capable clients will know to call
lheads instead'''
various
hgext: add largefiles extension...
r15168 if lfutil.islfilesrepo(repo):
Gregory Szorc
wireproto: stop aliasing wire protocol types (API)...
r37309 return wireprototypes.ooberror(LARGEFILES_REQUIRED_MSG)
Gregory Szorc
largefiles: wrap heads command handler more directly...
r37502
return orig(repo, proto)
various
hgext: add largefiles extension...
r15168
Augie Fackler
formatting: blacken the codebase...
r43346
Na'Tosha Bard
largefiles: remove use of underscores that breaks coding convention
r16247 def sshrepocallstream(self, cmd, **args):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if cmd == b'heads' and self.capable(b'largefiles'):
cmd = b'lheads'
if cmd == b'batch' and self.capable(b'largefiles'):
Augie Fackler
cleanup: remove pointless r-prefixes on single-quoted strings...
r43906 args['cmds'] = args[r'cmds'].replace(b'heads ', b'lheads ')
Na'Tosha Bard
largefiles: remove use of underscores that breaks coding convention
r16247 return ssholdcallstream(self, cmd, **args)
various
hgext: add largefiles extension...
r15168
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
largefiles: mark headre as bytes regex...
r36330 headsre = re.compile(br'(^|;)heads\b')
Mads Kiilerich
largefiles: make the protocol hack for replacing heads with lheads more precise...
r19917
Augie Fackler
formatting: blacken the codebase...
r43346
Na'Tosha Bard
largefiles: remove use of underscores that breaks coding convention
r16247 def httprepocallstream(self, cmd, **args):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if cmd == b'heads' and self.capable(b'largefiles'):
cmd = b'lheads'
if cmd == b'batch' and self.capable(b'largefiles'):
Augie Fackler
cleanup: remove pointless r-prefixes on single-quoted strings...
r43906 args['cmds'] = headsre.sub(b'lheads', args['cmds'])
Na'Tosha Bard
largefiles: remove use of underscores that breaks coding convention
r16247 return httpoldcallstream(self, cmd, **args)