mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'fix/specify_shell_in_exports' into 'master'
fix: explicitly set shell type in export.sh for bash and zsh Closes IDF-11137, IDF-11138, and IDFGH-13713 See merge request espressif/esp-idf!33558
This commit is contained in:
commit
fe29994924
@ -19,15 +19,19 @@ fi
|
|||||||
# Attempt to identify the ESP-IDF directory
|
# Attempt to identify the ESP-IDF directory
|
||||||
idf_path="."
|
idf_path="."
|
||||||
|
|
||||||
|
shell_type="detect"
|
||||||
|
|
||||||
# shellcheck disable=SC2128,SC2169,SC2039,SC3054,SC3028 # ignore array expansion warning
|
# shellcheck disable=SC2128,SC2169,SC2039,SC3054,SC3028 # ignore array expansion warning
|
||||||
if test -n "${BASH_SOURCE-}"
|
if test -n "${BASH_SOURCE-}"
|
||||||
then
|
then
|
||||||
# shellcheck disable=SC3028,SC3054 # unreachable with 'dash'
|
# shellcheck disable=SC3028,SC3054 # unreachable with 'dash'
|
||||||
idf_path=$(dirname "${BASH_SOURCE[0]}")
|
idf_path=$(dirname "${BASH_SOURCE[0]}")
|
||||||
|
shell_type="bash"
|
||||||
elif test -n "${ZSH_VERSION-}"
|
elif test -n "${ZSH_VERSION-}"
|
||||||
then
|
then
|
||||||
# shellcheck disable=SC2296 # ignore parameter starts with '{' because it's zsh
|
# shellcheck disable=SC2296 # ignore parameter starts with '{' because it's zsh
|
||||||
idf_path=$(dirname "${(%):-%x}")
|
idf_path=$(dirname "${(%):-%x}")
|
||||||
|
shell_type="zsh"
|
||||||
elif test -n "${IDF_PATH-}"
|
elif test -n "${IDF_PATH-}"
|
||||||
then
|
then
|
||||||
idf_path=$IDF_PATH
|
idf_path=$IDF_PATH
|
||||||
@ -46,7 +50,7 @@ fi
|
|||||||
. "${idf_path}/tools/detect_python.sh"
|
. "${idf_path}/tools/detect_python.sh"
|
||||||
|
|
||||||
# Evaluate the ESP-IDF environment set up by the activate.py script.
|
# Evaluate the ESP-IDF environment set up by the activate.py script.
|
||||||
idf_exports=$("$ESP_PYTHON" "${idf_path}/tools/activate.py" --export)
|
idf_exports=$("$ESP_PYTHON" "${idf_path}/tools/activate.py" --export --shell $shell_type)
|
||||||
eval "${idf_exports}"
|
eval "${idf_exports}"
|
||||||
unset idf_path
|
unset idf_path
|
||||||
return 0
|
return 0
|
||||||
|
@ -25,7 +25,7 @@ def parse_arguments() -> argparse.Namespace:
|
|||||||
epilog='On Windows, run `python activate.py` to execute this script in the current terminal window.')
|
epilog='On Windows, run `python activate.py` to execute this script in the current terminal window.')
|
||||||
parser.add_argument('-s', '--shell',
|
parser.add_argument('-s', '--shell',
|
||||||
metavar='SHELL',
|
metavar='SHELL',
|
||||||
default=os.environ.get('ESP_IDF_SHELL', None),
|
default=os.environ.get('ESP_IDF_SHELL', 'detect'),
|
||||||
help='Explicitly specify shell to start. For example bash, zsh, powershell.exe, cmd.exe')
|
help='Explicitly specify shell to start. For example bash, zsh, powershell.exe, cmd.exe')
|
||||||
parser.add_argument('-l', '--list',
|
parser.add_argument('-l', '--list',
|
||||||
action='store_true',
|
action='store_true',
|
||||||
@ -38,6 +38,7 @@ def parse_arguments() -> argparse.Namespace:
|
|||||||
help=('Disable ANSI color escape sequences.'))
|
help=('Disable ANSI color escape sequences.'))
|
||||||
parser.add_argument('-d', '--debug',
|
parser.add_argument('-d', '--debug',
|
||||||
action='store_true',
|
action='store_true',
|
||||||
|
default=bool(os.environ.get('ESP_IDF_EXPORT_DEBUG')),
|
||||||
help=('Enable debug information.'))
|
help=('Enable debug information.'))
|
||||||
parser.add_argument('-q', '--quiet',
|
parser.add_argument('-q', '--quiet',
|
||||||
action='store_true',
|
action='store_true',
|
||||||
@ -100,17 +101,21 @@ def get_idf_env() -> Dict[str,str]:
|
|||||||
def detect_shell(args: Any) -> str:
|
def detect_shell(args: Any) -> str:
|
||||||
import psutil
|
import psutil
|
||||||
|
|
||||||
if args.shell is not None:
|
if args.shell != 'detect':
|
||||||
|
debug(f'Shell explicitly stated: "{args.shell}"')
|
||||||
return str(args.shell)
|
return str(args.shell)
|
||||||
|
|
||||||
current_pid = os.getpid()
|
current_pid = os.getpid()
|
||||||
detected_shell_name = ''
|
detected_shell_name = ''
|
||||||
while True:
|
while True:
|
||||||
parent_pid = psutil.Process(current_pid).ppid()
|
parent_pid = psutil.Process(current_pid).ppid()
|
||||||
parent_name = os.path.basename(psutil.Process(parent_pid).exe())
|
parent = psutil.Process(parent_pid)
|
||||||
|
parent_cmdline = parent.cmdline()
|
||||||
|
parent_exe = parent_cmdline[0].lstrip('-')
|
||||||
|
parent_name = os.path.basename(parent_exe)
|
||||||
|
debug(f'Parent: pid: {parent_pid}, cmdline: {parent_cmdline}, exe: {parent_exe}, name: {parent_name}')
|
||||||
if not parent_name.lower().startswith('python'):
|
if not parent_name.lower().startswith('python'):
|
||||||
detected_shell_name = parent_name
|
detected_shell_name = parent_name
|
||||||
conf.DETECTED_SHELL_PATH = psutil.Process(parent_pid).exe()
|
|
||||||
break
|
break
|
||||||
current_pid = parent_pid
|
current_pid = parent_pid
|
||||||
|
|
||||||
@ -143,6 +148,7 @@ def main() -> None:
|
|||||||
# Fill config global holder
|
# Fill config global holder
|
||||||
conf.ARGS = args
|
conf.ARGS = args
|
||||||
|
|
||||||
|
debug(f'command line: {sys.argv}')
|
||||||
if conf.ARGS.list:
|
if conf.ARGS.list:
|
||||||
oprint(SUPPORTED_SHELLS)
|
oprint(SUPPORTED_SHELLS)
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
@ -17,7 +17,7 @@ CONSOLE_STDERR = Console(stderr=True, width=255)
|
|||||||
CONSOLE_STDOUT = Console(width=255)
|
CONSOLE_STDOUT = Console(width=255)
|
||||||
|
|
||||||
|
|
||||||
def status_message(msg: str, rv_on_ok: bool=False, die_on_err: bool=True) -> Callable:
|
def status_message(msg: str, msg_result: str='', rv_on_ok: bool=False, die_on_err: bool=True) -> Callable:
|
||||||
def inner(func: Callable) -> Callable:
|
def inner(func: Callable) -> Callable:
|
||||||
def wrapper(*args: Any, **kwargs: Any) -> Any:
|
def wrapper(*args: Any, **kwargs: Any) -> Any:
|
||||||
eprint(f'[dark_orange]*[/dark_orange] {msg} ... ', end='')
|
eprint(f'[dark_orange]*[/dark_orange] {msg} ... ', end='')
|
||||||
@ -34,6 +34,8 @@ def status_message(msg: str, rv_on_ok: bool=False, die_on_err: bool=True) -> Cal
|
|||||||
|
|
||||||
if rv_on_ok:
|
if rv_on_ok:
|
||||||
eprint(f'[green]{rv}[/green]')
|
eprint(f'[green]{rv}[/green]')
|
||||||
|
elif msg_result:
|
||||||
|
eprint(f'[green]{msg_result}[/green]')
|
||||||
else:
|
else:
|
||||||
eprint('[green]OK[/green]')
|
eprint('[green]OK[/green]')
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ import os
|
|||||||
import re
|
import re
|
||||||
import shutil
|
import shutil
|
||||||
import sys
|
import sys
|
||||||
|
import textwrap
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from subprocess import run
|
from subprocess import run
|
||||||
from tempfile import gettempdir
|
from tempfile import gettempdir
|
||||||
@ -72,10 +73,6 @@ class UnixShell(Shell):
|
|||||||
# Basic POSIX shells does not support autocompletion
|
# Basic POSIX shells does not support autocompletion
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def init_file(self) -> None:
|
|
||||||
with open(self.script_file_path, 'w') as fd:
|
|
||||||
self.export_file(fd)
|
|
||||||
|
|
||||||
def export_file(self, fd: TextIO) -> None:
|
def export_file(self, fd: TextIO) -> None:
|
||||||
fd.write(f'{self.deactivate_cmd}\n')
|
fd.write(f'{self.deactivate_cmd}\n')
|
||||||
for var, value in self.new_esp_idf_env.items():
|
for var, value in self.new_esp_idf_env.items():
|
||||||
@ -87,7 +84,8 @@ class UnixShell(Shell):
|
|||||||
'Go to the project directory and run:\n\n idf.py build"\n'))
|
'Go to the project directory and run:\n\n idf.py build"\n'))
|
||||||
|
|
||||||
def export(self) -> None:
|
def export(self) -> None:
|
||||||
self.init_file()
|
with open(self.script_file_path, 'w') as fd:
|
||||||
|
self.export_file(fd)
|
||||||
print(f'. {self.script_file_path}')
|
print(f'. {self.script_file_path}')
|
||||||
|
|
||||||
def click_ver(self) -> int:
|
def click_ver(self) -> int:
|
||||||
@ -95,26 +93,23 @@ class UnixShell(Shell):
|
|||||||
|
|
||||||
|
|
||||||
class BashShell(UnixShell):
|
class BashShell(UnixShell):
|
||||||
def get_bash_major_minor(self) -> float:
|
@status_message('Shell completion', msg_result='Autocompletion code generated')
|
||||||
env = self.expanded_env()
|
|
||||||
bash_interpreter = conf.DETECTED_SHELL_PATH if conf.DETECTED_SHELL_PATH else 'bash'
|
|
||||||
stdout = run_cmd([bash_interpreter, '-c', 'echo ${BASH_VERSINFO[0]}.${BASH_VERSINFO[1]}'], env=env)
|
|
||||||
bash_maj_min = float(stdout)
|
|
||||||
return bash_maj_min
|
|
||||||
|
|
||||||
@status_message('Shell completion', die_on_err=False)
|
|
||||||
def autocompletion(self) -> str:
|
def autocompletion(self) -> str:
|
||||||
bash_maj_min = self.get_bash_major_minor()
|
bash_source = 'bash_source' if self.click_ver() >= 8 else 'source_bash'
|
||||||
# Click supports bash version >= 4.4
|
autocom = textwrap.dedent(f"""
|
||||||
# https://click.palletsprojects.com/en/8.1.x/changes/#version-8-0-0
|
WARNING_MSG="WARNING: Failed to load shell autocompletion for bash version: $BASH_VERSION!"
|
||||||
if bash_maj_min < 4.4:
|
if test ${{BASH_VERSINFO[0]}} -lt 4
|
||||||
raise RuntimeError('Autocompletion not supported')
|
then
|
||||||
|
echo "$WARNING_MSG"
|
||||||
|
else
|
||||||
|
if ! eval "$(env LANG=en _IDF.PY_COMPLETE={bash_source} idf.py)"
|
||||||
|
then
|
||||||
|
echo "$WARNING_MSG"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
""")
|
||||||
|
|
||||||
env = self.expanded_env()
|
return autocom
|
||||||
env['LANG'] = 'en'
|
|
||||||
env['_IDF.PY_COMPLETE'] = 'bash_source' if self.click_ver() >= 8 else 'source_bash'
|
|
||||||
stdout: str = run_cmd([sys.executable, conf.IDF_PY], env=env)
|
|
||||||
return stdout
|
|
||||||
|
|
||||||
def init_file(self) -> None:
|
def init_file(self) -> None:
|
||||||
with open(self.script_file_path, 'w') as fd:
|
with open(self.script_file_path, 'w') as fd:
|
||||||
@ -133,13 +128,19 @@ class BashShell(UnixShell):
|
|||||||
|
|
||||||
|
|
||||||
class ZshShell(UnixShell):
|
class ZshShell(UnixShell):
|
||||||
@status_message('Shell completion', die_on_err=False)
|
@status_message('Shell completion', msg_result='Autocompletion code generated')
|
||||||
def autocompletion(self) -> str:
|
def autocompletion(self) -> str:
|
||||||
env = self.expanded_env()
|
zsh_source = 'zsh_source' if self.click_ver() >= 8 else 'source_zsh'
|
||||||
env['LANG'] = 'en'
|
autocom = textwrap.dedent(f"""
|
||||||
env['_IDF.PY_COMPLETE'] = 'zsh_source' if self.click_ver() >= 8 else 'source_zsh'
|
WARNING_MSG="WARNING: Failed to load shell autocompletion for zsh version: $ZSH_VERSION!"
|
||||||
stdout = run_cmd([sys.executable, conf.IDF_PY], env=env)
|
autoload -Uz compinit && compinit -u
|
||||||
return f'autoload -Uz compinit && compinit -u\n{stdout}'
|
if ! eval "$(env _IDF.PY_COMPLETE={zsh_source} idf.py)"
|
||||||
|
then
|
||||||
|
echo "$WARNING_MSG"
|
||||||
|
fi
|
||||||
|
""")
|
||||||
|
|
||||||
|
return autocom
|
||||||
|
|
||||||
def init_file(self) -> None:
|
def init_file(self) -> None:
|
||||||
# If ZDOTDIR is unset, HOME is used instead.
|
# If ZDOTDIR is unset, HOME is used instead.
|
||||||
@ -188,6 +189,10 @@ class FishShell(UnixShell):
|
|||||||
stdout: str = run_cmd([sys.executable, conf.IDF_PY], env=env)
|
stdout: str = run_cmd([sys.executable, conf.IDF_PY], env=env)
|
||||||
return stdout
|
return stdout
|
||||||
|
|
||||||
|
def init_file(self) -> None:
|
||||||
|
with open(self.script_file_path, 'w') as fd:
|
||||||
|
self.export_file(fd)
|
||||||
|
|
||||||
def spawn(self) -> None:
|
def spawn(self) -> None:
|
||||||
self.init_file()
|
self.init_file()
|
||||||
new_env = os.environ.copy()
|
new_env = os.environ.copy()
|
||||||
|
@ -22,7 +22,6 @@ class Config:
|
|||||||
self.IDF_TOOLS_PY = os.path.join(self.IDF_PATH, 'tools', 'idf_tools.py')
|
self.IDF_TOOLS_PY = os.path.join(self.IDF_PATH, 'tools', 'idf_tools.py')
|
||||||
self.IDF_PY = os.path.join(self.IDF_PATH, 'tools', 'idf.py')
|
self.IDF_PY = os.path.join(self.IDF_PATH, 'tools', 'idf.py')
|
||||||
self.ARGS: Optional[argparse.Namespace] = None
|
self.ARGS: Optional[argparse.Namespace] = None
|
||||||
self.DETECTED_SHELL_PATH: str = ''
|
|
||||||
|
|
||||||
|
|
||||||
# Global variable instance
|
# Global variable instance
|
||||||
|
Loading…
Reference in New Issue
Block a user