Rev 4863: BZR_COLUMNS can override terminal_width() in http://bazaar.launchpad.net/~vila/bzr/integration
Vincent Ladeuil
v.ladeuil+lp at free.fr
Fri Dec 4 10:38:21 GMT 2009
At http://bazaar.launchpad.net/~vila/bzr/integration
------------------------------------------------------------
revno: 4863 [merge]
revision-id: v.ladeuil+lp at free.fr-20091204103804-ezdgsf6iucib6v8x
parent: pqm at pqm.ubuntu.com-20091204080756-orgsvo74a1jk13rs
parent: v.ladeuil+lp at free.fr-20091204103655-r00e0gz8z3lbni0r
committer: Vincent Ladeuil <v.ladeuil+lp at free.fr>
branch nick: integration
timestamp: Fri 2009-12-04 11:38:04 +0100
message:
BZR_COLUMNS can override terminal_width()
modified:
NEWS NEWS-20050323055033-4e00b5db738777ff
bzrlib/help.py help.py-20050505025907-4dd7a6d63912f894
bzrlib/help_topics/__init__.py help_topics.py-20060920210027-rnim90q9e0bwxvy4-1
bzrlib/log.py log.py-20050505065812-c40ce11702fe5fb1
bzrlib/osutils.py osutils.py-20050309040759-eeaff12fbf77ac86
bzrlib/status.py status.py-20050505062338-431bfa63ec9b19e6
bzrlib/tests/__init__.py selftest.py-20050531073622-8d0e3c8845c97a64
bzrlib/tests/blackbox/test_ignore.py test_ignore.py-20060703063225-4tm8dc2pa7wwg2t3-1
bzrlib/tests/blackbox/test_too_much.py blackbox.py-20050620052131-a7370d756399f615
bzrlib/tests/test_osutils.py test_osutils.py-20051201224856-e48ee24c12182989
bzrlib/ui/text.py text.py-20051130153916-2e438cffc8afc478
bzrlib/win32utils.py win32console.py-20051021033308-123c6c929d04973d
-------------- next part --------------
=== modified file 'NEWS'
--- a/NEWS 2009-12-04 08:07:56 +0000
+++ b/NEWS 2009-12-04 10:38:04 +0000
@@ -26,6 +26,13 @@
* ``bzr commit`` now has a ``--commit-time`` option.
(Alexander Sack, #459276)
+* The ``BZR_COLUMNS`` envrionment variable can be set to force bzr to
+ respect a given terminal width. This can be useful when output is
+ redirected or in obscure cases where the default value is not
+ appropriate. Pagers can use it to get a better control of the line
+ lengths.
+ (Vincent Ladeuil)
+
Bug Fixes
*********
@@ -45,6 +52,12 @@
* Lots of bugfixes for the test suite on Windows. We should once again
have a test suite with no failures on Windows. (John Arbash Meinel)
+* ``osutils.terminal_width()`` obeys the BZR_COLUMNS envrionment
+ variable but returns None if the terminal is not a tty (when output is
+ redirected for example). Also fixes its usage under OSes that doesn't
+ provide termios.TIOCGWINSZ.
+ (Joke de Buhr, Vincent Ladeuil, #353370, #62539)
+
* Terminate ssh subprocesses when no references to them remain, fixing
subprocess and file descriptor leaks. (Andrew Bennetts, #426662)
=== modified file 'bzrlib/help.py'
--- a/bzrlib/help.py 2009-06-19 09:06:56 +0000
+++ b/bzrlib/help.py 2009-12-02 15:24:34 +0000
@@ -78,7 +78,11 @@
shown_commands = [(n, o) for n, o in commands if o.hidden == hidden]
max_name = max(len(n) for n, o in shown_commands)
indent = ' ' * (max_name + 1)
- width = osutils.terminal_width() - 1
+ width = osutils.terminal_width()
+ if width is None:
+ width = osutils.default_terminal_width
+ # we need one extra space for terminals that wrap on last char
+ width = width - 1
for cmd_name, cmd_object in sorted(shown_commands):
plugin_name = cmd_object.plugin_name()
=== modified file 'bzrlib/help_topics/__init__.py'
--- a/bzrlib/help_topics/__init__.py 2009-12-02 23:11:43 +0000
+++ b/bzrlib/help_topics/__init__.py 2009-12-04 10:38:04 +0000
@@ -585,6 +585,7 @@
BZR_SSH Path to SSH client, or one of paramiko, openssh, sshcorp, plink.
BZR_LOG Location of .bzr.log (use '/dev/null' to suppress log).
BZR_LOG (Win32) Location of .bzr.log (use 'NUL' to suppress log).
+BZR_COLUMNS Override implicit terminal width.
BZR_CONCURRENCY Number of processes that can be run concurrently (selftest).
================ =================================================================
"""
=== modified file 'bzrlib/log.py'
--- a/bzrlib/log.py 2009-11-30 12:24:55 +0000
+++ b/bzrlib/log.py 2009-12-02 16:21:42 +0000
@@ -1573,12 +1573,16 @@
def __init__(self, *args, **kwargs):
super(LineLogFormatter, self).__init__(*args, **kwargs)
- self._max_chars = terminal_width() - 1
+ width = terminal_width()
+ if width is not None:
+ # we need one extra space for terminals that wrap on last char
+ width = width - 1
+ self._max_chars = width
def truncate(self, str, max_len):
- if len(str) <= max_len:
+ if max_len is None or len(str) <= max_len:
return str
- return str[:max_len-3]+'...'
+ return str[:max_len-3] + '...'
def date_string(self, rev):
return format_date(rev.timestamp, rev.timezone or 0,
=== modified file 'bzrlib/osutils.py'
--- a/bzrlib/osutils.py 2009-12-02 07:56:16 +0000
+++ b/bzrlib/osutils.py 2009-12-04 10:36:55 +0000
@@ -1330,25 +1330,51 @@
normalized_filename = _inaccessible_normalized_filename
+default_terminal_width = 80
+"""The default terminal width for ttys.
+
+This is defined so that higher levels can share a common fallback value when
+terminal_width() returns None.
+"""
+
+
def terminal_width():
- """Return estimated terminal width."""
+ """Return terminal width.
+
+ None is returned if the width can't established precisely.
+ """
+
+ # If BZR_COLUMNS is set, take it, user is always right
+ try:
+ return int(os.environ['BZR_COLUMNS'])
+ except (KeyError, ValueError):
+ pass
+
+ # If COLUMNS is set, take it, the terminal knows better
+ try:
+ return int(os.environ['COLUMNS'])
+ except (KeyError, ValueError):
+ pass
+
+ isatty = getattr(sys.stdout, 'isatty', None)
+ if isatty is None or not isatty():
+ # Don't guess, setting BZR_COLUMNS is the recommended way to override.
+ return None
+
if sys.platform == 'win32':
- return win32utils.get_console_size()[0]
- width = 0
+ return win32utils.get_console_size(defaultx=None)[0]
+
try:
import struct, fcntl, termios
s = struct.pack('HHHH', 0, 0, 0, 0)
x = fcntl.ioctl(1, termios.TIOCGWINSZ, s)
width = struct.unpack('HHHH', x)[1]
- except IOError:
- pass
- if width <= 0:
- try:
- width = int(os.environ['COLUMNS'])
- except:
- pass
- if width <= 0:
- width = 80
+ except (IOError, AttributeError):
+ return None
+
+ if width <= 0:
+ # Consider invalid values as meaning no width
+ return None
return width
=== modified file 'bzrlib/status.py'
--- a/bzrlib/status.py 2009-08-06 05:07:12 +0000
+++ b/bzrlib/status.py 2009-12-02 15:24:34 +0000
@@ -197,8 +197,10 @@
if len(parents) < 2:
return
- # we need one extra space for terminals that wrap on last char
- term_width = osutils.terminal_width() - 1
+ term_width = osutils.terminal_width()
+ if term_width is not None:
+ # we need one extra space for terminals that wrap on last char
+ term_width = term_width - 1
if short:
first_prefix = 'P '
sub_prefix = 'P. '
@@ -206,6 +208,14 @@
first_prefix = ' '
sub_prefix = ' '
+ def show_log_message(rev, prefix):
+ if term_width is None:
+ width = term_width
+ else:
+ width = term_width - len(prefix)
+ log_message = log_formatter.log_string(None, rev, width, prefix=prefix)
+ to_file.write(log_message + '\n')
+
pending = parents[1:]
branch = new.branch
last_revision = parents[0]
@@ -213,7 +223,8 @@
if verbose:
to_file.write('pending merges:\n')
else:
- to_file.write('pending merge tips: (use -v to see all merge revisions)\n')
+ to_file.write('pending merge tips:'
+ ' (use -v to see all merge revisions)\n')
graph = branch.repository.get_graph()
other_revisions = [last_revision]
log_formatter = log.LineLogFormatter(to_file)
@@ -227,9 +238,7 @@
continue
# Log the merge, as it gets a slightly different formatting
- log_message = log_formatter.log_string(None, rev,
- term_width - len(first_prefix))
- to_file.write(first_prefix + log_message + '\n')
+ show_log_message(rev, first_prefix)
if not verbose:
continue
@@ -267,10 +276,7 @@
if rev is None:
to_file.write(sub_prefix + '(ghost) ' + sub_merge + '\n')
continue
- log_message = log_formatter.log_string(None,
- revisions[sub_merge],
- term_width - len(sub_prefix))
- to_file.write(sub_prefix + log_message + '\n')
+ show_log_message(revisions[sub_merge], sub_prefix)
def _filter_nonexistent(orig_paths, old_tree, new_tree):
=== modified file 'bzrlib/tests/__init__.py'
--- a/bzrlib/tests/__init__.py 2009-12-03 18:10:26 +0000
+++ b/bzrlib/tests/__init__.py 2009-12-04 10:38:04 +0000
@@ -533,11 +533,15 @@
def report_test_start(self, test):
self.count += 1
name = self._shortened_test_description(test)
- # width needs space for 6 char status, plus 1 for slash, plus an
- # 11-char time string, plus a trailing blank
- # when NUMBERED_DIRS: plus 5 chars on test number, plus 1 char on space
- self.stream.write(self._ellipsize_to_right(name,
- osutils.terminal_width()-18))
+ width = osutils.terminal_width()
+ if width is not None:
+ # width needs space for 6 char status, plus 1 for slash, plus an
+ # 11-char time string, plus a trailing blank
+ # when NUMBERED_DIRS: plus 5 chars on test number, plus 1 char on
+ # space
+ self.stream.write(self._ellipsize_to_right(name, width-18))
+ else:
+ self.stream.write(name)
self.stream.flush()
def _error_summary(self, err):
@@ -1532,6 +1536,7 @@
'TERM': 'dumb',
'LINES': '25',
'COLUMNS': '80',
+ 'BZR_COLUMNS': '80',
# SSH Agent
'SSH_AUTH_SOCK': None,
# Proxies
=== modified file 'bzrlib/tests/blackbox/test_ignore.py'
--- a/bzrlib/tests/blackbox/test_ignore.py 2009-03-23 14:59:43 +0000
+++ b/bzrlib/tests/blackbox/test_ignore.py 2009-10-23 10:41:15 +0000
@@ -32,7 +32,6 @@
from bzrlib.errors import BzrCommandError
from bzrlib.osutils import (
pathjoin,
- terminal_width,
)
from bzrlib.tests.test_sftp_transport import TestCaseWithSFTPServer
from bzrlib.tests.blackbox import ExternalBase
=== modified file 'bzrlib/tests/blackbox/test_too_much.py'
--- a/bzrlib/tests/blackbox/test_too_much.py 2009-09-17 11:54:41 +0000
+++ b/bzrlib/tests/blackbox/test_too_much.py 2009-12-02 15:24:34 +0000
@@ -44,11 +44,6 @@
)
from bzrlib.branch import Branch
from bzrlib.errors import BzrCommandError
-from bzrlib.osutils import (
- has_symlinks,
- pathjoin,
- terminal_width,
- )
from bzrlib.tests.http_utils import TestCaseWithWebserver
from bzrlib.tests.test_sftp_transport import TestCaseWithSFTPServer
from bzrlib.tests.blackbox import ExternalBase
@@ -87,7 +82,7 @@
os.rmdir('revertdir')
self.run_bzr('revert')
- if has_symlinks():
+ if osutils.has_symlinks():
os.symlink('/unlikely/to/exist', 'symlink')
self.run_bzr('add symlink')
self.run_bzr('commit -m f')
@@ -374,7 +369,7 @@
self.run_bzr('init')
self.assertIsSameRealPath(self.run_bzr('root')[0].rstrip(),
- pathjoin(self.test_dir, 'branch1'))
+ osutils.pathjoin(self.test_dir, 'branch1'))
progress("status of new file")
@@ -443,9 +438,10 @@
log_out = self.run_bzr('log --line')[0]
# determine the widest line we want
- max_width = terminal_width() - 1
- for line in log_out.splitlines():
- self.assert_(len(line) <= max_width, len(line))
+ max_width = osutils.terminal_width()
+ if max_width is not None:
+ for line in log_out.splitlines():
+ self.assert_(len(line) <= max_width - 1, len(line))
self.assert_("this is my new commit and" not in log_out)
self.assert_("this is my new commit" in log_out)
@@ -462,7 +458,7 @@
self.run_bzr('info')
- if has_symlinks():
+ if osutils.has_symlinks():
progress("symlinks")
mkdir('symlinks')
chdir('symlinks')
=== modified file 'bzrlib/tests/test_osutils.py'
--- a/bzrlib/tests/test_osutils.py 2009-12-02 07:56:16 +0000
+++ b/bzrlib/tests/test_osutils.py 2009-12-02 16:21:42 +0000
@@ -23,6 +23,7 @@
import socket
import stat
import sys
+import termios
import time
from bzrlib import (
@@ -1922,3 +1923,63 @@
r"bzr: warning: some compiled extensions could not be loaded; "
"see <https://answers\.launchpad\.net/bzr/\+faq/703>\n"
)
+
+
+class TestTerminalWidth(tests.TestCase):
+
+ def test_default_values(self):
+ self.assertEquals(80, osutils.default_terminal_width)
+
+ def test_defaults_to_BZR_COLUMNS(self):
+ # BZR_COLUMNS is set by the test framework
+ self.assertEquals('80', os.environ['BZR_COLUMNS'])
+ os.environ['BZR_COLUMNS'] = '12'
+ self.assertEquals(12, osutils.terminal_width())
+
+ def test_falls_back_to_COLUMNS(self):
+ del os.environ['BZR_COLUMNS']
+ os.environ['COLUMNS'] = '42'
+ self.assertEquals(42, osutils.terminal_width())
+
+ def test_tty_default_without_columns(self):
+ del os.environ['BZR_COLUMNS']
+ del os.environ['COLUMNS']
+ orig_stdout = sys.stdout
+ def restore():
+ sys.stdout = orig_stdout
+ self.addCleanup(restore)
+
+ class I_am_a_tty(object):
+ def isatty(self):
+ return True
+
+ sys.stdout = I_am_a_tty()
+ self.assertEquals(None, osutils.terminal_width())
+
+ def test_non_tty_default_without_columns(self):
+ del os.environ['BZR_COLUMNS']
+ del os.environ['COLUMNS']
+ orig_stdout = sys.stdout
+ def restore():
+ sys.stdout = orig_stdout
+ self.addCleanup(restore)
+ sys.stdout = None
+ self.assertEquals(None, osutils.terminal_width())
+
+ def test_TIOCGWINSZ(self):
+ # bug 63539 is about a termios without TIOCGWINSZ attribute
+ exist = True
+ try:
+ orig = termios.TIOCGWINSZ
+ except AttributeError:
+ exist = False
+
+ def restore():
+ if exist:
+ termios.TIOCGWINSZ = orig
+ self.addCleanup(restore)
+
+ del termios.TIOCGWINSZ
+ del os.environ['BZR_COLUMNS']
+ del os.environ['COLUMNS']
+ self.assertEquals(None, osutils.terminal_width())
=== modified file 'bzrlib/ui/text.py'
--- a/bzrlib/ui/text.py 2009-09-23 06:29:46 +0000
+++ b/bzrlib/ui/text.py 2009-12-02 15:24:34 +0000
@@ -234,8 +234,10 @@
def _show_line(self, s):
# sys.stderr.write("progress %r\n" % s)
- n = self._width - 1
- self._term_file.write('\r%-*.*s\r' % (n, n, s))
+ if self._width is not None:
+ n = self._width - 1
+ s = '%-*.*s' % (n, n, s)
+ self._term_file.write('\r' + s + '\r')
def clear(self):
if self._have_output:
=== modified file 'bzrlib/win32utils.py'
--- a/bzrlib/win32utils.py 2009-11-20 16:42:28 +0000
+++ b/bzrlib/win32utils.py 2009-12-02 16:21:42 +0000
@@ -182,7 +182,7 @@
return (defaultx, defaulty)
# To avoid problem with redirecting output via pipe
- # need to use stderr instead of stdout
+ # we need to use stderr instead of stdout
h = ctypes.windll.kernel32.GetStdHandle(WIN32_STDERR_HANDLE)
csbi = ctypes.create_string_buffer(22)
res = ctypes.windll.kernel32.GetConsoleScreenBufferInfo(h, csbi)
More information about the bazaar-commits
mailing list