remotestore.py
114 lines
| 4.0 KiB
| text/x-python
|
PythonLexer
various
|
r15168 | # Copyright 2010-2011 Fog Creek Software | ||
# Copyright 2010-2011 Unity Technologies | ||||
# | ||||
# This software may be used and distributed according to the terms of the | ||||
# GNU General Public License version 2 or any later version. | ||||
Mads Kiilerich
|
r17425 | '''remote largefile store; the base class for wirestore''' | ||
various
|
r15168 | |||
Pierre-Yves David
|
r26587 | from mercurial import util, wireproto, error | ||
various
|
r15168 | from mercurial.i18n import _ | ||
timeless
|
r28883 | urlerr = util.urlerr | ||
urlreq = util.urlreq | ||||
various
|
r15168 | import lfutil | ||
import basestore | ||||
class remotestore(basestore.basestore): | ||||
Greg Ward
|
r15252 | '''a largefile store accessed over a network''' | ||
various
|
r15168 | def __init__(self, ui, repo, url): | ||
super(remotestore, self).__init__(ui, repo, url) | ||||
def put(self, source, hash): | ||||
if self.sendfile(source, hash): | ||||
Pierre-Yves David
|
r26587 | raise error.Abort( | ||
various
|
r15168 | _('remotestore: could not put %s to remote store %s') | ||
Mads Kiilerich
|
r19950 | % (source, util.hidepassword(self.url))) | ||
various
|
r15168 | self.ui.debug( | ||
Mads Kiilerich
|
r19950 | _('remotestore: put %s to remote store %s\n') | ||
% (source, util.hidepassword(self.url))) | ||||
various
|
r15168 | |||
Na'Tosha Bard
|
r17127 | def exists(self, hashes): | ||
Augie Fackler
|
r20688 | return dict((h, s == 0) for (h, s) in # dict-from-generator | ||
self._stat(hashes).iteritems()) | ||||
various
|
r15168 | |||
def sendfile(self, filename, hash): | ||||
self.ui.debug('remotestore: sendfile(%s, %s)\n' % (filename, hash)) | ||||
fd = None | ||||
try: | ||||
Matt Mackall
|
r25079 | fd = lfutil.httpsendfile(self.ui, filename) | ||
various
|
r15168 | return self._put(hash, fd) | ||
Gregory Szorc
|
r25660 | except IOError as e: | ||
Pierre-Yves David
|
r26587 | raise error.Abort( | ||
Matt Mackall
|
r25079 | _('remotestore: could not open file %s: %s') | ||
% (filename, str(e))) | ||||
various
|
r15168 | finally: | ||
if fd: | ||||
fd.close() | ||||
def _getfile(self, tmpfile, filename, hash): | ||||
try: | ||||
Mads Kiilerich
|
r19004 | chunks = self._get(hash) | ||
timeless
|
r28883 | except urlerr.httperror as e: | ||
Pierre-Yves David
|
r26587 | # 401s get converted to error.Aborts; everything else is fine being | ||
various
|
r15168 | # turned into a StoreError | ||
raise basestore.StoreError(filename, hash, self.url, str(e)) | ||||
timeless
|
r28883 | except urlerr.urlerror as e: | ||
various
|
r15168 | # This usually indicates a connection problem, so don't | ||
# keep trying with the other files... they will probably | ||||
# all fail too. | ||||
Pierre-Yves David
|
r26587 | raise error.Abort('%s: %s' % | ||
Mads Kiilerich
|
r19950 | (util.hidepassword(self.url), e.reason)) | ||
Gregory Szorc
|
r25660 | except IOError as e: | ||
various
|
r15168 | raise basestore.StoreError(filename, hash, self.url, str(e)) | ||
Mads Kiilerich
|
r19004 | return lfutil.copyandhash(chunks, tmpfile) | ||
various
|
r15168 | |||
def _verifyfile(self, cctx, cset, contents, standin, verified): | ||||
filename = lfutil.splitstandin(standin) | ||||
if not filename: | ||||
return False | ||||
fctx = cctx[standin] | ||||
key = (filename, fctx.filenode()) | ||||
if key in verified: | ||||
return False | ||||
verified.add(key) | ||||
Mads Kiilerich
|
r18482 | expecthash = fctx.data()[0:40] | ||
stat = self._stat([expecthash])[expecthash] | ||||
various
|
r15168 | if not stat: | ||
return False | ||||
elif stat == 1: | ||||
self.ui.warn( | ||||
_('changeset %s: %s: contents differ\n') | ||||
% (cset, filename)) | ||||
return True # failed | ||||
elif stat == 2: | ||||
self.ui.warn( | ||||
_('changeset %s: %s missing\n') | ||||
% (cset, filename)) | ||||
return True # failed | ||||
else: | ||||
Greg Ward
|
r15253 | raise RuntimeError('verify failed: unexpected response from ' | ||
'statlfile (%r)' % stat) | ||||
Na'Tosha Bard
|
r17127 | |||
def batch(self): | ||||
'''Support for remote batching.''' | ||||
Mads Kiilerich
|
r21084 | return wireproto.remotebatch(self) | ||
liscju
|
r28442 | |||
def _put(self, hash, fd): | ||||
'''Put file with the given hash in the remote store.''' | ||||
raise NotImplementedError('abstract method') | ||||
def _get(self, hash): | ||||
'''Get file with the given hash from the remote store.''' | ||||
raise NotImplementedError('abstract method') | ||||
def _stat(self, hashes): | ||||
'''Get information about availability of files specified by | ||||
hashes in the remote store. Return dictionary mapping hashes | ||||
to return code where 0 means that file is available, other | ||||
values if not.''' | ||||
raise NotImplementedError('abstract method') | ||||