summaryrefslogtreecommitdiffstats
path: root/bitbake/lib/bb/ui/knotty.py
diff options
context:
space:
mode:
Diffstat (limited to 'bitbake/lib/bb/ui/knotty.py')
-rw-r--r--bitbake/lib/bb/ui/knotty.py114
1 files changed, 101 insertions, 13 deletions
diff --git a/bitbake/lib/bb/ui/knotty.py b/bitbake/lib/bb/ui/knotty.py
index 34b5969e6b..304ba293d1 100644
--- a/bitbake/lib/bb/ui/knotty.py
+++ b/bitbake/lib/bb/ui/knotty.py
@@ -27,6 +27,9 @@ import logging
27import progressbar 27import progressbar
28import signal 28import signal
29import bb.msg 29import bb.msg
30import fcntl
31import struct
32import copy
30from bb.ui import uihelper 33from bb.ui import uihelper
31 34
32logger = logging.getLogger("BitBake") 35logger = logging.getLogger("BitBake")
@@ -84,39 +87,124 @@ def pluralise(singular, plural, qty):
84 else: 87 else:
85 return plural % qty 88 return plural % qty
86 89
90
91class InteractConsoleLogFilter(logging.Filter):
92 def __init__(self, tf, format):
93 self.tf = tf
94 self.format = format
95
96 def filter(self, record):
97 if record.levelno == self.format.NOTE and (record.msg.startswith("Running") or record.msg.startswith("package ")):
98 return False
99 self.tf.clearFooter()
100 return True
101
87class TerminalFilter(object): 102class TerminalFilter(object):
103 columns = 80
104
105 def sigwinch_handle(self, signum, frame):
106 self.columns = self.getTerminalColumns()
107 if self._sigwinch_default:
108 self._sigwinch_default(signum, frame)
109
110 def getTerminalColumns(self):
111 def ioctl_GWINSZ(fd):
112 try:
113 cr = struct.unpack('hh', fcntl.ioctl(fd, self.termios.TIOCGWINSZ, '1234'))
114 except:
115 return None
116 return cr
117 cr = ioctl_GWINSZ(sys.stdout.fileno())
118 if not cr:
119 try:
120 fd = os.open(os.ctermid(), os.O_RDONLY)
121 cr = ioctl_GWINSZ(fd)
122 os.close(fd)
123 except:
124 pass
125 if not cr:
126 try:
127 cr = (env['LINES'], env['COLUMNS'])
128 except:
129 cr = (25, 80)
130 return cr[1]
131
88 def __init__(self, main, helper, console, format): 132 def __init__(self, main, helper, console, format):
89 self.main = main 133 self.main = main
90 self.helper = helper 134 self.helper = helper
135 self.cuu = None
136 self.stdinbackup = None
137 self.interactive = sys.stdout.isatty()
138 self.footer_present = False
139 self.lastpids = []
140
141 if not self.interactive:
142 return
143
144 import curses
145 import termios
146 self.curses = curses
147 self.termios = termios
148 try:
149 fd = sys.stdin.fileno()
150 self.stdinbackup = termios.tcgetattr(fd)
151 new = copy.deepcopy(self.stdinbackup)
152 new[3] = new[3] & ~termios.ECHO
153 termios.tcsetattr(fd, termios.TCSADRAIN, new)
154 curses.setupterm()
155 self.ed = curses.tigetstr("ed")
156 if self.ed:
157 self.cuu = curses.tigetstr("cuu")
158 try:
159 self._sigwinch_default = signal.getsignal(signal.SIGWINCH)
160 signal.signal(signal.SIGWINCH, self.sigwinch_handle)
161 except:
162 pass
163 self.columns = self.getTerminalColumns()
164 except:
165 self.cuu = None
166 console.addFilter(InteractConsoleLogFilter(self, format))
91 167
92 def clearFooter(self): 168 def clearFooter(self):
93 return 169 if self.footer_present:
170 lines = self.footer_present
171 sys.stdout.write(self.curses.tparm(self.cuu, lines))
172 sys.stdout.write(self.curses.tparm(self.ed))
173 self.footer_present = False
94 174
95 def updateFooter(self): 175 def updateFooter(self):
96 if not main.shutdown or not self.helper.needUpdate: 176 if not self.cuu:
97 return 177 return
98
99 activetasks = self.helper.running_tasks 178 activetasks = self.helper.running_tasks
179 failedtasks = self.helper.failed_tasks
100 runningpids = self.helper.running_pids 180 runningpids = self.helper.running_pids
101 181 if self.footer_present and (self.lastpids == runningpids):
102 if len(runningpids) == 0: 182 return
183 if self.footer_present:
184 self.clearFooter()
185 if not activetasks:
103 return 186 return
104
105 self.helper.getTasks()
106
107 tasks = [] 187 tasks = []
108 for t in runningpids: 188 for t in runningpids:
109 tasks.append("%s (pid %s)" % (activetasks[t]["title"], t)) 189 tasks.append("%s (pid %s)" % (activetasks[t]["title"], t))
110 190
111 if main.shutdown: 191 if self.main.shutdown:
112 print("Waiting for %s running tasks to finish:" % len(activetasks)) 192 content = "Waiting for %s running tasks to finish:" % len(activetasks)
113 else: 193 else:
114 print("Currently %s running tasks (%s of %s):" % (len(activetasks), self.helper.tasknumber_current, self.helper.tasknumber_total)) 194 content = "Currently %s running tasks (%s of %s):" % (len(activetasks), self.helper.tasknumber_current, self.helper.tasknumber_total)
195 print content
196 lines = 1 + int(len(content) / (self.columns + 1))
115 for tasknum, task in enumerate(tasks): 197 for tasknum, task in enumerate(tasks):
116 print("%s: %s" % (tasknum, task)) 198 content = "%s: %s" % (tasknum, task)
199 print content
200 lines = lines + 1 + int(len(content) / (self.columns + 1))
201 self.footer_present = lines
202 self.lastpids = runningpids[:]
117 203
118 def finish(self): 204 def finish(self):
119 return 205 if self.stdinbackup:
206 fd = sys.stdin.fileno()
207 self.termios.tcsetattr(fd, self.termios.TCSADRAIN, self.stdinbackup)
120 208
121def main(server, eventHandler, tf = TerminalFilter): 209def main(server, eventHandler, tf = TerminalFilter):
122 210