rtpjpegdepay: fix logic error when checking if an EOI is present
[platform/upstream/gstreamer.git] / gst-env.py
index 0fa40f5..a1868c1 100755 (executable)
@@ -1,25 +1,22 @@
 #!/usr/bin/env python3
 
 import argparse
-import contextlib
 import glob
 import json
 import os
 import platform
 import re
-import site
 import shlex
 import shutil
 import subprocess
-import sys
 import tempfile
 import pathlib
 import signal
 from functools import lru_cache
 from pathlib import PurePath, Path
+from sys import exit
 
-from distutils.sysconfig import get_python_lib
-from distutils.util import strtobool
+from typing import Any
 
 from scripts.common import get_meson
 from scripts.common import git
@@ -43,6 +40,28 @@ SHAREDLIB_REG = re.compile(r'\.so|\.dylib|\.dll')
 GSTPLUGIN_FILEPATH_REG_TEMPLATE = r'.*/{libdir}/gstreamer-1.0/[^/]+$'
 GSTPLUGIN_FILEPATH_REG = None
 
+BC_RC = '''
+BASH_COMPLETION_SCRIPTS="{bash_completions}"
+BASH_COMPLETION_PATHS="{bash_completions_paths}"
+for p in $BASH_COMPLETION_PATHS; do
+for f in $BASH_COMPLETION_SCRIPTS; do
+  [ -f "$p/$f" ] && . "$p/$f"
+done
+done
+'''
+BASH_COMPLETION_PATHS = [SCRIPTDIR + '/subprojects/gstreamer/data/bash-completion/completions']
+BASH_COMPLETION_PATHS += [SCRIPTDIR + '/subprojects/gst-devtools/validate/data/bash-completion/completions']
+
+
+def str_to_bool(value: Any) -> bool:
+    """Return whether the provided string (or any value really) represents true. Otherwise false.
+    Just like plugin server stringToBoolean.
+    """
+    if not value:
+        return False
+    return str(value).lower() in ("y", "yes", "t", "true", "on", "1")
+
+
 def listify(o):
     if isinstance(o, str):
         return [o]
@@ -50,6 +69,7 @@ def listify(o):
         return o
     raise AssertionError('Object {!r} must be a string or a list'.format(o))
 
+
 def stringify(o):
     if isinstance(o, str):
         return o
@@ -59,7 +79,10 @@ def stringify(o):
         raise AssertionError('Did not expect object {!r} to have more than one element'.format(o))
     raise AssertionError('Object {!r} must be a string or a list'.format(o))
 
+
 def prepend_env_var(env, var, value, sysroot):
+    if var is None:
+        return
     if value.startswith(sysroot):
         value = value[len(sysroot):]
     # Try not to exceed maximum length limits for env vars on Windows
@@ -73,6 +96,7 @@ def prepend_env_var(env, var, value, sysroot):
     env[var] = val + env_val
     env[var] = env[var].replace(os.pathsep + os.pathsep, os.pathsep).strip(os.pathsep)
 
+
 def get_target_install_filename(target, filename):
     '''
     Checks whether this file is one of the files installed by the target
@@ -83,6 +107,7 @@ def get_target_install_filename(target, filename):
             return install_filename
     return None
 
+
 def get_pkgconfig_variable_from_pcfile(pcfile, varname):
     variables = {}
     substre = re.compile('\$\{[^${}]+\}')
@@ -100,6 +125,7 @@ def get_pkgconfig_variable_from_pcfile(pcfile, varname):
             variables[key] = value
     return variables.get(varname, '')
 
+
 @lru_cache()
 def get_pkgconfig_variable(builddir, pcname, varname):
     '''
@@ -124,6 +150,7 @@ def is_gio_module(target, filename, builddir):
         return False
     return True
 
+
 def is_library_target_and_not_plugin(target, filename):
     '''
     Don't add plugins to PATH/LD_LIBRARY_PATH because:
@@ -146,6 +173,7 @@ def is_library_target_and_not_plugin(target, filename):
         return False
     return True
 
+
 def is_binary_target_and_in_path(target, filename, bindir):
     if target['type'] != 'executable':
         return False
@@ -177,6 +205,7 @@ def get_wine_subprocess_env(options, env):
 
     return env
 
+
 def setup_gdb(options):
     python_paths = set()
 
@@ -220,23 +249,36 @@ def setup_gdb(options):
     return python_paths
 
 
+def is_bash_completion_available(options):
+    return os.path.exists(os.path.join(options.builddir, 'subprojects/gstreamer/data/bash-completion/helpers/gst'))
+
+
 def get_subprocess_env(options, gst_version):
     env = os.environ.copy()
 
     env["CURRENT_GST"] = os.path.normpath(SCRIPTDIR)
     env["GST_VERSION"] = gst_version
-    env["GST_VALIDATE_SCENARIOS_PATH"] = os.path.normpath(
-        "%s/subprojects/gst-devtools/validate/data/scenarios" % SCRIPTDIR)
+    prepend_env_var(env, "GST_VALIDATE_SCENARIOS_PATH", os.path.normpath(
+        "%s/subprojects/gst-devtools/validate/data/scenarios" % SCRIPTDIR),
+        options.sysroot)
     env["GST_VALIDATE_PLUGIN_PATH"] = os.path.normpath(
         "%s/subprojects/gst-devtools/validate/plugins" % options.builddir)
-    env["GST_VALIDATE_APPS_DIR"] = os.path.normpath(
-        "%s/subprojects/gst-editing-services/tests/validate" % SCRIPTDIR)
-    env["GST_ENV"] = 'gst-' + gst_version
+    prepend_env_var(env, "GST_VALIDATE_APPS_DIR", os.path.normpath(
+        "%s/subprojects/gst-editing-services/tests/validate" % SCRIPTDIR),
+        options.sysroot)
+    env["GST_ENV"] = gst_version
     env["GST_REGISTRY"] = os.path.normpath(options.builddir + "/registry.dat")
     prepend_env_var(env, "PATH", os.path.normpath(
         "%s/subprojects/gst-devtools/validate/tools" % options.builddir),
         options.sysroot)
 
+    prepend_env_var(env, "GST_VALIDATE_SCENARIOS_PATH", os.path.normpath(
+        "%s/subprojects/gst-examples/webrtc/check/validate/scenarios" %
+        SCRIPTDIR), options.sysroot)
+    prepend_env_var(env, "GST_VALIDATE_APPS_DIR", os.path.normpath(
+        "%s/subprojects/gst-examples/webrtc/check/validate/apps" %
+        SCRIPTDIR), options.sysroot)
+
     if options.wine:
         return get_wine_subprocess_env(options, env)
 
@@ -252,7 +294,8 @@ def get_subprocess_env(options, gst_version):
     if os.name == 'nt':
         lib_path_envvar = 'PATH'
     elif platform.system() == 'Darwin':
-        lib_path_envvar = 'DYLD_LIBRARY_PATH'
+        # RPATH is sufficient on macOS, and DYLD_LIBRARY_PATH can cause issues with dynamic linker path priority
+        lib_path_envvar = None
     else:
         lib_path_envvar = 'LD_LIBRARY_PATH'
 
@@ -276,13 +319,17 @@ def get_subprocess_env(options, gst_version):
                     options.sysroot)
 
     # gst-indent
-    prepend_env_var(env, "PATH", os.path.join(SCRIPTDIR, 'gstreamer', 'tools'),
+    prepend_env_var(env, "PATH", os.path.join(SCRIPTDIR, 'scripts'),
                     options.sysroot)
 
     # tools: gst-launch-1.0, gst-inspect-1.0
     prepend_env_var(env, "PATH", os.path.join(options.builddir, 'subprojects',
                                               'gstreamer', 'tools'),
                     options.sysroot)
+    # plugin scanner and generator
+    prepend_env_var(env, "PATH", os.path.join(options.builddir, 'subprojects',
+                                              'gstreamer', 'docs'),
+                    options.sysroot)
     prepend_env_var(env, "PATH", os.path.join(options.builddir, 'subprojects',
                                               'gst-plugins-base', 'tools'),
                     options.sysroot)
@@ -344,10 +391,16 @@ def get_subprocess_env(options, gst_version):
                                 os.path.join(options.builddir, root),
                                 options.sysroot)
 
-    with open(os.path.join(options.builddir, 'GstPluginsPath.json')) as f:
-        for plugin_path in json.load(f):
-            prepend_env_var(env, 'GST_PLUGIN_PATH', plugin_path,
-                            options.sysroot)
+    # Search for the Plugin paths file either in the build directory root
+    # or check if gstreamer is a subproject of another project
+    for sub_directories in [[], ['subprojects', 'gstreamer']]:
+        plugin_paths = os.path.join(options.builddir, *sub_directories, 'GstPluginsPath.json')
+        if os.path.exists(plugin_paths):
+            with open(plugin_paths) as f:
+                for plugin_path in json.load(f):
+                    prepend_env_var(env, 'GST_PLUGIN_PATH', plugin_path,
+                                    options.sysroot)
+            break
 
     # Sort to iterate in a consistent order (`set`s and `hash`es are randomized)
     for p in sorted(paths):
@@ -360,11 +413,11 @@ def get_subprocess_env(options, gst_version):
     presets = set()
     encoding_targets = set()
     python_dirs = setup_gdb(options)
+    overrides_dirs = set()
     if '--installed' in subprocess.check_output(meson + ['introspect', '-h']).decode():
         installed_s = subprocess.check_output(meson + ['introspect', options.builddir, '--installed'])
         for path, installpath in json.loads(installed_s.decode()).items():
             installpath_parts = pathlib.Path(installpath).parts
-            path_parts = pathlib.Path(path).parts
 
             # We want to add all python modules to the PYTHONPATH
             # in a manner consistent with the way they would be imported:
@@ -377,10 +430,18 @@ def get_subprocess_env(options, gst_version):
             # /usr/lib/site-packages/foo/bar.py , we will not add anything
             # to PYTHONPATH, but the current approach works with pygobject
             # and gst-python at least.
+            py_package = None
             if 'site-packages' in installpath_parts:
-                install_subpath = os.path.join(*installpath_parts[installpath_parts.index('site-packages') + 1:])
+                py_package = 'site-packages'
+            elif 'dist-packages' in installpath_parts:
+                py_package = 'dist-packages'
+            if  py_package:
+                install_subpath = os.path.join(*installpath_parts[installpath_parts.index(py_package) + 1:])
                 if path.endswith(install_subpath):
-                    python_dirs.add(path[:len (install_subpath) * -1])
+                    if os.path.commonprefix(["gi/overrides", install_subpath]):
+                        overrides_dirs.add(os.path.dirname(path))
+                    else:
+                        python_dirs.add(path[:len(install_subpath) * -1])
 
             if path.endswith('.prs'):
                 presets.add(os.path.dirname(path))
@@ -406,21 +467,28 @@ def get_subprocess_env(options, gst_version):
     for python_dir in sorted(python_dirs):
         prepend_env_var(env, 'PYTHONPATH', python_dir, options.sysroot)
 
+    for python_dir in sorted(overrides_dirs):
+        prepend_env_var(env, '_GI_OVERRIDES_PATH', python_dir, options.sysroot)
+
     mesonpath = os.path.join(SCRIPTDIR, "meson")
     if os.path.join(mesonpath):
         # Add meson/ into PYTHONPATH if we are using a local meson
         prepend_env_var(env, 'PYTHONPATH', mesonpath, options.sysroot)
 
+    # Ensure that gst-python/gi is used first
+    prepend_env_var(env, "PYTHONPATH", os.path.join(SCRIPTDIR, 'subprojects', 'gst-python'),
+                    options.sysroot)
+
     # For devhelp books
     if 'XDG_DATA_DIRS' not in env or not env['XDG_DATA_DIRS']:
         # Preserve default paths when empty
         prepend_env_var(env, 'XDG_DATA_DIRS', '/usr/local/share/:/usr/share/', '')
 
-    prepend_env_var (env, 'XDG_DATA_DIRS', os.path.join(options.builddir,
-                                                        'subprojects',
-                                                        'gst-docs',
-                                                        'GStreamer-doc'),
-                     options.sysroot)
+    prepend_env_var(env, 'XDG_DATA_DIRS', os.path.join(options.builddir,
+                                                       'subprojects',
+                                                       'gst-docs',
+                                                       'GStreamer-doc'),
+                    options.sysroot)
 
     if 'XDG_CONFIG_DIRS' not in env or not env['XDG_CONFIG_DIRS']:
         # Preserve default paths when empty
@@ -431,11 +499,14 @@ def get_subprocess_env(options, gst_version):
 
     return env
 
+
 def get_windows_shell():
-    command = ['powershell.exe' ,'-noprofile', '-executionpolicy', 'bypass', '-file', 'cmd_or_ps.ps1']
-    result = subprocess.check_output(command, cwd=SCRIPTDIR)
+    command = ['powershell.exe', '-noprofile', '-executionpolicy', 'bypass', '-file',
+        os.path.join(SCRIPTDIR, 'data', 'misc', 'cmd_or_ps.ps1')]
+    result = subprocess.check_output(command)
     return result.decode().strip()
 
+
 if __name__ == "__main__":
     parser = argparse.ArgumentParser(prog="gst-env")
 
@@ -473,37 +544,52 @@ if __name__ == "__main__":
 
     # The following incantation will retrieve the current branch name.
     try:
-      gst_version = git("rev-parse", "--symbolic-full-name", "--abbrev-ref", "HEAD",
-                        repository_path=options.srcdir).strip('\n')
+        gst_version = git("rev-parse", "--symbolic-full-name", "--abbrev-ref", "HEAD",
+                          repository_path=options.srcdir).strip('\n')
     except subprocess.CalledProcessError:
-      gst_version = "unknown"
+        gst_version = "unknown"
 
     if options.wine:
         gst_version += '-' + os.path.basename(options.wine)
 
     env = get_subprocess_env(options, gst_version)
-    if not args:
-        if os.name == 'nt':
-            shell = get_windows_shell()
-            if shell == 'powershell.exe':
-                args = ['powershell.exe']
-                args += ['-NoLogo', '-NoExit']
-                prompt = 'function global:prompt {  "[gst-' + gst_version + '"+"] PS " + $PWD + "> "}'
-                args += ['-Command', prompt]
+    if os.name == 'nt':
+        shell = get_windows_shell()
+        if shell in ['powershell.exe', 'pwsh.exe']:
+            new_args = [shell, '-NoLogo']
+            if not args:
+                prompt = 'function global:prompt {  "[' + gst_version + '"+"] PS " + $PWD + "> "}'
+                new_args += ['-NoExit', '-Command', prompt]
             else:
-                args = [os.environ.get("COMSPEC", r"C:\WINDOWS\system32\cmd.exe")]
-                args += ['/k', 'prompt [gst-{}] $P$G'.format(gst_version)]
+                new_args += ['-NonInteractive', '-Command'] + args
+            args = new_args
         else:
+            new_args = [os.environ.get("COMSPEC", r"C:\WINDOWS\system32\cmd.exe")]
+            if not args:
+                new_args += ['/k', 'prompt [{}] $P$G'.format(gst_version)]
+            else:
+                new_args += ['/c', 'start', '/b', '/wait'] + args
+            args = new_args
+    if not args:
+        if os.name != 'nt':
             args = [os.environ.get("SHELL", os.path.realpath("/bin/sh"))]
-        if args[0].endswith('bash') and not strtobool(os.environ.get("GST_BUILD_DISABLE_PS1_OVERRIDE", r"FALSE")):
+        if args[0].endswith('bash') and not str_to_bool(os.environ.get("GST_BUILD_DISABLE_PS1_OVERRIDE", r"FALSE")):
             # Let the GC remove the tmp file
             tmprc = tempfile.NamedTemporaryFile(mode='w')
             bashrc = os.path.expanduser('~/.bashrc')
             if os.path.exists(bashrc):
                 with open(bashrc, 'r') as src:
                     shutil.copyfileobj(src, tmprc)
-            tmprc.write('\nexport PS1="[gst-%s] $PS1"' % gst_version)
+            tmprc.write('\nexport PS1="[%s] $PS1"' % gst_version)
             tmprc.flush()
+            if is_bash_completion_available(options):
+                bash_completions_files = []
+                for p in BASH_COMPLETION_PATHS:
+                    if os.path.exists(p):
+                        bash_completions_files += os.listdir(path=p)
+                bc_rc = BC_RC.format(bash_completions=' '.join(bash_completions_files), bash_completions_paths=' '.join(BASH_COMPLETION_PATHS))
+                tmprc.write(bc_rc)
+                tmprc.flush()
             args.append("--rcfile")
             args.append(tmprc.name)
         elif args[0].endswith('fish'):
@@ -515,7 +601,7 @@ if __name__ == "__main__":
             args.append('--init-command')
             prompt_cmd = '''functions --copy fish_prompt original_fish_prompt
             function fish_prompt
-                echo -n '[gst-{}] '(original_fish_prompt)
+                echo -n '[{}] '(original_fish_prompt)
             end'''.format(gst_version)
             args.append(prompt_cmd)
         elif args[0].endswith('zsh'):
@@ -526,7 +612,7 @@ if __name__ == "__main__":
             if os.path.exists(zshrc):
                 with open(zshrc, 'r') as src:
                     shutil.copyfileobj(src, tmprc)
-            tmprc.write('\nexport PROMPT="[gst-{}] $PROMPT"'.format(gst_version))
+            tmprc.write('\nexport PROMPT="[{}] $PROMPT"'.format(gst_version))
             tmprc.flush()
             env['ZDOTDIR'] = tmpdir.name
     try:
@@ -535,6 +621,10 @@ if __name__ == "__main__":
                 print('{}={}'.format(name, shlex.quote(value)))
                 print('export {}'.format(name))
         else:
+            if os.environ.get("CI_PROJECT_NAME"):
+                print("Ignoring SIGINT when running on the CI,"
+                      " as we get spurious sigint in there for some reason.")
+                signal.signal(signal.SIGINT, signal.SIG_IGN)
             exit(subprocess.call(args, close_fds=False, env=env))
 
     except subprocess.CalledProcessError as e: