##// END OF EJS Templates
heptapod-ci: turn off pipelines for merge request events...
heptapod-ci: turn off pipelines for merge request events These are always duplicated by the external (from the user) push, or internal (from Heptapod itself) push pipeline, so they're entirely redundant.

File last commit:

r49730:6000f5b2 default
r51634:929655c0 stable
Show More
proto.py
217 lines | 7.5 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.
import os
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()
Augie Fackler
formatting: blacken the codebase...
r43346
various
hgext: add largefiles extension...
r15168 def putlfile(repo, proto, sha):
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """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):
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """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):
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """Server command for checking if a largefile is present - returns '2\n' if
Mads Kiilerich
largefiles: add some docstrings
r28576 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'
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 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):
Joerg Sonnenberger
largefiles: redo heads interception...
r46816 orig_commandexecutor = repo.commandexecutor
various
hgext: add largefiles extension...
r15168 class lfileswirerepository(repo.__class__):
Joerg Sonnenberger
largefiles: redo heads interception...
r46816 def commandexecutor(self):
executor = orig_commandexecutor()
if self.capable(b'largefiles'):
orig_callcommand = executor.callcommand
class lfscommandexecutor(executor.__class__):
def callcommand(self, command, args):
if command == b'heads':
command = b'lheads'
return orig_callcommand(command, args)
executor.__class__ = lfscommandexecutor
return executor
@wireprotov1peer.batchable
def lheads(self):
return self.heads.batchable(self)
various
hgext: add largefiles extension...
r15168 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):
Valentin Gatien-Baron
wireprotov1peer: update all rpcs to use the new batchable scheme...
r48687 def decode(d):
try:
return int(d)
except (ValueError, urlerr.httperror):
# If the server returns anything but an integer followed by a
# newline, newline, it's not speaking our language; if we get
# an HTTP error, we can't be sure the largefile is present;
# either way, consider it missing.
return 2
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 result = {b'sha': sha}
Valentin Gatien-Baron
wireprotov1peer: update all rpcs to use the new batchable scheme...
r48687 return result, decode
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):
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """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)