##// END OF EJS Templates
lfs: enable the final download count status message...
Matt Harbison -
r37783:ab04972a default
parent child Browse files
Show More
@@ -1,581 +1,580 b''
1 1 # blobstore.py - local and remote (speaking Git-LFS protocol) blob storages
2 2 #
3 3 # Copyright 2017 Facebook, Inc.
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 from __future__ import absolute_import
9 9
10 10 import errno
11 11 import hashlib
12 12 import json
13 13 import os
14 14 import re
15 15 import socket
16 16
17 17 from mercurial.i18n import _
18 18
19 19 from mercurial import (
20 20 error,
21 21 pathutil,
22 22 pycompat,
23 23 url as urlmod,
24 24 util,
25 25 vfs as vfsmod,
26 26 worker,
27 27 )
28 28
29 29 from ..largefiles import lfutil
30 30
31 31 # 64 bytes for SHA256
32 32 _lfsre = re.compile(br'\A[a-f0-9]{64}\Z')
33 33
34 34 class lfsvfs(vfsmod.vfs):
35 35 def join(self, path):
36 36 """split the path at first two characters, like: XX/XXXXX..."""
37 37 if not _lfsre.match(path):
38 38 raise error.ProgrammingError('unexpected lfs path: %s' % path)
39 39 return super(lfsvfs, self).join(path[0:2], path[2:])
40 40
41 41 def walk(self, path=None, onerror=None):
42 42 """Yield (dirpath, [], oids) tuple for blobs under path
43 43
44 44 Oids only exist in the root of this vfs, so dirpath is always ''.
45 45 """
46 46 root = os.path.normpath(self.base)
47 47 # when dirpath == root, dirpath[prefixlen:] becomes empty
48 48 # because len(dirpath) < prefixlen.
49 49 prefixlen = len(pathutil.normasprefix(root))
50 50 oids = []
51 51
52 52 for dirpath, dirs, files in os.walk(self.reljoin(self.base, path or ''),
53 53 onerror=onerror):
54 54 dirpath = dirpath[prefixlen:]
55 55
56 56 # Silently skip unexpected files and directories
57 57 if len(dirpath) == 2:
58 58 oids.extend([dirpath + f for f in files
59 59 if _lfsre.match(dirpath + f)])
60 60
61 61 yield ('', [], oids)
62 62
63 63 class nullvfs(lfsvfs):
64 64 def __init__(self):
65 65 pass
66 66
67 67 def exists(self, oid):
68 68 return False
69 69
70 70 def read(self, oid):
71 71 # store.read() calls into here if the blob doesn't exist in its
72 72 # self.vfs. Raise the same error as a normal vfs when asked to read a
73 73 # file that doesn't exist. The only difference is the full file path
74 74 # isn't available in the error.
75 75 raise IOError(errno.ENOENT, '%s: No such file or directory' % oid)
76 76
77 77 def walk(self, path=None, onerror=None):
78 78 return ('', [], [])
79 79
80 80 def write(self, oid, data):
81 81 pass
82 82
83 83 class filewithprogress(object):
84 84 """a file-like object that supports __len__ and read.
85 85
86 86 Useful to provide progress information for how many bytes are read.
87 87 """
88 88
89 89 def __init__(self, fp, callback):
90 90 self._fp = fp
91 91 self._callback = callback # func(readsize)
92 92 fp.seek(0, os.SEEK_END)
93 93 self._len = fp.tell()
94 94 fp.seek(0)
95 95
96 96 def __len__(self):
97 97 return self._len
98 98
99 99 def read(self, size):
100 100 if self._fp is None:
101 101 return b''
102 102 data = self._fp.read(size)
103 103 if data:
104 104 if self._callback:
105 105 self._callback(len(data))
106 106 else:
107 107 self._fp.close()
108 108 self._fp = None
109 109 return data
110 110
111 111 class local(object):
112 112 """Local blobstore for large file contents.
113 113
114 114 This blobstore is used both as a cache and as a staging area for large blobs
115 115 to be uploaded to the remote blobstore.
116 116 """
117 117
118 118 def __init__(self, repo):
119 119 fullpath = repo.svfs.join('lfs/objects')
120 120 self.vfs = lfsvfs(fullpath)
121 121
122 122 if repo.ui.configbool('experimental', 'lfs.disableusercache'):
123 123 self.cachevfs = nullvfs()
124 124 else:
125 125 usercache = lfutil._usercachedir(repo.ui, 'lfs')
126 126 self.cachevfs = lfsvfs(usercache)
127 127 self.ui = repo.ui
128 128
129 129 def open(self, oid):
130 130 """Open a read-only file descriptor to the named blob, in either the
131 131 usercache or the local store."""
132 132 # The usercache is the most likely place to hold the file. Commit will
133 133 # write to both it and the local store, as will anything that downloads
134 134 # the blobs. However, things like clone without an update won't
135 135 # populate the local store. For an init + push of a local clone,
136 136 # the usercache is the only place it _could_ be. If not present, the
137 137 # missing file msg here will indicate the local repo, not the usercache.
138 138 if self.cachevfs.exists(oid):
139 139 return self.cachevfs(oid, 'rb')
140 140
141 141 return self.vfs(oid, 'rb')
142 142
143 143 def download(self, oid, src):
144 144 """Read the blob from the remote source in chunks, verify the content,
145 145 and write to this local blobstore."""
146 146 sha256 = hashlib.sha256()
147 147
148 148 with self.vfs(oid, 'wb', atomictemp=True) as fp:
149 149 for chunk in util.filechunkiter(src, size=1048576):
150 150 fp.write(chunk)
151 151 sha256.update(chunk)
152 152
153 153 realoid = sha256.hexdigest()
154 154 if realoid != oid:
155 155 raise LfsCorruptionError(_('corrupt remote lfs object: %s')
156 156 % oid)
157 157
158 158 self._linktousercache(oid)
159 159
160 160 def write(self, oid, data):
161 161 """Write blob to local blobstore.
162 162
163 163 This should only be called from the filelog during a commit or similar.
164 164 As such, there is no need to verify the data. Imports from a remote
165 165 store must use ``download()`` instead."""
166 166 with self.vfs(oid, 'wb', atomictemp=True) as fp:
167 167 fp.write(data)
168 168
169 169 self._linktousercache(oid)
170 170
171 171 def _linktousercache(self, oid):
172 172 # XXX: should we verify the content of the cache, and hardlink back to
173 173 # the local store on success, but truncate, write and link on failure?
174 174 if (not self.cachevfs.exists(oid)
175 175 and not isinstance(self.cachevfs, nullvfs)):
176 176 self.ui.note(_('lfs: adding %s to the usercache\n') % oid)
177 177 lfutil.link(self.vfs.join(oid), self.cachevfs.join(oid))
178 178
179 179 def read(self, oid, verify=True):
180 180 """Read blob from local blobstore."""
181 181 if not self.vfs.exists(oid):
182 182 blob = self._read(self.cachevfs, oid, verify)
183 183
184 184 # Even if revlog will verify the content, it needs to be verified
185 185 # now before making the hardlink to avoid propagating corrupt blobs.
186 186 # Don't abort if corruption is detected, because `hg verify` will
187 187 # give more useful info about the corruption- simply don't add the
188 188 # hardlink.
189 189 if verify or hashlib.sha256(blob).hexdigest() == oid:
190 190 self.ui.note(_('lfs: found %s in the usercache\n') % oid)
191 191 lfutil.link(self.cachevfs.join(oid), self.vfs.join(oid))
192 192 else:
193 193 self.ui.note(_('lfs: found %s in the local lfs store\n') % oid)
194 194 blob = self._read(self.vfs, oid, verify)
195 195 return blob
196 196
197 197 def _read(self, vfs, oid, verify):
198 198 """Read blob (after verifying) from the given store"""
199 199 blob = vfs.read(oid)
200 200 if verify:
201 201 _verify(oid, blob)
202 202 return blob
203 203
204 204 def verify(self, oid):
205 205 """Indicate whether or not the hash of the underlying file matches its
206 206 name."""
207 207 sha256 = hashlib.sha256()
208 208
209 209 with self.open(oid) as fp:
210 210 for chunk in util.filechunkiter(fp, size=1048576):
211 211 sha256.update(chunk)
212 212
213 213 return oid == sha256.hexdigest()
214 214
215 215 def has(self, oid):
216 216 """Returns True if the local blobstore contains the requested blob,
217 217 False otherwise."""
218 218 return self.cachevfs.exists(oid) or self.vfs.exists(oid)
219 219
220 220 class _gitlfsremote(object):
221 221
222 222 def __init__(self, repo, url):
223 223 ui = repo.ui
224 224 self.ui = ui
225 225 baseurl, authinfo = url.authinfo()
226 226 self.baseurl = baseurl.rstrip('/')
227 227 useragent = repo.ui.config('experimental', 'lfs.user-agent')
228 228 if not useragent:
229 229 useragent = 'git-lfs/2.3.4 (Mercurial %s)' % util.version()
230 230 self.urlopener = urlmod.opener(ui, authinfo, useragent)
231 231 self.retry = ui.configint('lfs', 'retry')
232 232
233 233 def writebatch(self, pointers, fromstore):
234 234 """Batch upload from local to remote blobstore."""
235 235 self._batch(_deduplicate(pointers), fromstore, 'upload')
236 236
237 237 def readbatch(self, pointers, tostore):
238 238 """Batch download from remote to local blostore."""
239 239 self._batch(_deduplicate(pointers), tostore, 'download')
240 240
241 241 def _batchrequest(self, pointers, action):
242 242 """Get metadata about objects pointed by pointers for given action
243 243
244 244 Return decoded JSON object like {'objects': [{'oid': '', 'size': 1}]}
245 245 See https://github.com/git-lfs/git-lfs/blob/master/docs/api/batch.md
246 246 """
247 247 objects = [{'oid': p.oid(), 'size': p.size()} for p in pointers]
248 248 requestdata = json.dumps({
249 249 'objects': objects,
250 250 'operation': action,
251 251 })
252 252 batchreq = util.urlreq.request('%s/objects/batch' % self.baseurl,
253 253 data=requestdata)
254 254 batchreq.add_header('Accept', 'application/vnd.git-lfs+json')
255 255 batchreq.add_header('Content-Type', 'application/vnd.git-lfs+json')
256 256 try:
257 257 rsp = self.urlopener.open(batchreq)
258 258 rawjson = rsp.read()
259 259 except util.urlerr.httperror as ex:
260 260 raise LfsRemoteError(_('LFS HTTP error: %s (action=%s)')
261 261 % (ex, action))
262 262 try:
263 263 response = json.loads(rawjson)
264 264 except ValueError:
265 265 raise LfsRemoteError(_('LFS server returns invalid JSON: %s')
266 266 % rawjson)
267 267
268 268 if self.ui.debugflag:
269 269 self.ui.debug('Status: %d\n' % rsp.status)
270 270 # lfs-test-server and hg serve return headers in different order
271 271 self.ui.debug('%s\n'
272 272 % '\n'.join(sorted(str(rsp.info()).splitlines())))
273 273
274 274 if 'objects' in response:
275 275 response['objects'] = sorted(response['objects'],
276 276 key=lambda p: p['oid'])
277 277 self.ui.debug('%s\n'
278 278 % json.dumps(response, indent=2,
279 279 separators=('', ': '), sort_keys=True))
280 280
281 281 return response
282 282
283 283 def _checkforservererror(self, pointers, responses, action):
284 284 """Scans errors from objects
285 285
286 286 Raises LfsRemoteError if any objects have an error"""
287 287 for response in responses:
288 288 # The server should return 404 when objects cannot be found. Some
289 289 # server implementation (ex. lfs-test-server) does not set "error"
290 290 # but just removes "download" from "actions". Treat that case
291 291 # as the same as 404 error.
292 292 if 'error' not in response:
293 293 if (action == 'download'
294 294 and action not in response.get('actions', [])):
295 295 code = 404
296 296 else:
297 297 continue
298 298 else:
299 299 # An error dict without a code doesn't make much sense, so
300 300 # treat as a server error.
301 301 code = response.get('error').get('code', 500)
302 302
303 303 ptrmap = {p.oid(): p for p in pointers}
304 304 p = ptrmap.get(response['oid'], None)
305 305 if p:
306 306 filename = getattr(p, 'filename', 'unknown')
307 307 errors = {
308 308 404: 'The object does not exist',
309 309 410: 'The object was removed by the owner',
310 310 422: 'Validation error',
311 311 500: 'Internal server error',
312 312 }
313 313 msg = errors.get(code, 'status code %d' % code)
314 314 raise LfsRemoteError(_('LFS server error for "%s": %s')
315 315 % (filename, msg))
316 316 else:
317 317 raise LfsRemoteError(
318 318 _('LFS server error. Unsolicited response for oid %s')
319 319 % response['oid'])
320 320
321 321 def _extractobjects(self, response, pointers, action):
322 322 """extract objects from response of the batch API
323 323
324 324 response: parsed JSON object returned by batch API
325 325 return response['objects'] filtered by action
326 326 raise if any object has an error
327 327 """
328 328 # Scan errors from objects - fail early
329 329 objects = response.get('objects', [])
330 330 self._checkforservererror(pointers, objects, action)
331 331
332 332 # Filter objects with given action. Practically, this skips uploading
333 333 # objects which exist in the server.
334 334 filteredobjects = [o for o in objects if action in o.get('actions', [])]
335 335
336 336 return filteredobjects
337 337
338 338 def _basictransfer(self, obj, action, localstore):
339 339 """Download or upload a single object using basic transfer protocol
340 340
341 341 obj: dict, an object description returned by batch API
342 342 action: string, one of ['upload', 'download']
343 343 localstore: blobstore.local
344 344
345 345 See https://github.com/git-lfs/git-lfs/blob/master/docs/api/\
346 346 basic-transfers.md
347 347 """
348 348 oid = pycompat.bytestr(obj['oid'])
349 349
350 350 href = pycompat.bytestr(obj['actions'][action].get('href'))
351 351 headers = obj['actions'][action].get('header', {}).items()
352 352
353 353 request = util.urlreq.request(href)
354 354 if action == 'upload':
355 355 # If uploading blobs, read data from local blobstore.
356 356 if not localstore.verify(oid):
357 357 raise error.Abort(_('detected corrupt lfs object: %s') % oid,
358 358 hint=_('run hg verify'))
359 359 request.data = filewithprogress(localstore.open(oid), None)
360 360 request.get_method = lambda: 'PUT'
361 361 request.add_header('Content-Type', 'application/octet-stream')
362 362
363 363 for k, v in headers:
364 364 request.add_header(k, v)
365 365
366 366 response = b''
367 367 try:
368 368 req = self.urlopener.open(request)
369 369
370 370 if self.ui.debugflag:
371 371 self.ui.debug('Status: %d\n' % req.status)
372 372 # lfs-test-server and hg serve return headers in different order
373 373 self.ui.debug('%s\n'
374 374 % '\n'.join(sorted(str(req.info()).splitlines())))
375 375
376 376 if action == 'download':
377 377 # If downloading blobs, store downloaded data to local blobstore
378 378 localstore.download(oid, req)
379 379 else:
380 380 while True:
381 381 data = req.read(1048576)
382 382 if not data:
383 383 break
384 384 response += data
385 385 if response:
386 386 self.ui.debug('lfs %s response: %s' % (action, response))
387 387 except util.urlerr.httperror as ex:
388 388 if self.ui.debugflag:
389 389 self.ui.debug('%s: %s\n' % (oid, ex.read()))
390 390 raise LfsRemoteError(_('HTTP error: %s (oid=%s, action=%s)')
391 391 % (ex, oid, action))
392 392
393 393 def _batch(self, pointers, localstore, action):
394 394 if action not in ['upload', 'download']:
395 395 raise error.ProgrammingError('invalid Git-LFS action: %s' % action)
396 396
397 397 response = self._batchrequest(pointers, action)
398 398 objects = self._extractobjects(response, pointers, action)
399 399 total = sum(x.get('size', 0) for x in objects)
400 400 sizes = {}
401 401 for obj in objects:
402 402 sizes[obj.get('oid')] = obj.get('size', 0)
403 403 topic = {'upload': _('lfs uploading'),
404 404 'download': _('lfs downloading')}[action]
405 405 if len(objects) > 1:
406 406 self.ui.note(_('lfs: need to transfer %d objects (%s)\n')
407 407 % (len(objects), util.bytecount(total)))
408 408 self.ui.progress(topic, 0, total=total)
409 409 def transfer(chunk):
410 410 for obj in chunk:
411 411 objsize = obj.get('size', 0)
412 412 if self.ui.verbose:
413 413 if action == 'download':
414 414 msg = _('lfs: downloading %s (%s)\n')
415 415 elif action == 'upload':
416 416 msg = _('lfs: uploading %s (%s)\n')
417 417 self.ui.note(msg % (obj.get('oid'),
418 418 util.bytecount(objsize)))
419 419 retry = self.retry
420 420 while True:
421 421 try:
422 422 self._basictransfer(obj, action, localstore)
423 423 yield 1, obj.get('oid')
424 424 break
425 425 except socket.error as ex:
426 426 if retry > 0:
427 427 self.ui.note(
428 428 _('lfs: failed: %r (remaining retry %d)\n')
429 429 % (ex, retry))
430 430 retry -= 1
431 431 continue
432 432 raise
433 433
434 434 # Until https multiplexing gets sorted out
435 435 if self.ui.configbool('experimental', 'lfs.worker-enable'):
436 436 oids = worker.worker(self.ui, 0.1, transfer, (),
437 437 sorted(objects, key=lambda o: o.get('oid')))
438 438 else:
439 439 oids = transfer(sorted(objects, key=lambda o: o.get('oid')))
440 440
441 441 processed = 0
442 442 blobs = 0
443 443 for _one, oid in oids:
444 444 processed += sizes[oid]
445 445 blobs += 1
446 446 self.ui.progress(topic, processed, total=total)
447 447 self.ui.note(_('lfs: processed: %s\n') % oid)
448 448 self.ui.progress(topic, pos=None, total=total)
449 449
450 450 if blobs > 0:
451 451 if action == 'upload':
452 452 self.ui.status(_('lfs: uploaded %d files (%s)\n')
453 453 % (blobs, util.bytecount(processed)))
454 # TODO: coalesce the download requests, and comment this in
455 #elif action == 'download':
456 # self.ui.status(_('lfs: downloaded %d files (%s)\n')
457 # % (blobs, util.bytecount(processed)))
454 elif action == 'download':
455 self.ui.status(_('lfs: downloaded %d files (%s)\n')
456 % (blobs, util.bytecount(processed)))
458 457
459 458 def __del__(self):
460 459 # copied from mercurial/httppeer.py
461 460 urlopener = getattr(self, 'urlopener', None)
462 461 if urlopener:
463 462 for h in urlopener.handlers:
464 463 h.close()
465 464 getattr(h, "close_all", lambda : None)()
466 465
467 466 class _dummyremote(object):
468 467 """Dummy store storing blobs to temp directory."""
469 468
470 469 def __init__(self, repo, url):
471 470 fullpath = repo.vfs.join('lfs', url.path)
472 471 self.vfs = lfsvfs(fullpath)
473 472
474 473 def writebatch(self, pointers, fromstore):
475 474 for p in _deduplicate(pointers):
476 475 content = fromstore.read(p.oid(), verify=True)
477 476 with self.vfs(p.oid(), 'wb', atomictemp=True) as fp:
478 477 fp.write(content)
479 478
480 479 def readbatch(self, pointers, tostore):
481 480 for p in _deduplicate(pointers):
482 481 with self.vfs(p.oid(), 'rb') as fp:
483 482 tostore.download(p.oid(), fp)
484 483
485 484 class _nullremote(object):
486 485 """Null store storing blobs to /dev/null."""
487 486
488 487 def __init__(self, repo, url):
489 488 pass
490 489
491 490 def writebatch(self, pointers, fromstore):
492 491 pass
493 492
494 493 def readbatch(self, pointers, tostore):
495 494 pass
496 495
497 496 class _promptremote(object):
498 497 """Prompt user to set lfs.url when accessed."""
499 498
500 499 def __init__(self, repo, url):
501 500 pass
502 501
503 502 def writebatch(self, pointers, fromstore, ui=None):
504 503 self._prompt()
505 504
506 505 def readbatch(self, pointers, tostore, ui=None):
507 506 self._prompt()
508 507
509 508 def _prompt(self):
510 509 raise error.Abort(_('lfs.url needs to be configured'))
511 510
512 511 _storemap = {
513 512 'https': _gitlfsremote,
514 513 'http': _gitlfsremote,
515 514 'file': _dummyremote,
516 515 'null': _nullremote,
517 516 None: _promptremote,
518 517 }
519 518
520 519 def _deduplicate(pointers):
521 520 """Remove any duplicate oids that exist in the list"""
522 521 reduced = util.sortdict()
523 522 for p in pointers:
524 523 reduced[p.oid()] = p
525 524 return reduced.values()
526 525
527 526 def _verify(oid, content):
528 527 realoid = hashlib.sha256(content).hexdigest()
529 528 if realoid != oid:
530 529 raise LfsCorruptionError(_('detected corrupt lfs object: %s') % oid,
531 530 hint=_('run hg verify'))
532 531
533 532 def remote(repo, remote=None):
534 533 """remotestore factory. return a store in _storemap depending on config
535 534
536 535 If ``lfs.url`` is specified, use that remote endpoint. Otherwise, try to
537 536 infer the endpoint, based on the remote repository using the same path
538 537 adjustments as git. As an extension, 'http' is supported as well so that
539 538 ``hg serve`` works out of the box.
540 539
541 540 https://github.com/git-lfs/git-lfs/blob/master/docs/api/server-discovery.md
542 541 """
543 542 lfsurl = repo.ui.config('lfs', 'url')
544 543 url = util.url(lfsurl or '')
545 544 if lfsurl is None:
546 545 if remote:
547 546 path = remote
548 547 elif util.safehasattr(repo, '_subtoppath'):
549 548 # The pull command sets this during the optional update phase, which
550 549 # tells exactly where the pull originated, whether 'paths.default'
551 550 # or explicit.
552 551 path = repo._subtoppath
553 552 else:
554 553 # TODO: investigate 'paths.remote:lfsurl' style path customization,
555 554 # and fall back to inferring from 'paths.remote' if unspecified.
556 555 path = repo.ui.config('paths', 'default') or ''
557 556
558 557 defaulturl = util.url(path)
559 558
560 559 # TODO: support local paths as well.
561 560 # TODO: consider the ssh -> https transformation that git applies
562 561 if defaulturl.scheme in (b'http', b'https'):
563 562 if defaulturl.path and defaulturl.path[:-1] != b'/':
564 563 defaulturl.path += b'/'
565 564 defaulturl.path = (defaulturl.path or b'') + b'.git/info/lfs'
566 565
567 566 url = util.url(bytes(defaulturl))
568 567 repo.ui.note(_('lfs: assuming remote store: %s\n') % url)
569 568
570 569 scheme = url.scheme
571 570 if scheme not in _storemap:
572 571 raise error.Abort(_('lfs: unknown url scheme: %s') % scheme)
573 572 return _storemap[scheme](repo, url)
574 573
575 574 class LfsRemoteError(error.RevlogError):
576 575 pass
577 576
578 577 class LfsCorruptionError(error.Abort):
579 578 """Raised when a corrupt blob is detected, aborting an operation
580 579
581 580 It exists to allow specialized handling on the server side."""
@@ -1,332 +1,333 b''
1 1 #require serve no-reposimplestore
2 2
3 3 $ cat >> $HGRCPATH <<EOF
4 4 > [extensions]
5 5 > lfs=
6 6 > [lfs]
7 7 > track=all()
8 8 > [web]
9 9 > push_ssl = False
10 10 > allow-push = *
11 11 > EOF
12 12
13 13 Serving LFS files can experimentally be turned off. The long term solution is
14 14 to support the 'verify' action in both client and server, so that the server can
15 15 tell the client to store files elsewhere.
16 16
17 17 $ hg init server
18 18 $ hg --config "lfs.usercache=$TESTTMP/servercache" \
19 19 > --config experimental.lfs.serve=False -R server serve -d \
20 20 > -p $HGPORT --pid-file=hg.pid -A $TESTTMP/access.log -E $TESTTMP/errors.log
21 21 $ cat hg.pid >> $DAEMON_PIDS
22 22
23 23 Uploads fail...
24 24
25 25 $ hg init client
26 26 $ echo 'this-is-an-lfs-file' > client/lfs.bin
27 27 $ hg -R client ci -Am 'initial commit'
28 28 adding lfs.bin
29 29 $ hg -R client push http://localhost:$HGPORT
30 30 pushing to http://localhost:$HGPORT/
31 31 searching for changes
32 32 abort: LFS HTTP error: HTTP Error 400: no such method: .git (action=upload)!
33 33 [255]
34 34
35 35 ... so do a local push to make the data available. Remove the blob from the
36 36 default cache, so it attempts to download.
37 37 $ hg --config "lfs.usercache=$TESTTMP/servercache" \
38 38 > --config "lfs.url=null://" \
39 39 > -R client push -q server
40 40 $ mv `hg config lfs.usercache` $TESTTMP/servercache
41 41
42 42 Downloads fail...
43 43
44 44 $ hg clone http://localhost:$HGPORT httpclone
45 45 requesting all changes
46 46 adding changesets
47 47 adding manifests
48 48 adding file changes
49 49 added 1 changesets with 1 changes to 1 files
50 50 new changesets 525251863cad
51 51 updating to branch default
52 52 abort: LFS HTTP error: HTTP Error 400: no such method: .git (action=download)!
53 53 [255]
54 54
55 55 $ $PYTHON $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
56 56
57 57 $ cat $TESTTMP/access.log $TESTTMP/errors.log
58 58 $LOCALIP - - [$LOGDATE$] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
59 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 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 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 62 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 400 - (glob)
63 63 $LOCALIP - - [$LOGDATE$] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
64 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 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 66 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 400 - (glob)
67 67
68 68 Blob URIs are correct when --prefix is used
69 69
70 70 $ rm -f $TESTTMP/access.log $TESTTMP/errors.log
71 71 $ hg --config "lfs.usercache=$TESTTMP/servercache" -R server serve -d \
72 72 > -p $HGPORT --pid-file=hg.pid --prefix=subdir/mount/point \
73 73 > -A $TESTTMP/access.log -E $TESTTMP/errors.log
74 74 $ cat hg.pid >> $DAEMON_PIDS
75 75
76 76 $ hg clone --debug http://localhost:$HGPORT/subdir/mount/point cloned2
77 77 using http://localhost:$HGPORT/subdir/mount/point
78 78 sending capabilities command
79 79 query 1; heads
80 80 sending batch command
81 81 requesting all changes
82 82 sending getbundle command
83 83 bundle2-input-bundle: with-transaction
84 84 bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
85 85 adding changesets
86 86 add changeset 525251863cad
87 87 adding manifests
88 88 adding file changes
89 89 adding lfs.bin revisions
90 90 added 1 changesets with 1 changes to 1 files
91 91 calling hook pretxnchangegroup.lfs: hgext.lfs.checkrequireslfs
92 92 bundle2-input-part: total payload size 648
93 93 bundle2-input-part: "listkeys" (params: 1 mandatory) supported
94 94 bundle2-input-part: "phase-heads" supported
95 95 bundle2-input-part: total payload size 24
96 96 bundle2-input-part: "cache:rev-branch-cache" supported
97 97 bundle2-input-part: total payload size 39
98 98 bundle2-input-bundle: 3 parts total
99 99 checking for updated bookmarks
100 100 updating the branch cache
101 101 new changesets 525251863cad
102 102 updating to branch default
103 103 resolving manifests
104 104 branchmerge: False, force: False, partial: False
105 105 ancestor: 000000000000, local: 000000000000+, remote: 525251863cad
106 106 lfs: assuming remote store: http://localhost:$HGPORT/subdir/mount/point/.git/info/lfs
107 107 Status: 200
108 108 Content-Length: 371
109 109 Content-Type: application/vnd.git-lfs+json
110 110 Date: $HTTP_DATE$
111 111 Server: testing stub value
112 112 {
113 113 "objects": [
114 114 {
115 115 "actions": {
116 116 "download": {
117 117 "expires_at": "$ISO_8601_DATE_TIME$"
118 118 "header": {
119 119 "Accept": "application/vnd.git-lfs"
120 120 }
121 121 "href": "http://localhost:$HGPORT/subdir/mount/point/.hg/lfs/objects/f03217a32529a28a42d03b1244fe09b6e0f9fd06d7b966d4d50567be2abe6c0e"
122 122 }
123 123 }
124 124 "oid": "f03217a32529a28a42d03b1244fe09b6e0f9fd06d7b966d4d50567be2abe6c0e"
125 125 "size": 20
126 126 }
127 127 ]
128 128 "transfer": "basic"
129 129 }
130 130 lfs: downloading f03217a32529a28a42d03b1244fe09b6e0f9fd06d7b966d4d50567be2abe6c0e (20 bytes)
131 131 Status: 200
132 132 Content-Length: 20
133 133 Content-Type: application/octet-stream
134 134 Date: $HTTP_DATE$
135 135 Server: testing stub value
136 136 lfs: adding f03217a32529a28a42d03b1244fe09b6e0f9fd06d7b966d4d50567be2abe6c0e to the usercache
137 137 lfs: processed: f03217a32529a28a42d03b1244fe09b6e0f9fd06d7b966d4d50567be2abe6c0e
138 lfs: downloaded 1 files (20 bytes)
138 139 lfs.bin: remote created -> g
139 140 getting lfs.bin
140 141 lfs: found f03217a32529a28a42d03b1244fe09b6e0f9fd06d7b966d4d50567be2abe6c0e in the local lfs store
141 142 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
142 143
143 144 $ $PYTHON $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
144 145
145 146 $ cat $TESTTMP/access.log $TESTTMP/errors.log
146 147 $LOCALIP - - [$LOGDATE$] "GET /subdir/mount/point?cmd=capabilities HTTP/1.1" 200 - (glob)
147 148 $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 149 $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 150 $LOCALIP - - [$LOGDATE$] "POST /subdir/mount/point/.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
150 151 $LOCALIP - - [$LOGDATE$] "GET /subdir/mount/point/.hg/lfs/objects/f03217a32529a28a42d03b1244fe09b6e0f9fd06d7b966d4d50567be2abe6c0e HTTP/1.1" 200 - (glob)
151 152
152 153 $ cat >> $TESTTMP/lfsstoreerror.py <<EOF
153 154 > import errno
154 155 > from hgext.lfs import blobstore
155 156 >
156 157 > _numverifies = 0
157 158 > _readerr = True
158 159 >
159 160 > def reposetup(ui, repo):
160 161 > # Nothing to do with a remote repo
161 162 > if not repo.local():
162 163 > return
163 164 >
164 165 > store = repo.svfs.lfslocalblobstore
165 166 > class badstore(store.__class__):
166 167 > def download(self, oid, src):
167 168 > '''Called in the server to handle reading from the client in a
168 169 > PUT request.'''
169 170 > origread = src.read
170 171 > def _badread(nbytes):
171 172 > # Simulate bad data/checksum failure from the client
172 173 > return b'0' * len(origread(nbytes))
173 174 > src.read = _badread
174 175 > super(badstore, self).download(oid, src)
175 176 >
176 177 > def _read(self, vfs, oid, verify):
177 178 > '''Called in the server to read data for a GET request, and then
178 179 > calls self._verify() on it before returning.'''
179 180 > global _readerr
180 181 > # One time simulation of a read error
181 182 > if _readerr:
182 183 > _readerr = False
183 184 > raise IOError(errno.EIO, '%s: I/O error' % oid)
184 185 > # Simulate corrupt content on client download
185 186 > blobstore._verify(oid, 'dummy content')
186 187 >
187 188 > def verify(self, oid):
188 189 > '''Called in the server to populate the Batch API response,
189 190 > letting the client re-upload if the file is corrupt.'''
190 191 > # Fail verify in Batch API for one clone command and one push
191 192 > # command with an IOError. Then let it through to access other
192 193 > # functions. Checksum failure is tested elsewhere.
193 194 > global _numverifies
194 195 > _numverifies += 1
195 196 > if _numverifies <= 2:
196 197 > raise IOError(errno.EIO, '%s: I/O error' % oid)
197 198 > return super(badstore, self).verify(oid)
198 199 >
199 200 > store.__class__ = badstore
200 201 > EOF
201 202
202 203 $ rm -rf `hg config lfs.usercache`
203 204 $ rm -f $TESTTMP/access.log $TESTTMP/errors.log
204 205 $ hg --config "lfs.usercache=$TESTTMP/servercache" \
205 206 > --config extensions.lfsstoreerror=$TESTTMP/lfsstoreerror.py \
206 207 > -R server serve -d \
207 208 > -p $HGPORT1 --pid-file=hg.pid -A $TESTTMP/access.log -E $TESTTMP/errors.log
208 209 $ cat hg.pid >> $DAEMON_PIDS
209 210
210 211 Test an I/O error in localstore.verify() (Batch API) with GET
211 212
212 213 $ hg clone http://localhost:$HGPORT1 httpclone2
213 214 requesting all changes
214 215 adding changesets
215 216 adding manifests
216 217 adding file changes
217 218 added 1 changesets with 1 changes to 1 files
218 219 new changesets 525251863cad
219 220 updating to branch default
220 221 abort: LFS server error for "lfs.bin": Internal server error!
221 222 [255]
222 223
223 224 Test an I/O error in localstore.verify() (Batch API) with PUT
224 225
225 226 $ echo foo > client/lfs.bin
226 227 $ hg -R client ci -m 'mod lfs'
227 228 $ hg -R client push http://localhost:$HGPORT1
228 229 pushing to http://localhost:$HGPORT1/
229 230 searching for changes
230 231 abort: LFS server error for "unknown": Internal server error!
231 232 [255]
232 233 TODO: figure out how to associate the file name in the error above
233 234
234 235 Test a bad checksum sent by the client in the transfer API
235 236
236 237 $ hg -R client push http://localhost:$HGPORT1
237 238 pushing to http://localhost:$HGPORT1/
238 239 searching for changes
239 240 abort: HTTP error: HTTP Error 422: corrupt blob (oid=b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c, action=upload)!
240 241 [255]
241 242
242 243 $ echo 'test lfs file' > server/lfs3.bin
243 244 $ hg --config experimental.lfs.disableusercache=True \
244 245 > -R server ci -Aqm 'another lfs file'
245 246 $ hg -R client pull -q http://localhost:$HGPORT1
246 247
247 248 Test an I/O error during the processing of the GET request
248 249
249 250 $ hg --config lfs.url=http://localhost:$HGPORT1/.git/info/lfs \
250 251 > -R client update -r tip
251 252 abort: HTTP error: HTTP Error 500: Internal Server Error (oid=276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d, action=download)!
252 253 [255]
253 254
254 255 Test a checksum failure during the processing of the GET request
255 256
256 257 $ hg --config lfs.url=http://localhost:$HGPORT1/.git/info/lfs \
257 258 > -R client update -r tip
258 259 abort: HTTP error: HTTP Error 422: corrupt blob (oid=276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d, action=download)!
259 260 [255]
260 261
261 262 $ $PYTHON $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
262 263
263 264 $ cat $TESTTMP/access.log
264 265 $LOCALIP - - [$LOGDATE$] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
265 266 $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 267 $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 268 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
268 269 $LOCALIP - - [$LOGDATE$] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
269 270 $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 271 $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 272 $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 273 $LOCALIP - - [$LOGDATE$] "GET /?cmd=branchmap HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
273 274 $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 275 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
275 276 $LOCALIP - - [$LOGDATE$] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
276 277 $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 278 $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 279 $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 280 $LOCALIP - - [$LOGDATE$] "GET /?cmd=branchmap HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
280 281 $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 282 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
282 283 $LOCALIP - - [$LOGDATE$] "PUT /.hg/lfs/objects/b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c HTTP/1.1" 422 - (glob)
283 284 $LOCALIP - - [$LOGDATE$] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
284 285 $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 286 $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 287 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
287 288 $LOCALIP - - [$LOGDATE$] "GET /.hg/lfs/objects/276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d HTTP/1.1" 500 - (glob)
288 289 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
289 290 $LOCALIP - - [$LOGDATE$] "GET /.hg/lfs/objects/276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d HTTP/1.1" 422 - (glob)
290 291
291 292 $ grep -v ' File "' $TESTTMP/errors.log
292 293 $LOCALIP - - [$ERRDATE$] HG error: Exception happened while processing request '/.git/info/lfs/objects/batch': (glob)
293 294 $LOCALIP - - [$ERRDATE$] HG error: Traceback (most recent call last): (glob)
294 295 $LOCALIP - - [$ERRDATE$] HG error: verifies = store.verify(oid) (glob)
295 296 $LOCALIP - - [$ERRDATE$] HG error: raise IOError(errno.EIO, '%s: I/O error' % oid) (glob)
296 297 $LOCALIP - - [$ERRDATE$] HG error: IOError: [Errno 5] f03217a32529a28a42d03b1244fe09b6e0f9fd06d7b966d4d50567be2abe6c0e: I/O error (glob)
297 298 $LOCALIP - - [$ERRDATE$] HG error: (glob)
298 299 $LOCALIP - - [$ERRDATE$] HG error: Exception happened while processing request '/.git/info/lfs/objects/batch': (glob)
299 300 $LOCALIP - - [$ERRDATE$] HG error: Traceback (most recent call last): (glob)
300 301 $LOCALIP - - [$ERRDATE$] HG error: verifies = store.verify(oid) (glob)
301 302 $LOCALIP - - [$ERRDATE$] HG error: raise IOError(errno.EIO, '%s: I/O error' % oid) (glob)
302 303 $LOCALIP - - [$ERRDATE$] HG error: IOError: [Errno 5] b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c: I/O error (glob)
303 304 $LOCALIP - - [$ERRDATE$] HG error: (glob)
304 305 $LOCALIP - - [$ERRDATE$] HG error: Exception happened while processing request '/.hg/lfs/objects/b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c': (glob)
305 306 $LOCALIP - - [$ERRDATE$] HG error: Traceback (most recent call last): (glob)
306 307 $LOCALIP - - [$ERRDATE$] HG error: localstore.download(oid, req.bodyfh) (glob)
307 308 $LOCALIP - - [$ERRDATE$] HG error: super(badstore, self).download(oid, src) (glob)
308 309 $LOCALIP - - [$ERRDATE$] HG error: % oid) (glob)
309 310 $LOCALIP - - [$ERRDATE$] HG error: LfsCorruptionError: corrupt remote lfs object: b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c (glob)
310 311 $LOCALIP - - [$ERRDATE$] HG error: (glob)
311 312 $LOCALIP - - [$ERRDATE$] Exception happened during processing request '/.hg/lfs/objects/276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d': (glob)
312 313 Traceback (most recent call last):
313 314 self.do_write()
314 315 self.do_hgweb()
315 316 for chunk in self.server.application(env, self._start_response):
316 317 for r in self._runwsgi(req, res, repo):
317 318 rctx, req, res, self.check_perm)
318 319 return func(*(args + a), **kw)
319 320 lambda perm:
320 321 res.setbodybytes(localstore.read(oid))
321 322 blob = self._read(self.vfs, oid, verify)
322 323 raise IOError(errno.EIO, '%s: I/O error' % oid)
323 324 IOError: [Errno 5] 276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d: I/O error
324 325
325 326 $LOCALIP - - [$ERRDATE$] HG error: Exception happened while processing request '/.hg/lfs/objects/276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d': (glob)
326 327 $LOCALIP - - [$ERRDATE$] HG error: Traceback (most recent call last): (glob)
327 328 $LOCALIP - - [$ERRDATE$] HG error: res.setbodybytes(localstore.read(oid)) (glob)
328 329 $LOCALIP - - [$ERRDATE$] HG error: blob = self._read(self.vfs, oid, verify) (glob)
329 330 $LOCALIP - - [$ERRDATE$] HG error: blobstore._verify(oid, 'dummy content') (glob)
330 331 $LOCALIP - - [$ERRDATE$] HG error: hint=_('run hg verify')) (glob)
331 332 $LOCALIP - - [$ERRDATE$] HG error: LfsCorruptionError: detected corrupt lfs object: 276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d (glob)
332 333 $LOCALIP - - [$ERRDATE$] HG error: (glob)
@@ -1,445 +1,450 b''
1 1 #testcases lfsremote-on lfsremote-off
2 2 #require serve no-reposimplestore
3 3
4 4 This test splits `hg serve` with and without using the extension into separate
5 5 tests cases. The tests are broken down as follows, where "LFS"/"No-LFS"
6 6 indicates whether or not there are commits that use an LFS file, and "D"/"E"
7 7 indicates whether or not the extension is loaded. The "X" cases are not tested
8 8 individually, because the lfs requirement causes the process to bail early if
9 9 the extension is disabled.
10 10
11 11 . Server
12 12 .
13 13 . No-LFS LFS
14 14 . +----------------------------+
15 15 . | || D | E | D | E |
16 16 . |---++=======================|
17 17 . C | D || N/A | #1 | X | #4 |
18 18 . l No +---++-----------------------|
19 19 . i LFS | E || #2 | #2 | X | #5 |
20 20 . e +---++-----------------------|
21 21 . n | D || X | X | X | X |
22 22 . t LFS |---++-----------------------|
23 23 . | E || #3 | #3 | X | #6 |
24 24 . |---++-----------------------+
25 25
26 26 $ hg init server
27 27 $ SERVER_REQUIRES="$TESTTMP/server/.hg/requires"
28 28
29 29 Skip the experimental.changegroup3=True config. Failure to agree on this comes
30 30 first, and causes a "ValueError: no common changegroup version" or "abort:
31 31 HTTP Error 500: Internal Server Error", if the extension is only loaded on one
32 32 side. If that *is* enabled, the subsequent failure is "abort: missing processor
33 33 for flag '0x2000'!" if the extension is only loaded on one side (possibly also
34 34 masked by the Internal Server Error message).
35 35 $ cat >> $HGRCPATH <<EOF
36 36 > [experimental]
37 37 > lfs.disableusercache = True
38 38 > [lfs]
39 39 > threshold=10
40 40 > [web]
41 41 > allow_push=*
42 42 > push_ssl=False
43 43 > EOF
44 44
45 45 #if lfsremote-on
46 46 $ hg --config extensions.lfs= -R server \
47 47 > serve -p $HGPORT -d --pid-file=hg.pid --errorlog=$TESTTMP/errors.log
48 48 #else
49 49 $ hg --config extensions.lfs=! -R server \
50 50 > serve -p $HGPORT -d --pid-file=hg.pid --errorlog=$TESTTMP/errors.log
51 51 #endif
52 52
53 53 $ cat hg.pid >> $DAEMON_PIDS
54 54 $ hg clone -q http://localhost:$HGPORT client
55 55 $ grep 'lfs' client/.hg/requires $SERVER_REQUIRES
56 56 [1]
57 57
58 58 --------------------------------------------------------------------------------
59 59 Case #1: client with non-lfs content and the extension disabled; server with
60 60 non-lfs content, and the extension enabled.
61 61
62 62 $ cd client
63 63 $ echo 'non-lfs' > nonlfs.txt
64 64 $ hg ci -Aqm 'non-lfs'
65 65 $ grep 'lfs' .hg/requires $SERVER_REQUIRES
66 66 [1]
67 67
68 68 #if lfsremote-on
69 69
70 70 $ hg push -q
71 71 $ grep 'lfs' .hg/requires $SERVER_REQUIRES
72 72 [1]
73 73
74 74 $ hg clone -q http://localhost:$HGPORT $TESTTMP/client1_clone
75 75 $ grep 'lfs' $TESTTMP/client1_clone/.hg/requires $SERVER_REQUIRES
76 76 [1]
77 77
78 78 $ hg init $TESTTMP/client1_pull
79 79 $ hg -R $TESTTMP/client1_pull pull -q http://localhost:$HGPORT
80 80 $ grep 'lfs' $TESTTMP/client1_pull/.hg/requires $SERVER_REQUIRES
81 81 [1]
82 82
83 83 $ hg identify http://localhost:$HGPORT
84 84 d437e1d24fbd
85 85
86 86 #endif
87 87
88 88 --------------------------------------------------------------------------------
89 89 Case #2: client with non-lfs content and the extension enabled; server with
90 90 non-lfs content, and the extension state controlled by #testcases.
91 91
92 92 $ cat >> $HGRCPATH <<EOF
93 93 > [extensions]
94 94 > lfs =
95 95 > EOF
96 96 $ echo 'non-lfs' > nonlfs2.txt
97 97 $ hg ci -Aqm 'non-lfs file with lfs client'
98 98
99 99 Since no lfs content has been added yet, the push is allowed, even when the
100 100 extension is not enabled remotely.
101 101
102 102 $ hg push -q
103 103 $ grep 'lfs' .hg/requires $SERVER_REQUIRES
104 104 [1]
105 105
106 106 $ hg clone -q http://localhost:$HGPORT $TESTTMP/client2_clone
107 107 $ grep 'lfs' $TESTTMP/client2_clone/.hg/requires $SERVER_REQUIRES
108 108 [1]
109 109
110 110 $ hg init $TESTTMP/client2_pull
111 111 $ hg -R $TESTTMP/client2_pull pull -q http://localhost:$HGPORT
112 112 $ grep 'lfs' $TESTTMP/client2_pull/.hg/requires $SERVER_REQUIRES
113 113 [1]
114 114
115 115 $ hg identify http://localhost:$HGPORT
116 116 1477875038c6
117 117
118 118 --------------------------------------------------------------------------------
119 119 Case #3: client with lfs content and the extension enabled; server with
120 120 non-lfs content, and the extension state controlled by #testcases. The server
121 121 should have an 'lfs' requirement after it picks up its first commit with a blob.
122 122
123 123 $ echo 'this is a big lfs file' > lfs.bin
124 124 $ hg ci -Aqm 'lfs'
125 125 $ grep 'lfs' .hg/requires $SERVER_REQUIRES
126 126 .hg/requires:lfs
127 127
128 128 #if lfsremote-off
129 129 $ hg push -q
130 130 abort: required features are not supported in the destination: lfs
131 131 (enable the lfs extension on the server)
132 132 [255]
133 133 #else
134 134 $ hg push -q
135 135 #endif
136 136 $ grep 'lfs' .hg/requires $SERVER_REQUIRES
137 137 .hg/requires:lfs
138 138 $TESTTMP/server/.hg/requires:lfs (lfsremote-on !)
139 139
140 140 $ hg clone -q http://localhost:$HGPORT $TESTTMP/client3_clone
141 141 $ grep 'lfs' $TESTTMP/client3_clone/.hg/requires $SERVER_REQUIRES || true
142 142 $TESTTMP/client3_clone/.hg/requires:lfs (lfsremote-on !)
143 143 $TESTTMP/server/.hg/requires:lfs (lfsremote-on !)
144 144
145 145 $ hg init $TESTTMP/client3_pull
146 146 $ hg -R $TESTTMP/client3_pull pull -q http://localhost:$HGPORT
147 147 $ grep 'lfs' $TESTTMP/client3_pull/.hg/requires $SERVER_REQUIRES || true
148 148 $TESTTMP/client3_pull/.hg/requires:lfs (lfsremote-on !)
149 149 $TESTTMP/server/.hg/requires:lfs (lfsremote-on !)
150 150
151 151 The difference here is the push failed above when the extension isn't
152 152 enabled on the server.
153 153 $ hg identify http://localhost:$HGPORT
154 154 8374dc4052cb (lfsremote-on !)
155 155 1477875038c6 (lfsremote-off !)
156 156
157 157 Don't bother testing the lfsremote-off cases- the server won't be able
158 158 to launch if there's lfs content and the extension is disabled.
159 159
160 160 #if lfsremote-on
161 161
162 162 --------------------------------------------------------------------------------
163 163 Case #4: client with non-lfs content and the extension disabled; server with
164 164 lfs content, and the extension enabled.
165 165
166 166 $ cat >> $HGRCPATH <<EOF
167 167 > [extensions]
168 168 > lfs = !
169 169 > EOF
170 170
171 171 $ hg init $TESTTMP/client4
172 172 $ cd $TESTTMP/client4
173 173 $ cat >> .hg/hgrc <<EOF
174 174 > [paths]
175 175 > default = http://localhost:$HGPORT
176 176 > EOF
177 177 $ echo 'non-lfs' > nonlfs2.txt
178 178 $ hg ci -Aqm 'non-lfs'
179 179 $ grep 'lfs' .hg/requires $SERVER_REQUIRES
180 180 $TESTTMP/server/.hg/requires:lfs
181 181
182 182 $ hg push -q --force
183 183 warning: repository is unrelated
184 184 $ grep 'lfs' .hg/requires $SERVER_REQUIRES
185 185 $TESTTMP/server/.hg/requires:lfs
186 186
187 187 TODO: fail more gracefully.
188 188
189 189 $ hg clone -q http://localhost:$HGPORT $TESTTMP/client4_clone
190 190 abort: HTTP Error 500: Internal Server Error
191 191 [255]
192 192 $ grep 'lfs' $TESTTMP/client4_clone/.hg/requires $SERVER_REQUIRES
193 193 grep: $TESTTMP/client4_clone/.hg/requires: $ENOENT$
194 194 $TESTTMP/server/.hg/requires:lfs
195 195 [2]
196 196
197 197 TODO: fail more gracefully.
198 198
199 199 $ hg init $TESTTMP/client4_pull
200 200 $ hg -R $TESTTMP/client4_pull pull -q http://localhost:$HGPORT
201 201 abort: HTTP Error 500: Internal Server Error
202 202 [255]
203 203 $ grep 'lfs' $TESTTMP/client4_pull/.hg/requires $SERVER_REQUIRES
204 204 $TESTTMP/server/.hg/requires:lfs
205 205
206 206 $ hg identify http://localhost:$HGPORT
207 207 03b080fa9d93
208 208
209 209 --------------------------------------------------------------------------------
210 210 Case #5: client with non-lfs content and the extension enabled; server with
211 211 lfs content, and the extension enabled.
212 212
213 213 $ cat >> $HGRCPATH <<EOF
214 214 > [extensions]
215 215 > lfs =
216 216 > EOF
217 217 $ echo 'non-lfs' > nonlfs3.txt
218 218 $ hg ci -Aqm 'non-lfs file with lfs client'
219 219
220 220 $ hg push -q
221 221 $ grep 'lfs' .hg/requires $SERVER_REQUIRES
222 222 $TESTTMP/server/.hg/requires:lfs
223 223
224 224 $ hg clone -q http://localhost:$HGPORT $TESTTMP/client5_clone
225 225 $ grep 'lfs' $TESTTMP/client5_clone/.hg/requires $SERVER_REQUIRES
226 226 $TESTTMP/client5_clone/.hg/requires:lfs
227 227 $TESTTMP/server/.hg/requires:lfs
228 228
229 229 $ hg init $TESTTMP/client5_pull
230 230 $ hg -R $TESTTMP/client5_pull pull -q http://localhost:$HGPORT
231 231 $ grep 'lfs' $TESTTMP/client5_pull/.hg/requires $SERVER_REQUIRES
232 232 $TESTTMP/client5_pull/.hg/requires:lfs
233 233 $TESTTMP/server/.hg/requires:lfs
234 234
235 235 $ hg identify http://localhost:$HGPORT
236 236 c729025cc5e3
237 237
238 238 --------------------------------------------------------------------------------
239 239 Case #6: client with lfs content and the extension enabled; server with
240 240 lfs content, and the extension enabled.
241 241
242 242 $ echo 'this is another lfs file' > lfs2.txt
243 243 $ hg ci -Aqm 'lfs file with lfs client'
244 244
245 245 $ hg --config paths.default= push -v http://localhost:$HGPORT
246 246 pushing to http://localhost:$HGPORT/
247 247 lfs: assuming remote store: http://localhost:$HGPORT/.git/info/lfs
248 248 searching for changes
249 249 remote has heads on branch 'default' that are not known locally: 8374dc4052cb
250 250 lfs: uploading a82f1c5cea0d40e3bb3a849686bb4e6ae47ca27e614de55c1ed0325698ef68de (25 bytes)
251 251 lfs: processed: a82f1c5cea0d40e3bb3a849686bb4e6ae47ca27e614de55c1ed0325698ef68de
252 252 lfs: uploaded 1 files (25 bytes)
253 253 1 changesets found
254 254 uncompressed size of bundle content:
255 255 206 (changelog)
256 256 172 (manifests)
257 257 275 lfs2.txt
258 258 remote: adding changesets
259 259 remote: adding manifests
260 260 remote: adding file changes
261 261 remote: added 1 changesets with 1 changes to 1 files
262 262 $ grep 'lfs' .hg/requires $SERVER_REQUIRES
263 263 .hg/requires:lfs
264 264 $TESTTMP/server/.hg/requires:lfs
265 265
266 266 $ hg clone -q http://localhost:$HGPORT $TESTTMP/client6_clone
267 267 $ grep 'lfs' $TESTTMP/client6_clone/.hg/requires $SERVER_REQUIRES
268 268 $TESTTMP/client6_clone/.hg/requires:lfs
269 269 $TESTTMP/server/.hg/requires:lfs
270 270
271 271 $ hg init $TESTTMP/client6_pull
272 272 $ hg -R $TESTTMP/client6_pull pull -u -v http://localhost:$HGPORT
273 273 pulling from http://localhost:$HGPORT/
274 274 requesting all changes
275 275 adding changesets
276 276 adding manifests
277 277 adding file changes
278 278 added 6 changesets with 5 changes to 5 files (+1 heads)
279 279 calling hook pretxnchangegroup.lfs: hgext.lfs.checkrequireslfs
280 280 new changesets d437e1d24fbd:d3b84d50eacb
281 281 resolving manifests
282 282 lfs: assuming remote store: http://localhost:$HGPORT/.git/info/lfs
283 283 lfs: downloading a82f1c5cea0d40e3bb3a849686bb4e6ae47ca27e614de55c1ed0325698ef68de (25 bytes)
284 284 lfs: processed: a82f1c5cea0d40e3bb3a849686bb4e6ae47ca27e614de55c1ed0325698ef68de
285 lfs: downloaded 1 files (25 bytes)
285 286 getting lfs2.txt
286 287 lfs: found a82f1c5cea0d40e3bb3a849686bb4e6ae47ca27e614de55c1ed0325698ef68de in the local lfs store
287 288 getting nonlfs2.txt
288 289 getting nonlfs3.txt
289 290 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
290 291 updated to "d3b84d50eacb: lfs file with lfs client"
291 292 1 other heads for branch "default"
292 293 $ grep 'lfs' $TESTTMP/client6_pull/.hg/requires $SERVER_REQUIRES
293 294 $TESTTMP/client6_pull/.hg/requires:lfs
294 295 $TESTTMP/server/.hg/requires:lfs
295 296
296 297 $ hg identify http://localhost:$HGPORT
297 298 d3b84d50eacb
298 299
299 300 --------------------------------------------------------------------------------
300 301 Misc: process dies early if a requirement exists and the extension is disabled
301 302
302 303 $ hg --config extensions.lfs=! summary
303 304 abort: repository requires features unknown to this Mercurial: lfs!
304 305 (see https://mercurial-scm.org/wiki/MissingRequirement for more information)
305 306 [255]
306 307
307 308 $ echo 'this is an lfs file' > $TESTTMP/client6_clone/lfspair1.bin
308 309 $ echo 'this is an lfs file too' > $TESTTMP/client6_clone/lfspair2.bin
309 310 $ hg -R $TESTTMP/client6_clone ci -Aqm 'add lfs pair'
310 311 $ hg -R $TESTTMP/client6_clone push -q
311 312
312 313 $ hg clone -qU http://localhost:$HGPORT $TESTTMP/bulkfetch
313 314
314 315 Export will prefetch all needed files across all needed revisions
315 316
316 317 $ hg -R $TESTTMP/bulkfetch -v export -r 0:tip -o all.export
317 318 lfs: assuming remote store: http://localhost:$HGPORT/.git/info/lfs
318 319 exporting patches:
319 320 lfs: assuming remote store: http://localhost:$HGPORT/.git/info/lfs
320 321 lfs: need to transfer 4 objects (92 bytes)
321 322 lfs: downloading a82f1c5cea0d40e3bb3a849686bb4e6ae47ca27e614de55c1ed0325698ef68de (25 bytes)
322 323 lfs: processed: a82f1c5cea0d40e3bb3a849686bb4e6ae47ca27e614de55c1ed0325698ef68de
323 324 lfs: downloading bed80f00180ac404b843628ab56a1c1984d6145c391cd1628a7dd7d2598d71fc (23 bytes)
324 325 lfs: processed: bed80f00180ac404b843628ab56a1c1984d6145c391cd1628a7dd7d2598d71fc
325 326 lfs: downloading cf1b2787b74e66547d931b6ebe28ff63303e803cb2baa14a8f57c4383d875782 (20 bytes)
326 327 lfs: processed: cf1b2787b74e66547d931b6ebe28ff63303e803cb2baa14a8f57c4383d875782
327 328 lfs: downloading d96eda2c74b56e95cfb5ffb66b6503e198cc6fc4a09dc877de925feebc65786e (24 bytes)
328 329 lfs: processed: d96eda2c74b56e95cfb5ffb66b6503e198cc6fc4a09dc877de925feebc65786e
330 lfs: downloaded 4 files (92 bytes)
329 331 all.export
330 332 lfs: found bed80f00180ac404b843628ab56a1c1984d6145c391cd1628a7dd7d2598d71fc in the local lfs store
331 333 lfs: found a82f1c5cea0d40e3bb3a849686bb4e6ae47ca27e614de55c1ed0325698ef68de in the local lfs store
332 334 lfs: found cf1b2787b74e66547d931b6ebe28ff63303e803cb2baa14a8f57c4383d875782 in the local lfs store
333 335 lfs: found d96eda2c74b56e95cfb5ffb66b6503e198cc6fc4a09dc877de925feebc65786e in the local lfs store
334 336
335 337 Export with selected files is used with `extdiff --patch`
336 338
337 339 $ rm -r $TESTTMP/bulkfetch/.hg/store/lfs
338 340 $ hg --config extensions.extdiff= \
339 341 > -R $TESTTMP/bulkfetch -v extdiff -r 2:tip --patch $TESTTMP/bulkfetch/lfs.bin
340 342 lfs: assuming remote store: http://localhost:$HGPORT/.git/info/lfs
341 343 lfs: assuming remote store: http://localhost:$HGPORT/.git/info/lfs
342 344 lfs: downloading bed80f00180ac404b843628ab56a1c1984d6145c391cd1628a7dd7d2598d71fc (23 bytes)
343 345 lfs: processed: bed80f00180ac404b843628ab56a1c1984d6145c391cd1628a7dd7d2598d71fc
346 lfs: downloaded 1 files (23 bytes)
344 347 */hg-8374dc4052cb.patch (glob)
345 348 lfs: found bed80f00180ac404b843628ab56a1c1984d6145c391cd1628a7dd7d2598d71fc in the local lfs store
346 349 */hg-9640b57e77b1.patch (glob)
347 350 --- */hg-8374dc4052cb.patch * (glob)
348 351 +++ */hg-9640b57e77b1.patch * (glob)
349 352 @@ -2,12 +2,7 @@
350 353 # User test
351 354 # Date 0 0
352 355 # Thu Jan 01 00:00:00 1970 +0000
353 356 -# Node ID 8374dc4052cbd388e79d9dc4ddb29784097aa354
354 357 -# Parent 1477875038c60152e391238920a16381c627b487
355 358 -lfs
356 359 +# Node ID 9640b57e77b14c3a0144fb4478b6cc13e13ea0d1
357 360 +# Parent d3b84d50eacbd56638e11abce6b8616aaba54420
358 361 +add lfs pair
359 362
360 363 -diff -r 1477875038c6 -r 8374dc4052cb lfs.bin
361 364 ---- /dev/null Thu Jan 01 00:00:00 1970 +0000
362 365 -+++ b/lfs.bin Thu Jan 01 00:00:00 1970 +0000
363 366 -@@ -0,0 +1,1 @@
364 367 -+this is a big lfs file
365 368 cleaning up temp directory
366 369 [1]
367 370
368 371 Diff will prefetch files
369 372
370 373 $ rm -r $TESTTMP/bulkfetch/.hg/store/lfs
371 374 $ hg -R $TESTTMP/bulkfetch -v diff -r 2:tip
372 375 lfs: assuming remote store: http://localhost:$HGPORT/.git/info/lfs
373 376 lfs: assuming remote store: http://localhost:$HGPORT/.git/info/lfs
374 377 lfs: need to transfer 4 objects (92 bytes)
375 378 lfs: downloading a82f1c5cea0d40e3bb3a849686bb4e6ae47ca27e614de55c1ed0325698ef68de (25 bytes)
376 379 lfs: processed: a82f1c5cea0d40e3bb3a849686bb4e6ae47ca27e614de55c1ed0325698ef68de
377 380 lfs: downloading bed80f00180ac404b843628ab56a1c1984d6145c391cd1628a7dd7d2598d71fc (23 bytes)
378 381 lfs: processed: bed80f00180ac404b843628ab56a1c1984d6145c391cd1628a7dd7d2598d71fc
379 382 lfs: downloading cf1b2787b74e66547d931b6ebe28ff63303e803cb2baa14a8f57c4383d875782 (20 bytes)
380 383 lfs: processed: cf1b2787b74e66547d931b6ebe28ff63303e803cb2baa14a8f57c4383d875782
381 384 lfs: downloading d96eda2c74b56e95cfb5ffb66b6503e198cc6fc4a09dc877de925feebc65786e (24 bytes)
382 385 lfs: processed: d96eda2c74b56e95cfb5ffb66b6503e198cc6fc4a09dc877de925feebc65786e
386 lfs: downloaded 4 files (92 bytes)
383 387 lfs: found bed80f00180ac404b843628ab56a1c1984d6145c391cd1628a7dd7d2598d71fc in the local lfs store
384 388 lfs: found a82f1c5cea0d40e3bb3a849686bb4e6ae47ca27e614de55c1ed0325698ef68de in the local lfs store
385 389 lfs: found cf1b2787b74e66547d931b6ebe28ff63303e803cb2baa14a8f57c4383d875782 in the local lfs store
386 390 lfs: found d96eda2c74b56e95cfb5ffb66b6503e198cc6fc4a09dc877de925feebc65786e in the local lfs store
387 391 diff -r 8374dc4052cb -r 9640b57e77b1 lfs.bin
388 392 --- a/lfs.bin Thu Jan 01 00:00:00 1970 +0000
389 393 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
390 394 @@ -1,1 +0,0 @@
391 395 -this is a big lfs file
392 396 diff -r 8374dc4052cb -r 9640b57e77b1 lfs2.txt
393 397 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
394 398 +++ b/lfs2.txt Thu Jan 01 00:00:00 1970 +0000
395 399 @@ -0,0 +1,1 @@
396 400 +this is another lfs file
397 401 diff -r 8374dc4052cb -r 9640b57e77b1 lfspair1.bin
398 402 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
399 403 +++ b/lfspair1.bin Thu Jan 01 00:00:00 1970 +0000
400 404 @@ -0,0 +1,1 @@
401 405 +this is an lfs file
402 406 diff -r 8374dc4052cb -r 9640b57e77b1 lfspair2.bin
403 407 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
404 408 +++ b/lfspair2.bin Thu Jan 01 00:00:00 1970 +0000
405 409 @@ -0,0 +1,1 @@
406 410 +this is an lfs file too
407 411 diff -r 8374dc4052cb -r 9640b57e77b1 nonlfs.txt
408 412 --- a/nonlfs.txt Thu Jan 01 00:00:00 1970 +0000
409 413 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
410 414 @@ -1,1 +0,0 @@
411 415 -non-lfs
412 416 diff -r 8374dc4052cb -r 9640b57e77b1 nonlfs3.txt
413 417 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
414 418 +++ b/nonlfs3.txt Thu Jan 01 00:00:00 1970 +0000
415 419 @@ -0,0 +1,1 @@
416 420 +non-lfs
417 421
418 422 Only the files required by diff are prefetched
419 423
420 424 $ rm -r $TESTTMP/bulkfetch/.hg/store/lfs
421 425 $ hg -R $TESTTMP/bulkfetch -v diff -r 2:tip $TESTTMP/bulkfetch/lfspair2.bin
422 426 lfs: assuming remote store: http://localhost:$HGPORT/.git/info/lfs
423 427 lfs: assuming remote store: http://localhost:$HGPORT/.git/info/lfs
424 428 lfs: downloading d96eda2c74b56e95cfb5ffb66b6503e198cc6fc4a09dc877de925feebc65786e (24 bytes)
425 429 lfs: processed: d96eda2c74b56e95cfb5ffb66b6503e198cc6fc4a09dc877de925feebc65786e
430 lfs: downloaded 1 files (24 bytes)
426 431 lfs: found d96eda2c74b56e95cfb5ffb66b6503e198cc6fc4a09dc877de925feebc65786e in the local lfs store
427 432 diff -r 8374dc4052cb -r 9640b57e77b1 lfspair2.bin
428 433 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
429 434 +++ b/lfspair2.bin Thu Jan 01 00:00:00 1970 +0000
430 435 @@ -0,0 +1,1 @@
431 436 +this is an lfs file too
432 437
433 438 #endif
434 439
435 440 $ $PYTHON $TESTDIR/killdaemons.py $DAEMON_PIDS
436 441
437 442 #if lfsremote-on
438 443 $ cat $TESTTMP/errors.log | grep '^[A-Z]'
439 444 Traceback (most recent call last):
440 445 ValueError: no common changegroup version
441 446 Traceback (most recent call last):
442 447 ValueError: no common changegroup version
443 448 #else
444 449 $ cat $TESTTMP/errors.log
445 450 #endif
@@ -1,937 +1,942 b''
1 1 #require no-reposimplestore
2 2 #testcases git-server hg-server
3 3
4 4 #if git-server
5 5 #require lfs-test-server
6 6 #else
7 7 #require serve
8 8 #endif
9 9
10 10 #if git-server
11 11 $ LFS_LISTEN="tcp://:$HGPORT"
12 12 $ LFS_HOST="localhost:$HGPORT"
13 13 $ LFS_PUBLIC=1
14 14 $ export LFS_LISTEN LFS_HOST LFS_PUBLIC
15 15 #else
16 16 $ LFS_HOST="localhost:$HGPORT/.git/info/lfs"
17 17 #endif
18 18
19 19 #if no-windows git-server
20 20 $ lfs-test-server &> lfs-server.log &
21 21 $ echo $! >> $DAEMON_PIDS
22 22 #endif
23 23
24 24 #if windows git-server
25 25 $ cat >> $TESTTMP/spawn.py <<EOF
26 26 > import os
27 27 > import subprocess
28 28 > import sys
29 29 >
30 30 > for path in os.environ["PATH"].split(os.pathsep):
31 31 > exe = os.path.join(path, 'lfs-test-server.exe')
32 32 > if os.path.exists(exe):
33 33 > with open('lfs-server.log', 'wb') as out:
34 34 > p = subprocess.Popen(exe, stdout=out, stderr=out)
35 35 > sys.stdout.write('%s\n' % p.pid)
36 36 > sys.exit(0)
37 37 > sys.exit(1)
38 38 > EOF
39 39 $ $PYTHON $TESTTMP/spawn.py >> $DAEMON_PIDS
40 40 #endif
41 41
42 42 $ cat >> $HGRCPATH <<EOF
43 43 > [extensions]
44 44 > lfs=
45 45 > [lfs]
46 46 > url=http://foo:bar@$LFS_HOST
47 47 > track=all()
48 48 > [web]
49 49 > push_ssl = False
50 50 > allow-push = *
51 51 > EOF
52 52
53 53 Use a separate usercache, otherwise the server sees what the client commits, and
54 54 never requests a transfer.
55 55
56 56 #if hg-server
57 57 $ hg init server
58 58 $ hg --config "lfs.usercache=$TESTTMP/servercache" -R server serve -d \
59 59 > -p $HGPORT --pid-file=hg.pid -A $TESTTMP/access.log -E $TESTTMP/errors.log
60 60 $ cat hg.pid >> $DAEMON_PIDS
61 61 #endif
62 62
63 63 $ hg init repo1
64 64 $ cd repo1
65 65 $ echo THIS-IS-LFS > a
66 66 $ hg commit -m a -A a
67 67
68 68 A push can be serviced directly from the usercache if it isn't in the local
69 69 store.
70 70
71 71 $ hg init ../repo2
72 72 $ mv .hg/store/lfs .hg/store/lfs_
73 73 $ hg push ../repo2 --debug
74 74 http auth: user foo, password ***
75 75 pushing to ../repo2
76 76 http auth: user foo, password ***
77 77 http auth: user foo, password ***
78 78 query 1; heads
79 79 searching for changes
80 80 1 total queries in *s (glob)
81 81 listing keys for "phases"
82 82 checking for updated bookmarks
83 83 listing keys for "bookmarks"
84 84 lfs: computing set of blobs to upload
85 85 Status: 200
86 86 Content-Length: 309 (git-server !)
87 87 Content-Length: 350 (hg-server !)
88 88 Content-Type: application/vnd.git-lfs+json
89 89 Date: $HTTP_DATE$
90 90 Server: testing stub value (hg-server !)
91 91 {
92 92 "objects": [
93 93 {
94 94 "actions": {
95 95 "upload": {
96 96 "expires_at": "$ISO_8601_DATE_TIME$"
97 97 "header": {
98 98 "Accept": "application/vnd.git-lfs"
99 99 }
100 100 "href": "http://localhost:$HGPORT/objects/31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b" (git-server !)
101 101 "href": "http://localhost:$HGPORT/.hg/lfs/objects/31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b" (hg-server !)
102 102 }
103 103 }
104 104 "oid": "31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b"
105 105 "size": 12
106 106 }
107 107 ]
108 108 "transfer": "basic" (hg-server !)
109 109 }
110 110 lfs: uploading 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b (12 bytes)
111 111 Status: 200 (git-server !)
112 112 Status: 201 (hg-server !)
113 113 Content-Length: 0
114 114 Content-Type: text/plain; charset=utf-8
115 115 Date: $HTTP_DATE$
116 116 Server: testing stub value (hg-server !)
117 117 lfs: processed: 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b
118 118 lfs: uploaded 1 files (12 bytes)
119 119 1 changesets found
120 120 list of changesets:
121 121 99a7098854a3984a5c9eab0fc7a2906697b7cb5c
122 122 bundle2-output-bundle: "HG20", 4 parts total
123 123 bundle2-output-part: "replycaps" * bytes payload (glob)
124 124 bundle2-output-part: "check:heads" streamed payload
125 125 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
126 126 bundle2-output-part: "phase-heads" 24 bytes payload
127 127 bundle2-input-bundle: with-transaction
128 128 bundle2-input-part: "replycaps" supported
129 129 bundle2-input-part: total payload size * (glob)
130 130 bundle2-input-part: "check:heads" supported
131 131 bundle2-input-part: total payload size 20
132 132 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
133 133 adding changesets
134 134 add changeset 99a7098854a3
135 135 adding manifests
136 136 adding file changes
137 137 adding a revisions
138 138 added 1 changesets with 1 changes to 1 files
139 139 calling hook pretxnchangegroup.lfs: hgext.lfs.checkrequireslfs
140 140 bundle2-input-part: total payload size 617
141 141 bundle2-input-part: "phase-heads" supported
142 142 bundle2-input-part: total payload size 24
143 143 bundle2-input-bundle: 3 parts total
144 144 updating the branch cache
145 145 bundle2-output-bundle: "HG20", 1 parts total
146 146 bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload
147 147 bundle2-input-bundle: no-transaction
148 148 bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported
149 149 bundle2-input-bundle: 0 parts total
150 150 listing keys for "phases"
151 151 $ mv .hg/store/lfs_ .hg/store/lfs
152 152
153 153 Clear the cache to force a download
154 154 $ rm -rf `hg config lfs.usercache`
155 155 $ cd ../repo2
156 156 $ hg update tip --debug
157 157 http auth: user foo, password ***
158 158 resolving manifests
159 159 branchmerge: False, force: False, partial: False
160 160 ancestor: 000000000000, local: 000000000000+, remote: 99a7098854a3
161 161 http auth: user foo, password ***
162 162 Status: 200
163 163 Content-Length: 311 (git-server !)
164 164 Content-Length: 352 (hg-server !)
165 165 Content-Type: application/vnd.git-lfs+json
166 166 Date: $HTTP_DATE$
167 167 Server: testing stub value (hg-server !)
168 168 {
169 169 "objects": [
170 170 {
171 171 "actions": {
172 172 "download": {
173 173 "expires_at": "$ISO_8601_DATE_TIME$"
174 174 "header": {
175 175 "Accept": "application/vnd.git-lfs"
176 176 }
177 177 "href": "http://localhost:$HGPORT/*/31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b" (glob)
178 178 }
179 179 }
180 180 "oid": "31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b"
181 181 "size": 12
182 182 }
183 183 ]
184 184 "transfer": "basic" (hg-server !)
185 185 }
186 186 lfs: downloading 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b (12 bytes)
187 187 Status: 200
188 188 Content-Length: 12
189 189 Content-Type: text/plain; charset=utf-8 (git-server !)
190 190 Content-Type: application/octet-stream (hg-server !)
191 191 Date: $HTTP_DATE$
192 192 Server: testing stub value (hg-server !)
193 193 lfs: adding 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b to the usercache
194 194 lfs: processed: 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b
195 lfs: downloaded 1 files (12 bytes)
195 196 a: remote created -> g
196 197 getting a
197 198 lfs: found 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b in the local lfs store
198 199 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
199 200
200 201 When the server has some blobs already. `hg serve` doesn't offer to upload
201 202 blobs that it already knows about. Note that lfs-test-server is simply
202 203 toggling the action to 'download'. The Batch API spec says it should omit the
203 204 actions property completely.
204 205
205 206 $ hg mv a b
206 207 $ echo ANOTHER-LARGE-FILE > c
207 208 $ echo ANOTHER-LARGE-FILE2 > d
208 209 $ hg commit -m b-and-c -A b c d
209 210 $ hg push ../repo1 --debug
210 211 http auth: user foo, password ***
211 212 pushing to ../repo1
212 213 http auth: user foo, password ***
213 214 http auth: user foo, password ***
214 215 query 1; heads
215 216 searching for changes
216 217 all remote heads known locally
217 218 listing keys for "phases"
218 219 checking for updated bookmarks
219 220 listing keys for "bookmarks"
220 221 listing keys for "bookmarks"
221 222 lfs: computing set of blobs to upload
222 223 Status: 200
223 224 Content-Length: 901 (git-server !)
224 225 Content-Length: 755 (hg-server !)
225 226 Content-Type: application/vnd.git-lfs+json
226 227 Date: $HTTP_DATE$
227 228 Server: testing stub value (hg-server !)
228 229 {
229 230 "objects": [
230 231 {
231 232 "actions": { (git-server !)
232 233 "download": { (git-server !)
233 234 "expires_at": "$ISO_8601_DATE_TIME$" (git-server !)
234 235 "header": { (git-server !)
235 236 "Accept": "application/vnd.git-lfs" (git-server !)
236 237 } (git-server !)
237 238 "href": "http://localhost:$HGPORT/objects/31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b" (git-server !)
238 239 } (git-server !)
239 240 } (git-server !)
240 241 "oid": "31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b"
241 242 "size": 12
242 243 }
243 244 {
244 245 "actions": {
245 246 "upload": {
246 247 "expires_at": "$ISO_8601_DATE_TIME$"
247 248 "header": {
248 249 "Accept": "application/vnd.git-lfs"
249 250 }
250 251 "href": "http://localhost:$HGPORT/*/37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19" (glob)
251 252 }
252 253 }
253 254 "oid": "37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19"
254 255 "size": 20
255 256 }
256 257 {
257 258 "actions": {
258 259 "upload": {
259 260 "expires_at": "$ISO_8601_DATE_TIME$"
260 261 "header": {
261 262 "Accept": "application/vnd.git-lfs"
262 263 }
263 264 "href": "http://localhost:$HGPORT/*/d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998" (glob)
264 265 }
265 266 }
266 267 "oid": "d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998"
267 268 "size": 19
268 269 }
269 270 ]
270 271 "transfer": "basic" (hg-server !)
271 272 }
272 273 lfs: need to transfer 2 objects (39 bytes)
273 274 lfs: uploading 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19 (20 bytes)
274 275 Status: 200 (git-server !)
275 276 Status: 201 (hg-server !)
276 277 Content-Length: 0
277 278 Content-Type: text/plain; charset=utf-8
278 279 Date: $HTTP_DATE$
279 280 Server: testing stub value (hg-server !)
280 281 lfs: processed: 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19
281 282 lfs: uploading d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 (19 bytes)
282 283 Status: 200 (git-server !)
283 284 Status: 201 (hg-server !)
284 285 Content-Length: 0
285 286 Content-Type: text/plain; charset=utf-8
286 287 Date: $HTTP_DATE$
287 288 Server: testing stub value (hg-server !)
288 289 lfs: processed: d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
289 290 lfs: uploaded 2 files (39 bytes)
290 291 1 changesets found
291 292 list of changesets:
292 293 dfca2c9e2ef24996aa61ba2abd99277d884b3d63
293 294 bundle2-output-bundle: "HG20", 5 parts total
294 295 bundle2-output-part: "replycaps" * bytes payload (glob)
295 296 bundle2-output-part: "check:phases" 24 bytes payload
296 297 bundle2-output-part: "check:heads" streamed payload
297 298 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
298 299 bundle2-output-part: "phase-heads" 24 bytes payload
299 300 bundle2-input-bundle: with-transaction
300 301 bundle2-input-part: "replycaps" supported
301 302 bundle2-input-part: total payload size * (glob)
302 303 bundle2-input-part: "check:phases" supported
303 304 bundle2-input-part: total payload size 24
304 305 bundle2-input-part: "check:heads" supported
305 306 bundle2-input-part: total payload size 20
306 307 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
307 308 adding changesets
308 309 add changeset dfca2c9e2ef2
309 310 adding manifests
310 311 adding file changes
311 312 adding b revisions
312 313 adding c revisions
313 314 adding d revisions
314 315 added 1 changesets with 3 changes to 3 files
315 316 bundle2-input-part: total payload size 1315
316 317 bundle2-input-part: "phase-heads" supported
317 318 bundle2-input-part: total payload size 24
318 319 bundle2-input-bundle: 4 parts total
319 320 updating the branch cache
320 321 bundle2-output-bundle: "HG20", 1 parts total
321 322 bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload
322 323 bundle2-input-bundle: no-transaction
323 324 bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported
324 325 bundle2-input-bundle: 0 parts total
325 326 listing keys for "phases"
326 327
327 328 Clear the cache to force a download
328 329 $ rm -rf `hg config lfs.usercache`
329 330 $ hg --repo ../repo1 update tip --debug
330 331 http auth: user foo, password ***
331 332 resolving manifests
332 333 branchmerge: False, force: False, partial: False
333 334 ancestor: 99a7098854a3, local: 99a7098854a3+, remote: dfca2c9e2ef2
334 335 http auth: user foo, password ***
335 336 Status: 200
336 337 Content-Length: 608 (git-server !)
337 338 Content-Length: 670 (hg-server !)
338 339 Content-Type: application/vnd.git-lfs+json
339 340 Date: $HTTP_DATE$
340 341 Server: testing stub value (hg-server !)
341 342 {
342 343 "objects": [
343 344 {
344 345 "actions": {
345 346 "download": {
346 347 "expires_at": "$ISO_8601_DATE_TIME$"
347 348 "header": {
348 349 "Accept": "application/vnd.git-lfs"
349 350 }
350 351 "href": "http://localhost:$HGPORT/*/37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19" (glob)
351 352 }
352 353 }
353 354 "oid": "37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19"
354 355 "size": 20
355 356 }
356 357 {
357 358 "actions": {
358 359 "download": {
359 360 "expires_at": "$ISO_8601_DATE_TIME$"
360 361 "header": {
361 362 "Accept": "application/vnd.git-lfs"
362 363 }
363 364 "href": "http://localhost:$HGPORT/*/d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998" (glob)
364 365 }
365 366 }
366 367 "oid": "d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998"
367 368 "size": 19
368 369 }
369 370 ]
370 371 "transfer": "basic" (hg-server !)
371 372 }
372 373 lfs: need to transfer 2 objects (39 bytes)
373 374 lfs: downloading 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19 (20 bytes)
374 375 Status: 200
375 376 Content-Length: 20
376 377 Content-Type: text/plain; charset=utf-8 (git-server !)
377 378 Content-Type: application/octet-stream (hg-server !)
378 379 Date: $HTTP_DATE$
379 380 Server: testing stub value (hg-server !)
380 381 lfs: adding 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19 to the usercache
381 382 lfs: processed: 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19
382 383 lfs: downloading d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 (19 bytes)
383 384 Status: 200
384 385 Content-Length: 19
385 386 Content-Type: text/plain; charset=utf-8 (git-server !)
386 387 Content-Type: application/octet-stream (hg-server !)
387 388 Date: $HTTP_DATE$
388 389 Server: testing stub value (hg-server !)
389 390 lfs: adding d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 to the usercache
390 391 lfs: processed: d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
392 lfs: downloaded 2 files (39 bytes)
391 393 b: remote created -> g
392 394 getting b
393 395 lfs: found 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b in the local lfs store
394 396 c: remote created -> g
395 397 getting c
396 398 lfs: found d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 in the local lfs store
397 399 d: remote created -> g
398 400 getting d
399 401 lfs: found 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19 in the local lfs store
400 402 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
401 403
402 404 Test a corrupt file download, but clear the cache first to force a download.
403 405 `hg serve` indicates a corrupt file without transferring it, unlike
404 406 lfs-test-server.
405 407
406 408 $ rm -rf `hg config lfs.usercache`
407 409 #if git-server
408 410 $ cp $TESTTMP/lfs-content/d1/1e/1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 blob
409 411 $ echo 'damage' > $TESTTMP/lfs-content/d1/1e/1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
410 412 #else
411 413 $ cp $TESTTMP/server/.hg/store/lfs/objects/d1/1e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 blob
412 414 $ echo 'damage' > $TESTTMP/server/.hg/store/lfs/objects/d1/1e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
413 415 #endif
414 416 $ rm ../repo1/.hg/store/lfs/objects/d1/1e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
415 417 $ rm ../repo1/*
416 418
417 419 TODO: give the proper error indication from `hg serve`
418 420
419 421 $ hg --repo ../repo1 update -C tip --debug
420 422 http auth: user foo, password ***
421 423 resolving manifests
422 424 branchmerge: False, force: True, partial: False
423 425 ancestor: dfca2c9e2ef2+, local: dfca2c9e2ef2+, remote: dfca2c9e2ef2
424 426 http auth: user foo, password ***
425 427 Status: 200
426 428 Content-Length: 311 (git-server !)
427 429 Content-Length: 183 (hg-server !)
428 430 Content-Type: application/vnd.git-lfs+json
429 431 Date: $HTTP_DATE$
430 432 Server: testing stub value (hg-server !)
431 433 {
432 434 "objects": [
433 435 {
434 436 "actions": { (git-server !)
435 437 "download": { (git-server !)
436 438 "expires_at": "$ISO_8601_DATE_TIME$" (git-server !)
437 439 "header": { (git-server !)
438 440 "Accept": "application/vnd.git-lfs" (git-server !)
439 441 } (git-server !)
440 442 "href": "http://localhost:$HGPORT/objects/d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998" (git-server !)
441 443 } (git-server !)
442 444 "error": { (hg-server !)
443 445 "code": 422 (hg-server !)
444 446 "message": "The object is corrupt" (hg-server !)
445 447 }
446 448 "oid": "d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998"
447 449 "size": 19
448 450 }
449 451 ]
450 452 "transfer": "basic" (hg-server !)
451 453 }
452 454 lfs: downloading d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 (19 bytes) (git-server !)
453 455 Status: 200 (git-server !)
454 456 Content-Length: 7 (git-server !)
455 457 Content-Type: text/plain; charset=utf-8 (git-server !)
456 458 Date: $HTTP_DATE$ (git-server !)
457 459 abort: corrupt remote lfs object: d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 (git-server !)
458 460 abort: LFS server error for "c": Validation error! (hg-server !)
459 461 [255]
460 462
461 463 The corrupted blob is not added to the usercache or local store
462 464
463 465 $ test -f ../repo1/.hg/store/lfs/objects/d1/1e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
464 466 [1]
465 467 $ test -f `hg config lfs.usercache`/d1/1e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
466 468 [1]
467 469 #if git-server
468 470 $ cp blob $TESTTMP/lfs-content/d1/1e/1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
469 471 #else
470 472 $ cp blob $TESTTMP/server/.hg/store/lfs/objects/d1/1e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
471 473 #endif
472 474
473 475 Test a corrupted file upload
474 476
475 477 $ echo 'another lfs blob' > b
476 478 $ hg ci -m 'another blob'
477 479 $ echo 'damage' > .hg/store/lfs/objects/e6/59058e26b07b39d2a9c7145b3f99b41f797b6621c8076600e9cb7ee88291f0
478 480 $ hg push --debug ../repo1
479 481 http auth: user foo, password ***
480 482 pushing to ../repo1
481 483 http auth: user foo, password ***
482 484 http auth: user foo, password ***
483 485 query 1; heads
484 486 searching for changes
485 487 all remote heads known locally
486 488 listing keys for "phases"
487 489 checking for updated bookmarks
488 490 listing keys for "bookmarks"
489 491 listing keys for "bookmarks"
490 492 lfs: computing set of blobs to upload
491 493 Status: 200
492 494 Content-Length: 309 (git-server !)
493 495 Content-Length: 350 (hg-server !)
494 496 Content-Type: application/vnd.git-lfs+json
495 497 Date: $HTTP_DATE$
496 498 Server: testing stub value (hg-server !)
497 499 {
498 500 "objects": [
499 501 {
500 502 "actions": {
501 503 "upload": {
502 504 "expires_at": "$ISO_8601_DATE_TIME$"
503 505 "header": {
504 506 "Accept": "application/vnd.git-lfs"
505 507 }
506 508 "href": "http://localhost:$HGPORT/*/e659058e26b07b39d2a9c7145b3f99b41f797b6621c8076600e9cb7ee88291f0" (glob)
507 509 }
508 510 }
509 511 "oid": "e659058e26b07b39d2a9c7145b3f99b41f797b6621c8076600e9cb7ee88291f0"
510 512 "size": 17
511 513 }
512 514 ]
513 515 "transfer": "basic" (hg-server !)
514 516 }
515 517 lfs: uploading e659058e26b07b39d2a9c7145b3f99b41f797b6621c8076600e9cb7ee88291f0 (17 bytes)
516 518 abort: detected corrupt lfs object: e659058e26b07b39d2a9c7145b3f99b41f797b6621c8076600e9cb7ee88291f0
517 519 (run hg verify)
518 520 [255]
519 521
520 522 Archive will prefetch blobs in a group
521 523
522 524 $ rm -rf .hg/store/lfs `hg config lfs.usercache`
523 525 $ hg archive --debug -r 1 ../archive
524 526 http auth: user foo, password ***
525 527 http auth: user foo, password ***
526 528 Status: 200
527 529 Content-Length: 905 (git-server !)
528 530 Content-Length: 988 (hg-server !)
529 531 Content-Type: application/vnd.git-lfs+json
530 532 Date: $HTTP_DATE$
531 533 Server: testing stub value (hg-server !)
532 534 {
533 535 "objects": [
534 536 {
535 537 "actions": {
536 538 "download": {
537 539 "expires_at": "$ISO_8601_DATE_TIME$"
538 540 "header": {
539 541 "Accept": "application/vnd.git-lfs"
540 542 }
541 543 "href": "http://localhost:$HGPORT/*/31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b" (glob)
542 544 }
543 545 }
544 546 "oid": "31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b"
545 547 "size": 12
546 548 }
547 549 {
548 550 "actions": {
549 551 "download": {
550 552 "expires_at": "$ISO_8601_DATE_TIME$"
551 553 "header": {
552 554 "Accept": "application/vnd.git-lfs"
553 555 }
554 556 "href": "http://localhost:$HGPORT/*/37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19" (glob)
555 557 }
556 558 }
557 559 "oid": "37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19"
558 560 "size": 20
559 561 }
560 562 {
561 563 "actions": {
562 564 "download": {
563 565 "expires_at": "$ISO_8601_DATE_TIME$"
564 566 "header": {
565 567 "Accept": "application/vnd.git-lfs"
566 568 }
567 569 "href": "http://localhost:$HGPORT/*/d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998" (glob)
568 570 }
569 571 }
570 572 "oid": "d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998"
571 573 "size": 19
572 574 }
573 575 ]
574 576 "transfer": "basic" (hg-server !)
575 577 }
576 578 lfs: need to transfer 3 objects (51 bytes)
577 579 lfs: downloading 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b (12 bytes)
578 580 Status: 200
579 581 Content-Length: 12
580 582 Content-Type: text/plain; charset=utf-8 (git-server !)
581 583 Content-Type: application/octet-stream (hg-server !)
582 584 Date: $HTTP_DATE$
583 585 Server: testing stub value (hg-server !)
584 586 lfs: adding 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b to the usercache
585 587 lfs: processed: 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b
586 588 lfs: downloading 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19 (20 bytes)
587 589 Status: 200
588 590 Content-Length: 20
589 591 Content-Type: text/plain; charset=utf-8 (git-server !)
590 592 Content-Type: application/octet-stream (hg-server !)
591 593 Date: $HTTP_DATE$
592 594 Server: testing stub value (hg-server !)
593 595 lfs: adding 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19 to the usercache
594 596 lfs: processed: 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19
595 597 lfs: downloading d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 (19 bytes)
596 598 Status: 200
597 599 Content-Length: 19
598 600 Content-Type: text/plain; charset=utf-8 (git-server !)
599 601 Content-Type: application/octet-stream (hg-server !)
600 602 Date: $HTTP_DATE$
601 603 Server: testing stub value (hg-server !)
602 604 lfs: adding d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 to the usercache
603 605 lfs: processed: d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
606 lfs: downloaded 3 files (51 bytes)
604 607 lfs: found 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b in the local lfs store
605 608 lfs: found 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b in the local lfs store
606 609 lfs: found d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 in the local lfs store
607 610 lfs: found 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19 in the local lfs store
608 611 $ find ../archive | sort
609 612 ../archive
610 613 ../archive/.hg_archival.txt
611 614 ../archive/a
612 615 ../archive/b
613 616 ../archive/c
614 617 ../archive/d
615 618
616 619 Cat will prefetch blobs in a group
617 620
618 621 $ rm -rf .hg/store/lfs `hg config lfs.usercache`
619 622 $ hg cat --debug -r 1 a b c nonexistent
620 623 http auth: user foo, password ***
621 624 http auth: user foo, password ***
622 625 Status: 200
623 626 Content-Length: 608 (git-server !)
624 627 Content-Length: 670 (hg-server !)
625 628 Content-Type: application/vnd.git-lfs+json
626 629 Date: $HTTP_DATE$
627 630 Server: testing stub value (hg-server !)
628 631 {
629 632 "objects": [
630 633 {
631 634 "actions": {
632 635 "download": {
633 636 "expires_at": "$ISO_8601_DATE_TIME$"
634 637 "header": {
635 638 "Accept": "application/vnd.git-lfs"
636 639 }
637 640 "href": "http://localhost:$HGPORT/*/31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b" (glob)
638 641 }
639 642 }
640 643 "oid": "31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b"
641 644 "size": 12
642 645 }
643 646 {
644 647 "actions": {
645 648 "download": {
646 649 "expires_at": "$ISO_8601_DATE_TIME$"
647 650 "header": {
648 651 "Accept": "application/vnd.git-lfs"
649 652 }
650 653 "href": "http://localhost:$HGPORT/*/d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998" (glob)
651 654 }
652 655 }
653 656 "oid": "d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998"
654 657 "size": 19
655 658 }
656 659 ]
657 660 "transfer": "basic" (hg-server !)
658 661 }
659 662 lfs: need to transfer 2 objects (31 bytes)
660 663 lfs: downloading 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b (12 bytes)
661 664 Status: 200
662 665 Content-Length: 12
663 666 Content-Type: text/plain; charset=utf-8 (git-server !)
664 667 Content-Type: application/octet-stream (hg-server !)
665 668 Date: $HTTP_DATE$
666 669 Server: testing stub value (hg-server !)
667 670 lfs: adding 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b to the usercache
668 671 lfs: processed: 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b
669 672 lfs: downloading d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 (19 bytes)
670 673 Status: 200
671 674 Content-Length: 19
672 675 Content-Type: text/plain; charset=utf-8 (git-server !)
673 676 Content-Type: application/octet-stream (hg-server !)
674 677 Date: $HTTP_DATE$
675 678 Server: testing stub value (hg-server !)
676 679 lfs: adding d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 to the usercache
677 680 lfs: processed: d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
681 lfs: downloaded 2 files (31 bytes)
678 682 lfs: found 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b in the local lfs store
679 683 THIS-IS-LFS
680 684 lfs: found 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b in the local lfs store
681 685 THIS-IS-LFS
682 686 lfs: found d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 in the local lfs store
683 687 ANOTHER-LARGE-FILE
684 688 nonexistent: no such file in rev dfca2c9e2ef2
685 689
686 690 Revert will prefetch blobs in a group
687 691
688 692 $ rm -rf .hg/store/lfs
689 693 $ rm -rf `hg config lfs.usercache`
690 694 $ rm *
691 695 $ hg revert --all -r 1 --debug
692 696 http auth: user foo, password ***
693 697 adding a
694 698 reverting b
695 699 reverting c
696 700 reverting d
697 701 http auth: user foo, password ***
698 702 Status: 200
699 703 Content-Length: 905 (git-server !)
700 704 Content-Length: 988 (hg-server !)
701 705 Content-Type: application/vnd.git-lfs+json
702 706 Date: $HTTP_DATE$
703 707 Server: testing stub value (hg-server !)
704 708 {
705 709 "objects": [
706 710 {
707 711 "actions": {
708 712 "download": {
709 713 "expires_at": "$ISO_8601_DATE_TIME$"
710 714 "header": {
711 715 "Accept": "application/vnd.git-lfs"
712 716 }
713 717 "href": "http://localhost:$HGPORT/*/31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b" (glob)
714 718 }
715 719 }
716 720 "oid": "31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b"
717 721 "size": 12
718 722 }
719 723 {
720 724 "actions": {
721 725 "download": {
722 726 "expires_at": "$ISO_8601_DATE_TIME$"
723 727 "header": {
724 728 "Accept": "application/vnd.git-lfs"
725 729 }
726 730 "href": "http://localhost:$HGPORT/*/37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19" (glob)
727 731 }
728 732 }
729 733 "oid": "37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19"
730 734 "size": 20
731 735 }
732 736 {
733 737 "actions": {
734 738 "download": {
735 739 "expires_at": "$ISO_8601_DATE_TIME$"
736 740 "header": {
737 741 "Accept": "application/vnd.git-lfs"
738 742 }
739 743 "href": "http://localhost:$HGPORT/*/d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998" (glob)
740 744 }
741 745 }
742 746 "oid": "d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998"
743 747 "size": 19
744 748 }
745 749 ]
746 750 "transfer": "basic" (hg-server !)
747 751 }
748 752 lfs: need to transfer 3 objects (51 bytes)
749 753 lfs: downloading 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b (12 bytes)
750 754 Status: 200
751 755 Content-Length: 12
752 756 Content-Type: text/plain; charset=utf-8 (git-server !)
753 757 Content-Type: application/octet-stream (hg-server !)
754 758 Date: $HTTP_DATE$
755 759 Server: testing stub value (hg-server !)
756 760 lfs: adding 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b to the usercache
757 761 lfs: processed: 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b
758 762 lfs: downloading 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19 (20 bytes)
759 763 Status: 200
760 764 Content-Length: 20
761 765 Content-Type: text/plain; charset=utf-8 (git-server !)
762 766 Content-Type: application/octet-stream (hg-server !)
763 767 Date: $HTTP_DATE$
764 768 Server: testing stub value (hg-server !)
765 769 lfs: adding 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19 to the usercache
766 770 lfs: processed: 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19
767 771 lfs: downloading d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 (19 bytes)
768 772 Status: 200
769 773 Content-Length: 19
770 774 Content-Type: text/plain; charset=utf-8 (git-server !)
771 775 Content-Type: application/octet-stream (hg-server !)
772 776 Date: $HTTP_DATE$
773 777 Server: testing stub value (hg-server !)
774 778 lfs: adding d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 to the usercache
775 779 lfs: processed: d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
780 lfs: downloaded 3 files (51 bytes)
776 781 lfs: found 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b in the local lfs store
777 782 lfs: found d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 in the local lfs store
778 783 lfs: found 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19 in the local lfs store
779 784 lfs: found 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b in the local lfs store
780 785
781 786 Check error message when the remote missed a blob:
782 787
783 788 $ echo FFFFF > b
784 789 $ hg commit -m b -A b
785 790 $ echo FFFFF >> b
786 791 $ hg commit -m b b
787 792 $ rm -rf .hg/store/lfs
788 793 $ rm -rf `hg config lfs.usercache`
789 794 $ hg update -C '.^' --debug
790 795 http auth: user foo, password ***
791 796 resolving manifests
792 797 branchmerge: False, force: True, partial: False
793 798 ancestor: 62fdbaf221c6+, local: 62fdbaf221c6+, remote: ef0564edf47e
794 799 http auth: user foo, password ***
795 800 Status: 200
796 801 Content-Length: 308 (git-server !)
797 802 Content-Length: 186 (hg-server !)
798 803 Content-Type: application/vnd.git-lfs+json
799 804 Date: $HTTP_DATE$
800 805 Server: testing stub value (hg-server !)
801 806 {
802 807 "objects": [
803 808 {
804 809 "actions": { (git-server !)
805 810 "upload": { (git-server !)
806 811 "expires_at": "$ISO_8601_DATE_TIME$" (git-server !)
807 812 "header": { (git-server !)
808 813 "Accept": "application/vnd.git-lfs" (git-server !)
809 814 } (git-server !)
810 815 "href": "http://localhost:$HGPORT/objects/8e6ea5f6c066b44a0efa43bcce86aea73f17e6e23f0663df0251e7524e140a13" (git-server !)
811 816 } (git-server !)
812 817 "error": { (hg-server !)
813 818 "code": 404 (hg-server !)
814 819 "message": "The object does not exist" (hg-server !)
815 820 }
816 821 "oid": "8e6ea5f6c066b44a0efa43bcce86aea73f17e6e23f0663df0251e7524e140a13"
817 822 "size": 6
818 823 }
819 824 ]
820 825 "transfer": "basic" (hg-server !)
821 826 }
822 827 abort: LFS server error for "b": The object does not exist!
823 828 [255]
824 829
825 830 Check error message when object does not exist:
826 831
827 832 $ cd $TESTTMP
828 833 $ hg init test && cd test
829 834 $ echo "[extensions]" >> .hg/hgrc
830 835 $ echo "lfs=" >> .hg/hgrc
831 836 $ echo "[lfs]" >> .hg/hgrc
832 837 $ echo "threshold=1" >> .hg/hgrc
833 838 $ echo a > a
834 839 $ hg add a
835 840 $ hg commit -m 'test'
836 841 $ echo aaaaa > a
837 842 $ hg commit -m 'largefile'
838 843 $ hg debugdata a 1 # verify this is no the file content but includes "oid", the LFS "pointer".
839 844 version https://git-lfs.github.com/spec/v1
840 845 oid sha256:bdc26931acfb734b142a8d675f205becf27560dc461f501822de13274fe6fc8a
841 846 size 6
842 847 x-is-binary 0
843 848 $ cd ..
844 849 $ rm -rf `hg config lfs.usercache`
845 850
846 851 (Restart the server in a different location so it no longer has the content)
847 852
848 853 $ $PYTHON $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
849 854
850 855 #if hg-server
851 856 $ cat $TESTTMP/access.log $TESTTMP/errors.log
852 857 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
853 858 $LOCALIP - - [$LOGDATE$] "PUT /.hg/lfs/objects/31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b HTTP/1.1" 201 - (glob)
854 859 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
855 860 $LOCALIP - - [$LOGDATE$] "GET /.hg/lfs/objects/31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b HTTP/1.1" 200 - (glob)
856 861 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
857 862 $LOCALIP - - [$LOGDATE$] "PUT /.hg/lfs/objects/37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19 HTTP/1.1" 201 - (glob)
858 863 $LOCALIP - - [$LOGDATE$] "PUT /.hg/lfs/objects/d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 HTTP/1.1" 201 - (glob)
859 864 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
860 865 $LOCALIP - - [$LOGDATE$] "GET /.hg/lfs/objects/37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19 HTTP/1.1" 200 - (glob)
861 866 $LOCALIP - - [$LOGDATE$] "GET /.hg/lfs/objects/d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 HTTP/1.1" 200 - (glob)
862 867 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
863 868 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
864 869 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
865 870 $LOCALIP - - [$LOGDATE$] "GET /.hg/lfs/objects/31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b HTTP/1.1" 200 - (glob)
866 871 $LOCALIP - - [$LOGDATE$] "GET /.hg/lfs/objects/37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19 HTTP/1.1" 200 - (glob)
867 872 $LOCALIP - - [$LOGDATE$] "GET /.hg/lfs/objects/d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 HTTP/1.1" 200 - (glob)
868 873 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
869 874 $LOCALIP - - [$LOGDATE$] "GET /.hg/lfs/objects/31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b HTTP/1.1" 200 - (glob)
870 875 $LOCALIP - - [$LOGDATE$] "GET /.hg/lfs/objects/d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 HTTP/1.1" 200 - (glob)
871 876 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
872 877 $LOCALIP - - [$LOGDATE$] "GET /.hg/lfs/objects/31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b HTTP/1.1" 200 - (glob)
873 878 $LOCALIP - - [$LOGDATE$] "GET /.hg/lfs/objects/37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19 HTTP/1.1" 200 - (glob)
874 879 $LOCALIP - - [$LOGDATE$] "GET /.hg/lfs/objects/d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 HTTP/1.1" 200 - (glob)
875 880 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
876 881 #endif
877 882
878 883 $ rm $DAEMON_PIDS
879 884 $ mkdir $TESTTMP/lfs-server2
880 885 $ cd $TESTTMP/lfs-server2
881 886 #if no-windows git-server
882 887 $ lfs-test-server &> lfs-server.log &
883 888 $ echo $! >> $DAEMON_PIDS
884 889 #endif
885 890
886 891 #if windows git-server
887 892 $ $PYTHON $TESTTMP/spawn.py >> $DAEMON_PIDS
888 893 #endif
889 894
890 895 #if hg-server
891 896 $ hg init server2
892 897 $ hg --config "lfs.usercache=$TESTTMP/servercache2" -R server2 serve -d \
893 898 > -p $HGPORT --pid-file=hg.pid -A $TESTTMP/access.log -E $TESTTMP/errors.log
894 899 $ cat hg.pid >> $DAEMON_PIDS
895 900 #endif
896 901
897 902 $ cd $TESTTMP
898 903 $ hg --debug clone test test2
899 904 http auth: user foo, password ***
900 905 linked 6 files
901 906 http auth: user foo, password ***
902 907 updating to branch default
903 908 resolving manifests
904 909 branchmerge: False, force: False, partial: False
905 910 ancestor: 000000000000, local: 000000000000+, remote: d2a338f184a8
906 911 http auth: user foo, password ***
907 912 Status: 200
908 913 Content-Length: 308 (git-server !)
909 914 Content-Length: 186 (hg-server !)
910 915 Content-Type: application/vnd.git-lfs+json
911 916 Date: $HTTP_DATE$
912 917 Server: testing stub value (hg-server !)
913 918 {
914 919 "objects": [
915 920 {
916 921 "actions": { (git-server !)
917 922 "upload": { (git-server !)
918 923 "expires_at": "$ISO_8601_DATE_TIME$" (git-server !)
919 924 "header": { (git-server !)
920 925 "Accept": "application/vnd.git-lfs" (git-server !)
921 926 } (git-server !)
922 927 "href": "http://localhost:$HGPORT/objects/bdc26931acfb734b142a8d675f205becf27560dc461f501822de13274fe6fc8a" (git-server !)
923 928 } (git-server !)
924 929 "error": { (hg-server !)
925 930 "code": 404 (hg-server !)
926 931 "message": "The object does not exist" (hg-server !)
927 932 }
928 933 "oid": "bdc26931acfb734b142a8d675f205becf27560dc461f501822de13274fe6fc8a"
929 934 "size": 6
930 935 }
931 936 ]
932 937 "transfer": "basic" (hg-server !)
933 938 }
934 939 abort: LFS server error for "a": The object does not exist!
935 940 [255]
936 941
937 942 $ $PYTHON $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
General Comments 0
You need to be logged in to leave comments. Login now