##// END OF EJS Templates
large-files: also open the context in the subdirstate
large-files: also open the context in the subdirstate

File last commit:

r49730:6000f5b2 default
r51037:308aff02 default
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)