##// END OF EJS Templates
lfs: log information about Internal Server Errors reported in the Batch API...
Matt Harbison -
r37708:726c4102 default
parent child Browse files
Show More
@@ -1,291 +1,307 b''
1 # wireprotolfsserver.py - lfs protocol server side implementation
1 # wireprotolfsserver.py - lfs protocol server side implementation
2 #
2 #
3 # Copyright 2018 Matt Harbison <matt_harbison@yahoo.com>
3 # Copyright 2018 Matt Harbison <matt_harbison@yahoo.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import datetime
10 import datetime
11 import errno
11 import errno
12 import json
12 import json
13 import traceback
13
14
14 from mercurial.hgweb import (
15 from mercurial.hgweb import (
15 common as hgwebcommon,
16 common as hgwebcommon,
16 )
17 )
17
18
18 from mercurial import (
19 from mercurial import (
19 pycompat,
20 pycompat,
20 )
21 )
21
22
22 HTTP_OK = hgwebcommon.HTTP_OK
23 HTTP_OK = hgwebcommon.HTTP_OK
23 HTTP_CREATED = hgwebcommon.HTTP_CREATED
24 HTTP_CREATED = hgwebcommon.HTTP_CREATED
24 HTTP_BAD_REQUEST = hgwebcommon.HTTP_BAD_REQUEST
25 HTTP_BAD_REQUEST = hgwebcommon.HTTP_BAD_REQUEST
25 HTTP_NOT_FOUND = hgwebcommon.HTTP_NOT_FOUND
26 HTTP_NOT_FOUND = hgwebcommon.HTTP_NOT_FOUND
26
27
27 def handlewsgirequest(orig, rctx, req, res, checkperm):
28 def handlewsgirequest(orig, rctx, req, res, checkperm):
28 """Wrap wireprotoserver.handlewsgirequest() to possibly process an LFS
29 """Wrap wireprotoserver.handlewsgirequest() to possibly process an LFS
29 request if it is left unprocessed by the wrapped method.
30 request if it is left unprocessed by the wrapped method.
30 """
31 """
31 if orig(rctx, req, res, checkperm):
32 if orig(rctx, req, res, checkperm):
32 return True
33 return True
33
34
34 if not rctx.repo.ui.configbool('experimental', 'lfs.serve'):
35 if not rctx.repo.ui.configbool('experimental', 'lfs.serve'):
35 return False
36 return False
36
37
37 if not req.dispatchpath:
38 if not req.dispatchpath:
38 return False
39 return False
39
40
40 try:
41 try:
41 if req.dispatchpath == b'.git/info/lfs/objects/batch':
42 if req.dispatchpath == b'.git/info/lfs/objects/batch':
42 checkperm(rctx, req, 'pull')
43 checkperm(rctx, req, 'pull')
43 return _processbatchrequest(rctx.repo, req, res)
44 return _processbatchrequest(rctx.repo, req, res)
44 # TODO: reserve and use a path in the proposed http wireprotocol /api/
45 # TODO: reserve and use a path in the proposed http wireprotocol /api/
45 # namespace?
46 # namespace?
46 elif req.dispatchpath.startswith(b'.hg/lfs/objects'):
47 elif req.dispatchpath.startswith(b'.hg/lfs/objects'):
47 return _processbasictransfer(rctx.repo, req, res,
48 return _processbasictransfer(rctx.repo, req, res,
48 lambda perm:
49 lambda perm:
49 checkperm(rctx, req, perm))
50 checkperm(rctx, req, perm))
50 return False
51 return False
51 except hgwebcommon.ErrorResponse as e:
52 except hgwebcommon.ErrorResponse as e:
52 # XXX: copied from the handler surrounding wireprotoserver._callhttp()
53 # XXX: copied from the handler surrounding wireprotoserver._callhttp()
53 # in the wrapped function. Should this be moved back to hgweb to
54 # in the wrapped function. Should this be moved back to hgweb to
54 # be a common handler?
55 # be a common handler?
55 for k, v in e.headers:
56 for k, v in e.headers:
56 res.headers[k] = v
57 res.headers[k] = v
57 res.status = hgwebcommon.statusmessage(e.code, pycompat.bytestr(e))
58 res.status = hgwebcommon.statusmessage(e.code, pycompat.bytestr(e))
58 res.setbodybytes(b'0\n%s\n' % pycompat.bytestr(e))
59 res.setbodybytes(b'0\n%s\n' % pycompat.bytestr(e))
59 return True
60 return True
60
61
61 def _sethttperror(res, code, message=None):
62 def _sethttperror(res, code, message=None):
62 res.status = hgwebcommon.statusmessage(code, message=message)
63 res.status = hgwebcommon.statusmessage(code, message=message)
63 res.headers[b'Content-Type'] = b'text/plain; charset=utf-8'
64 res.headers[b'Content-Type'] = b'text/plain; charset=utf-8'
64 res.setbodybytes(b'')
65 res.setbodybytes(b'')
65
66
67 def _logexception(req):
68 """Write information about the current exception to wsgi.errors."""
69 tb = pycompat.sysbytes(traceback.format_exc())
70 errorlog = req.rawenv[r'wsgi.errors']
71
72 uri = b''
73 if req.apppath:
74 uri += req.apppath
75 uri += b'/' + req.dispatchpath
76
77 errorlog.write(b"Exception happened while processing request '%s':\n%s" %
78 (uri, tb))
79
66 def _processbatchrequest(repo, req, res):
80 def _processbatchrequest(repo, req, res):
67 """Handle a request for the Batch API, which is the gateway to granting file
81 """Handle a request for the Batch API, which is the gateway to granting file
68 access.
82 access.
69
83
70 https://github.com/git-lfs/git-lfs/blob/master/docs/api/batch.md
84 https://github.com/git-lfs/git-lfs/blob/master/docs/api/batch.md
71 """
85 """
72
86
73 # Mercurial client request:
87 # Mercurial client request:
74 #
88 #
75 # HOST: localhost:$HGPORT
89 # HOST: localhost:$HGPORT
76 # ACCEPT: application/vnd.git-lfs+json
90 # ACCEPT: application/vnd.git-lfs+json
77 # ACCEPT-ENCODING: identity
91 # ACCEPT-ENCODING: identity
78 # USER-AGENT: git-lfs/2.3.4 (Mercurial 4.5.2+1114-f48b9754f04c+20180316)
92 # USER-AGENT: git-lfs/2.3.4 (Mercurial 4.5.2+1114-f48b9754f04c+20180316)
79 # Content-Length: 125
93 # Content-Length: 125
80 # Content-Type: application/vnd.git-lfs+json
94 # Content-Type: application/vnd.git-lfs+json
81 #
95 #
82 # {
96 # {
83 # "objects": [
97 # "objects": [
84 # {
98 # {
85 # "oid": "31cf...8e5b"
99 # "oid": "31cf...8e5b"
86 # "size": 12
100 # "size": 12
87 # }
101 # }
88 # ]
102 # ]
89 # "operation": "upload"
103 # "operation": "upload"
90 # }
104 # }
91
105
92 if (req.method != b'POST'
106 if (req.method != b'POST'
93 or req.headers[b'Content-Type'] != b'application/vnd.git-lfs+json'
107 or req.headers[b'Content-Type'] != b'application/vnd.git-lfs+json'
94 or req.headers[b'Accept'] != b'application/vnd.git-lfs+json'):
108 or req.headers[b'Accept'] != b'application/vnd.git-lfs+json'):
95 # TODO: figure out what the proper handling for a bad request to the
109 # TODO: figure out what the proper handling for a bad request to the
96 # Batch API is.
110 # Batch API is.
97 _sethttperror(res, HTTP_BAD_REQUEST, b'Invalid Batch API request')
111 _sethttperror(res, HTTP_BAD_REQUEST, b'Invalid Batch API request')
98 return True
112 return True
99
113
100 # XXX: specify an encoding?
114 # XXX: specify an encoding?
101 lfsreq = json.loads(req.bodyfh.read())
115 lfsreq = json.loads(req.bodyfh.read())
102
116
103 # If no transfer handlers are explicitly requested, 'basic' is assumed.
117 # If no transfer handlers are explicitly requested, 'basic' is assumed.
104 if 'basic' not in lfsreq.get('transfers', ['basic']):
118 if 'basic' not in lfsreq.get('transfers', ['basic']):
105 _sethttperror(res, HTTP_BAD_REQUEST,
119 _sethttperror(res, HTTP_BAD_REQUEST,
106 b'Only the basic LFS transfer handler is supported')
120 b'Only the basic LFS transfer handler is supported')
107 return True
121 return True
108
122
109 operation = lfsreq.get('operation')
123 operation = lfsreq.get('operation')
110 if operation not in ('upload', 'download'):
124 if operation not in ('upload', 'download'):
111 _sethttperror(res, HTTP_BAD_REQUEST,
125 _sethttperror(res, HTTP_BAD_REQUEST,
112 b'Unsupported LFS transfer operation: %s' % operation)
126 b'Unsupported LFS transfer operation: %s' % operation)
113 return True
127 return True
114
128
115 localstore = repo.svfs.lfslocalblobstore
129 localstore = repo.svfs.lfslocalblobstore
116
130
117 objects = [p for p in _batchresponseobjects(req, lfsreq.get('objects', []),
131 objects = [p for p in _batchresponseobjects(req, lfsreq.get('objects', []),
118 operation, localstore)]
132 operation, localstore)]
119
133
120 rsp = {
134 rsp = {
121 'transfer': 'basic',
135 'transfer': 'basic',
122 'objects': objects,
136 'objects': objects,
123 }
137 }
124
138
125 res.status = hgwebcommon.statusmessage(HTTP_OK)
139 res.status = hgwebcommon.statusmessage(HTTP_OK)
126 res.headers[b'Content-Type'] = b'application/vnd.git-lfs+json'
140 res.headers[b'Content-Type'] = b'application/vnd.git-lfs+json'
127 res.setbodybytes(pycompat.bytestr(json.dumps(rsp)))
141 res.setbodybytes(pycompat.bytestr(json.dumps(rsp)))
128
142
129 return True
143 return True
130
144
131 def _batchresponseobjects(req, objects, action, store):
145 def _batchresponseobjects(req, objects, action, store):
132 """Yield one dictionary of attributes for the Batch API response for each
146 """Yield one dictionary of attributes for the Batch API response for each
133 object in the list.
147 object in the list.
134
148
135 req: The parsedrequest for the Batch API request
149 req: The parsedrequest for the Batch API request
136 objects: The list of objects in the Batch API object request list
150 objects: The list of objects in the Batch API object request list
137 action: 'upload' or 'download'
151 action: 'upload' or 'download'
138 store: The local blob store for servicing requests"""
152 store: The local blob store for servicing requests"""
139
153
140 # Successful lfs-test-server response to solict an upload:
154 # Successful lfs-test-server response to solict an upload:
141 # {
155 # {
142 # u'objects': [{
156 # u'objects': [{
143 # u'size': 12,
157 # u'size': 12,
144 # u'oid': u'31cf...8e5b',
158 # u'oid': u'31cf...8e5b',
145 # u'actions': {
159 # u'actions': {
146 # u'upload': {
160 # u'upload': {
147 # u'href': u'http://localhost:$HGPORT/objects/31cf...8e5b',
161 # u'href': u'http://localhost:$HGPORT/objects/31cf...8e5b',
148 # u'expires_at': u'0001-01-01T00:00:00Z',
162 # u'expires_at': u'0001-01-01T00:00:00Z',
149 # u'header': {
163 # u'header': {
150 # u'Accept': u'application/vnd.git-lfs'
164 # u'Accept': u'application/vnd.git-lfs'
151 # }
165 # }
152 # }
166 # }
153 # }
167 # }
154 # }]
168 # }]
155 # }
169 # }
156
170
157 # TODO: Sort out the expires_at/expires_in/authenticated keys.
171 # TODO: Sort out the expires_at/expires_in/authenticated keys.
158
172
159 for obj in objects:
173 for obj in objects:
160 # Convert unicode to ASCII to create a filesystem path
174 # Convert unicode to ASCII to create a filesystem path
161 oid = obj.get('oid').encode('ascii')
175 oid = obj.get('oid').encode('ascii')
162 rsp = {
176 rsp = {
163 'oid': oid,
177 'oid': oid,
164 'size': obj.get('size'), # XXX: should this check the local size?
178 'size': obj.get('size'), # XXX: should this check the local size?
165 #'authenticated': True,
179 #'authenticated': True,
166 }
180 }
167
181
168 exists = True
182 exists = True
169 verifies = False
183 verifies = False
170
184
171 # Verify an existing file on the upload request, so that the client is
185 # Verify an existing file on the upload request, so that the client is
172 # solicited to re-upload if it corrupt locally. Download requests are
186 # solicited to re-upload if it corrupt locally. Download requests are
173 # also verified, so the error can be flagged in the Batch API response.
187 # also verified, so the error can be flagged in the Batch API response.
174 # (Maybe we can use this to short circuit the download for `hg verify`,
188 # (Maybe we can use this to short circuit the download for `hg verify`,
175 # IFF the client can assert that the remote end is an hg server.)
189 # IFF the client can assert that the remote end is an hg server.)
176 # Otherwise, it's potentially overkill on download, since it is also
190 # Otherwise, it's potentially overkill on download, since it is also
177 # verified as the file is streamed to the caller.
191 # verified as the file is streamed to the caller.
178 try:
192 try:
179 verifies = store.verify(oid)
193 verifies = store.verify(oid)
180 except IOError as inst:
194 except IOError as inst:
181 if inst.errno != errno.ENOENT:
195 if inst.errno != errno.ENOENT:
196 _logexception(req)
197
182 rsp['error'] = {
198 rsp['error'] = {
183 'code': 500,
199 'code': 500,
184 'message': inst.strerror or 'Internal Server Server'
200 'message': inst.strerror or 'Internal Server Server'
185 }
201 }
186 yield rsp
202 yield rsp
187 continue
203 continue
188
204
189 exists = False
205 exists = False
190
206
191 # Items are always listed for downloads. They are dropped for uploads
207 # Items are always listed for downloads. They are dropped for uploads
192 # IFF they already exist locally.
208 # IFF they already exist locally.
193 if action == 'download':
209 if action == 'download':
194 if not exists:
210 if not exists:
195 rsp['error'] = {
211 rsp['error'] = {
196 'code': 404,
212 'code': 404,
197 'message': "The object does not exist"
213 'message': "The object does not exist"
198 }
214 }
199 yield rsp
215 yield rsp
200 continue
216 continue
201
217
202 elif not verifies:
218 elif not verifies:
203 rsp['error'] = {
219 rsp['error'] = {
204 'code': 422, # XXX: is this the right code?
220 'code': 422, # XXX: is this the right code?
205 'message': "The object is corrupt"
221 'message': "The object is corrupt"
206 }
222 }
207 yield rsp
223 yield rsp
208 continue
224 continue
209
225
210 elif verifies:
226 elif verifies:
211 yield rsp # Skip 'actions': already uploaded
227 yield rsp # Skip 'actions': already uploaded
212 continue
228 continue
213
229
214 expiresat = datetime.datetime.now() + datetime.timedelta(minutes=10)
230 expiresat = datetime.datetime.now() + datetime.timedelta(minutes=10)
215
231
216 rsp['actions'] = {
232 rsp['actions'] = {
217 '%s' % action: {
233 '%s' % action: {
218 'href': '%s%s/.hg/lfs/objects/%s'
234 'href': '%s%s/.hg/lfs/objects/%s'
219 % (req.baseurl, req.apppath, oid),
235 % (req.baseurl, req.apppath, oid),
220 # datetime.isoformat() doesn't include the 'Z' suffix
236 # datetime.isoformat() doesn't include the 'Z' suffix
221 "expires_at": expiresat.strftime('%Y-%m-%dT%H:%M:%SZ'),
237 "expires_at": expiresat.strftime('%Y-%m-%dT%H:%M:%SZ'),
222 'header': {
238 'header': {
223 # The spec doesn't mention the Accept header here, but avoid
239 # The spec doesn't mention the Accept header here, but avoid
224 # a gratuitous deviation from lfs-test-server in the test
240 # a gratuitous deviation from lfs-test-server in the test
225 # output.
241 # output.
226 'Accept': 'application/vnd.git-lfs'
242 'Accept': 'application/vnd.git-lfs'
227 }
243 }
228 }
244 }
229 }
245 }
230
246
231 yield rsp
247 yield rsp
232
248
233 def _processbasictransfer(repo, req, res, checkperm):
249 def _processbasictransfer(repo, req, res, checkperm):
234 """Handle a single file upload (PUT) or download (GET) action for the Basic
250 """Handle a single file upload (PUT) or download (GET) action for the Basic
235 Transfer Adapter.
251 Transfer Adapter.
236
252
237 After determining if the request is for an upload or download, the access
253 After determining if the request is for an upload or download, the access
238 must be checked by calling ``checkperm()`` with either 'pull' or 'upload'
254 must be checked by calling ``checkperm()`` with either 'pull' or 'upload'
239 before accessing the files.
255 before accessing the files.
240
256
241 https://github.com/git-lfs/git-lfs/blob/master/docs/api/basic-transfers.md
257 https://github.com/git-lfs/git-lfs/blob/master/docs/api/basic-transfers.md
242 """
258 """
243
259
244 method = req.method
260 method = req.method
245 oid = req.dispatchparts[-1]
261 oid = req.dispatchparts[-1]
246 localstore = repo.svfs.lfslocalblobstore
262 localstore = repo.svfs.lfslocalblobstore
247
263
248 if len(req.dispatchparts) != 4:
264 if len(req.dispatchparts) != 4:
249 _sethttperror(res, HTTP_NOT_FOUND)
265 _sethttperror(res, HTTP_NOT_FOUND)
250 return True
266 return True
251
267
252 if method == b'PUT':
268 if method == b'PUT':
253 checkperm('upload')
269 checkperm('upload')
254
270
255 # TODO: verify Content-Type?
271 # TODO: verify Content-Type?
256
272
257 existed = localstore.has(oid)
273 existed = localstore.has(oid)
258
274
259 # TODO: how to handle timeouts? The body proxy handles limiting to
275 # TODO: how to handle timeouts? The body proxy handles limiting to
260 # Content-Length, but what happens if a client sends less than it
276 # Content-Length, but what happens if a client sends less than it
261 # says it will?
277 # says it will?
262
278
263 # TODO: download() will abort if the checksum fails. It should raise
279 # TODO: download() will abort if the checksum fails. It should raise
264 # something checksum specific that can be caught here, and turned
280 # something checksum specific that can be caught here, and turned
265 # into an http code.
281 # into an http code.
266 localstore.download(oid, req.bodyfh)
282 localstore.download(oid, req.bodyfh)
267
283
268 statusmessage = hgwebcommon.statusmessage
284 statusmessage = hgwebcommon.statusmessage
269 res.status = statusmessage(HTTP_OK if existed else HTTP_CREATED)
285 res.status = statusmessage(HTTP_OK if existed else HTTP_CREATED)
270
286
271 # There's no payload here, but this is the header that lfs-test-server
287 # There's no payload here, but this is the header that lfs-test-server
272 # sends back. This eliminates some gratuitous test output conditionals.
288 # sends back. This eliminates some gratuitous test output conditionals.
273 res.headers[b'Content-Type'] = b'text/plain; charset=utf-8'
289 res.headers[b'Content-Type'] = b'text/plain; charset=utf-8'
274 res.setbodybytes(b'')
290 res.setbodybytes(b'')
275
291
276 return True
292 return True
277 elif method == b'GET':
293 elif method == b'GET':
278 checkperm('pull')
294 checkperm('pull')
279
295
280 res.status = hgwebcommon.statusmessage(HTTP_OK)
296 res.status = hgwebcommon.statusmessage(HTTP_OK)
281 res.headers[b'Content-Type'] = b'application/octet-stream'
297 res.headers[b'Content-Type'] = b'application/octet-stream'
282
298
283 # TODO: figure out how to send back the file in chunks, instead of
299 # TODO: figure out how to send back the file in chunks, instead of
284 # reading the whole thing.
300 # reading the whole thing.
285 res.setbodybytes(localstore.read(oid))
301 res.setbodybytes(localstore.read(oid))
286
302
287 return True
303 return True
288 else:
304 else:
289 _sethttperror(res, HTTP_BAD_REQUEST,
305 _sethttperror(res, HTTP_BAD_REQUEST,
290 message=b'Unsupported LFS transfer method: %s' % method)
306 message=b'Unsupported LFS transfer method: %s' % method)
291 return True
307 return True
@@ -1,334 +1,346 b''
1 #require serve no-reposimplestore
1 #require serve no-reposimplestore
2
2
3 $ cat >> $HGRCPATH <<EOF
3 $ cat >> $HGRCPATH <<EOF
4 > [extensions]
4 > [extensions]
5 > lfs=
5 > lfs=
6 > [lfs]
6 > [lfs]
7 > track=all()
7 > track=all()
8 > [web]
8 > [web]
9 > push_ssl = False
9 > push_ssl = False
10 > allow-push = *
10 > allow-push = *
11 > EOF
11 > EOF
12
12
13 Serving LFS files can experimentally be turned off. The long term solution is
13 Serving LFS files can experimentally be turned off. The long term solution is
14 to support the 'verify' action in both client and server, so that the server can
14 to support the 'verify' action in both client and server, so that the server can
15 tell the client to store files elsewhere.
15 tell the client to store files elsewhere.
16
16
17 $ hg init server
17 $ hg init server
18 $ hg --config "lfs.usercache=$TESTTMP/servercache" \
18 $ hg --config "lfs.usercache=$TESTTMP/servercache" \
19 > --config experimental.lfs.serve=False -R server serve -d \
19 > --config experimental.lfs.serve=False -R server serve -d \
20 > -p $HGPORT --pid-file=hg.pid -A $TESTTMP/access.log -E $TESTTMP/errors.log
20 > -p $HGPORT --pid-file=hg.pid -A $TESTTMP/access.log -E $TESTTMP/errors.log
21 $ cat hg.pid >> $DAEMON_PIDS
21 $ cat hg.pid >> $DAEMON_PIDS
22
22
23 Uploads fail...
23 Uploads fail...
24
24
25 $ hg init client
25 $ hg init client
26 $ echo 'this-is-an-lfs-file' > client/lfs.bin
26 $ echo 'this-is-an-lfs-file' > client/lfs.bin
27 $ hg -R client ci -Am 'initial commit'
27 $ hg -R client ci -Am 'initial commit'
28 adding lfs.bin
28 adding lfs.bin
29 $ hg -R client push http://localhost:$HGPORT
29 $ hg -R client push http://localhost:$HGPORT
30 pushing to http://localhost:$HGPORT/
30 pushing to http://localhost:$HGPORT/
31 searching for changes
31 searching for changes
32 abort: LFS HTTP error: HTTP Error 400: no such method: .git (action=upload)!
32 abort: LFS HTTP error: HTTP Error 400: no such method: .git (action=upload)!
33 [255]
33 [255]
34
34
35 ... so do a local push to make the data available. Remove the blob from the
35 ... so do a local push to make the data available. Remove the blob from the
36 default cache, so it attempts to download.
36 default cache, so it attempts to download.
37 $ hg --config "lfs.usercache=$TESTTMP/servercache" \
37 $ hg --config "lfs.usercache=$TESTTMP/servercache" \
38 > --config "lfs.url=null://" \
38 > --config "lfs.url=null://" \
39 > -R client push -q server
39 > -R client push -q server
40 $ mv `hg config lfs.usercache` $TESTTMP/servercache
40 $ mv `hg config lfs.usercache` $TESTTMP/servercache
41
41
42 Downloads fail...
42 Downloads fail...
43
43
44 $ hg clone http://localhost:$HGPORT httpclone
44 $ hg clone http://localhost:$HGPORT httpclone
45 requesting all changes
45 requesting all changes
46 adding changesets
46 adding changesets
47 adding manifests
47 adding manifests
48 adding file changes
48 adding file changes
49 added 1 changesets with 1 changes to 1 files
49 added 1 changesets with 1 changes to 1 files
50 new changesets 525251863cad
50 new changesets 525251863cad
51 updating to branch default
51 updating to branch default
52 abort: LFS HTTP error: HTTP Error 400: no such method: .git (action=download)!
52 abort: LFS HTTP error: HTTP Error 400: no such method: .git (action=download)!
53 [255]
53 [255]
54
54
55 $ $PYTHON $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
55 $ $PYTHON $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
56
56
57 $ cat $TESTTMP/access.log $TESTTMP/errors.log
57 $ cat $TESTTMP/access.log $TESTTMP/errors.log
58 $LOCALIP - - [$LOGDATE$] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
58 $LOCALIP - - [$LOGDATE$] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
59 $LOCALIP - - [$LOGDATE$] "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D525251863cad618e55d483555f3d00a2ca99597e x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
59 $LOCALIP - - [$LOGDATE$] "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D525251863cad618e55d483555f3d00a2ca99597e x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
60 $LOCALIP - - [$LOGDATE$] "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
60 $LOCALIP - - [$LOGDATE$] "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
61 $LOCALIP - - [$LOGDATE$] "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
61 $LOCALIP - - [$LOGDATE$] "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
62 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 400 - (glob)
62 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 400 - (glob)
63 $LOCALIP - - [$LOGDATE$] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
63 $LOCALIP - - [$LOGDATE$] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
64 $LOCALIP - - [$LOGDATE$] "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
64 $LOCALIP - - [$LOGDATE$] "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
65 $LOCALIP - - [$LOGDATE$] "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bookmarks=1&bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%252C03%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Aphases%253Dheads%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps%250Arev-branch-cache%250Astream%253Dv2&cg=1&common=0000000000000000000000000000000000000000&heads=525251863cad618e55d483555f3d00a2ca99597e&listkeys=bookmarks&phases=1 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
65 $LOCALIP - - [$LOGDATE$] "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bookmarks=1&bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%252C03%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Aphases%253Dheads%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps%250Arev-branch-cache%250Astream%253Dv2&cg=1&common=0000000000000000000000000000000000000000&heads=525251863cad618e55d483555f3d00a2ca99597e&listkeys=bookmarks&phases=1 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
66 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 400 - (glob)
66 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 400 - (glob)
67
67
68 Blob URIs are correct when --prefix is used
68 Blob URIs are correct when --prefix is used
69
69
70 $ rm -f $TESTTMP/access.log $TESTTMP/errors.log
70 $ rm -f $TESTTMP/access.log $TESTTMP/errors.log
71 $ hg --config "lfs.usercache=$TESTTMP/servercache" -R server serve -d \
71 $ hg --config "lfs.usercache=$TESTTMP/servercache" -R server serve -d \
72 > -p $HGPORT --pid-file=hg.pid --prefix=subdir/mount/point \
72 > -p $HGPORT --pid-file=hg.pid --prefix=subdir/mount/point \
73 > -A $TESTTMP/access.log -E $TESTTMP/errors.log
73 > -A $TESTTMP/access.log -E $TESTTMP/errors.log
74 $ cat hg.pid >> $DAEMON_PIDS
74 $ cat hg.pid >> $DAEMON_PIDS
75
75
76 $ hg --config lfs.url=http://localhost:$HGPORT/subdir/mount/point/.git/info/lfs \
76 $ hg --config lfs.url=http://localhost:$HGPORT/subdir/mount/point/.git/info/lfs \
77 > clone --debug http://localhost:$HGPORT/subdir/mount/point cloned2
77 > clone --debug http://localhost:$HGPORT/subdir/mount/point cloned2
78 using http://localhost:$HGPORT/subdir/mount/point
78 using http://localhost:$HGPORT/subdir/mount/point
79 sending capabilities command
79 sending capabilities command
80 query 1; heads
80 query 1; heads
81 sending batch command
81 sending batch command
82 requesting all changes
82 requesting all changes
83 sending getbundle command
83 sending getbundle command
84 bundle2-input-bundle: with-transaction
84 bundle2-input-bundle: with-transaction
85 bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
85 bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
86 adding changesets
86 adding changesets
87 add changeset 525251863cad
87 add changeset 525251863cad
88 adding manifests
88 adding manifests
89 adding file changes
89 adding file changes
90 adding lfs.bin revisions
90 adding lfs.bin revisions
91 added 1 changesets with 1 changes to 1 files
91 added 1 changesets with 1 changes to 1 files
92 calling hook pretxnchangegroup.lfs: hgext.lfs.checkrequireslfs
92 calling hook pretxnchangegroup.lfs: hgext.lfs.checkrequireslfs
93 bundle2-input-part: total payload size 648
93 bundle2-input-part: total payload size 648
94 bundle2-input-part: "listkeys" (params: 1 mandatory) supported
94 bundle2-input-part: "listkeys" (params: 1 mandatory) supported
95 bundle2-input-part: "phase-heads" supported
95 bundle2-input-part: "phase-heads" supported
96 bundle2-input-part: total payload size 24
96 bundle2-input-part: total payload size 24
97 bundle2-input-part: "cache:rev-branch-cache" supported
97 bundle2-input-part: "cache:rev-branch-cache" supported
98 bundle2-input-part: total payload size 39
98 bundle2-input-part: total payload size 39
99 bundle2-input-bundle: 3 parts total
99 bundle2-input-bundle: 3 parts total
100 checking for updated bookmarks
100 checking for updated bookmarks
101 updating the branch cache
101 updating the branch cache
102 new changesets 525251863cad
102 new changesets 525251863cad
103 updating to branch default
103 updating to branch default
104 resolving manifests
104 resolving manifests
105 branchmerge: False, force: False, partial: False
105 branchmerge: False, force: False, partial: False
106 ancestor: 000000000000, local: 000000000000+, remote: 525251863cad
106 ancestor: 000000000000, local: 000000000000+, remote: 525251863cad
107 Status: 200
107 Status: 200
108 Content-Length: 371
108 Content-Length: 371
109 Content-Type: application/vnd.git-lfs+json
109 Content-Type: application/vnd.git-lfs+json
110 Date: $HTTP_DATE$
110 Date: $HTTP_DATE$
111 Server: testing stub value
111 Server: testing stub value
112 {
112 {
113 "objects": [
113 "objects": [
114 {
114 {
115 "actions": {
115 "actions": {
116 "download": {
116 "download": {
117 "expires_at": "$ISO_8601_DATE_TIME$"
117 "expires_at": "$ISO_8601_DATE_TIME$"
118 "header": {
118 "header": {
119 "Accept": "application/vnd.git-lfs"
119 "Accept": "application/vnd.git-lfs"
120 }
120 }
121 "href": "http://localhost:$HGPORT/subdir/mount/point/.hg/lfs/objects/f03217a32529a28a42d03b1244fe09b6e0f9fd06d7b966d4d50567be2abe6c0e"
121 "href": "http://localhost:$HGPORT/subdir/mount/point/.hg/lfs/objects/f03217a32529a28a42d03b1244fe09b6e0f9fd06d7b966d4d50567be2abe6c0e"
122 }
122 }
123 }
123 }
124 "oid": "f03217a32529a28a42d03b1244fe09b6e0f9fd06d7b966d4d50567be2abe6c0e"
124 "oid": "f03217a32529a28a42d03b1244fe09b6e0f9fd06d7b966d4d50567be2abe6c0e"
125 "size": 20
125 "size": 20
126 }
126 }
127 ]
127 ]
128 "transfer": "basic"
128 "transfer": "basic"
129 }
129 }
130 lfs: downloading f03217a32529a28a42d03b1244fe09b6e0f9fd06d7b966d4d50567be2abe6c0e (20 bytes)
130 lfs: downloading f03217a32529a28a42d03b1244fe09b6e0f9fd06d7b966d4d50567be2abe6c0e (20 bytes)
131 Status: 200
131 Status: 200
132 Content-Length: 20
132 Content-Length: 20
133 Content-Type: application/octet-stream
133 Content-Type: application/octet-stream
134 Date: $HTTP_DATE$
134 Date: $HTTP_DATE$
135 Server: testing stub value
135 Server: testing stub value
136 lfs: adding f03217a32529a28a42d03b1244fe09b6e0f9fd06d7b966d4d50567be2abe6c0e to the usercache
136 lfs: adding f03217a32529a28a42d03b1244fe09b6e0f9fd06d7b966d4d50567be2abe6c0e to the usercache
137 lfs: processed: f03217a32529a28a42d03b1244fe09b6e0f9fd06d7b966d4d50567be2abe6c0e
137 lfs: processed: f03217a32529a28a42d03b1244fe09b6e0f9fd06d7b966d4d50567be2abe6c0e
138 lfs.bin: remote created -> g
138 lfs.bin: remote created -> g
139 getting lfs.bin
139 getting lfs.bin
140 lfs: found f03217a32529a28a42d03b1244fe09b6e0f9fd06d7b966d4d50567be2abe6c0e in the local lfs store
140 lfs: found f03217a32529a28a42d03b1244fe09b6e0f9fd06d7b966d4d50567be2abe6c0e in the local lfs store
141 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
141 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
142
142
143 $ $PYTHON $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
143 $ $PYTHON $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
144
144
145 $ cat $TESTTMP/access.log $TESTTMP/errors.log
145 $ cat $TESTTMP/access.log $TESTTMP/errors.log
146 $LOCALIP - - [$LOGDATE$] "GET /subdir/mount/point?cmd=capabilities HTTP/1.1" 200 - (glob)
146 $LOCALIP - - [$LOGDATE$] "GET /subdir/mount/point?cmd=capabilities HTTP/1.1" 200 - (glob)
147 $LOCALIP - - [$LOGDATE$] "GET /subdir/mount/point?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
147 $LOCALIP - - [$LOGDATE$] "GET /subdir/mount/point?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
148 $LOCALIP - - [$LOGDATE$] "GET /subdir/mount/point?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bookmarks=1&bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%252C03%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Aphases%253Dheads%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps%250Arev-branch-cache%250Astream%253Dv2&cg=1&common=0000000000000000000000000000000000000000&heads=525251863cad618e55d483555f3d00a2ca99597e&listkeys=bookmarks&phases=1 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
148 $LOCALIP - - [$LOGDATE$] "GET /subdir/mount/point?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bookmarks=1&bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%252C03%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Aphases%253Dheads%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps%250Arev-branch-cache%250Astream%253Dv2&cg=1&common=0000000000000000000000000000000000000000&heads=525251863cad618e55d483555f3d00a2ca99597e&listkeys=bookmarks&phases=1 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
149 $LOCALIP - - [$LOGDATE$] "POST /subdir/mount/point/.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
149 $LOCALIP - - [$LOGDATE$] "POST /subdir/mount/point/.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
150 $LOCALIP - - [$LOGDATE$] "GET /subdir/mount/point/.hg/lfs/objects/f03217a32529a28a42d03b1244fe09b6e0f9fd06d7b966d4d50567be2abe6c0e HTTP/1.1" 200 - (glob)
150 $LOCALIP - - [$LOGDATE$] "GET /subdir/mount/point/.hg/lfs/objects/f03217a32529a28a42d03b1244fe09b6e0f9fd06d7b966d4d50567be2abe6c0e HTTP/1.1" 200 - (glob)
151
151
152 $ cat >> $TESTTMP/lfsstoreerror.py <<EOF
152 $ cat >> $TESTTMP/lfsstoreerror.py <<EOF
153 > import errno
153 > import errno
154 > from hgext.lfs import blobstore
154 > from hgext.lfs import blobstore
155 >
155 >
156 > _numverifies = 0
156 > _numverifies = 0
157 > _readerr = True
157 > _readerr = True
158 >
158 >
159 > def reposetup(ui, repo):
159 > def reposetup(ui, repo):
160 > # Nothing to do with a remote repo
160 > # Nothing to do with a remote repo
161 > if not repo.local():
161 > if not repo.local():
162 > return
162 > return
163 >
163 >
164 > store = repo.svfs.lfslocalblobstore
164 > store = repo.svfs.lfslocalblobstore
165 > class badstore(store.__class__):
165 > class badstore(store.__class__):
166 > def download(self, oid, src):
166 > def download(self, oid, src):
167 > '''Called in the server to handle reading from the client in a
167 > '''Called in the server to handle reading from the client in a
168 > PUT request.'''
168 > PUT request.'''
169 > origread = src.read
169 > origread = src.read
170 > def _badread(nbytes):
170 > def _badread(nbytes):
171 > # Simulate bad data/checksum failure from the client
171 > # Simulate bad data/checksum failure from the client
172 > return b'0' * len(origread(nbytes))
172 > return b'0' * len(origread(nbytes))
173 > src.read = _badread
173 > src.read = _badread
174 > super(badstore, self).download(oid, src)
174 > super(badstore, self).download(oid, src)
175 >
175 >
176 > def _read(self, vfs, oid, verify):
176 > def _read(self, vfs, oid, verify):
177 > '''Called in the server to read data for a GET request, and then
177 > '''Called in the server to read data for a GET request, and then
178 > calls self._verify() on it before returning.'''
178 > calls self._verify() on it before returning.'''
179 > global _readerr
179 > global _readerr
180 > # One time simulation of a read error
180 > # One time simulation of a read error
181 > if _readerr:
181 > if _readerr:
182 > _readerr = False
182 > _readerr = False
183 > raise IOError(errno.EIO, '%s: I/O error' % oid)
183 > raise IOError(errno.EIO, '%s: I/O error' % oid)
184 > # Simulate corrupt content on client download
184 > # Simulate corrupt content on client download
185 > blobstore._verify(oid, 'dummy content')
185 > blobstore._verify(oid, 'dummy content')
186 >
186 >
187 > def verify(self, oid):
187 > def verify(self, oid):
188 > '''Called in the server to populate the Batch API response,
188 > '''Called in the server to populate the Batch API response,
189 > letting the client re-upload if the file is corrupt.'''
189 > letting the client re-upload if the file is corrupt.'''
190 > # Fail verify in Batch API for one clone command and one push
190 > # Fail verify in Batch API for one clone command and one push
191 > # command with an IOError. Then let it through to access other
191 > # command with an IOError. Then let it through to access other
192 > # functions. Checksum failure is tested elsewhere.
192 > # functions. Checksum failure is tested elsewhere.
193 > global _numverifies
193 > global _numverifies
194 > _numverifies += 1
194 > _numverifies += 1
195 > if _numverifies <= 2:
195 > if _numverifies <= 2:
196 > raise IOError(errno.EIO, '%s: I/O error' % oid)
196 > raise IOError(errno.EIO, '%s: I/O error' % oid)
197 > return super(badstore, self).verify(oid)
197 > return super(badstore, self).verify(oid)
198 >
198 >
199 > store.__class__ = badstore
199 > store.__class__ = badstore
200 > EOF
200 > EOF
201
201
202 $ rm -rf `hg config lfs.usercache`
202 $ rm -rf `hg config lfs.usercache`
203 $ rm -f $TESTTMP/access.log $TESTTMP/errors.log
203 $ rm -f $TESTTMP/access.log $TESTTMP/errors.log
204 $ hg --config "lfs.usercache=$TESTTMP/servercache" \
204 $ hg --config "lfs.usercache=$TESTTMP/servercache" \
205 > --config extensions.lfsstoreerror=$TESTTMP/lfsstoreerror.py \
205 > --config extensions.lfsstoreerror=$TESTTMP/lfsstoreerror.py \
206 > -R server serve -d \
206 > -R server serve -d \
207 > -p $HGPORT1 --pid-file=hg.pid -A $TESTTMP/access.log -E $TESTTMP/errors.log
207 > -p $HGPORT1 --pid-file=hg.pid -A $TESTTMP/access.log -E $TESTTMP/errors.log
208 $ cat hg.pid >> $DAEMON_PIDS
208 $ cat hg.pid >> $DAEMON_PIDS
209
209
210 Test an I/O error in localstore.verify() (Batch API) with GET
210 Test an I/O error in localstore.verify() (Batch API) with GET
211
211
212 $ hg clone http://localhost:$HGPORT1 httpclone2
212 $ hg clone http://localhost:$HGPORT1 httpclone2
213 requesting all changes
213 requesting all changes
214 adding changesets
214 adding changesets
215 adding manifests
215 adding manifests
216 adding file changes
216 adding file changes
217 added 1 changesets with 1 changes to 1 files
217 added 1 changesets with 1 changes to 1 files
218 new changesets 525251863cad
218 new changesets 525251863cad
219 updating to branch default
219 updating to branch default
220 abort: LFS server error for "lfs.bin": Internal server error!
220 abort: LFS server error for "lfs.bin": Internal server error!
221 [255]
221 [255]
222
222
223 Test an I/O error in localstore.verify() (Batch API) with PUT
223 Test an I/O error in localstore.verify() (Batch API) with PUT
224
224
225 $ echo foo > client/lfs.bin
225 $ echo foo > client/lfs.bin
226 $ hg -R client ci -m 'mod lfs'
226 $ hg -R client ci -m 'mod lfs'
227 $ hg -R client push http://localhost:$HGPORT1
227 $ hg -R client push http://localhost:$HGPORT1
228 pushing to http://localhost:$HGPORT1/
228 pushing to http://localhost:$HGPORT1/
229 searching for changes
229 searching for changes
230 abort: LFS server error for "unknown": Internal server error!
230 abort: LFS server error for "unknown": Internal server error!
231 [255]
231 [255]
232 TODO: figure out how to associate the file name in the error above
232 TODO: figure out how to associate the file name in the error above
233
233
234 Test a bad checksum sent by the client in the transfer API
234 Test a bad checksum sent by the client in the transfer API
235
235
236 $ hg -R client push http://localhost:$HGPORT1
236 $ hg -R client push http://localhost:$HGPORT1
237 pushing to http://localhost:$HGPORT1/
237 pushing to http://localhost:$HGPORT1/
238 searching for changes
238 searching for changes
239 abort: HTTP error: HTTP Error 500: Internal Server Error (oid=b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c, action=upload)!
239 abort: HTTP error: HTTP Error 500: Internal Server Error (oid=b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c, action=upload)!
240 [255]
240 [255]
241
241
242 $ echo 'test lfs file' > server/lfs3.bin
242 $ echo 'test lfs file' > server/lfs3.bin
243 $ hg --config experimental.lfs.disableusercache=True \
243 $ hg --config experimental.lfs.disableusercache=True \
244 > -R server ci -Aqm 'another lfs file'
244 > -R server ci -Aqm 'another lfs file'
245 $ hg -R client pull -q http://localhost:$HGPORT1
245 $ hg -R client pull -q http://localhost:$HGPORT1
246
246
247 Test an I/O error during the processing of the GET request
247 Test an I/O error during the processing of the GET request
248
248
249 $ hg --config lfs.url=http://localhost:$HGPORT1/.git/info/lfs \
249 $ hg --config lfs.url=http://localhost:$HGPORT1/.git/info/lfs \
250 > -R client update -r tip
250 > -R client update -r tip
251 abort: HTTP error: HTTP Error 500: Internal Server Error (oid=276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d, action=download)!
251 abort: HTTP error: HTTP Error 500: Internal Server Error (oid=276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d, action=download)!
252 [255]
252 [255]
253
253
254 Test a checksum failure during the processing of the GET request
254 Test a checksum failure during the processing of the GET request
255
255
256 $ hg --config lfs.url=http://localhost:$HGPORT1/.git/info/lfs \
256 $ hg --config lfs.url=http://localhost:$HGPORT1/.git/info/lfs \
257 > -R client update -r tip
257 > -R client update -r tip
258 abort: HTTP error: HTTP Error 500: Internal Server Error (oid=276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d, action=download)!
258 abort: HTTP error: HTTP Error 500: Internal Server Error (oid=276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d, action=download)!
259 [255]
259 [255]
260
260
261 $ $PYTHON $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
261 $ $PYTHON $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
262
262
263 $ cat $TESTTMP/access.log
263 $ cat $TESTTMP/access.log
264 $LOCALIP - - [$LOGDATE$] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
264 $LOCALIP - - [$LOGDATE$] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
265 $LOCALIP - - [$LOGDATE$] "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
265 $LOCALIP - - [$LOGDATE$] "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
266 $LOCALIP - - [$LOGDATE$] "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bookmarks=1&bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%252C03%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Aphases%253Dheads%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps%250Arev-branch-cache%250Astream%253Dv2&cg=1&common=0000000000000000000000000000000000000000&heads=525251863cad618e55d483555f3d00a2ca99597e&listkeys=bookmarks&phases=1 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
266 $LOCALIP - - [$LOGDATE$] "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bookmarks=1&bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%252C03%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Aphases%253Dheads%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps%250Arev-branch-cache%250Astream%253Dv2&cg=1&common=0000000000000000000000000000000000000000&heads=525251863cad618e55d483555f3d00a2ca99597e&listkeys=bookmarks&phases=1 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
267 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
267 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
268 $LOCALIP - - [$LOGDATE$] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
268 $LOCALIP - - [$LOGDATE$] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
269 $LOCALIP - - [$LOGDATE$] "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D392c05922088bacf8e68a6939b480017afbf245d x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
269 $LOCALIP - - [$LOGDATE$] "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D392c05922088bacf8e68a6939b480017afbf245d x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
270 $LOCALIP - - [$LOGDATE$] "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
270 $LOCALIP - - [$LOGDATE$] "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
271 $LOCALIP - - [$LOGDATE$] "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
271 $LOCALIP - - [$LOGDATE$] "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
272 $LOCALIP - - [$LOGDATE$] "GET /?cmd=branchmap HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
272 $LOCALIP - - [$LOGDATE$] "GET /?cmd=branchmap HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
273 $LOCALIP - - [$LOGDATE$] "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
273 $LOCALIP - - [$LOGDATE$] "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
274 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
274 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
275 $LOCALIP - - [$LOGDATE$] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
275 $LOCALIP - - [$LOGDATE$] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
276 $LOCALIP - - [$LOGDATE$] "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D392c05922088bacf8e68a6939b480017afbf245d x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
276 $LOCALIP - - [$LOGDATE$] "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D392c05922088bacf8e68a6939b480017afbf245d x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
277 $LOCALIP - - [$LOGDATE$] "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
277 $LOCALIP - - [$LOGDATE$] "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
278 $LOCALIP - - [$LOGDATE$] "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
278 $LOCALIP - - [$LOGDATE$] "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
279 $LOCALIP - - [$LOGDATE$] "GET /?cmd=branchmap HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
279 $LOCALIP - - [$LOGDATE$] "GET /?cmd=branchmap HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
280 $LOCALIP - - [$LOGDATE$] "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
280 $LOCALIP - - [$LOGDATE$] "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
281 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
281 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
282 $LOCALIP - - [$LOGDATE$] "PUT /.hg/lfs/objects/b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c HTTP/1.1" 500 - (glob)
282 $LOCALIP - - [$LOGDATE$] "PUT /.hg/lfs/objects/b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c HTTP/1.1" 500 - (glob)
283 $LOCALIP - - [$LOGDATE$] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
283 $LOCALIP - - [$LOGDATE$] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
284 $LOCALIP - - [$LOGDATE$] "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D392c05922088bacf8e68a6939b480017afbf245d x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
284 $LOCALIP - - [$LOGDATE$] "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D392c05922088bacf8e68a6939b480017afbf245d x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
285 $LOCALIP - - [$LOGDATE$] "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bookmarks=1&bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%252C03%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Aphases%253Dheads%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps%250Arev-branch-cache%250Astream%253Dv2&cg=1&common=525251863cad618e55d483555f3d00a2ca99597e&heads=506bf3d83f78c54b89e81c6411adee19fdf02156+525251863cad618e55d483555f3d00a2ca99597e&listkeys=bookmarks&phases=1 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
285 $LOCALIP - - [$LOGDATE$] "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bookmarks=1&bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%252C03%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Aphases%253Dheads%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps%250Arev-branch-cache%250Astream%253Dv2&cg=1&common=525251863cad618e55d483555f3d00a2ca99597e&heads=506bf3d83f78c54b89e81c6411adee19fdf02156+525251863cad618e55d483555f3d00a2ca99597e&listkeys=bookmarks&phases=1 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
286 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
286 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
287 $LOCALIP - - [$LOGDATE$] "GET /.hg/lfs/objects/276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d HTTP/1.1" 500 - (glob)
287 $LOCALIP - - [$LOGDATE$] "GET /.hg/lfs/objects/276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d HTTP/1.1" 500 - (glob)
288 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
288 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
289 $LOCALIP - - [$LOGDATE$] "GET /.hg/lfs/objects/276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d HTTP/1.1" 500 - (glob)
289 $LOCALIP - - [$LOGDATE$] "GET /.hg/lfs/objects/276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d HTTP/1.1" 500 - (glob)
290
290
291 $ grep -v ' File "' $TESTTMP/errors.log
291 $ grep -v ' File "' $TESTTMP/errors.log
292 $LOCALIP - - [$ERRDATE$] HG error: Exception happened while processing request '/.git/info/lfs/objects/batch': (glob)
293 $LOCALIP - - [$ERRDATE$] HG error: Traceback (most recent call last): (glob)
294 $LOCALIP - - [$ERRDATE$] HG error: verifies = store.verify(oid) (glob)
295 $LOCALIP - - [$ERRDATE$] HG error: raise IOError(errno.EIO, '%s: I/O error' % oid) (glob)
296 $LOCALIP - - [$ERRDATE$] HG error: IOError: [Errno 5] f03217a32529a28a42d03b1244fe09b6e0f9fd06d7b966d4d50567be2abe6c0e: I/O error (glob)
297 $LOCALIP - - [$ERRDATE$] HG error: (glob)
298 $LOCALIP - - [$ERRDATE$] HG error: Exception happened while processing request '/.git/info/lfs/objects/batch': (glob)
299 $LOCALIP - - [$ERRDATE$] HG error: Traceback (most recent call last): (glob)
300 $LOCALIP - - [$ERRDATE$] HG error: verifies = store.verify(oid) (glob)
301 $LOCALIP - - [$ERRDATE$] HG error: raise IOError(errno.EIO, '%s: I/O error' % oid) (glob)
302 $LOCALIP - - [$ERRDATE$] HG error: IOError: [Errno 5] b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c: I/O error (glob)
303 $LOCALIP - - [$ERRDATE$] HG error: (glob)
292 $LOCALIP - - [$ERRDATE$] Exception happened during processing request '/.hg/lfs/objects/b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c': (glob)
304 $LOCALIP - - [$ERRDATE$] Exception happened during processing request '/.hg/lfs/objects/b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c': (glob)
293 Traceback (most recent call last):
305 Traceback (most recent call last):
294 self.do_write()
306 self.do_write()
295 self.do_hgweb()
307 self.do_hgweb()
296 for chunk in self.server.application(env, self._start_response):
308 for chunk in self.server.application(env, self._start_response):
297 for r in self._runwsgi(req, res, repo):
309 for r in self._runwsgi(req, res, repo):
298 rctx, req, res, self.check_perm)
310 rctx, req, res, self.check_perm)
299 return func(*(args + a), **kw)
311 return func(*(args + a), **kw)
300 lambda perm:
312 lambda perm:
301 localstore.download(oid, req.bodyfh)
313 localstore.download(oid, req.bodyfh)
302 super(badstore, self).download(oid, src)
314 super(badstore, self).download(oid, src)
303 raise error.Abort(_('corrupt remote lfs object: %s') % oid)
315 raise error.Abort(_('corrupt remote lfs object: %s') % oid)
304 Abort: corrupt remote lfs object: b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c
316 Abort: corrupt remote lfs object: b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c
305
317
306 $LOCALIP - - [$ERRDATE$] Exception happened during processing request '/.hg/lfs/objects/276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d': (glob)
318 $LOCALIP - - [$ERRDATE$] Exception happened during processing request '/.hg/lfs/objects/276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d': (glob)
307 Traceback (most recent call last):
319 Traceback (most recent call last):
308 self.do_write()
320 self.do_write()
309 self.do_hgweb()
321 self.do_hgweb()
310 for chunk in self.server.application(env, self._start_response):
322 for chunk in self.server.application(env, self._start_response):
311 for r in self._runwsgi(req, res, repo):
323 for r in self._runwsgi(req, res, repo):
312 rctx, req, res, self.check_perm)
324 rctx, req, res, self.check_perm)
313 return func(*(args + a), **kw)
325 return func(*(args + a), **kw)
314 lambda perm:
326 lambda perm:
315 res.setbodybytes(localstore.read(oid))
327 res.setbodybytes(localstore.read(oid))
316 blob = self._read(self.vfs, oid, verify)
328 blob = self._read(self.vfs, oid, verify)
317 raise IOError(errno.EIO, '%s: I/O error' % oid)
329 raise IOError(errno.EIO, '%s: I/O error' % oid)
318 IOError: [Errno 5] 276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d: I/O error
330 IOError: [Errno 5] 276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d: I/O error
319
331
320 $LOCALIP - - [$ERRDATE$] Exception happened during processing request '/.hg/lfs/objects/276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d': (glob)
332 $LOCALIP - - [$ERRDATE$] Exception happened during processing request '/.hg/lfs/objects/276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d': (glob)
321 Traceback (most recent call last):
333 Traceback (most recent call last):
322 self.do_write()
334 self.do_write()
323 self.do_hgweb()
335 self.do_hgweb()
324 for chunk in self.server.application(env, self._start_response):
336 for chunk in self.server.application(env, self._start_response):
325 for r in self._runwsgi(req, res, repo):
337 for r in self._runwsgi(req, res, repo):
326 rctx, req, res, self.check_perm)
338 rctx, req, res, self.check_perm)
327 return func(*(args + a), **kw)
339 return func(*(args + a), **kw)
328 lambda perm:
340 lambda perm:
329 res.setbodybytes(localstore.read(oid))
341 res.setbodybytes(localstore.read(oid))
330 blob = self._read(self.vfs, oid, verify)
342 blob = self._read(self.vfs, oid, verify)
331 blobstore._verify(oid, 'dummy content')
343 blobstore._verify(oid, 'dummy content')
332 hint=_('run hg verify'))
344 hint=_('run hg verify'))
333 Abort: detected corrupt lfs object: 276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d
345 Abort: detected corrupt lfs object: 276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d
334
346
General Comments 0
You need to be logged in to leave comments. Login now