def test_scrape(self): views.announce(self._build_announce_request_object(ip='1.1.1.1', port='1234', left='0', event='completed')) views.announce(self._build_announce_request_object(ip='2.2.2.2', port='1234', left='200')) # Scrape with info_hash specified query_string = { 'info_hash': SAMPLE_HASH } request = Request(EnvironBuilder( method='GET', query_string=query_string ).get_environ()) response_data = bencode.bdecode(views.scrape(request).data) self.assertEqual(response_data, { 'files': { SAMPLE_HASH: { 'complete': 1, 'downloaded': 1, 'incomplete': 1, } }, }) # Scrape with no info_hash specified request = Request(EnvironBuilder(method='GET').get_environ()) response_data = bencode.bdecode(views.scrape(request).data) self.assertEqual(response_data.get('files').get(SAMPLE_HASH), { 'complete': 1, 'downloaded': 1, 'incomplete': 1, })
def read_revision_from_string(self, text): # TODO: consider writing a Revision decoder, rather than using the # generic bencode decoder # However, to decode all 25k revisions of bzr takes approx 1.3s # If we remove all extra validation that goes down to about 1.2s. # Of that time, probably 0.6s is spend in bencode.bdecode(). # Regardless 'time bzr log' of everything is 7+s, so 1.3s to # extract revision texts isn't a majority of time. ret = bencode.bdecode(text) if not isinstance(ret, list): raise ValueError("invalid revision text") schema = self._schema # timezone is allowed to be missing, but should be set bits = {'timezone': None} for key, value in ret: # Will raise KeyError if not a valid part of the schema, or an # entry is given 2 times. var_name, expected_type, validator = schema[key] if value.__class__ is not expected_type: raise ValueError('key %s did not conform to the expected type' ' %s, but was %s' % (key, expected_type, type(value))) if validator is not None: value = validator(value) bits[var_name] = value if len(bits) != len(schema): missing = [key for key, (var_name, _, _) in schema.iteritems() if var_name not in bits] raise ValueError('Revision text was missing expected keys %s.' ' text %r' % (missing, text)) del bits[None] # Get rid of 'format' since it doesn't get mapped rev = _mod_revision.Revision(**bits) return rev
def _set_revision(self, revision): if revision is None: return self._revision = revision if revision.committer is not None: self.committer.set_text(revision.committer) else: self.committer.set_text("") author = revision.properties.get('author', '') if author != '': self.author.set_text(author) self.author.show() self.author_label.show() else: self.author.hide() self.author_label.hide() if revision.timestamp is not None: self.timestamp.set_text(format_date(revision.timestamp, revision.timezone)) try: self.branchnick.show() self.branchnick_label.show() self.branchnick.set_text(revision.properties['branch-nick']) except KeyError: self.branchnick.hide() self.branchnick_label.hide() self._add_parents_or_children(revision.parent_ids, self.parents_widgets, self.parents_table) file_info = revision.properties.get('file-info', None) if file_info is not None: try: file_info = bdecode(file_info.encode('UTF-8')) except ValueError: trace.note('Invalid per-file info for revision:%s, value: %r', revision.revision_id, file_info) file_info = None if file_info: if self._file_id is None: text = [] for fi in file_info: text.append('%(path)s\n%(message)s' % fi) self.file_info_buffer.set_text('\n'.join(text)) self.file_info_box.show() else: text = [] for fi in file_info: if fi['file_id'] == self._file_id: text.append(fi['message']) if text: self.file_info_buffer.set_text('\n'.join(text)) self.file_info_box.show() else: self.file_info_box.hide() else: self.file_info_box.hide()
def save_commit_messages(local, master, old_revno, old_revid, new_revno, new_revid): b = local if b is None: b = master mgr = SavedCommitMessagesManager(None, b) graph = b.repository.get_graph() revid_iterator = graph.iter_lefthand_ancestry(old_revid) cur_revno = old_revno new_revision_id = old_revid graph = b.repository.get_graph() for rev_id in revid_iterator: if cur_revno == new_revno: break cur_revno -= 1 rev = b.repository.get_revision(rev_id) file_info = rev.properties.get('file-info', None) if file_info is None: file_info = {} else: file_info = bencode.bdecode(file_info.encode('UTF-8')) global_message = osutils.safe_unicode(rev.message) # Concatenate comment of the uncommitted revision mgr.insert(global_message, file_info) parents = graph.get_parent_map([rev_id]).get(rev_id, None) if not parents: continue mgr.save(None, b)
def test_announce(self): response_data = bencode.bdecode(views.announce( self._build_announce_request_object(ip='1.1.1.1', port='1234') ).data) self.assert_( utils.compact('1.1.1.1', 1234)in response_data.get('peers') )
def do_with_locked_branch(self, branch, value_dict, name, section): utf8_dict = bencode.bdecode(value_dict) value_dict = {} for key, value in utf8_dict.items(): value_dict[key.decode('utf8')] = value.decode('utf8') if not section: section = None branch._get_config().set_option(value_dict, name, section) return SuccessfulSmartServerResponse(())
def test_failure(self): # Announce with no info_hash specified request = Request(EnvironBuilder(method='GET').get_environ()) response_data = bencode.bdecode(views.announce(request).data) failure = { 'failure reason': 'Missing info_hash', 'failure code': 101, } self.assertEqual(response_data, failure)
def test_post_announce(self): # Try HTTP POST to announce instead of GET request = Request(EnvironBuilder(method='POST').get_environ()) response_data = bencode.bdecode(views.announce(request).data) failure = { 'failure reason': 'Invalid request type: client request was not a HTTP GET', 'failure code': 100 } self.assertEqual(response_data, failure)
def test_bad_info_hash(self): """ Announcing with an info_hash that's not registed should give a failure """ request = self._build_announce_request_object( info_hash='\x98H\x16\xfd2\x96"\x87n\x14\x90v4&No3.\x9f\xb2' ) response_data = bencode.bdecode(views.announce(request).data) failure = { 'failure reason': 'info_hash not found in the database', 'failure code': 200, } self.assertEqual(response_data, failure)
def decode_progress(self, bencoded_data): """Decodes string of bencoded progress output to list of updates Duplicates logic decoding logic from `SubProcessWidget.readStdout` and `SubProcessWidget.setProgress` which would be good to factor out. """ updates = [] for line in bencoded_data.split("\n"): if line.startswith(SUB_PROGRESS): n, transport_activity, task_info = bencode.bdecode( line[len(SUB_PROGRESS):]) if n == 1000000 and not task_info: task_message = u"Finished!" else: task_message = " / ".join(task_info).decode("utf-8") updates.append((n, transport_activity, task_message)) return updates
def iter_records(self): """Iterate through bundle records :return: a generator of (bytes, metadata, content_kind, revision_id, file_id) """ iterator = pack.iter_records_from_file(self._container_file) for names, bytes in iterator: if len(names) != 1: raise errors.BadBundle('Record has %d names instead of 1' % len(names)) metadata = bencode.bdecode(bytes) if metadata['storage_kind'] == 'header': bytes = None else: _unused, bytes = iterator.next() yield (bytes, metadata) + self.decode_name(names[0][0])
def __init__(self, tree=None, branch=None): """If branch is None, builds empty messages, otherwise reads them from branch's disk storage. 'tree' argument is for the future.""" if branch is None: self.global_message = u'' self.file_messages = {} else: config = branch.get_config() self.global_message = config.get_user_option( 'gtk_global_commit_message', expand=False) if self.global_message is None: self.global_message = u'' file_messages = config.get_user_option( 'gtk_file_commit_messages' , expand=False) if file_messages: # unicode and B-encoded: self.file_messages = bencode.bdecode( file_messages.encode('UTF-8')) else: self.file_messages = {}
def _set_revision(self, revision): if revision is None: return self.avatarsbox.reset() self._revision = revision if revision.committer is not None: self.committer.set_text(revision.committer) self.avatarsbox.add(revision.committer, "committer") else: self.committer.set_text("") self.avatarsbox.hide() author = revision.properties.get("author", "") self.avatarsbox.merge(revision.get_apparent_authors(), "author") if author != "": self.author.set_text(author) self.author.show() self.author_label.show() else: self.author.hide() self.author_label.hide() if revision.timestamp is not None: self.timestamp.set_text(format_date(revision.timestamp, revision.timezone)) try: self.branchnick.show() self.branchnick_label.show() self.branchnick.set_text(revision.properties["branch-nick"]) except KeyError: self.branchnick.hide() self.branchnick_label.hide() self._add_parents_or_children(revision.parent_ids, self.parents_widgets, self.parents_table) file_info = revision.properties.get("file-info", None) if file_info is not None: try: file_info = bdecode(file_info.encode("UTF-8")) except ValueError: trace.note("Invalid per-file info for revision:%s, value: %r", revision.revision_id, file_info) file_info = None if file_info: if self._file_id is None: text = [] for fi in file_info: text.append("%(path)s\n%(message)s" % fi) self.file_info_buffer.set_text("\n".join(text)) self.file_info_box.show() else: text = [] for fi in file_info: if fi["file_id"] == self._file_id: text.append(fi["message"]) if text: self.file_info_buffer.set_text("\n".join(text)) self.file_info_box.show() else: self.file_info_box.hide() else: self.file_info_box.hide()
def export_branch(repo, name): ref = '%s/heads/%s' % (prefix, name) tip = marks.get_tip(name) branch = get_remote_branch(name) repo = branch.repository branch.lock_read() revs = branch.iter_merge_sorted_revisions(None, tip, 'exclude', 'forward') try: tip_revno = branch.revision_id_to_revno(tip) last_revno, _ = branch.last_revision_info() total = last_revno - tip_revno except bzrlib.errors.NoSuchRevision: tip_revno = 0 total = 0 for revid, _, seq, _ in revs: if marks.is_marked(revid): continue rev = repo.get_revision(revid) revno = seq[0] parents = rev.parent_ids time = rev.timestamp tz = rev.timezone committer = rev.committer.encode('utf-8') committer = "%s %u %s" % (fixup_user(committer), time, gittz(tz)) authors = rev.get_apparent_authors() if authors: author = authors[0].encode('utf-8') author = "%s %u %s" % (fixup_user(author), time, gittz(tz)) else: author = committer msg = rev.message.encode('utf-8') msg += '\n' if rev.properties.has_key('file-info'): from bzrlib import bencode try: files = bencode.bdecode(rev.properties['file-info'].encode('utf-8')) except Exception, e: # protect against repository corruption # (happens in the wild, see MySQL tree) files = () rmsg = msg.rstrip('\r\n ') file_comments = [] for file in files: fmsg = file['message'].rstrip('\r\n ') # Skip empty file comments and file comments identical to the # commit comment (they originate from tools and policies that # require writing per-file comments and users simply copy-paste # revision comment over, these comments add no value as a part of # the commit comment). if fmsg == '' or fmsg == rmsg: continue file_comments.append(file['path'] + ':') for l in fmsg.split('\n'): file_comments.append(' ' + l) msg += '\n' + '\n'.join(file_comments) + '\n' if len(parents) == 0: parent = bzrlib.revision.NULL_REVISION else: parent = parents[0] cur_tree = repo.revision_tree(revid) prev = repo.revision_tree(parent) modified, removed = get_filechanges(cur_tree, prev) modified_final = export_files(cur_tree, modified) if len(parents) == 0: print 'reset %s' % ref print "commit %s" % ref print "mark :%d" % (marks.get_mark(revid)) print "author %s" % (author) print "committer %s" % (committer) print "data %d" % (len(msg)) print msg for i, p in enumerate(parents): try: m = rev_to_mark(p) except KeyError: # ghost? continue if i == 0: print "from :%s" % m else: print "merge :%s" % m for f in removed: print "D %s" % (f,) for f in modified_final: print "M %s :%u %s" % f print if len(seq) > 1: # let's skip branch revisions from the progress report continue progress = (revno - tip_revno) if (progress % 100 == 0): if total: print "progress revision %d '%s' (%d/%d)" % (revno, name, progress, total) else: print "progress revision %d '%s' (%d)" % (revno, name, progress)
def export_branch(repo, name): ref = '%s/heads/%s' % (prefix, name) tip = marks.get_tip(name) branch = get_remote_branch(name) repo = branch.repository branch.lock_read() revs = branch.iter_merge_sorted_revisions(None, tip, 'exclude', 'forward') try: tip_revno = branch.revision_id_to_revno(tip) last_revno, _ = branch.last_revision_info() total = last_revno - tip_revno except bzrlib.errors.NoSuchRevision: tip_revno = 0 total = 0 for revid, _, seq, _ in revs: if marks.is_marked(revid): continue rev = repo.get_revision(revid) revno = seq[0] parents = rev.parent_ids time = rev.timestamp tz = rev.timezone committer = rev.committer.encode('utf-8') committer = "%s %u %s" % (fixup_user(committer), time, gittz(tz)) authors = rev.get_apparent_authors() if authors: author = authors[0].encode('utf-8') author = "%s %u %s" % (fixup_user(author), time, gittz(tz)) else: author = committer msg = rev.message.encode('utf-8') msg += '\n' if rev.properties.has_key('file-info'): from bzrlib import bencode try: files = bencode.bdecode( rev.properties['file-info'].encode('utf-8')) except Exception, e: # protect against repository corruption # (happens in the wild, see MySQL tree) files = () rmsg = msg.rstrip('\r\n ') file_comments = [] for file in files: fmsg = file['message'].rstrip('\r\n ') # Skip empty file comments and file comments identical to the # commit comment (they originate from tools and policies that # require writing per-file comments and users simply copy-paste # revision comment over, these comments add no value as a part of # the commit comment). if fmsg == '' or fmsg == rmsg: continue file_comments.append(file['path'] + ':') for l in fmsg.split('\n'): file_comments.append(' ' + l) msg += '\n' + '\n'.join(file_comments) + '\n' if len(parents) == 0: parent = bzrlib.revision.NULL_REVISION else: parent = parents[0] cur_tree = repo.revision_tree(revid) prev = repo.revision_tree(parent) modified, removed = get_filechanges(cur_tree, prev) modified_final = export_files(cur_tree, modified) if len(parents) == 0: print 'reset %s' % ref print "commit %s" % ref print "mark :%d" % (marks.get_mark(revid)) print "author %s" % (author) print "committer %s" % (committer) print "data %d" % (len(msg)) print msg for i, p in enumerate(parents): try: m = rev_to_mark(p) except KeyError: # ghost? continue if i == 0: print "from :%s" % m else: print "merge :%s" % m for f in removed: print "D %s" % (f, ) for f in modified_final: print "M %s :%u %s" % f print if len(seq) > 1: # let's skip branch revisions from the progress report continue progress = (revno - tip_revno) if (progress % 100 == 0): if total: print "progress revision %d '%s' (%d/%d)" % (revno, name, progress, total) else: print "progress revision %d '%s' (%d)" % (revno, name, progress)
def _torrent_to_dict(data): dictionary = bencode.bdecode(data) dictionary['info']['pieces'] = binascii.hexlify( dictionary['info']['pieces'] ) return unicode_dict(dictionary)
def _info_hash(self): return sha1(bencode.bencode( bencode.bdecode(self.torrent_file).get('info') )).hexdigest()