mercurial/wireproto.py
changeset 11627 04f76a954842
parent 11625 cdeb861335d5
child 11879 4e804302d30c
equal deleted inserted replaced
11626:2f8adc60e013 11627:04f76a954842
     7 
     7 
     8 import urllib, tempfile, os
     8 import urllib, tempfile, os
     9 from i18n import _
     9 from i18n import _
    10 from node import bin, hex
    10 from node import bin, hex
    11 import changegroup as changegroupmod
    11 import changegroup as changegroupmod
    12 import streamclone, repo, error, encoding, util
    12 import repo, error, encoding, util, store
    13 import pushkey as pushkey_
    13 import pushkey as pushkey_
    14 
    14 
    15 # list of nodes encoding / decoding
    15 # list of nodes encoding / decoding
    16 
    16 
    17 def decodelist(l, sep=' '):
    17 def decodelist(l, sep=' '):
   169         r.append(encodelist(b) + "\n")
   169         r.append(encodelist(b) + "\n")
   170     return "".join(r)
   170     return "".join(r)
   171 
   171 
   172 def capabilities(repo, proto):
   172 def capabilities(repo, proto):
   173     caps = 'lookup changegroupsubset branchmap pushkey'.split()
   173     caps = 'lookup changegroupsubset branchmap pushkey'.split()
   174     if streamclone.allowed(repo.ui):
   174     if _allowstream(repo.ui):
   175         caps.append('stream=%d' % repo.changelog.version)
   175         caps.append('stream=%d' % repo.changelog.version)
   176     caps.append('unbundle=%s' % ','.join(changegroupmod.bundlepriority))
   176     caps.append('unbundle=%s' % ','.join(changegroupmod.bundlepriority))
   177     return ' '.join(caps)
   177     return ' '.join(caps)
   178 
   178 
   179 def changegroup(repo, proto, roots):
   179 def changegroup(repo, proto, roots):
   218 
   218 
   219 def pushkey(repo, proto, namespace, key, old, new):
   219 def pushkey(repo, proto, namespace, key, old, new):
   220     r = pushkey_.push(repo, namespace, key, old, new)
   220     r = pushkey_.push(repo, namespace, key, old, new)
   221     return '%s\n' % int(r)
   221     return '%s\n' % int(r)
   222 
   222 
       
   223 def _allowstream(ui):
       
   224     return ui.configbool('server', 'uncompressed', True, untrusted=True)
       
   225 
   223 def stream(repo, proto):
   226 def stream(repo, proto):
   224     return streamres(streamclone.stream_out(repo))
   227     '''If the server supports streaming clone, it advertises the "stream"
       
   228     capability with a value representing the version and flags of the repo
       
   229     it is serving. Client checks to see if it understands the format.
       
   230 
       
   231     The format is simple: the server writes out a line with the amount
       
   232     of files, then the total amount of bytes to be transfered (separated
       
   233     by a space). Then, for each file, the server first writes the filename
       
   234     and filesize (separated by the null character), then the file contents.
       
   235     '''
       
   236 
       
   237     if not _allowstream(repo.ui):
       
   238         return '1\n'
       
   239 
       
   240     entries = []
       
   241     total_bytes = 0
       
   242     try:
       
   243         # get consistent snapshot of repo, lock during scan
       
   244         lock = repo.lock()
       
   245         try:
       
   246             repo.ui.debug('scanning\n')
       
   247             for name, ename, size in repo.store.walk():
       
   248                 entries.append((name, size))
       
   249                 total_bytes += size
       
   250         finally:
       
   251             lock.release()
       
   252     except error.LockError:
       
   253         return '2\n' # error: 2
       
   254 
       
   255     def streamer(repo, entries, total):
       
   256         '''stream out all metadata files in repository.'''
       
   257         yield '0\n' # success
       
   258         repo.ui.debug('%d files, %d bytes to transfer\n' %
       
   259                       (len(entries), total_bytes))
       
   260         yield '%d %d\n' % (len(entries), total_bytes)
       
   261         for name, size in entries:
       
   262             repo.ui.debug('sending %s (%d bytes)\n' % (name, size))
       
   263             # partially encode name over the wire for backwards compat
       
   264             yield '%s\0%d\n' % (store.encodedir(name), size)
       
   265             for chunk in util.filechunkiter(repo.sopener(name), limit=size):
       
   266                 yield chunk
       
   267 
       
   268     return streamres(streamer(repo, entries, total_bytes))
   225 
   269 
   226 def unbundle(repo, proto, heads):
   270 def unbundle(repo, proto, heads):
   227     their_heads = decodelist(heads)
   271     their_heads = decodelist(heads)
   228 
   272 
   229     def check_heads():
   273     def check_heads():