From: Jan Kiszka <jan.kiszka@siemens.com>
To: isar-users <isar-users@googlegroups.com>
Subject: [PATCH v5 25/27] Add OE class and library elements for terminal support
Date: Sun, 22 Sep 2019 20:17:09 +0200 [thread overview]
Message-ID: <b032b3fb4025e0f2a42ce714fd9db4960c869a9c.1569176231.git.jan.kiszka@siemens.com> (raw)
In-Reply-To: <cover.1569176231.git.jan.kiszka@siemens.com>
In-Reply-To: <cover.1569176231.git.jan.kiszka@siemens.com>
From: Jan Kiszka <jan.kiszka@siemens.com>
This imports the terminal class from OE core revision 95ad56262963 along
with its dependencies under meta/lib/oe and a helper script. Files are
almost unmodified, just augmented by a note for their origin, SPDX tags
where missing and freed of three whitespace issues.
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
meta/classes/terminal.bbclass | 112 +++++++++++++
meta/lib/oe/classutils.py | 49 ++++++
meta/lib/oe/data.py | 53 ++++++
meta/lib/oe/maketype.py | 112 +++++++++++++
meta/lib/oe/terminal.py | 315 ++++++++++++++++++++++++++++++++++++
meta/lib/oe/types.py | 187 +++++++++++++++++++++
scripts/oe-gnome-terminal-phonehome | 14 ++
7 files changed, 842 insertions(+)
create mode 100644 meta/classes/terminal.bbclass
create mode 100644 meta/lib/oe/classutils.py
create mode 100644 meta/lib/oe/data.py
create mode 100644 meta/lib/oe/maketype.py
create mode 100644 meta/lib/oe/terminal.py
create mode 100644 meta/lib/oe/types.py
create mode 100755 scripts/oe-gnome-terminal-phonehome
diff --git a/meta/classes/terminal.bbclass b/meta/classes/terminal.bbclass
new file mode 100644
index 0000000..8436d7f
--- /dev/null
+++ b/meta/classes/terminal.bbclass
@@ -0,0 +1,112 @@
+#
+# Imported from openembedded-core
+#
+# SPDX-License-Identifier: MIT
+#
+
+OE_TERMINAL ?= 'auto'
+OE_TERMINAL[type] = 'choice'
+OE_TERMINAL[choices] = 'auto none \
+ ${@oe_terminal_prioritized()}'
+
+OE_TERMINAL_EXPORTS += 'EXTRA_OEMAKE CACHED_CONFIGUREVARS CONFIGUREOPTS EXTRA_OECONF'
+OE_TERMINAL_EXPORTS[type] = 'list'
+
+XAUTHORITY ?= "${HOME}/.Xauthority"
+SHELL ?= "bash"
+
+def oe_terminal_prioritized():
+ import oe.terminal
+ return " ".join(o.name for o in oe.terminal.prioritized())
+
+def emit_terminal_func(command, envdata, d):
+ import bb.build
+ cmd_func = 'do_terminal'
+
+ envdata.setVar(cmd_func, 'exec ' + command)
+ envdata.setVarFlag(cmd_func, 'func', '1')
+
+ runfmt = d.getVar('BB_RUNFMT') or "run.{func}.{pid}"
+ runfile = runfmt.format(func=cmd_func, task=cmd_func, taskfunc=cmd_func, pid=os.getpid())
+ runfile = os.path.join(d.getVar('T'), runfile)
+ bb.utils.mkdirhier(os.path.dirname(runfile))
+
+ with open(runfile, 'w') as script:
+ script.write(bb.build.shell_trap_code())
+ bb.data.emit_func(cmd_func, script, envdata)
+ script.write(cmd_func)
+ script.write("\n")
+ os.chmod(runfile, 0o755)
+
+ return runfile
+
+def oe_terminal(command, title, d):
+ import oe.data
+ import oe.terminal
+
+ envdata = bb.data.init()
+
+ for v in os.environ:
+ envdata.setVar(v, os.environ[v])
+ envdata.setVarFlag(v, 'export', '1')
+
+ for export in oe.data.typed_value('OE_TERMINAL_EXPORTS', d):
+ value = d.getVar(export)
+ if value is not None:
+ os.environ[export] = str(value)
+ envdata.setVar(export, str(value))
+ envdata.setVarFlag(export, 'export', '1')
+ if export == "PSEUDO_DISABLED":
+ if "PSEUDO_UNLOAD" in os.environ:
+ del os.environ["PSEUDO_UNLOAD"]
+ envdata.delVar("PSEUDO_UNLOAD")
+
+ # Add in all variables from the user's original environment which
+ # haven't subsequntly been set/changed
+ origbbenv = d.getVar("BB_ORIGENV", False) or {}
+ for key in origbbenv:
+ if key in envdata:
+ continue
+ value = origbbenv.getVar(key)
+ if value is not None:
+ os.environ[key] = str(value)
+ envdata.setVar(key, str(value))
+ envdata.setVarFlag(key, 'export', '1')
+
+ # Use original PATH as a fallback
+ path = d.getVar('PATH') + ":" + origbbenv.getVar('PATH')
+ os.environ['PATH'] = path
+ envdata.setVar('PATH', path)
+
+ # A complex PS1 might need more escaping of chars.
+ # Lets not export PS1 instead.
+ envdata.delVar("PS1")
+
+ # Replace command with an executable wrapper script
+ command = emit_terminal_func(command, envdata, d)
+
+ terminal = oe.data.typed_value('OE_TERMINAL', d).lower()
+ if terminal == 'none':
+ bb.fatal('Devshell usage disabled with OE_TERMINAL')
+ elif terminal != 'auto':
+ try:
+ oe.terminal.spawn(terminal, command, title, None, d)
+ return
+ except oe.terminal.UnsupportedTerminal:
+ bb.warn('Unsupported terminal "%s", defaulting to "auto"' %
+ terminal)
+ except oe.terminal.ExecutionError as exc:
+ bb.fatal('Unable to spawn terminal %s: %s' % (terminal, exc))
+
+ try:
+ oe.terminal.spawn_preferred(command, title, None, d)
+ except oe.terminal.NoSupportedTerminals as nosup:
+ nosup.terms.remove("false")
+ cmds = '\n\t'.join(nosup.terms).replace("{command}",
+ "do_terminal").replace("{title}", title)
+ bb.fatal('No valid terminal found, unable to open devshell.\n' +
+ 'Tried the following commands:\n\t%s' % cmds)
+ except oe.terminal.ExecutionError as exc:
+ bb.fatal('Unable to spawn terminal %s: %s' % (terminal, exc))
+
+oe_terminal[vardepsexclude] = "BB_ORIGENV"
diff --git a/meta/lib/oe/classutils.py b/meta/lib/oe/classutils.py
new file mode 100644
index 0000000..d879191
--- /dev/null
+++ b/meta/lib/oe/classutils.py
@@ -0,0 +1,49 @@
+#
+# Imported from openembedded-core
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
+
+class ClassRegistryMeta(type):
+ """Give each ClassRegistry their own registry"""
+ def __init__(cls, name, bases, attrs):
+ cls.registry = {}
+ type.__init__(cls, name, bases, attrs)
+
+class ClassRegistry(type, metaclass=ClassRegistryMeta):
+ """Maintain a registry of classes, indexed by name.
+
+Note that this implementation requires that the names be unique, as it uses
+a dictionary to hold the classes by name.
+
+The name in the registry can be overridden via the 'name' attribute of the
+class, and the 'priority' attribute controls priority. The prioritized()
+method returns the registered classes in priority order.
+
+Subclasses of ClassRegistry may define an 'implemented' property to exert
+control over whether the class will be added to the registry (e.g. to keep
+abstract base classes out of the registry)."""
+ priority = 0
+ def __init__(cls, name, bases, attrs):
+ super(ClassRegistry, cls).__init__(name, bases, attrs)
+ try:
+ if not cls.implemented:
+ return
+ except AttributeError:
+ pass
+
+ try:
+ cls.name
+ except AttributeError:
+ cls.name = name
+ cls.registry[cls.name] = cls
+
+ @classmethod
+ def prioritized(tcls):
+ return sorted(list(tcls.registry.values()),
+ key=lambda v: (v.priority, v.name), reverse=True)
+
+ def unregister(cls):
+ for key in cls.registry.keys():
+ if cls.registry[key] is cls:
+ del cls.registry[key]
diff --git a/meta/lib/oe/data.py b/meta/lib/oe/data.py
new file mode 100644
index 0000000..b832e9b
--- /dev/null
+++ b/meta/lib/oe/data.py
@@ -0,0 +1,53 @@
+#
+# Imported from openembedded-core
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
+
+import json
+import oe.maketype
+
+def typed_value(key, d):
+ """Construct a value for the specified metadata variable, using its flags
+ to determine the type and parameters for construction."""
+ var_type = d.getVarFlag(key, 'type')
+ flags = d.getVarFlags(key)
+ if flags is not None:
+ flags = dict((flag, d.expand(value))
+ for flag, value in list(flags.items()))
+ else:
+ flags = {}
+
+ try:
+ return oe.maketype.create(d.getVar(key) or '', var_type, **flags)
+ except (TypeError, ValueError) as exc:
+ bb.msg.fatal("Data", "%s: %s" % (key, str(exc)))
+
+def export2json(d, json_file, expand=True, searchString="",replaceString=""):
+ data2export = {}
+ keys2export = []
+
+ for key in d.keys():
+ if key.startswith("_"):
+ continue
+ elif key.startswith("BB"):
+ continue
+ elif key.startswith("B_pn"):
+ continue
+ elif key.startswith("do_"):
+ continue
+ elif d.getVarFlag(key, "func"):
+ continue
+
+ keys2export.append(key)
+
+ for key in keys2export:
+ try:
+ data2export[key] = d.getVar(key, expand).replace(searchString,replaceString)
+ except bb.data_smart.ExpansionError:
+ data2export[key] = ''
+ except AttributeError:
+ pass
+
+ with open(json_file, "w") as f:
+ json.dump(data2export, f, skipkeys=True, indent=4, sort_keys=True)
diff --git a/meta/lib/oe/maketype.py b/meta/lib/oe/maketype.py
new file mode 100644
index 0000000..969a22b
--- /dev/null
+++ b/meta/lib/oe/maketype.py
@@ -0,0 +1,112 @@
+#
+# Imported from openembedded-core
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
+"""OpenEmbedded variable typing support
+
+Types are defined in the metadata by name, using the 'type' flag on a
+variable. Other flags may be utilized in the construction of the types. See
+the arguments of the type's factory for details.
+"""
+
+import inspect
+import oe.types as types
+try:
+ # Python 3.7+
+ from collections.abc import Callable
+except ImportError:
+ # Python < 3.7
+ from collections import Callable
+
+available_types = {}
+
+class MissingFlag(TypeError):
+ """A particular flag is required to construct the type, but has not been
+ provided."""
+ def __init__(self, flag, type):
+ self.flag = flag
+ self.type = type
+ TypeError.__init__(self)
+
+ def __str__(self):
+ return "Type '%s' requires flag '%s'" % (self.type, self.flag)
+
+def factory(var_type):
+ """Return the factory for a specified type."""
+ if var_type is None:
+ raise TypeError("No type specified. Valid types: %s" %
+ ', '.join(available_types))
+ try:
+ return available_types[var_type]
+ except KeyError:
+ raise TypeError("Invalid type '%s':\n Valid types: %s" %
+ (var_type, ', '.join(available_types)))
+
+def create(value, var_type, **flags):
+ """Create an object of the specified type, given the specified flags and
+ string value."""
+ obj = factory(var_type)
+ objflags = {}
+ for flag in obj.flags:
+ if flag not in flags:
+ if flag not in obj.optflags:
+ raise MissingFlag(flag, var_type)
+ else:
+ objflags[flag] = flags[flag]
+
+ return obj(value, **objflags)
+
+def get_callable_args(obj):
+ """Grab all but the first argument of the specified callable, returning
+ the list, as well as a list of which of the arguments have default
+ values."""
+ if type(obj) is type:
+ obj = obj.__init__
+
+ sig = inspect.signature(obj)
+ args = list(sig.parameters.keys())
+ defaults = list(s for s in sig.parameters.keys() if sig.parameters[s].default != inspect.Parameter.empty)
+ flaglist = []
+ if args:
+ if len(args) > 1 and args[0] == 'self':
+ args = args[1:]
+ flaglist.extend(args)
+
+ optional = set()
+ if defaults:
+ optional |= set(flaglist[-len(defaults):])
+ return flaglist, optional
+
+def factory_setup(name, obj):
+ """Prepare a factory for use."""
+ args, optional = get_callable_args(obj)
+ extra_args = args[1:]
+ if extra_args:
+ obj.flags, optional = extra_args, optional
+ obj.optflags = set(optional)
+ else:
+ obj.flags = obj.optflags = ()
+
+ if not hasattr(obj, 'name'):
+ obj.name = name
+
+def register(name, factory):
+ """Register a type, given its name and a factory callable.
+
+ Determines the required and optional flags from the factory's
+ arguments."""
+ factory_setup(name, factory)
+ available_types[factory.name] = factory
+
+
+# Register all our included types
+for name in dir(types):
+ if name.startswith('_'):
+ continue
+
+ obj = getattr(types, name)
+ if not isinstance(obj, Callable):
+ continue
+
+ register(name, obj)
diff --git a/meta/lib/oe/terminal.py b/meta/lib/oe/terminal.py
new file mode 100644
index 0000000..0d875c3
--- /dev/null
+++ b/meta/lib/oe/terminal.py
@@ -0,0 +1,315 @@
+#
+# Imported from openembedded-core
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
+import logging
+import oe.classutils
+import shlex
+from bb.process import Popen, ExecutionError
+from distutils.version import LooseVersion
+
+logger = logging.getLogger('BitBake.OE.Terminal')
+
+
+class UnsupportedTerminal(Exception):
+ pass
+
+class NoSupportedTerminals(Exception):
+ def __init__(self, terms):
+ self.terms = terms
+
+
+class Registry(oe.classutils.ClassRegistry):
+ command = None
+
+ def __init__(cls, name, bases, attrs):
+ super(Registry, cls).__init__(name.lower(), bases, attrs)
+
+ @property
+ def implemented(cls):
+ return bool(cls.command)
+
+
+class Terminal(Popen, metaclass=Registry):
+ def __init__(self, sh_cmd, title=None, env=None, d=None):
+ fmt_sh_cmd = self.format_command(sh_cmd, title)
+ try:
+ Popen.__init__(self, fmt_sh_cmd, env=env)
+ except OSError as exc:
+ import errno
+ if exc.errno == errno.ENOENT:
+ raise UnsupportedTerminal(self.name)
+ else:
+ raise
+
+ def format_command(self, sh_cmd, title):
+ fmt = {'title': title or 'Terminal', 'command': sh_cmd, 'cwd': os.getcwd() }
+ if isinstance(self.command, str):
+ return shlex.split(self.command.format(**fmt))
+ else:
+ return [element.format(**fmt) for element in self.command]
+
+class XTerminal(Terminal):
+ def __init__(self, sh_cmd, title=None, env=None, d=None):
+ Terminal.__init__(self, sh_cmd, title, env, d)
+ if not os.environ.get('DISPLAY'):
+ raise UnsupportedTerminal(self.name)
+
+class Gnome(XTerminal):
+ command = 'gnome-terminal -t "{title}" -x {command}'
+ priority = 2
+
+ def __init__(self, sh_cmd, title=None, env=None, d=None):
+ # Recent versions of gnome-terminal does not support non-UTF8 charset:
+ # https://bugzilla.gnome.org/show_bug.cgi?id=732127; as a workaround,
+ # clearing the LC_ALL environment variable so it uses the locale.
+ # Once fixed on the gnome-terminal project, this should be removed.
+ if os.getenv('LC_ALL'): os.putenv('LC_ALL','')
+
+ XTerminal.__init__(self, sh_cmd, title, env, d)
+
+class Mate(XTerminal):
+ command = 'mate-terminal --disable-factory -t "{title}" -x {command}'
+ priority = 2
+
+class Xfce(XTerminal):
+ command = 'xfce4-terminal -T "{title}" -e "{command}"'
+ priority = 2
+
+class Terminology(XTerminal):
+ command = 'terminology -T="{title}" -e {command}'
+ priority = 2
+
+class Konsole(XTerminal):
+ command = 'konsole --separate --workdir . -p tabtitle="{title}" -e {command}'
+ priority = 2
+
+ def __init__(self, sh_cmd, title=None, env=None, d=None):
+ # Check version
+ vernum = check_terminal_version("konsole")
+ if vernum and LooseVersion(vernum) < '2.0.0':
+ # Konsole from KDE 3.x
+ self.command = 'konsole -T "{title}" -e {command}'
+ elif vernum and LooseVersion(vernum) < '16.08.1':
+ # Konsole pre 16.08.01 Has nofork
+ self.command = 'konsole --nofork --workdir . -p tabtitle="{title}" -e {command}'
+ XTerminal.__init__(self, sh_cmd, title, env, d)
+
+class XTerm(XTerminal):
+ command = 'xterm -T "{title}" -e {command}'
+ priority = 1
+
+class Rxvt(XTerminal):
+ command = 'rxvt -T "{title}" -e {command}'
+ priority = 1
+
+class Screen(Terminal):
+ command = 'screen -D -m -t "{title}" -S devshell {command}'
+
+ def __init__(self, sh_cmd, title=None, env=None, d=None):
+ s_id = "devshell_%i" % os.getpid()
+ self.command = "screen -D -m -t \"{title}\" -S %s {command}" % s_id
+ Terminal.__init__(self, sh_cmd, title, env, d)
+ msg = 'Screen started. Please connect in another terminal with ' \
+ '"screen -r %s"' % s_id
+ if (d):
+ bb.event.fire(bb.event.LogExecTTY(msg, "screen -r %s" % s_id,
+ 0.5, 10), d)
+ else:
+ logger.warning(msg)
+
+class TmuxRunning(Terminal):
+ """Open a new pane in the current running tmux window"""
+ name = 'tmux-running'
+ command = 'tmux split-window -c "{cwd}" "{command}"'
+ priority = 2.75
+
+ def __init__(self, sh_cmd, title=None, env=None, d=None):
+ if not bb.utils.which(os.getenv('PATH'), 'tmux'):
+ raise UnsupportedTerminal('tmux is not installed')
+
+ if not os.getenv('TMUX'):
+ raise UnsupportedTerminal('tmux is not running')
+
+ if not check_tmux_pane_size('tmux'):
+ raise UnsupportedTerminal('tmux pane too small or tmux < 1.9 version is being used')
+
+ Terminal.__init__(self, sh_cmd, title, env, d)
+
+class TmuxNewWindow(Terminal):
+ """Open a new window in the current running tmux session"""
+ name = 'tmux-new-window'
+ command = 'tmux new-window -c "{cwd}" -n "{title}" "{command}"'
+ priority = 2.70
+
+ def __init__(self, sh_cmd, title=None, env=None, d=None):
+ if not bb.utils.which(os.getenv('PATH'), 'tmux'):
+ raise UnsupportedTerminal('tmux is not installed')
+
+ if not os.getenv('TMUX'):
+ raise UnsupportedTerminal('tmux is not running')
+
+ Terminal.__init__(self, sh_cmd, title, env, d)
+
+class Tmux(Terminal):
+ """Start a new tmux session and window"""
+ command = 'tmux new -c "{cwd}" -d -s devshell -n devshell "{command}"'
+ priority = 0.75
+
+ def __init__(self, sh_cmd, title=None, env=None, d=None):
+ if not bb.utils.which(os.getenv('PATH'), 'tmux'):
+ raise UnsupportedTerminal('tmux is not installed')
+
+ # TODO: consider using a 'devshell' session shared amongst all
+ # devshells, if it's already there, add a new window to it.
+ window_name = 'devshell-%i' % os.getpid()
+
+ self.command = 'tmux new -c "{{cwd}}" -d -s {0} -n {0} "{{command}}"'.format(window_name)
+ Terminal.__init__(self, sh_cmd, title, env, d)
+
+ attach_cmd = 'tmux att -t {0}'.format(window_name)
+ msg = 'Tmux started. Please connect in another terminal with `tmux att -t {0}`'.format(window_name)
+ if d:
+ bb.event.fire(bb.event.LogExecTTY(msg, attach_cmd, 0.5, 10), d)
+ else:
+ logger.warning(msg)
+
+class Custom(Terminal):
+ command = 'false' # This is a placeholder
+ priority = 3
+
+ def __init__(self, sh_cmd, title=None, env=None, d=None):
+ self.command = d and d.getVar('OE_TERMINAL_CUSTOMCMD')
+ if self.command:
+ if not '{command}' in self.command:
+ self.command += ' {command}'
+ Terminal.__init__(self, sh_cmd, title, env, d)
+ logger.warning('Custom terminal was started.')
+ else:
+ logger.debug(1, 'No custom terminal (OE_TERMINAL_CUSTOMCMD) set')
+ raise UnsupportedTerminal('OE_TERMINAL_CUSTOMCMD not set')
+
+
+def prioritized():
+ return Registry.prioritized()
+
+def get_cmd_list():
+ terms = Registry.prioritized()
+ cmds = []
+ for term in terms:
+ if term.command:
+ cmds.append(term.command)
+ return cmds
+
+def spawn_preferred(sh_cmd, title=None, env=None, d=None):
+ """Spawn the first supported terminal, by priority"""
+ for terminal in prioritized():
+ try:
+ spawn(terminal.name, sh_cmd, title, env, d)
+ break
+ except UnsupportedTerminal:
+ continue
+ else:
+ raise NoSupportedTerminals(get_cmd_list())
+
+def spawn(name, sh_cmd, title=None, env=None, d=None):
+ """Spawn the specified terminal, by name"""
+ logger.debug(1, 'Attempting to spawn terminal "%s"', name)
+ try:
+ terminal = Registry.registry[name]
+ except KeyError:
+ raise UnsupportedTerminal(name)
+
+ # We need to know when the command completes but some terminals (at least
+ # gnome and tmux) gives us no way to do this. We therefore write the pid
+ # to a file using a "phonehome" wrapper script, then monitor the pid
+ # until it exits.
+ import tempfile
+ import time
+ pidfile = tempfile.NamedTemporaryFile(delete = False).name
+ try:
+ sh_cmd = bb.utils.which(os.getenv('PATH'), "oe-gnome-terminal-phonehome") + " " + pidfile + " " + sh_cmd
+ pipe = terminal(sh_cmd, title, env, d)
+ output = pipe.communicate()[0]
+ if output:
+ output = output.decode("utf-8")
+ if pipe.returncode != 0:
+ raise ExecutionError(sh_cmd, pipe.returncode, output)
+
+ while os.stat(pidfile).st_size <= 0:
+ time.sleep(0.01)
+ continue
+ with open(pidfile, "r") as f:
+ pid = int(f.readline())
+ finally:
+ os.unlink(pidfile)
+
+ while True:
+ try:
+ os.kill(pid, 0)
+ time.sleep(0.1)
+ except OSError:
+ return
+
+def check_tmux_pane_size(tmux):
+ import subprocess as sub
+ # On older tmux versions (<1.9), return false. The reason
+ # is that there is no easy way to get the height of the active panel
+ # on current window without nested formats (available from version 1.9)
+ vernum = check_terminal_version("tmux")
+ if vernum and LooseVersion(vernum) < '1.9':
+ return False
+ try:
+ p = sub.Popen('%s list-panes -F "#{?pane_active,#{pane_height},}"' % tmux,
+ shell=True,stdout=sub.PIPE,stderr=sub.PIPE)
+ out, err = p.communicate()
+ size = int(out.strip())
+ except OSError as exc:
+ import errno
+ if exc.errno == errno.ENOENT:
+ return None
+ else:
+ raise
+
+ return size/2 >= 19
+
+def check_terminal_version(terminalName):
+ import subprocess as sub
+ try:
+ cmdversion = '%s --version' % terminalName
+ if terminalName.startswith('tmux'):
+ cmdversion = '%s -V' % terminalName
+ newenv = os.environ.copy()
+ newenv["LANG"] = "C"
+ p = sub.Popen(['sh', '-c', cmdversion], stdout=sub.PIPE, stderr=sub.PIPE, env=newenv)
+ out, err = p.communicate()
+ ver_info = out.decode().rstrip().split('\n')
+ except OSError as exc:
+ import errno
+ if exc.errno == errno.ENOENT:
+ return None
+ else:
+ raise
+ vernum = None
+ for ver in ver_info:
+ if ver.startswith('Konsole'):
+ vernum = ver.split(' ')[-1]
+ if ver.startswith('GNOME Terminal'):
+ vernum = ver.split(' ')[-1]
+ if ver.startswith('MATE Terminal'):
+ vernum = ver.split(' ')[-1]
+ if ver.startswith('tmux'):
+ vernum = ver.split()[-1]
+ if ver.startswith('tmux next-'):
+ vernum = ver.split()[-1][5:]
+ return vernum
+
+def distro_name():
+ try:
+ p = Popen(['lsb_release', '-i'])
+ out, err = p.communicate()
+ distro = out.split(':')[1].strip().lower()
+ except:
+ distro = "unknown"
+ return distro
diff --git a/meta/lib/oe/types.py b/meta/lib/oe/types.py
new file mode 100644
index 0000000..ad8dd36
--- /dev/null
+++ b/meta/lib/oe/types.py
@@ -0,0 +1,187 @@
+#
+# Imported from openembedded-core
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
+
+import errno
+import re
+import os
+
+
+class OEList(list):
+ """OpenEmbedded 'list' type
+
+ Acts as an ordinary list, but is constructed from a string value and a
+ separator (optional), and re-joins itself when converted to a string with
+ str(). Set the variable type flag to 'list' to use this type, and the
+ 'separator' flag may be specified (defaulting to whitespace)."""
+
+ name = "list"
+
+ def __init__(self, value, separator = None):
+ if value is not None:
+ list.__init__(self, value.split(separator))
+ else:
+ list.__init__(self)
+
+ if separator is None:
+ self.separator = " "
+ else:
+ self.separator = separator
+
+ def __str__(self):
+ return self.separator.join(self)
+
+def choice(value, choices):
+ """OpenEmbedded 'choice' type
+
+ Acts as a multiple choice for the user. To use this, set the variable
+ type flag to 'choice', and set the 'choices' flag to a space separated
+ list of valid values."""
+ if not isinstance(value, str):
+ raise TypeError("choice accepts a string, not '%s'" % type(value))
+
+ value = value.lower()
+ choices = choices.lower()
+ if value not in choices.split():
+ raise ValueError("Invalid choice '%s'. Valid choices: %s" %
+ (value, choices))
+ return value
+
+class NoMatch(object):
+ """Stub python regex pattern object which never matches anything"""
+ def findall(self, string, flags=0):
+ return None
+
+ def finditer(self, string, flags=0):
+ return None
+
+ def match(self, flags=0):
+ return None
+
+ def search(self, string, flags=0):
+ return None
+
+ def split(self, string, maxsplit=0):
+ return None
+
+ def sub(pattern, repl, string, count=0):
+ return None
+
+ def subn(pattern, repl, string, count=0):
+ return None
+
+NoMatch = NoMatch()
+
+def regex(value, regexflags=None):
+ """OpenEmbedded 'regex' type
+
+ Acts as a regular expression, returning the pre-compiled regular
+ expression pattern object. To use this type, set the variable type flag
+ to 'regex', and optionally, set the 'regexflags' type to a space separated
+ list of the flags to control the regular expression matching (e.g.
+ FOO[regexflags] += 'ignorecase'). See the python documentation on the
+ 're' module for a list of valid flags."""
+
+ flagval = 0
+ if regexflags:
+ for flag in regexflags.split():
+ flag = flag.upper()
+ try:
+ flagval |= getattr(re, flag)
+ except AttributeError:
+ raise ValueError("Invalid regex flag '%s'" % flag)
+
+ if not value:
+ # Let's ensure that the default behavior for an undefined or empty
+ # variable is to match nothing. If the user explicitly wants to match
+ # anything, they can match '.*' instead.
+ return NoMatch
+
+ try:
+ return re.compile(value, flagval)
+ except re.error as exc:
+ raise ValueError("Invalid regex value '%s': %s" %
+ (value, exc.args[0]))
+
+def boolean(value):
+ """OpenEmbedded 'boolean' type
+
+ Valid values for true: 'yes', 'y', 'true', 't', '1'
+ Valid values for false: 'no', 'n', 'false', 'f', '0', None
+ """
+ if value is None:
+ return False
+
+ if isinstance(value, bool):
+ return value
+
+ if not isinstance(value, str):
+ raise TypeError("boolean accepts a string, not '%s'" % type(value))
+
+ value = value.lower()
+ if value in ('yes', 'y', 'true', 't', '1'):
+ return True
+ elif value in ('no', 'n', 'false', 'f', '0'):
+ return False
+ raise ValueError("Invalid boolean value '%s'" % value)
+
+def integer(value, numberbase=10):
+ """OpenEmbedded 'integer' type
+
+ Defaults to base 10, but this can be specified using the optional
+ 'numberbase' flag."""
+
+ return int(value, int(numberbase))
+
+_float = float
+def float(value, fromhex='false'):
+ """OpenEmbedded floating point type
+
+ To use this type, set the type flag to 'float', and optionally set the
+ 'fromhex' flag to a true value (obeying the same rules as for the
+ 'boolean' type) if the value is in base 16 rather than base 10."""
+
+ if boolean(fromhex):
+ return _float.fromhex(value)
+ else:
+ return _float(value)
+
+def path(value, relativeto='', normalize='true', mustexist='false'):
+ value = os.path.join(relativeto, value)
+
+ if boolean(normalize):
+ value = os.path.normpath(value)
+
+ if boolean(mustexist):
+ try:
+ open(value, 'r')
+ except IOError as exc:
+ if exc.errno == errno.ENOENT:
+ raise ValueError("{0}: {1}".format(value, os.strerror(errno.ENOENT)))
+
+ return value
+
+def is_x86(arch):
+ """
+ Check whether arch is x86 or x86_64
+ """
+ if arch.startswith('x86_') or re.match('i.*86', arch):
+ return True
+ else:
+ return False
+
+def qemu_use_kvm(kvm, target_arch):
+ """
+ Enable kvm if target_arch == build_arch or both of them are x86 archs.
+ """
+
+ use_kvm = False
+ if kvm and boolean(kvm):
+ build_arch = os.uname()[4]
+ if is_x86(build_arch) and is_x86(target_arch):
+ use_kvm = True
+ elif build_arch == target_arch:
+ use_kvm = True
+ return use_kvm
diff --git a/scripts/oe-gnome-terminal-phonehome b/scripts/oe-gnome-terminal-phonehome
new file mode 100755
index 0000000..5a321a2
--- /dev/null
+++ b/scripts/oe-gnome-terminal-phonehome
@@ -0,0 +1,14 @@
+#!/bin/sh
+#
+# Imported from openembedded-core
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Gnome terminal won't tell us which PID a given command is run as
+# or allow a single instance so we can't tell when it completes.
+# This allows us to figure out the PID of the target so we can tell
+# when its done.
+#
+echo $$ > $1
+shift
+exec $@
--
2.16.4
next prev parent reply other threads:[~2019-09-22 18:17 UTC|newest]
Thread overview: 78+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-09-22 18:16 [PATCH v5 00/27] Pending patches, fix for isar-bootstrap, devshell Jan Kiszka
2019-09-22 18:16 ` [PATCH v5 01/27] buildchroot: Properly deploy the build result Jan Kiszka
2019-09-22 18:16 ` [PATCH v5 02/27] sdk: Use clean-package-cache rather than open-coded cleanup Jan Kiszka
2019-09-22 18:16 ` [PATCH v5 03/27] sdk: Deploy earlier Jan Kiszka
2019-09-22 18:16 ` [PATCH v5 04/27] Remove unneeded PF tweakings Jan Kiszka
2019-09-22 18:16 ` [PATCH v5 05/27] image: Stop changing PF, tune WORKDIR and STAMP directly Jan Kiszka
2019-09-25 12:47 ` [PATCH v6 " Jan Kiszka
2019-09-22 18:16 ` [PATCH v5 06/27] image: Make WORKDIR and STAMPs IMAGE_TYPE-specific Jan Kiszka
2019-09-22 18:16 ` [PATCH v5 07/27] Adjust STAMP variables to use PN, rather than PF Jan Kiszka
2019-09-22 18:16 ` [PATCH v5 08/27] Align WORKDIR structure with OE Jan Kiszka
2019-09-22 18:16 ` [PATCH v5 09/27] isar-bootstrap: Unshare host bootstraps across different target distros Jan Kiszka
2019-09-22 18:16 ` [PATCH v5 10/27] isar-bootstrap: Clean up and fix rebuild Jan Kiszka
2019-09-22 18:16 ` [PATCH v5 11/27] gitlab-ci: Keep logs as artifacts on failure Jan Kiszka
2019-09-22 18:16 ` [PATCH v5 12/27] Detect false sharing of recipes Jan Kiszka
2019-09-24 18:02 ` [PATCH v6 " Jan Kiszka
2019-09-29 14:57 ` Baurzhan Ismagulov
2019-09-30 6:00 ` Jan Kiszka
2019-09-30 9:56 ` Baurzhan Ismagulov
2019-09-30 10:14 ` Jan Kiszka
2019-09-30 14:53 ` Baurzhan Ismagulov
2019-09-30 15:26 ` Jan Kiszka
2019-09-30 15:39 ` Baurzhan Ismagulov
2019-09-30 16:34 ` Jan Kiszka
2019-09-30 17:20 ` Baurzhan Ismagulov
2019-09-30 17:26 ` Jan Kiszka
2019-09-30 20:29 ` Baurzhan Ismagulov
2019-09-22 18:16 ` [PATCH v5 13/27] dpkg-base: Move do_deploy_deb before do_build Jan Kiszka
2019-10-02 7:09 ` Baurzhan Ismagulov
2019-09-22 18:16 ` [PATCH v5 14/27] base-apt: Move do_cache_config " Jan Kiszka
2019-09-22 18:16 ` [PATCH v5 15/27] wic-img: Use private tmp dir Jan Kiszka
2019-09-22 18:17 ` [PATCH v5 16/27] rootfs: Take isar-apt shared lock during repository operations Jan Kiszka
2019-09-22 18:17 ` [PATCH v5 17/27] Use deb.debian.org mirrors Jan Kiszka
2019-09-23 10:03 ` Baurzhan Ismagulov
2019-09-23 10:09 ` Jan Kiszka
2019-10-02 11:13 ` Baurzhan Ismagulov
2019-09-22 18:17 ` [PATCH v5 18/27] linux-custom: Control linux-libc-dev deployment manually Jan Kiszka
2019-09-22 18:17 ` [PATCH v5 19/27] dpkg-base: Wait for umount to succeed Jan Kiszka
2019-09-30 11:07 ` Baurzhan Ismagulov
2019-09-30 12:22 ` Jan Kiszka
2019-09-30 13:33 ` Baurzhan Ismagulov
2019-10-07 15:48 ` Baurzhan Ismagulov
2019-09-22 18:17 ` [PATCH v5 20/27] dpkg-base: Permit multiple clean runs Jan Kiszka
2019-09-22 18:17 ` [PATCH v5 21/27] buildchroot: Factor out common packages Jan Kiszka
2019-09-22 18:17 ` [PATCH v5 22/27] buildchroot: Do not build cross when there are no arch-specific outputs Jan Kiszka
2019-09-22 18:17 ` [PATCH v5 23/27] Add git-buildpackage support Jan Kiszka
2019-09-22 18:17 ` [PATCH v5 24/27] dbpg-raw: Only list top-level files in <pn>.install Jan Kiszka
2019-09-23 9:52 ` Baurzhan Ismagulov
2019-09-23 10:29 ` Jan Kiszka
2019-09-23 10:30 ` Baurzhan Ismagulov
2019-09-22 18:17 ` Jan Kiszka [this message]
2019-09-22 18:17 ` [PATCH v5 26/27] dpkg-base: Add devshell target Jan Kiszka
2019-09-22 18:17 ` [PATCH v5 27/27] linux-custom: Add libncurses-dev to KBUILD_DEPENDS Jan Kiszka
2019-09-23 6:33 ` [PATCH v5 00/27] Pending patches, fix for isar-bootstrap, devshell Baurzhan Ismagulov
2019-09-23 7:33 ` Jan Kiszka
2019-09-23 7:50 ` Baurzhan Ismagulov
2019-09-23 9:50 ` Baurzhan Ismagulov
2019-09-23 10:07 ` Jan Kiszka
2019-09-23 10:23 ` Baurzhan Ismagulov
2019-09-23 10:28 ` Jan Kiszka
2019-09-25 8:41 ` Baurzhan Ismagulov
2019-09-25 8:51 ` Jan Kiszka
2019-09-25 9:22 ` Baurzhan Ismagulov
2019-09-25 9:26 ` Jan Kiszka
2019-09-25 9:35 ` Baurzhan Ismagulov
2019-09-25 9:35 ` Jan Kiszka
2019-09-25 10:52 ` Baurzhan Ismagulov
2019-09-25 11:05 ` Jan Kiszka
2019-09-25 12:08 ` Baurzhan Ismagulov
2019-09-25 12:29 ` Jan Kiszka
2019-09-25 12:44 ` Baurzhan Ismagulov
2019-09-23 14:24 ` Henning Schild
2019-09-28 15:46 ` Baurzhan Ismagulov
2019-09-25 10:23 ` Henning Schild
2019-09-25 11:41 ` Jan Kiszka
2019-09-30 9:29 ` Baurzhan Ismagulov
2019-09-30 10:02 ` Jan Kiszka
2019-09-30 13:00 ` Baurzhan Ismagulov
2019-10-01 14:47 ` Baurzhan Ismagulov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=b032b3fb4025e0f2a42ce714fd9db4960c869a9c.1569176231.git.jan.kiszka@siemens.com \
--to=jan.kiszka@siemens.com \
--cc=isar-users@googlegroups.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox