mercurial/changegroup.py
changeset 26540 7469067de2ba
parent 26509 83d82fbefccb
child 26587 56b2bcea2529
equal deleted inserted replaced
26539:1956026e4db2 26540:7469067de2ba
    90 }
    90 }
    91 
    91 
    92 # hgweb uses this list to communicate its preferred type
    92 # hgweb uses this list to communicate its preferred type
    93 bundlepriority = ['HG10GZ', 'HG10BZ', 'HG10UN']
    93 bundlepriority = ['HG10GZ', 'HG10BZ', 'HG10UN']
    94 
    94 
    95 def writebundle(ui, cg, filename, bundletype, vfs=None, compression=None):
    95 def writechunks(ui, chunks, filename, vfs=None):
    96     """Write a bundle file and return its filename.
    96     """Write chunks to a file and return its filename.
    97 
    97 
       
    98     The stream is assumed to be a bundle file.
    98     Existing files will not be overwritten.
    99     Existing files will not be overwritten.
    99     If no filename is specified, a temporary file is created.
   100     If no filename is specified, a temporary file is created.
   100     bz2 compression can be turned off.
       
   101     The bundle file will be deleted in case of errors.
       
   102     """
   101     """
   103 
       
   104     fh = None
   102     fh = None
   105     cleanup = None
   103     cleanup = None
   106     try:
   104     try:
   107         if filename:
   105         if filename:
   108             if vfs:
   106             if vfs:
   111                 fh = open(filename, "wb")
   109                 fh = open(filename, "wb")
   112         else:
   110         else:
   113             fd, filename = tempfile.mkstemp(prefix="hg-bundle-", suffix=".hg")
   111             fd, filename = tempfile.mkstemp(prefix="hg-bundle-", suffix=".hg")
   114             fh = os.fdopen(fd, "wb")
   112             fh = os.fdopen(fd, "wb")
   115         cleanup = filename
   113         cleanup = filename
   116 
   114         for c in chunks:
   117         if bundletype == "HG20":
   115             fh.write(c)
   118             from . import bundle2
       
   119             bundle = bundle2.bundle20(ui)
       
   120             bundle.setcompression(compression)
       
   121             part = bundle.newpart('changegroup', data=cg.getchunks())
       
   122             part.addparam('version', cg.version)
       
   123             z = util.compressors[None]()
       
   124             chunkiter = bundle.getchunks()
       
   125         else:
       
   126             # compression argument is only for the bundle2 case
       
   127             assert compression is None
       
   128             if cg.version != '01':
       
   129                 raise util.Abort(_('old bundle types only supports v1 '
       
   130                                    'changegroups'))
       
   131             header, comp = bundletypes[bundletype]
       
   132             fh.write(header)
       
   133             if comp not in util.compressors:
       
   134                 raise util.Abort(_('unknown stream compression type: %s')
       
   135                                  % comp)
       
   136             z = util.compressors[comp]()
       
   137             chunkiter = cg.getchunks()
       
   138 
       
   139         # parse the changegroup data, otherwise we will block
       
   140         # in case of sshrepo because we don't know the end of the stream
       
   141 
       
   142         # an empty chunkgroup is the end of the changegroup
       
   143         # a changegroup has at least 2 chunkgroups (changelog and manifest).
       
   144         # after that, an empty chunkgroup is the end of the changegroup
       
   145         for chunk in chunkiter:
       
   146             fh.write(z.compress(chunk))
       
   147         fh.write(z.flush())
       
   148         cleanup = None
   116         cleanup = None
   149         return filename
   117         return filename
   150     finally:
   118     finally:
   151         if fh is not None:
   119         if fh is not None:
   152             fh.close()
   120             fh.close()
   153         if cleanup is not None:
   121         if cleanup is not None:
   154             if filename and vfs:
   122             if filename and vfs:
   155                 vfs.unlink(cleanup)
   123                 vfs.unlink(cleanup)
   156             else:
   124             else:
   157                 os.unlink(cleanup)
   125                 os.unlink(cleanup)
       
   126 
       
   127 def writebundle(ui, cg, filename, bundletype, vfs=None, compression=None):
       
   128     """Write a bundle file and return its filename.
       
   129 
       
   130     Existing files will not be overwritten.
       
   131     If no filename is specified, a temporary file is created.
       
   132     bz2 compression can be turned off.
       
   133     The bundle file will be deleted in case of errors.
       
   134     """
       
   135 
       
   136     if bundletype == "HG20":
       
   137         from . import bundle2
       
   138         bundle = bundle2.bundle20(ui)
       
   139         bundle.setcompression(compression)
       
   140         part = bundle.newpart('changegroup', data=cg.getchunks())
       
   141         part.addparam('version', cg.version)
       
   142         chunkiter = bundle.getchunks()
       
   143     else:
       
   144         # compression argument is only for the bundle2 case
       
   145         assert compression is None
       
   146         if cg.version != '01':
       
   147             raise util.Abort(_('old bundle types only supports v1 '
       
   148                                'changegroups'))
       
   149         header, comp = bundletypes[bundletype]
       
   150         if comp not in util.compressors:
       
   151             raise util.Abort(_('unknown stream compression type: %s')
       
   152                              % comp)
       
   153         z = util.compressors[comp]()
       
   154         subchunkiter = cg.getchunks()
       
   155         def chunkiter():
       
   156             yield header
       
   157             for chunk in subchunkiter:
       
   158                 yield z.compress(chunk)
       
   159             yield z.flush()
       
   160         chunkiter = chunkiter()
       
   161 
       
   162     # parse the changegroup data, otherwise we will block
       
   163     # in case of sshrepo because we don't know the end of the stream
       
   164 
       
   165     # an empty chunkgroup is the end of the changegroup
       
   166     # a changegroup has at least 2 chunkgroups (changelog and manifest).
       
   167     # after that, an empty chunkgroup is the end of the changegroup
       
   168     return writechunks(ui, chunkiter, filename, vfs=vfs)
   158 
   169 
   159 class cg1unpacker(object):
   170 class cg1unpacker(object):
   160     deltaheader = _CHANGEGROUPV1_DELTA_HEADER
   171     deltaheader = _CHANGEGROUPV1_DELTA_HEADER
   161     deltaheadersize = struct.calcsize(deltaheader)
   172     deltaheadersize = struct.calcsize(deltaheader)
   162     version = '01'
   173     version = '01'