diff options
author | Richard Purdie <richard.purdie@linuxfoundation.org> | 2012-08-15 17:00:40 +0100 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2012-08-16 11:19:03 +0100 |
commit | c49a2529bffc38b4a1f40ccaccc578022b1517b1 (patch) | |
tree | 69aa2193eebf3929f5bcf762e110384a57e2736d | |
parent | 2718537b4b04eb3d80ab4d74171b58e7b8dd68b8 (diff) | |
download | poky-c49a2529bffc38b4a1f40ccaccc578022b1517b1.tar.gz |
bitbake: knotty2: Handle long lines of text and terminal window size changes
Long lines of text which wrapped on the terminal corrupted the output shown by
knotty2. This patch catches such errors by becomming aware of the terminal size.
It also catches terminal window size change events and adapting to those
changes using a signal handler.
Based on a patch from Jason Wessel with several tweaks and enhancements
such as use of chained signal handlers and covering all output messages.
(Bitbake rev: 9afc9e4d14abec5ac326851d4bb689c1e8d45a43)
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-rw-r--r-- | bitbake/lib/bb/ui/knotty2.py | 52 |
1 files changed, 46 insertions, 6 deletions
diff --git a/bitbake/lib/bb/ui/knotty2.py b/bitbake/lib/bb/ui/knotty2.py index 65e941b4c3..57ad67f5b4 100644 --- a/bitbake/lib/bb/ui/knotty2.py +++ b/bitbake/lib/bb/ui/knotty2.py | |||
@@ -21,6 +21,10 @@ | |||
21 | from bb.ui import knotty | 21 | from bb.ui import knotty |
22 | import logging | 22 | import logging |
23 | import sys | 23 | import sys |
24 | import os | ||
25 | import fcntl | ||
26 | import struct | ||
27 | import copy | ||
24 | logger = logging.getLogger("BitBake") | 28 | logger = logging.getLogger("BitBake") |
25 | 29 | ||
26 | class InteractConsoleLogFilter(logging.Filter): | 30 | class InteractConsoleLogFilter(logging.Filter): |
@@ -35,6 +39,35 @@ class InteractConsoleLogFilter(logging.Filter): | |||
35 | return True | 39 | return True |
36 | 40 | ||
37 | class TerminalFilter2(object): | 41 | class TerminalFilter2(object): |
42 | columns = 80 | ||
43 | |||
44 | def sigwinch_handle(self, signum, frame): | ||
45 | self.columns = self.getTerminalColumns() | ||
46 | if self._sigwinch_default: | ||
47 | self._sigwinch_default(signum, frame) | ||
48 | |||
49 | def getTerminalColumns(self): | ||
50 | def ioctl_GWINSZ(fd): | ||
51 | try: | ||
52 | cr = struct.unpack('hh', fcntl.ioctl(fd, self.termios.TIOCGWINSZ, '1234')) | ||
53 | except: | ||
54 | return None | ||
55 | return cr | ||
56 | cr = ioctl_GWINSZ(sys.stdout.fileno()) | ||
57 | if not cr: | ||
58 | try: | ||
59 | fd = os.open(os.ctermid(), os.O_RDONLY) | ||
60 | cr = ioctl_GWINSZ(fd) | ||
61 | os.close(fd) | ||
62 | except: | ||
63 | pass | ||
64 | if not cr: | ||
65 | try: | ||
66 | cr = (env['LINES'], env['COLUMNS']) | ||
67 | except: | ||
68 | cr = (25, 80) | ||
69 | return cr[1] | ||
70 | |||
38 | def __init__(self, main, helper, console, format): | 71 | def __init__(self, main, helper, console, format): |
39 | self.main = main | 72 | self.main = main |
40 | self.helper = helper | 73 | self.helper = helper |
@@ -49,7 +82,6 @@ class TerminalFilter2(object): | |||
49 | 82 | ||
50 | import curses | 83 | import curses |
51 | import termios | 84 | import termios |
52 | import copy | ||
53 | self.curses = curses | 85 | self.curses = curses |
54 | self.termios = termios | 86 | self.termios = termios |
55 | try: | 87 | try: |
@@ -62,6 +94,12 @@ class TerminalFilter2(object): | |||
62 | self.ed = curses.tigetstr("ed") | 94 | self.ed = curses.tigetstr("ed") |
63 | if self.ed: | 95 | if self.ed: |
64 | self.cuu = curses.tigetstr("cuu") | 96 | self.cuu = curses.tigetstr("cuu") |
97 | try: | ||
98 | self._sigwinch_default = signal.getsignal(signal.SIGWINCH) | ||
99 | signal.signal(signal.SIGWINCH, self.sigwinch_handle) | ||
100 | except: | ||
101 | pass | ||
102 | self.columns = self.getTerminalColumns() | ||
65 | except: | 103 | except: |
66 | self.cuu = None | 104 | self.cuu = None |
67 | console.addFilter(InteractConsoleLogFilter(self, format)) | 105 | console.addFilter(InteractConsoleLogFilter(self, format)) |
@@ -85,18 +123,20 @@ class TerminalFilter2(object): | |||
85 | self.clearFooter() | 123 | self.clearFooter() |
86 | if not activetasks: | 124 | if not activetasks: |
87 | return | 125 | return |
88 | lines = 1 | ||
89 | tasks = [] | 126 | tasks = [] |
90 | for t in runningpids: | 127 | for t in runningpids: |
91 | tasks.append("%s (pid %s)" % (activetasks[t]["title"], t)) | 128 | tasks.append("%s (pid %s)" % (activetasks[t]["title"], t)) |
92 | 129 | ||
93 | if self.main.shutdown: | 130 | if self.main.shutdown: |
94 | print("Waiting for %s running tasks to finish:" % len(activetasks)) | 131 | content = "Waiting for %s running tasks to finish:" % len(activetasks) |
95 | else: | 132 | else: |
96 | print("Currently %s running tasks (%s of %s):" % (len(activetasks), self.helper.tasknumber_current, self.helper.tasknumber_total)) | 133 | content = "Currently %s running tasks (%s of %s):" % (len(activetasks), self.helper.tasknumber_current, self.helper.tasknumber_total) |
134 | print content | ||
135 | lines = 1 + int(len(content) / (self.columns + 1)) | ||
97 | for tasknum, task in enumerate(tasks): | 136 | for tasknum, task in enumerate(tasks): |
98 | print("%s: %s" % (tasknum, task)) | 137 | content = "%s: %s" % (tasknum, task) |
99 | lines = lines + 1 | 138 | print content |
139 | lines = lines + 1 + int(len(content) / (self.columns + 1)) | ||
100 | self.footer_present = lines | 140 | self.footer_present = lines |
101 | self.lastpids = runningpids[:] | 141 | self.lastpids = runningpids[:] |
102 | 142 | ||