def bundle2scratchbranch(op, part): """unbundle a bundle2 part containing a changegroup to store""" bundler = bundle2.bundle20(op.repo.ui) cgversion = part.params.get("cgversion", "01") cgpart = bundle2.bundlepart("changegroup", data=part.read()) cgpart.addparam("version", cgversion) bundler.addpart(cgpart) buf = util.chunkbuffer(bundler.getchunks()) fd, bundlefile = tempfile.mkstemp() try: try: fp = util.fdopen(fd, "wb") fp.write(buf.read()) finally: fp.close() server.storebundle(op, part.params, bundlefile) finally: try: os.unlink(bundlefile) except OSError as e: if e.errno != errno.ENOENT: raise return 1
def _createbundler(ui, repo, other): bundler = bundle2.bundle20(ui, bundle2.bundle2caps(other)) compress = ui.config("infinitepush", "bundlecompression", "UN") bundler.setcompression(compress) # Disallow pushback because we want to avoid taking repo locks. # And we don't need pushback anyway capsblob = bundle2.encodecaps(bundle2.getrepocaps(repo, allowpushback=False)) bundler.newpart("replycaps", data=pycompat.encodeutf8(capsblob)) return bundler
def processparts(orig, repo, op, unbundler): if unbundler.params.get("infinitepush") != "True": return orig(repo, op, unbundler) handleallparts = repo.ui.configbool("infinitepush", "storeallparts") partforwardingwhitelist = [constants.scratchmutationparttype] try: treemfmod = extensions.find("treemanifest") partforwardingwhitelist.append(treemfmod.TREEGROUP_PARTTYPE2) except KeyError: pass try: snapshot = extensions.find("snapshot") partforwardingwhitelist.append(snapshot.bundleparts.snapshotmetadataparttype) except KeyError: pass bundler = bundle2.bundle20(repo.ui) compress = repo.ui.config("infinitepush", "bundlecompression", "UN") bundler.setcompression(compress) cgparams = None scratchbookpart = None with bundle2.partiterator(repo, op, unbundler) as parts: for part in parts: bundlepart = None if part.type == "replycaps": # This configures the current operation to allow reply parts. bundle2._processpart(op, part) elif part.type == constants.scratchbranchparttype: # Scratch branch parts need to be converted to normal # changegroup parts, and the extra parameters stored for later # when we upload to the store. Eventually those parameters will # be put on the actual bundle instead of this part, then we can # send a vanilla changegroup instead of the scratchbranch part. cgversion = part.params.get("cgversion", "01") bundlepart = bundle2.bundlepart("changegroup", data=part.read()) bundlepart.addparam("version", cgversion) cgparams = part.params # If we're not dumping all parts into the new bundle, we need to # alert the future pushkey and phase-heads handler to skip # the part. if not handleallparts: op.records.add( constants.scratchbranchparttype + "_skippushkey", True ) op.records.add( constants.scratchbranchparttype + "_skipphaseheads", True ) elif part.type == constants.scratchbookmarksparttype: # Save this for later processing. Details below. # # Upstream https://phab.mercurial-scm.org/D1389 and its # follow-ups stop part.seek support to reduce memory usage # (https://bz.mercurial-scm.org/5691). So we need to copy # the part so it can be consumed later. scratchbookpart = copiedpart(part) else: if handleallparts or part.type in partforwardingwhitelist: # Ideally we would not process any parts, and instead just # forward them to the bundle for storage, but since this # differs from previous behavior, we need to put it behind a # config flag for incremental rollout. bundlepart = bundle2.bundlepart(part.type, data=part.read()) for key, value in pycompat.iteritems(part.params): bundlepart.addparam(key, value) # Certain parts require a response if part.type == "pushkey": if op.reply is not None: rpart = op.reply.newpart("reply:pushkey") rpart.addparam("in-reply-to", str(part.id), mandatory=False) rpart.addparam("return", "1", mandatory=False) else: bundle2._processpart(op, part) if handleallparts: op.records.add(part.type, {"return": 1}) if bundlepart: bundler.addpart(bundlepart) # If commits were sent, store them if cgparams: buf = util.chunkbuffer(bundler.getchunks()) fd, bundlefile = tempfile.mkstemp() try: try: fp = util.fdopen(fd, "wb") fp.write(buf.read()) finally: fp.close() storebundle(op, cgparams, bundlefile) finally: try: os.unlink(bundlefile) except Exception: # we would rather see the original exception pass # The scratch bookmark part is sent as part of a push backup. It needs to be # processed after the main bundle has been stored, so that any commits it # references are available in the store. if scratchbookpart: bundle2._processpart(op, scratchbookpart)