##// END OF EJS Templates
py3: use util.forcebytestr() to convert IOErrors to bytes...
Pulkit Goyal -
r36580:247e9bf4 default
parent child Browse files
Show More
@@ -1,126 +1,128 b''
1 # Copyright 2010-2011 Fog Creek Software
1 # Copyright 2010-2011 Fog Creek Software
2 # Copyright 2010-2011 Unity Technologies
2 # Copyright 2010-2011 Unity Technologies
3 #
3 #
4 # This software may be used and distributed according to the terms of the
4 # This software may be used and distributed according to the terms of the
5 # GNU General Public License version 2 or any later version.
5 # GNU General Public License version 2 or any later version.
6
6
7 '''remote largefile store; the base class for wirestore'''
7 '''remote largefile store; the base class for wirestore'''
8 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 from mercurial.i18n import _
10 from mercurial.i18n import _
11
11
12 from mercurial import (
12 from mercurial import (
13 error,
13 error,
14 util,
14 util,
15 )
15 )
16
16
17 from . import (
17 from . import (
18 basestore,
18 basestore,
19 lfutil,
19 lfutil,
20 localstore,
20 localstore,
21 )
21 )
22
22
23 urlerr = util.urlerr
23 urlerr = util.urlerr
24 urlreq = util.urlreq
24 urlreq = util.urlreq
25
25
26 class remotestore(basestore.basestore):
26 class remotestore(basestore.basestore):
27 '''a largefile store accessed over a network'''
27 '''a largefile store accessed over a network'''
28 def __init__(self, ui, repo, url):
28 def __init__(self, ui, repo, url):
29 super(remotestore, self).__init__(ui, repo, url)
29 super(remotestore, self).__init__(ui, repo, url)
30 self._lstore = None
30 self._lstore = None
31 if repo is not None:
31 if repo is not None:
32 self._lstore = localstore.localstore(self.ui, self.repo, self.repo)
32 self._lstore = localstore.localstore(self.ui, self.repo, self.repo)
33
33
34 def put(self, source, hash):
34 def put(self, source, hash):
35 if self.sendfile(source, hash):
35 if self.sendfile(source, hash):
36 raise error.Abort(
36 raise error.Abort(
37 _('remotestore: could not put %s to remote store %s')
37 _('remotestore: could not put %s to remote store %s')
38 % (source, util.hidepassword(self.url)))
38 % (source, util.hidepassword(self.url)))
39 self.ui.debug(
39 self.ui.debug(
40 _('remotestore: put %s to remote store %s\n')
40 _('remotestore: put %s to remote store %s\n')
41 % (source, util.hidepassword(self.url)))
41 % (source, util.hidepassword(self.url)))
42
42
43 def exists(self, hashes):
43 def exists(self, hashes):
44 return dict((h, s == 0) for (h, s) in # dict-from-generator
44 return dict((h, s == 0) for (h, s) in # dict-from-generator
45 self._stat(hashes).iteritems())
45 self._stat(hashes).iteritems())
46
46
47 def sendfile(self, filename, hash):
47 def sendfile(self, filename, hash):
48 self.ui.debug('remotestore: sendfile(%s, %s)\n' % (filename, hash))
48 self.ui.debug('remotestore: sendfile(%s, %s)\n' % (filename, hash))
49 try:
49 try:
50 with lfutil.httpsendfile(self.ui, filename) as fd:
50 with lfutil.httpsendfile(self.ui, filename) as fd:
51 return self._put(hash, fd)
51 return self._put(hash, fd)
52 except IOError as e:
52 except IOError as e:
53 raise error.Abort(
53 raise error.Abort(
54 _('remotestore: could not open file %s: %s')
54 _('remotestore: could not open file %s: %s')
55 % (filename, str(e)))
55 % (filename, util.forcebytestr(e)))
56
56
57 def _getfile(self, tmpfile, filename, hash):
57 def _getfile(self, tmpfile, filename, hash):
58 try:
58 try:
59 chunks = self._get(hash)
59 chunks = self._get(hash)
60 except urlerr.httperror as e:
60 except urlerr.httperror as e:
61 # 401s get converted to error.Aborts; everything else is fine being
61 # 401s get converted to error.Aborts; everything else is fine being
62 # turned into a StoreError
62 # turned into a StoreError
63 raise basestore.StoreError(filename, hash, self.url, str(e))
63 raise basestore.StoreError(filename, hash, self.url,
64 util.forcebytestr(e))
64 except urlerr.urlerror as e:
65 except urlerr.urlerror as e:
65 # This usually indicates a connection problem, so don't
66 # This usually indicates a connection problem, so don't
66 # keep trying with the other files... they will probably
67 # keep trying with the other files... they will probably
67 # all fail too.
68 # all fail too.
68 raise error.Abort('%s: %s' %
69 raise error.Abort('%s: %s' %
69 (util.hidepassword(self.url), e.reason))
70 (util.hidepassword(self.url), e.reason))
70 except IOError as e:
71 except IOError as e:
71 raise basestore.StoreError(filename, hash, self.url, str(e))
72 raise basestore.StoreError(filename, hash, self.url,
73 util.forcebytestr(e))
72
74
73 return lfutil.copyandhash(chunks, tmpfile)
75 return lfutil.copyandhash(chunks, tmpfile)
74
76
75 def _hashesavailablelocally(self, hashes):
77 def _hashesavailablelocally(self, hashes):
76 existslocallymap = self._lstore.exists(hashes)
78 existslocallymap = self._lstore.exists(hashes)
77 localhashes = [hash for hash in hashes if existslocallymap[hash]]
79 localhashes = [hash for hash in hashes if existslocallymap[hash]]
78 return localhashes
80 return localhashes
79
81
80 def _verifyfiles(self, contents, filestocheck):
82 def _verifyfiles(self, contents, filestocheck):
81 failed = False
83 failed = False
82 expectedhashes = [expectedhash
84 expectedhashes = [expectedhash
83 for cset, filename, expectedhash in filestocheck]
85 for cset, filename, expectedhash in filestocheck]
84 localhashes = self._hashesavailablelocally(expectedhashes)
86 localhashes = self._hashesavailablelocally(expectedhashes)
85 stats = self._stat([expectedhash for expectedhash in expectedhashes
87 stats = self._stat([expectedhash for expectedhash in expectedhashes
86 if expectedhash not in localhashes])
88 if expectedhash not in localhashes])
87
89
88 for cset, filename, expectedhash in filestocheck:
90 for cset, filename, expectedhash in filestocheck:
89 if expectedhash in localhashes:
91 if expectedhash in localhashes:
90 filetocheck = (cset, filename, expectedhash)
92 filetocheck = (cset, filename, expectedhash)
91 verifyresult = self._lstore._verifyfiles(contents,
93 verifyresult = self._lstore._verifyfiles(contents,
92 [filetocheck])
94 [filetocheck])
93 if verifyresult:
95 if verifyresult:
94 failed = True
96 failed = True
95 else:
97 else:
96 stat = stats[expectedhash]
98 stat = stats[expectedhash]
97 if stat:
99 if stat:
98 if stat == 1:
100 if stat == 1:
99 self.ui.warn(
101 self.ui.warn(
100 _('changeset %s: %s: contents differ\n')
102 _('changeset %s: %s: contents differ\n')
101 % (cset, filename))
103 % (cset, filename))
102 failed = True
104 failed = True
103 elif stat == 2:
105 elif stat == 2:
104 self.ui.warn(
106 self.ui.warn(
105 _('changeset %s: %s missing\n')
107 _('changeset %s: %s missing\n')
106 % (cset, filename))
108 % (cset, filename))
107 failed = True
109 failed = True
108 else:
110 else:
109 raise RuntimeError('verify failed: unexpected response '
111 raise RuntimeError('verify failed: unexpected response '
110 'from statlfile (%r)' % stat)
112 'from statlfile (%r)' % stat)
111 return failed
113 return failed
112
114
113 def _put(self, hash, fd):
115 def _put(self, hash, fd):
114 '''Put file with the given hash in the remote store.'''
116 '''Put file with the given hash in the remote store.'''
115 raise NotImplementedError('abstract method')
117 raise NotImplementedError('abstract method')
116
118
117 def _get(self, hash):
119 def _get(self, hash):
118 '''Get a iterator for content with the given hash.'''
120 '''Get a iterator for content with the given hash.'''
119 raise NotImplementedError('abstract method')
121 raise NotImplementedError('abstract method')
120
122
121 def _stat(self, hashes):
123 def _stat(self, hashes):
122 '''Get information about availability of files specified by
124 '''Get information about availability of files specified by
123 hashes in the remote store. Return dictionary mapping hashes
125 hashes in the remote store. Return dictionary mapping hashes
124 to return code where 0 means that file is available, other
126 to return code where 0 means that file is available, other
125 values if not.'''
127 values if not.'''
126 raise NotImplementedError('abstract method')
128 raise NotImplementedError('abstract method')
General Comments 0
You need to be logged in to leave comments. Login now