def unpack_chunks(hg_unbundle10_obj): """ This method provides a generator of parsed chunks of a "group" in a mercurial unbundle10 object which is created when a changeset that is pushed to a Tool Shed repository using hg push from the command line is read using readbundle. """ while True: length, = struct.unpack('>l', readexactly(hg_unbundle10_obj, 4)) if length <= 4: # We found a "null chunk", which ends the group. break if length < 84: raise Exception("negative data length") node, p1, p2, cs = struct.unpack('20s20s20s20s', readexactly(hg_unbundle10_obj, 80)) yield { 'node': node.encode('hex'), 'p1': p1.encode('hex'), 'p2': p2.encode('hex'), 'cs': cs.encode('hex'), 'data': [ patch for patch in unpack_patches(hg_unbundle10_obj, length - 84) ] }
def readbundle(fh): header = changegroup.readexactly(fh, 4) magic, version = header[0:2], header[2:4] if magic != 'HG': raise Exception('%s: not a Mercurial bundle' % fh.name) if version != '10': raise Exception('%s: unsupported bundle version %s' % (fh.name, version)) alg = changegroup.readexactly(fh, 2) return cg1unpacker(fh, alg)
def _handlechangespec(op, inpart): repo = op.repo cl = repo.changelog # changesets which need to be stripped entirely. either they're no longer # needed in the new narrow spec, or the server is sending a replacement # in the changegroup part. clkills = set() # A changespec part contains all the updates to ellipsis nodes # that will happen as a result of widening or narrowing a # repo. All the changes that this block encounters are ellipsis # nodes or flags to kill an existing ellipsis. chunksignal = changegroup.readexactly(inpart, 4) while chunksignal != _DONESIGNAL: if chunksignal == _KILLNODESIGNAL: # a node used to be an ellipsis but isn't anymore ck = changegroup.readexactly(inpart, 20) if cl.hasnode(ck): clkills.add(ck) else: raise error.Abort( _('unexpected changespec node chunk type: %s') % chunksignal) chunksignal = changegroup.readexactly(inpart, 4) if clkills: # preserve bookmarks that repair.strip() would otherwise strip bmstore = repo._bookmarks class dummybmstore(dict): def applychanges(self, repo, tr, changes): pass def recordchange(self, tr): # legacy version pass repo._bookmarks = dummybmstore() chgrpfile = repair.strip(op.ui, repo, list(clkills), backup=True, topic='widen') repo._bookmarks = bmstore if chgrpfile: op._widen_uninterr = repo.ui.uninterruptable() op._widen_uninterr.__enter__() # presence of _widen_bundle attribute activates widen handler later op._widen_bundle = chgrpfile # Set the new narrowspec if we're widening. The setnewnarrowpats() method # will currently always be there when using the core+narrowhg server, but # other servers may include a changespec part even when not widening (e.g. # because we're deepening a shallow repo). if util.safehasattr(repo, 'setnewnarrowpats'): repo.setnewnarrowpats()
def unpack_groups(fh): """ A generator of parsed groups from a bundle file. Decompress the bundle and discard the magic header before calling this function (i.e. call this function with a "changegroup" as input). Expects bundle format HG10 (the bundle format introduced in Mercurial 1.0). """ yield [chunk for chunk in unpack_chunks(fh)] # the changeloge group yield [chunk for chunk in unpack_chunks(fh)] # the manifest group while True: length, = struct.unpack('>l', readexactly(fh, 4)) if length <= 4: # found a "null meta chunk", which ends the changegroup break filename = readexactly(fh, length - 4).encode('string_escape') yield (filename, [chunk for chunk in unpack_chunks(fh)]) # a file group
def unpack_groups( hg_unbundle10_obj ): """ This method provides a generator of parsed groups from a mercurial unbundle10 object which is created when a changeset that is pushed to a tool shed repository using hg push from the command line is read using readbundle. """ # Process the changelog group. yield [ chunk for chunk in unpack_chunks( hg_unbundle10_obj ) ] # Process the manifest group. yield [ chunk for chunk in unpack_chunks( hg_unbundle10_obj ) ] while True: length, = struct.unpack( '>l', readexactly( hg_unbundle10_obj, 4 ) ) if length <= 4: # We found a "null meta chunk", which ends the changegroup. break filename = readexactly( hg_unbundle10_obj, length-4 ).encode( 'string_escape' ) # Process the file group. yield ( filename, [ chunk for chunk in unpack_chunks( hg_unbundle10_obj ) ] )
def unpack_chunks( hg_unbundle10_obj ): """ This method provides a generator of parsed chunks of a "group" in a mercurial unbundle10 object which is created when a changeset that is pushed to a tool shed repository using hg push from the command line is read using readbundle. """ while True: length, = struct.unpack( '>l', readexactly( hg_unbundle10_obj, 4 ) ) if length <= 4: # We found a "null chunk", which ends the group. break if length < 84: raise Exception( "negative data length" ) node, p1, p2, cs = struct.unpack( '20s20s20s20s', readexactly( hg_unbundle10_obj, 80 ) ) yield { 'node': node.encode( 'hex' ), 'p1': p1.encode( 'hex' ), 'p2': p2.encode( 'hex' ), 'cs': cs.encode( 'hex' ), 'data': [ patch for patch in unpack_patches( hg_unbundle10_obj, length - 84 ) ] }
def unpack_groups(hg_unbundle10_obj): """ This method provides a generator of parsed groups from a mercurial unbundle10 object which is created when a changeset that is pushed to a tool shed repository using hg push from the command line is read using readbundle. """ # Process the changelog group. yield [chunk for chunk in unpack_chunks(hg_unbundle10_obj)] # Process the manifest group. yield [chunk for chunk in unpack_chunks(hg_unbundle10_obj)] while True: length, = struct.unpack('>l', readexactly(hg_unbundle10_obj, 4)) if length <= 4: # We found a "null meta chunk", which ends the changegroup. break filename = readexactly(hg_unbundle10_obj, length - 4).encode('string_escape') # Process the file group. yield (filename, [chunk for chunk in unpack_chunks(hg_unbundle10_obj)])
def unpack_patches( hg_unbundle10_obj, remaining ): """ This method provides a generator of patches from the data field in a chunk. As there is no delimiter for this data field, a length argument is required. """ while remaining >= 12: start, end, blocklen = struct.unpack( '>lll', readexactly( hg_unbundle10_obj, 12 ) ) remaining -= 12 if blocklen > remaining: raise Exception( "unexpected end of patch stream" ) block = readexactly( hg_unbundle10_obj, blocklen ) remaining -= blocklen yield { 'start': start, 'end': end, 'blocklen': blocklen, 'block': block.encode( 'string_escape' ) } if remaining > 0: log.error("Unexpected end of patch stream, %s remaining", remaining) raise Exception( "unexpected end of patch stream" )
def unpack_patches( hg_unbundle10_obj, remaining ): """ This method provides a generator of patches from the data field in a chunk. As there is no delimiter for this data field, a length argument is required. """ while remaining >= 12: start, end, blocklen = struct.unpack( '>lll', readexactly( hg_unbundle10_obj, 12 ) ) remaining -= 12 if blocklen > remaining: raise Exception( "unexpected end of patch stream" ) block = readexactly( hg_unbundle10_obj, blocklen ) remaining -= blocklen yield { 'start': start, 'end': end, 'blocklen': blocklen, 'block': block.encode( 'string_escape' ) } if remaining > 0: print remaining raise Exception( "unexpected end of patch stream" )
def unpack_chunks(fh): """ A generator of parsed chunks of a "group" in a bundle file. Place the input head at the beginning of a group, and this function will yield parsed chunks until the end of the group (a "null chunk"). """ while True: length, = struct.unpack('>l', readexactly(fh, 4)) if length <= 4: # found a "null chunk", which ends the group break if length < 84: raise Exception("negative data length") node, p1, p2, cs = struct.unpack( '20s20s20s20s', readexactly(fh, 80) ) yield { 'node': node.encode('hex') , 'p1': p1.encode('hex') , 'p2': p2.encode('hex') , 'cs': cs.encode('hex') , 'data': [patch for patch in unpack_patches(fh, length - 84)] }
def unpack_patches(fh, remaining): """ A generator of patches from the data field in a chunk. As there is no delimiter for this data field, we require a length argument. """ while remaining >= 12: start, end, blocklen = struct.unpack('>lll', readexactly(fh, 12)) remaining -= 12 if blocklen > remaining: raise Exception("unexpected end of patch stream") block = readexactly(fh, blocklen) remaining -= blocklen yield { 'start': start , 'end': end , 'blocklen': blocklen , 'block': block.encode('string_escape') } if remaining > 0: print remaining raise Exception("unexpected end of patch stream")
def unpack_chunks(fh): """ A generator of parsed chunks of a "group" in a bundle file. Place the input head at the beginning of a group, and this function will yield parsed chunks until the end of the group (a "null chunk"). """ while True: length, = struct.unpack('>l', readexactly(fh, 4)) if length <= 4: # found a "null chunk", which ends the group break if length < 84: raise Exception("negative data length") node, p1, p2, cs = struct.unpack('20s20s20s20s', readexactly(fh, 80)) yield { 'node': node.encode('hex'), 'p1': p1.encode('hex'), 'p2': p2.encode('hex'), 'cs': cs.encode('hex'), 'data': [patch for patch in unpack_patches(fh, length - 84)] }