def test_unicode_commit_message_is_filename(self): """Unicode commit message same as a filename (Bug #563646). """ self.requireFeature(features.UnicodeFilenameFeature) file_name = u'\N{euro sign}' self.run_bzr(['init']) with open(file_name, 'w') as f: f.write('hello world') self.run_bzr(['add']) out, err = self.run_bzr(['commit', '-m', file_name]) reflags = re.MULTILINE|re.DOTALL|re.UNICODE te = osutils.get_terminal_encoding() self.assertContainsRe(err.decode(te), u'The commit message is a file name:', flags=reflags) # Run same test with a filename that causes encode # error for the terminal encoding. We do this # by forcing terminal encoding of ascii for # osutils.get_terminal_encoding which is used # by ui.text.show_warning default_get_terminal_enc = osutils.get_terminal_encoding try: osutils.get_terminal_encoding = lambda trace=None: 'ascii' file_name = u'foo\u1234' with open(file_name, 'w') as f: f.write('hello world') self.run_bzr(['add']) out, err = self.run_bzr(['commit', '-m', file_name]) reflags = re.MULTILINE|re.DOTALL|re.UNICODE te = osutils.get_terminal_encoding() self.assertContainsRe(err.decode(te, 'replace'), u'The commit message is a file name:', flags=reflags) finally: osutils.get_terminal_encoding = default_get_terminal_enc
def test_get_terminal_encoding_trace(self): self.make_wrapped_streams('stdout_encoding', 'stderr_encoding', 'stdin_encoding') # Calling get_terminal_encoding should not mutter when silent=True is # passed. log = self.get_log() osutils.get_terminal_encoding(trace=True) self.assertNotEqual(log, self.get_log())
def test_get_terminal_encoding(self): self.make_wrapped_streams('stdout_encoding', 'stderr_encoding', 'stdin_encoding') # first preference is stdout encoding self.assertEqual('stdout_encoding', osutils.get_terminal_encoding()) sys.stdout.encoding = None # if sys.stdout is None, fall back to sys.stdin self.assertEqual('stdin_encoding', osutils.get_terminal_encoding()) sys.stdin.encoding = None # and in the worst case, use bzrlib.user_encoding self.assertEqual('user_encoding', osutils.get_terminal_encoding())
def create_base(self): fs_enc = sys.getfilesystemencoding() terminal_enc = osutils.get_terminal_encoding() fname = self.info['filename'] dir_name = self.info['directory'] for thing in [fname, dir_name]: try: thing.encode(fs_enc) except UnicodeEncodeError: raise TestSkipped( ('Unable to represent path %r' ' in filesystem encoding "%s"') % (thing, fs_enc)) try: thing.encode(terminal_enc) except UnicodeEncodeError: raise TestSkipped(('Unable to represent path %r' ' in terminal encoding "%s"' ' (even though it is valid in' ' filesystem encoding "%s")') % (thing, terminal_enc, fs_enc)) wt = self.make_branch_and_tree('.') self.build_tree_contents([('a', 'foo\n')]) wt.add('a') wt.commit('adding a') self.build_tree_contents([('b', 'non-ascii \xFF\xFF\xFC\xFB\x00 in b\n')]) wt.add('b') wt.commit(self.info['message']) self.build_tree_contents([(fname, 'unicode filename\n')]) wt.add(fname) wt.commit(u'And a unicode file\n') self.wt = wt
def annotate_file_xml(branch, rev_id, file_id, to_file=None, show_ids=False, wt_root_path=None, file_path=None, full=False): """custom annotate_file that spits xml """ if to_file is None: to_file = sys.stdout encoding = getattr(to_file, 'encoding', None) or \ osutils.get_terminal_encoding() prevanno = '' last_rev_id = None to_file.write('<?xml version="1.0"?>') to_file.write(('<annotation workingtree-root="%s" %s>' % \ (wt_root_path, 'file="%s"' % file_path)).encode(encoding, 'replace')) if _annotate_file: # bzr < 1.8 annotations = _annotations(branch.repository, file_id, rev_id) annotation = list(_annotate_file(branch, rev_id, file_id)) else: tree = branch.repository.revision_tree(rev_id) annotations = tree.annotate_iter(file_id) annotation = list(_expand_annotations(annotations, branch)) for (revno_str, author, date_str, line_rev_id, text, origin) in _annotation_iter(annotation, annotations): if not show_ids: origin = None prevanno = _show_entry(to_file, prevanno, revno_str, author, date_str, line_rev_id, text, origin) to_file.write('</annotation>')
def get_parsed_patch(self, file_id, invert=False): """Return a parsed version of a file's patch. :param file_id: The id of the file to generate a patch for. :param invert: If True, provide an inverted patch (insertions displayed as removals, removals displayed as insertions). :return: A patches.Patch. """ diff_file = StringIO() if invert: old_tree = self.work_tree new_tree = self.target_tree else: old_tree = self.target_tree new_tree = self.work_tree old_path = old_tree.id2path(file_id) new_path = new_tree.id2path(file_id) text_differ = diff.DiffText( old_tree, new_tree, diff_file, path_encoding=osutils.get_terminal_encoding()) patch = text_differ.diff(file_id, old_path, new_path, 'file', 'file') diff_file.seek(0) return patches.parse_patch(diff_file)
def create_base(self): fs_enc = sys.getfilesystemencoding() terminal_enc = osutils.get_terminal_encoding() fname = self.info['filename'] dir_name = self.info['directory'] for thing in [fname, dir_name]: try: thing.encode(fs_enc) except UnicodeEncodeError: raise TestSkipped(('Unable to represent path %r' ' in filesystem encoding "%s"') % (thing, fs_enc)) try: thing.encode(terminal_enc) except UnicodeEncodeError: raise TestSkipped(('Unable to represent path %r' ' in terminal encoding "%s"' ' (even though it is valid in' ' filesystem encoding "%s")') % (thing, terminal_enc, fs_enc)) wt = self.make_branch_and_tree('.') self.build_tree_contents([('a', 'foo\n')]) wt.add('a') wt.commit('adding a') self.build_tree_contents( [('b', 'non-ascii \xFF\xFF\xFC\xFB\x00 in b\n')]) wt.add('b') wt.commit(self.info['message']) self.build_tree_contents([(fname, 'unicode filename\n')]) wt.add(fname) wt.commit(u'And a unicode file\n') self.wt = wt
def run(self, location, verbose=False): from bzrlib.bundle.serializer import read_bundle from bzrlib.bundle import read_mergeable_from_url from bzrlib import osutils term_encoding = osutils.get_terminal_encoding() bundle_info = read_mergeable_from_url(location) if isinstance(bundle_info, merge_directive._BaseMergeDirective): bundle_file = StringIO(bundle_info.get_raw_bundle()) bundle_info = read_bundle(bundle_file) else: if verbose: raise errors.BzrCommandError('--verbose requires a merge' ' directive') reader_method = getattr(bundle_info, 'get_bundle_reader', None) if reader_method is None: raise errors.BzrCommandError('Bundle format not supported') by_kind = {} file_ids = set() for bytes, parents, repo_kind, revision_id, file_id\ in reader_method().iter_records(): by_kind.setdefault(repo_kind, []).append( (bytes, parents, repo_kind, revision_id, file_id)) if file_id is not None: file_ids.add(file_id) self.outf.write('Records\n') for kind, records in sorted(by_kind.iteritems()): multiparent = sum(1 for b, m, k, r, f in records if len(m.get('parents', [])) > 1) self.outf.write('%s: %d (%d multiparent)\n' % \ (kind, len(records), multiparent)) self.outf.write('unique files: %d\n' % len(file_ids)) self.outf.write('\n') nicks = set() committers = set() for revision in bundle_info.real_revisions: if 'branch-nick' in revision.properties: nicks.add(revision.properties['branch-nick']) committers.add(revision.committer) self.outf.write('Revisions\n') self.outf.write(('nicks: %s\n' % ', '.join(sorted(nicks))).encode( term_encoding, 'replace')) self.outf.write( ('committers: \n%s\n' % '\n'.join(sorted(committers)).encode(term_encoding, 'replace'))) if verbose: self.outf.write('\n') bundle_file.seek(0) line = bundle_file.readline() line = bundle_file.readline() content = bundle_file.read().decode('bz2') self.outf.write("Decoded contents\n") self.outf.write(content) self.outf.write('\n')
def run(self, location, verbose=False): from bzrlib.bundle.serializer import read_bundle from bzrlib.bundle import read_mergeable_from_url from bzrlib import osutils term_encoding = osutils.get_terminal_encoding() bundle_info = read_mergeable_from_url(location) if isinstance(bundle_info, merge_directive.BaseMergeDirective): bundle_file = StringIO(bundle_info.get_raw_bundle()) bundle_info = read_bundle(bundle_file) else: if verbose: raise errors.BzrCommandError(gettext( '--verbose requires a merge directive')) reader_method = getattr(bundle_info, 'get_bundle_reader', None) if reader_method is None: raise errors.BzrCommandError(gettext('Bundle format not supported')) by_kind = {} file_ids = set() for bytes, parents, repo_kind, revision_id, file_id\ in reader_method().iter_records(): by_kind.setdefault(repo_kind, []).append( (bytes, parents, repo_kind, revision_id, file_id)) if file_id is not None: file_ids.add(file_id) self.outf.write(gettext('Records\n')) for kind, records in sorted(by_kind.iteritems()): multiparent = sum(1 for b, m, k, r, f in records if len(m.get('parents', [])) > 1) self.outf.write(gettext('{0}: {1} ({2} multiparent)\n').format( kind, len(records), multiparent)) self.outf.write(gettext('unique files: %d\n') % len(file_ids)) self.outf.write('\n') nicks = set() committers = set() for revision in bundle_info.real_revisions: if 'branch-nick' in revision.properties: nicks.add(revision.properties['branch-nick']) committers.add(revision.committer) self.outf.write(gettext('Revisions\n')) self.outf.write((gettext('nicks: %s\n') % ', '.join(sorted(nicks))).encode(term_encoding, 'replace')) self.outf.write((gettext('committers: \n%s\n') % '\n'.join(sorted(committers)).encode(term_encoding, 'replace'))) if verbose: self.outf.write('\n') bundle_file.seek(0) line = bundle_file.readline() line = bundle_file.readline() content = bundle_file.read().decode('bz2') self.outf.write(gettext("Decoded contents\n")) self.outf.write(content) self.outf.write('\n')
def show_changed_revisions(branch, old_rh, new_rh, to_file=None, log_format='long'): """Show the change in revision history comparing the old revision history to the new one. :param branch: The branch where the revisions exist :param old_rh: The old revision history :param new_rh: The new revision history :param to_file: A file to write the results to. If None, stdout will be used """ if to_file is None: to_file = codecs.getwriter(get_terminal_encoding())(sys.stdout, errors='replace') lf = log_formatter(log_format, show_ids=False, to_file=to_file, show_timezone='original') # This is the first index which is different between # old and new base_idx = None for i in xrange(max(len(new_rh), len(old_rh))): if (len(new_rh) <= i or len(old_rh) <= i or new_rh[i] != old_rh[i]): base_idx = i break if base_idx is None: to_file.write('Nothing seems to have changed\n') return ## TODO: It might be nice to do something like show_log ## and show the merged entries. But since this is the ## removed revisions, it shouldn't be as important if base_idx < len(old_rh): to_file.write('*'*60) to_file.write('\nRemoved Revisions:\n') for i in range(base_idx, len(old_rh)): rev = branch.repository.get_revision(old_rh[i]) lr = LogRevision(rev, i+1, 0, None) lf.log_revision(lr) to_file.write('*'*60) to_file.write('\n\n') if base_idx < len(new_rh): to_file.write('Added Revisions:\n') show_log(branch, lf, None, verbose=False, direction='forward', start_revision=base_idx+1, end_revision=len(new_rh), search=None)
def test_terminal_cp0(self): # test cp0 encoding (Windows returns cp0 when there is no encoding) self.make_wrapped_streams('cp0', 'cp0', 'cp0', user_encoding='latin-1', enable_fake_encodings=False) # cp0 is invalid encoding. We should fall back to user_encoding self.assertEqual('latin-1', osutils.get_terminal_encoding()) # check stderr self.assertEquals('', sys.stderr.getvalue())
def test_terminal_cp_unknown(self): # test against really unknown encoding # catch warning at stderr self.make_wrapped_streams('cp-unknown', 'cp-unknown', 'cp-unknown', user_encoding='latin-1', enable_fake_encodings=False) self.assertEqual('latin-1', osutils.get_terminal_encoding()) # check stderr self.assertEquals('bzr: warning: unknown terminal encoding cp-unknown.\n' ' Using encoding latin-1 instead.\n', sys.stderr.getvalue())
def main(argv=[]): server = Server("http://localhost:11111") try: args = ['bzr'] [args.append(arg) for arg in argv[1:]] exit_val, out, err = server.run_bzr_command(args, os.getcwd()) outf = setup_outf() outf.write(out.data.decode(osutils.get_terminal_encoding(), 'replace')) sys.stderr.write(err) outf.flush(); sys.stderr.flush(); sys.exit(exit_val) except Error, exc: sys.stderr.write(exc.__repr__()) raise
def test_unicode_commit_message_is_filename(self): """Unicode commit message same as a filename (Bug #563646). """ self.requireFeature(features.UnicodeFilenameFeature) file_name = u'\N{euro sign}' self.run_bzr(['init']) with open(file_name, 'w') as f: f.write('hello world') self.run_bzr(['add']) out, err = self.run_bzr(['commit', '-m', file_name]) reflags = re.MULTILINE | re.DOTALL | re.UNICODE te = osutils.get_terminal_encoding() self.assertContainsRe(err.decode(te), u'The commit message is a file name:', flags=reflags) # Run same test with a filename that causes encode # error for the terminal encoding. We do this # by forcing terminal encoding of ascii for # osutils.get_terminal_encoding which is used # by ui.text.show_warning default_get_terminal_enc = osutils.get_terminal_encoding try: osutils.get_terminal_encoding = lambda trace=None: 'ascii' file_name = u'foo\u1234' with open(file_name, 'w') as f: f.write('hello world') self.run_bzr(['add']) out, err = self.run_bzr(['commit', '-m', file_name]) reflags = re.MULTILINE | re.DOTALL | re.UNICODE te = osutils.get_terminal_encoding() self.assertContainsRe(err.decode(te, 'replace'), u'The commit message is a file name:', flags=reflags) finally: osutils.get_terminal_encoding = default_get_terminal_enc
def main(argv=[]): server = Server("http://localhost:11111") try: args = ['bzr'] [args.append(arg) for arg in argv[1:]] exit_val, out, err = server.run_bzr_command(args, os.getcwd()) outf = setup_outf() outf.write(out.data.decode(osutils.get_terminal_encoding(), 'replace')) sys.stderr.write(err) outf.flush() sys.stderr.flush() sys.exit(exit_val) except Error, exc: sys.stderr.write(exc.__repr__()) raise
def init_encodings(self, initial_encoding=None): _encodings = UniqueList() if initial_encoding: _encodings.append(initial_encoding) _encodings.append(get_user_encoding()) _encodings.append(get_terminal_encoding()) _encodings += python_encodings self.encodings = filter(is_valid_encoding, _encodings) if initial_encoding: if initial_encoding not in self.encodings: self.encodings.insert(0, initial_encoding) else: initial_encoding = 'utf-8' self._encoding = initial_encoding
def test_terminal_cp_unknown(self): # test against really unknown encoding # catch warning at stderr self.make_wrapped_streams('cp-unknown', 'cp-unknown', 'cp-unknown', user_encoding='latin-1', enable_fake_encodings=False) self.assertEqual('latin-1', osutils.get_terminal_encoding()) # check stderr self.assertEquals( 'bzr: warning: unknown terminal encoding cp-unknown.\n' ' Using encoding latin-1 instead.\n', sys.stderr.getvalue())
def _print_annotations(annotation, verbose, to_file, full): """Print annotations to to_file. :param to_file: The file to output the annotation to. :param verbose: Show all details rather than truncating to ensure reasonable text width. :param full: XXXX Not sure what this does. """ if len(annotation) == 0: max_origin_len = max_revno_len = max_revid_len = 0 else: max_origin_len = max(len(x[1]) for x in annotation) max_revno_len = max(len(x[0]) for x in annotation) max_revid_len = max(len(x[3]) for x in annotation) if not verbose: max_revno_len = min(max_revno_len, 12) max_revno_len = max(max_revno_len, 3) # Output the annotations prevanno = '' encoding = getattr(to_file, 'encoding', None) or \ osutils.get_terminal_encoding() for (revno_str, author, date_str, line_rev_id, text) in annotation: if verbose: anno = '%-*s %-*s %8s ' % (max_revno_len, revno_str, max_origin_len, author, date_str) else: if len(revno_str) > max_revno_len: revno_str = revno_str[:max_revno_len - 1] + '>' anno = "%-*s %-7s " % (max_revno_len, revno_str, author[:7]) if anno.lstrip() == "" and full: anno = prevanno try: to_file.write(anno) except UnicodeEncodeError: # cmd_annotate should be passing in an 'exact' object, which means # we have a direct handle to sys.stdout or equivalent. It may not # be able to handle the exact Unicode characters, but 'annotate' is # a user function (non-scripting), so shouldn't die because of # unrepresentable annotation characters. So encode using 'replace', # and write them again. to_file.write(anno.encode(encoding, 'replace')) to_file.write('| %s\n' % (text, )) prevanno = anno
def _print_annotations(annotation, verbose, to_file, full): """Print annotations to to_file. :param to_file: The file to output the annotation to. :param verbose: Show all details rather than truncating to ensure reasonable text width. :param full: XXXX Not sure what this does. """ if len(annotation) == 0: max_origin_len = max_revno_len = max_revid_len = 0 else: max_origin_len = max(len(x[1]) for x in annotation) max_revno_len = max(len(x[0]) for x in annotation) max_revid_len = max(len(x[3]) for x in annotation) if not verbose: max_revno_len = min(max_revno_len, 12) max_revno_len = max(max_revno_len, 3) # Output the annotations prevanno = '' encoding = getattr(to_file, 'encoding', None) or \ osutils.get_terminal_encoding() for (revno_str, author, date_str, line_rev_id, text) in annotation: if verbose: anno = '%-*s %-*s %8s ' % (max_revno_len, revno_str, max_origin_len, author, date_str) else: if len(revno_str) > max_revno_len: revno_str = revno_str[:max_revno_len-1] + '>' anno = "%-*s %-7s " % (max_revno_len, revno_str, author[:7]) if anno.lstrip() == "" and full: anno = prevanno try: to_file.write(anno) except UnicodeEncodeError: # cmd_annotate should be passing in an 'exact' object, which means # we have a direct handle to sys.stdout or equivalent. It may not # be able to handle the exact Unicode characters, but 'annotate' is # a user function (non-scripting), so shouldn't die because of # unrepresentable annotation characters. So encode using 'replace', # and write them again. to_file.write(anno.encode(encoding, 'replace')) to_file.write('| %s\n' % (text,)) prevanno = anno
def setup_outf(encoding_type='replace'): """Return a file linked to stdout, which has proper encoding.""" import codecs import bzrlib if encoding_type == 'exact': # force sys.stdout to be binary stream on win32 if sys.platform == 'win32': fileno = getattr(sys.stdout, 'fileno', None) if fileno: import msvcrt msvcrt.setmode(fileno(), os.O_BINARY) outf = sys.stdout return output_encoding = osutils.get_terminal_encoding() outf = codecs.getwriter(output_encoding)(sys.stdout, errors=encoding_type) outf.encoding = output_encoding return outf
def _check_can_encode_paths(self): fs_enc = osutils._fs_enc terminal_enc = osutils.get_terminal_encoding() fname = self.info['filename'] dir_name = self.info['directory'] for thing in [fname, dir_name]: try: thing.encode(fs_enc) except UnicodeEncodeError: raise tests.TestSkipped( 'Unable to represent path %r in filesystem encoding "%s"' % (thing, fs_enc)) try: thing.encode(terminal_enc) except UnicodeEncodeError: raise tests.TestSkipped( 'Unable to represent path %r in terminal encoding "%s"' ' (even though it is valid in filesystem encoding "%s")' % (thing, terminal_enc, fs_enc))
def get_parsed_patch(self, file_id, invert=False): """Return a parsed version of a file's patch. :param file_id: The id of the file to generate a patch for. :param invert: If True, provide an inverted patch (insertions displayed as removals, removals displayed as insertions). :return: A patches.Patch. """ diff_file = StringIO() if invert: old_tree = self.work_tree new_tree = self.target_tree else: old_tree = self.target_tree new_tree = self.work_tree old_path = old_tree.id2path(file_id) new_path = new_tree.id2path(file_id) text_differ = diff.DiffText(old_tree, new_tree, diff_file, path_encoding=osutils.get_terminal_encoding()) patch = text_differ.diff(file_id, old_path, new_path, 'file', 'file') diff_file.seek(0) return patches.parse_patch(diff_file)
def annotate_file(branch, rev_id, file_id, verbose=False, full=False, to_file=None, show_ids=False): """Annotate file_id at revision rev_id in branch. The branch should already be read_locked() when annotate_file is called. :param branch: The branch to look for revision numbers and history from. :param rev_id: The revision id to annotate. :param file_id: The file_id to annotate. :param verbose: Show all details rather than truncating to ensure reasonable text width. :param full: XXXX Not sure what this does. :param to_file: The file to output the annotation to; if None stdout is used. :param show_ids: Show revision ids in the annotation output. """ if to_file is None: to_file = sys.stdout # Handle the show_ids case last_rev_id = None if show_ids: annotations = _annotations(branch.repository, file_id, rev_id) max_origin_len = max(len(origin) for origin, text in annotations) for origin, text in annotations: if full or last_rev_id != origin: this = origin else: this = '' to_file.write('%*s | %s' % (max_origin_len, this, text)) last_rev_id = origin return # Calculate the lengths of the various columns annotation = list(_annotate_file(branch, rev_id, file_id)) if len(annotation) == 0: max_origin_len = max_revno_len = max_revid_len = 0 else: max_origin_len = max(len(x[1]) for x in annotation) max_revno_len = max(len(x[0]) for x in annotation) max_revid_len = max(len(x[3]) for x in annotation) if not verbose: max_revno_len = min(max_revno_len, 12) max_revno_len = max(max_revno_len, 3) # Output the annotations prevanno = '' encoding = getattr(to_file, 'encoding', None) or \ osutils.get_terminal_encoding() for (revno_str, author, date_str, line_rev_id, text) in annotation: if verbose: anno = '%-*s %-*s %8s ' % (max_revno_len, revno_str, max_origin_len, author, date_str) else: if len(revno_str) > max_revno_len: revno_str = revno_str[:max_revno_len-1] + '>' anno = "%-*s %-7s " % (max_revno_len, revno_str, author[:7]) if anno.lstrip() == "" and full: anno = prevanno try: to_file.write(anno) except UnicodeEncodeError: # cmd_annotate should be passing in an 'exact' object, which means # we have a direct handle to sys.stdout or equivalent. It may not # be able to handle the exact Unicode characters, but 'annotate' is # a user function (non-scripting), so shouldn't die because of # unrepresentable annotation characters. So encode using 'replace', # and write them again. to_file.write(anno.encode(encoding, 'replace')) to_file.write('| %s\n' % (text,)) prevanno = anno