diff options
author | Tudor Florea <tudor.florea@enea.com> | 2015-10-09 22:59:03 +0200 |
---|---|---|
committer | Tudor Florea <tudor.florea@enea.com> | 2015-10-09 22:59:03 +0200 |
commit | 972dcfcdbfe75dcfeb777150c136576cf1a71e99 (patch) | |
tree | 97a61cd7e293d7ae9d56ef7ed0f81253365bb026 /meta/lib/oe/terminal.py | |
download | poky-972dcfcdbfe75dcfeb777150c136576cf1a71e99.tar.gz |
initial commit for Enea Linux 5.0 arm
Signed-off-by: Tudor Florea <tudor.florea@enea.com>
Diffstat (limited to 'meta/lib/oe/terminal.py')
-rw-r--r-- | meta/lib/oe/terminal.py | 208 |
1 files changed, 208 insertions, 0 deletions
diff --git a/meta/lib/oe/terminal.py b/meta/lib/oe/terminal.py new file mode 100644 index 0000000000..0a623c75b1 --- /dev/null +++ b/meta/lib/oe/terminal.py | |||
@@ -0,0 +1,208 @@ | |||
1 | import logging | ||
2 | import oe.classutils | ||
3 | import shlex | ||
4 | from bb.process import Popen, ExecutionError | ||
5 | |||
6 | logger = logging.getLogger('BitBake.OE.Terminal') | ||
7 | |||
8 | |||
9 | class UnsupportedTerminal(Exception): | ||
10 | pass | ||
11 | |||
12 | class NoSupportedTerminals(Exception): | ||
13 | pass | ||
14 | |||
15 | |||
16 | class Registry(oe.classutils.ClassRegistry): | ||
17 | command = None | ||
18 | |||
19 | def __init__(cls, name, bases, attrs): | ||
20 | super(Registry, cls).__init__(name.lower(), bases, attrs) | ||
21 | |||
22 | @property | ||
23 | def implemented(cls): | ||
24 | return bool(cls.command) | ||
25 | |||
26 | |||
27 | class Terminal(Popen): | ||
28 | __metaclass__ = Registry | ||
29 | |||
30 | def __init__(self, sh_cmd, title=None, env=None, d=None): | ||
31 | fmt_sh_cmd = self.format_command(sh_cmd, title) | ||
32 | try: | ||
33 | Popen.__init__(self, fmt_sh_cmd, env=env) | ||
34 | except OSError as exc: | ||
35 | import errno | ||
36 | if exc.errno == errno.ENOENT: | ||
37 | raise UnsupportedTerminal(self.name) | ||
38 | else: | ||
39 | raise | ||
40 | |||
41 | def format_command(self, sh_cmd, title): | ||
42 | fmt = {'title': title or 'Terminal', 'command': sh_cmd} | ||
43 | if isinstance(self.command, basestring): | ||
44 | return shlex.split(self.command.format(**fmt)) | ||
45 | else: | ||
46 | return [element.format(**fmt) for element in self.command] | ||
47 | |||
48 | class XTerminal(Terminal): | ||
49 | def __init__(self, sh_cmd, title=None, env=None, d=None): | ||
50 | Terminal.__init__(self, sh_cmd, title, env, d) | ||
51 | if not os.environ.get('DISPLAY'): | ||
52 | raise UnsupportedTerminal(self.name) | ||
53 | |||
54 | class Gnome(XTerminal): | ||
55 | command = 'gnome-terminal -t "{title}" -x {command}' | ||
56 | priority = 2 | ||
57 | |||
58 | class Mate(XTerminal): | ||
59 | command = 'mate-terminal -t "{title}" -x {command}' | ||
60 | priority = 2 | ||
61 | |||
62 | class Xfce(XTerminal): | ||
63 | command = 'xfce4-terminal -T "{title}" -e "{command}"' | ||
64 | priority = 2 | ||
65 | |||
66 | class Konsole(XTerminal): | ||
67 | command = 'konsole -T "{title}" -e {command}' | ||
68 | priority = 2 | ||
69 | |||
70 | def __init__(self, sh_cmd, title=None, env=None, d=None): | ||
71 | # Check version | ||
72 | vernum = check_konsole_version("konsole") | ||
73 | if vernum: | ||
74 | if vernum.split('.')[0] == "2": | ||
75 | logger.debug(1, 'Konsole from KDE 4.x will not work as devshell, skipping') | ||
76 | raise UnsupportedTerminal(self.name) | ||
77 | XTerminal.__init__(self, sh_cmd, title, env, d) | ||
78 | |||
79 | class XTerm(XTerminal): | ||
80 | command = 'xterm -T "{title}" -e {command}' | ||
81 | priority = 1 | ||
82 | |||
83 | class Rxvt(XTerminal): | ||
84 | command = 'rxvt -T "{title}" -e {command}' | ||
85 | priority = 1 | ||
86 | |||
87 | class Screen(Terminal): | ||
88 | command = 'screen -D -m -t "{title}" -S devshell {command}' | ||
89 | |||
90 | def __init__(self, sh_cmd, title=None, env=None, d=None): | ||
91 | s_id = "devshell_%i" % os.getpid() | ||
92 | self.command = "screen -D -m -t \"{title}\" -S %s {command}" % s_id | ||
93 | Terminal.__init__(self, sh_cmd, title, env, d) | ||
94 | msg = 'Screen started. Please connect in another terminal with ' \ | ||
95 | '"screen -r %s"' % s_id | ||
96 | if (d): | ||
97 | bb.event.fire(bb.event.LogExecTTY(msg, "screen -r %s" % s_id, | ||
98 | 0.5, 10), d) | ||
99 | else: | ||
100 | logger.warn(msg) | ||
101 | |||
102 | class TmuxRunning(Terminal): | ||
103 | """Open a new pane in the current running tmux window""" | ||
104 | name = 'tmux-running' | ||
105 | command = 'tmux split-window "{command}"' | ||
106 | priority = 2.75 | ||
107 | |||
108 | def __init__(self, sh_cmd, title=None, env=None, d=None): | ||
109 | if not bb.utils.which(os.getenv('PATH'), 'tmux'): | ||
110 | raise UnsupportedTerminal('tmux is not installed') | ||
111 | |||
112 | if not os.getenv('TMUX'): | ||
113 | raise UnsupportedTerminal('tmux is not running') | ||
114 | |||
115 | Terminal.__init__(self, sh_cmd, title, env, d) | ||
116 | |||
117 | class Tmux(Terminal): | ||
118 | """Start a new tmux session and window""" | ||
119 | command = 'tmux new -d -s devshell -n devshell "{command}"' | ||
120 | priority = 0.75 | ||
121 | |||
122 | def __init__(self, sh_cmd, title=None, env=None, d=None): | ||
123 | if not bb.utils.which(os.getenv('PATH'), 'tmux'): | ||
124 | raise UnsupportedTerminal('tmux is not installed') | ||
125 | |||
126 | # TODO: consider using a 'devshell' session shared amongst all | ||
127 | # devshells, if it's already there, add a new window to it. | ||
128 | window_name = 'devshell-%i' % os.getpid() | ||
129 | |||
130 | self.command = 'tmux new -d -s {0} -n {0} "{{command}}"'.format(window_name) | ||
131 | Terminal.__init__(self, sh_cmd, title, env, d) | ||
132 | |||
133 | attach_cmd = 'tmux att -t {0}'.format(window_name) | ||
134 | msg = 'Tmux started. Please connect in another terminal with `tmux att -t {0}`'.format(window_name) | ||
135 | if d: | ||
136 | bb.event.fire(bb.event.LogExecTTY(msg, attach_cmd, 0.5, 10), d) | ||
137 | else: | ||
138 | logger.warn(msg) | ||
139 | |||
140 | class Custom(Terminal): | ||
141 | command = 'false' # This is a placeholder | ||
142 | priority = 3 | ||
143 | |||
144 | def __init__(self, sh_cmd, title=None, env=None, d=None): | ||
145 | self.command = d and d.getVar('OE_TERMINAL_CUSTOMCMD', True) | ||
146 | if self.command: | ||
147 | if not '{command}' in self.command: | ||
148 | self.command += ' {command}' | ||
149 | Terminal.__init__(self, sh_cmd, title, env, d) | ||
150 | logger.warn('Custom terminal was started.') | ||
151 | else: | ||
152 | logger.debug(1, 'No custom terminal (OE_TERMINAL_CUSTOMCMD) set') | ||
153 | raise UnsupportedTerminal('OE_TERMINAL_CUSTOMCMD not set') | ||
154 | |||
155 | |||
156 | def prioritized(): | ||
157 | return Registry.prioritized() | ||
158 | |||
159 | def spawn_preferred(sh_cmd, title=None, env=None, d=None): | ||
160 | """Spawn the first supported terminal, by priority""" | ||
161 | for terminal in prioritized(): | ||
162 | try: | ||
163 | spawn(terminal.name, sh_cmd, title, env, d) | ||
164 | break | ||
165 | except UnsupportedTerminal: | ||
166 | continue | ||
167 | else: | ||
168 | raise NoSupportedTerminals() | ||
169 | |||
170 | def spawn(name, sh_cmd, title=None, env=None, d=None): | ||
171 | """Spawn the specified terminal, by name""" | ||
172 | logger.debug(1, 'Attempting to spawn terminal "%s"', name) | ||
173 | try: | ||
174 | terminal = Registry.registry[name] | ||
175 | except KeyError: | ||
176 | raise UnsupportedTerminal(name) | ||
177 | |||
178 | pipe = terminal(sh_cmd, title, env, d) | ||
179 | output = pipe.communicate()[0] | ||
180 | if pipe.returncode != 0: | ||
181 | raise ExecutionError(sh_cmd, pipe.returncode, output) | ||
182 | |||
183 | def check_konsole_version(konsole): | ||
184 | import subprocess as sub | ||
185 | try: | ||
186 | p = sub.Popen(['sh', '-c', '%s --version' % konsole],stdout=sub.PIPE,stderr=sub.PIPE) | ||
187 | out, err = p.communicate() | ||
188 | ver_info = out.rstrip().split('\n') | ||
189 | except OSError as exc: | ||
190 | import errno | ||
191 | if exc.errno == errno.ENOENT: | ||
192 | return None | ||
193 | else: | ||
194 | raise | ||
195 | vernum = None | ||
196 | for ver in ver_info: | ||
197 | if ver.startswith('Konsole'): | ||
198 | vernum = ver.split(' ')[-1] | ||
199 | return vernum | ||
200 | |||
201 | def distro_name(): | ||
202 | try: | ||
203 | p = Popen(['lsb_release', '-i']) | ||
204 | out, err = p.communicate() | ||
205 | distro = out.split(':')[1].strip().lower() | ||
206 | except: | ||
207 | distro = "unknown" | ||
208 | return distro | ||