##// END OF EJS Templates
remotefilelogserver: remove pack-serving functionality...
Augie Fackler -
r40538:3b900876 default
parent child Browse files
Show More
@@ -12,16 +12,14 b' import stat'
12 import time
12 import time
13
13
14 from mercurial.i18n import _
14 from mercurial.i18n import _
15 from mercurial.node import bin, hex, nullid, nullrev
15 from mercurial.node import bin, hex, nullid
16 from mercurial import (
16 from mercurial import (
17 ancestor,
18 changegroup,
17 changegroup,
19 changelog,
18 changelog,
20 context,
19 context,
21 error,
20 error,
22 extensions,
21 extensions,
23 match,
22 match,
24 pycompat,
25 store,
23 store,
26 streamclone,
24 streamclone,
27 util,
25 util,
@@ -30,11 +28,9 b' from mercurial import ('
30 wireprotov1server,
28 wireprotov1server,
31 )
29 )
32 from . import (
30 from . import (
33 constants,
34 lz4wrapper,
31 lz4wrapper,
35 shallowrepo,
32 shallowrepo,
36 shallowutil,
33 shallowutil,
37 wirepack,
38 )
34 )
39
35
40 _sshv1server = wireprotoserver.sshv1protocolhandler
36 _sshv1server = wireprotoserver.sshv1protocolhandler
@@ -86,8 +82,6 b' def onetimesetup(ui):'
86 'getfiles', '', permission='pull')(getfiles)
82 'getfiles', '', permission='pull')(getfiles)
87 wireprotov1server.wireprotocommand(
83 wireprotov1server.wireprotocommand(
88 'getfile', 'file node', permission='pull')(getfile)
84 'getfile', 'file node', permission='pull')(getfile)
89 wireprotov1server.wireprotocommand(
90 'getpackv1', '*', permission='pull')(getpack)
91
85
92 class streamstate(object):
86 class streamstate(object):
93 match = None
87 match = None
@@ -421,134 +415,3 b' def gcserver(ui, repo):'
421 os.remove(filepath)
415 os.remove(filepath)
422
416
423 ui.progress(_removing, None)
417 ui.progress(_removing, None)
424
425 def getpack(repo, proto, args):
426 """A server api for requesting a pack of file information.
427 """
428 if shallowrepo.requirement in repo.requirements:
429 raise error.Abort(_('cannot fetch remote files from shallow repo'))
430 if not isinstance(proto, _sshv1server):
431 raise error.Abort(_('cannot fetch remote files over non-ssh protocol'))
432
433 def streamer():
434 """Request format:
435
436 [<filerequest>,...]\0\0
437 filerequest = <filename len: 2 byte><filename><count: 4 byte>
438 [<node: 20 byte>,...]
439
440 Response format:
441 [<fileresponse>,...]<10 null bytes>
442 fileresponse = <filename len: 2 byte><filename><history><deltas>
443 history = <count: 4 byte>[<history entry>,...]
444 historyentry = <node: 20 byte><p1: 20 byte><p2: 20 byte>
445 <linknode: 20 byte><copyfrom len: 2 byte><copyfrom>
446 deltas = <count: 4 byte>[<delta entry>,...]
447 deltaentry = <node: 20 byte><deltabase: 20 byte>
448 <delta len: 8 byte><delta>
449 """
450 fin = proto._fin
451 files = _receivepackrequest(fin)
452
453 # Sort the files by name, so we provide deterministic results
454 for filename, nodes in sorted(files.iteritems()):
455 fl = repo.file(filename)
456
457 # Compute history
458 history = []
459 for rev in ancestor.lazyancestors(fl.parentrevs,
460 [fl.rev(n) for n in nodes],
461 inclusive=True):
462 linkrev = fl.linkrev(rev)
463 node = fl.node(rev)
464 p1node, p2node = fl.parents(node)
465 copyfrom = ''
466 linknode = repo.changelog.node(linkrev)
467 if p1node == nullid:
468 copydata = fl.renamed(node)
469 if copydata:
470 copyfrom, copynode = copydata
471 p1node = copynode
472
473 history.append((node, p1node, p2node, linknode, copyfrom))
474
475 # Scan and send deltas
476 chain = _getdeltachain(fl, nodes, -1)
477
478 for chunk in wirepack.sendpackpart(filename, history, chain):
479 yield chunk
480
481 yield wirepack.closepart()
482 proto._fout.flush()
483
484 return wireprototypes.streamres(streamer())
485
486 def _receivepackrequest(stream):
487 files = {}
488 while True:
489 filenamelen = shallowutil.readunpack(stream,
490 constants.FILENAMESTRUCT)[0]
491 if filenamelen == 0:
492 break
493
494 filename = shallowutil.readexactly(stream, filenamelen)
495
496 nodecount = shallowutil.readunpack(stream,
497 constants.PACKREQUESTCOUNTSTRUCT)[0]
498
499 # Read N nodes
500 nodes = shallowutil.readexactly(stream, constants.NODESIZE * nodecount)
501 nodes = set(nodes[i:i + constants.NODESIZE] for i in
502 pycompat.xrange(0, len(nodes), constants.NODESIZE))
503
504 files[filename] = nodes
505
506 return files
507
508 def _getdeltachain(fl, nodes, stophint):
509 """Produces a chain of deltas that includes each of the given nodes.
510
511 `stophint` - The changeset rev number to stop at. If it's set to >= 0, we
512 will return not only the deltas for the requested nodes, but also all
513 necessary deltas in their delta chains, as long as the deltas have link revs
514 >= the stophint. This allows us to return an approximately minimal delta
515 chain when the user performs a pull. If `stophint` is set to -1, all nodes
516 will return full texts. """
517 chain = []
518
519 seen = set()
520 for node in nodes:
521 startrev = fl.rev(node)
522 cur = startrev
523 while True:
524 if cur in seen:
525 break
526 base = fl._revlog.deltaparent(cur)
527 linkrev = fl.linkrev(cur)
528 node = fl.node(cur)
529 p1, p2 = fl.parentrevs(cur)
530 if linkrev < stophint and cur != startrev:
531 break
532
533 # Return a full text if:
534 # - the caller requested it (via stophint == -1)
535 # - the revlog chain has ended (via base==null or base==node)
536 # - p1 is null. In some situations this can mean it's a copy, so
537 # we need to use fl.read() to remove the copymetadata.
538 if (stophint == -1 or base == nullrev or base == cur
539 or p1 == nullrev):
540 delta = fl.read(cur)
541 base = nullrev
542 else:
543 delta = fl._chunk(cur)
544
545 basenode = fl.node(base)
546 chain.append((node, basenode, delta))
547 seen.add(cur)
548
549 if base == nullrev:
550 break
551 cur = base
552
553 chain.reverse()
554 return chain
General Comments 0
You need to be logged in to leave comments. Login now