From nobody Mon Feb 9 07:05:17 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+56961+1787277+3901457@groups.io; helo=web01.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+56961+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1585957782; cv=none; d=zohomail.com; s=zohoarc; b=Z/RWAylnuev9vGNPComM7DsaoO/SYO8prKv/7tPgdY0J9QDq1TaK1scXg+sbrGzzYvXqLmCNY1nHEolbbGeA7azkXTT5VFXHmSXbPdgD49swfz4GZTJo7NWAbqmyHVJ8HiB0wwOaIvQ7uVdaRoM+qHegWWOF6qA74SDWctbaPa8= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1585957782; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Id:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=NNjoD2T8aESqB2dT/zzEt3NDRnVmZk/L4HSyxk8C0u8=; b=CtNbrhb5YOZy7/dL9ioZqGYBDHjgsR9l+rzVAZ6bBIfAHW2xulccJtfz696tSgY8dI+GFksuK+tXnTEbFhJoBKn/lHfN96Z3+niOapB7wlO9LNGGLnf/TN9EuOfOy+cdg64pTPu74Ys+R3X3yQ6LdDhlkqqJptnDEoLrtdcwp4A= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+56961+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) header.from= Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1585957782401441.25183805199913; Fri, 3 Apr 2020 16:49:42 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id aaKGYY1788612xg3NxPG0nh5; Fri, 03 Apr 2020 16:49:42 -0700 X-Received: from mga04.intel.com (mga04.intel.com []) by mx.groups.io with SMTP id smtpd.web10.117.1585957781089662050 for ; Fri, 03 Apr 2020 16:49:41 -0700 IronPort-SDR: 2sSb9+vf01iggQUrFEr6V7qW6jb6SXiJlMUpwjg3o2obNrVHoi/NvzSk+qIQwCCf2DXi0siXTb a6O8lg5mebVQ== X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-Received: from orsmga006.jf.intel.com ([10.7.209.51]) by fmsmga104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 03 Apr 2020 16:49:41 -0700 IronPort-SDR: YHCo+SflZQ+2PwtYavLuLJYe5dF6W+94o8/6KiNb0IiLe7HSHnAvj7ZKwkTrloV96GEm46rjPY ZCdVpysRO7cQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.72,341,1580803200"; d="scan'208";a="253528773" X-Received: from nldesimo-desk1.amr.corp.intel.com ([10.7.159.63]) by orsmga006.jf.intel.com with ESMTP; 03 Apr 2020 16:49:40 -0700 From: "Nate DeSimone" To: devel@edk2.groups.io Cc: Ashley DeSimone , Puja Pandya , Erik Bjorge , Prince Agyeman , Bret Barkelew , Philippe Mathieu-Daude Subject: [edk2-devel] [edk2-staging/EdkRepo] [PATCH V2 2/3] EdkRepo: Add command completion setup to install.py Date: Fri, 3 Apr 2020 16:49:31 -0700 Message-Id: <20200403234932.2497-3-nathaniel.l.desimone@intel.com> In-Reply-To: <20200403234932.2497-1-nathaniel.l.desimone@intel.com> References: <20200403234932.2497-1-nathaniel.l.desimone@intel.com> MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,nathaniel.l.desimone@intel.com X-Gm-Message-State: rVddkj8os5dWCG9qPG2BG9N1x1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1585957782; bh=TnymC0/JqQUe2Akv97ElfnE6sozk7EaTc7Ijse8F9pg=; h=Cc:Date:From:Reply-To:Subject:To; b=fAQQBDSoFB91MOdwHGqgKu3bxlIoyDzaHWbiLyXNmRECTjFNZdVLspVxd0MPOq1BGdV yICveOqbnITQ6xEE8EyDzL6tkiw8681tcCAX6ZgviuAOjUWq0O71QMVQzXYBV4NWtRv9q k8qCqmTgwxagIbrWgQefuEvw3Xu7aLYEOYw= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Type: text/plain; charset="utf-8" Add configuration of command completion scripts to install.py This enables edkrepo command completions to work "out of box" on most Linux systems by appending to the user's .bashrc and .zshrc startup scripts inclusion of the EdkRepo command completion scripts. Cc: Ashley DeSimone Cc: Puja Pandya Cc: Erik Bjorge Cc: Prince Agyeman Cc: Bret Barkelew Cc: Philippe Mathieu-Daude Signed-off-by: Nate DeSimone --- edkrepo_installer/linux-scripts/install.py | 285 ++++++++++++++++++++- 1 file changed, 283 insertions(+), 2 deletions(-) diff --git a/edkrepo_installer/linux-scripts/install.py b/edkrepo_installer= /linux-scripts/install.py index b2cdfed..52f0c52 100755 --- a/edkrepo_installer/linux-scripts/install.py +++ b/edkrepo_installer/linux-scripts/install.py @@ -15,6 +15,7 @@ import importlib.util import logging import os import platform +import re import stat import shutil import subprocess @@ -22,7 +23,7 @@ import sys import traceback import xml.etree.ElementTree as et =20 -tool_sign_on =3D 'Installer for edkrepo version {}\nCopyright(c) Intel Cor= poration, 2019' +tool_sign_on =3D 'Installer for edkrepo version {}\nCopyright(c) Intel Cor= poration, 2020' =20 # Data here should be maintained in a configuration file cfg_dir =3D '.edkrepo' @@ -31,6 +32,21 @@ cfg_src_dir =3D os.path.abspath('config') whl_src_dir =3D os.path.abspath('wheels') def_python =3D 'python3' =20 +# ZSH Configuration options +prompt_regex =3D re.compile(r"#\s+[Aa][Dd][Dd]\s+[Ee][Dd][Kk][Rr][Ee][Pp][= Oo]\s+&\s+[Gg][Ii][Tt]\s+[Tt][Oo]\s+[Tt][Hh][Ee]\s+[Pp][Rr][Oo][Mm][Pp][Tt]= ") +zsh_autoload_compinit_regex =3D re.compile(r"autoload\s+-U\s+compinit") +zsh_autoload_bashcompinit_regex =3D re.compile(r"autoload\s+-U\s+bashcompi= nit") +zsh_autoload_colors_regex =3D re.compile(r"autoload\s+-U\s+colors") +zsh_colors_regex =3D re.compile(r"\n\s*colors\n") +zsh_compinit_regex =3D re.compile(r"compinit\s+-u") +zsh_bashcompinit_regex =3D re.compile(r"\n\s*bashcompinit\n") +zsh_autoload_compinit =3D 'autoload -U compinit' +zsh_autoload_bashcompinit =3D 'autoload -U bashcompinit' +zsh_autoload_colors =3D 'autoload -U colors' +zsh_colors =3D 'colors' +zsh_compinit =3D 'compinit -u' +zsh_bashcompinit =3D 'bashcompinit' + def default_run(cmd): return subprocess.run(cmd, universal_newlines=3DTrue, stdout=3Dsubproc= ess.PIPE, stderr=3Dsubprocess.STDOUT, check=3DTrue) =20 @@ -51,8 +67,85 @@ def get_args(): parser.add_argument('-p', '--py', action=3D'store', default=3DNone, he= lp=3D'Specify the python command to use when installing') parser.add_argument('-u', '--user', action=3D'store', default=3DNone, = help=3D'Specify user account to install edkrepo support on') parser.add_argument('-v', '--verbose', action=3D'store_true', default= =3DFalse, help=3D'Enables verbose output') + parser.add_argument('--no-prompt', action=3D'store_true', default=3DFa= lse, help=3D'Do NOT add EdkRepo combo and git branch to the shell prompt') + parser.add_argument('--prompt', action=3D'store_true', default=3DFalse= , help=3D'Add EdkRepo combo and git branch to the shell prompt') return parser.parse_args() =20 +def is_prompt_customization_installed(user_home_dir): + script_files =3D [os.path.join(user_home_dir, '.bashrc'), os.path.join= (user_home_dir, '.zshrc')] + customization_installed =3D True + for script_file in script_files: + if os.path.isfile(script_file): + with open(script_file, 'r') as f: + script =3D f.read().strip() + data =3D prompt_regex.search(script) + if not data: + customization_installed =3D False + break + return customization_installed + +__add_prompt_customization =3D None +def get_add_prompt_customization(args, user_home_dir): + global __add_prompt_customization + if __add_prompt_customization is not None: + return __add_prompt_customization + if args.no_prompt: + __add_prompt_customization =3D False + return False + elif args.prompt: + __add_prompt_customization =3D True + return True + #Check if the prompt customization has already been installed + if is_prompt_customization_installed(user_home_dir): + __add_prompt_customization =3D False + return False + #If the prompt has not been installed and EdkRepo >=3D 2.0.0 is instal= led, then don't install the prompt customization + if shutil.which('edkrepo') is not None: + res =3D default_run(['edkrepo', '--version']) + if _check_version(res.stdout.replace('edkrepo ', '').strip(), '2.0= .0') >=3D 0: + __add_prompt_customization =3D False + return False + #Show the user an advertisement to see if they want the prompt customi= zation + from select import select + import termios + import tty + def get_key(timeout=3D-1): + key =3D None + old_settings =3D termios.tcgetattr(sys.stdin.fileno()) + try: + tty.setraw(sys.stdin.fileno()) + if timeout !=3D -1: + rlist, _, _ =3D select([sys.stdin], [], [], timeout) + if rlist: + key =3D sys.stdin.read(1) + else: + key =3D sys.stdin.read(1) + finally: + termios.tcsetattr(sys.stdin.fileno(), termios.TCSADRAIN, old_s= ettings) + return key + print('\nEdkRepo can show the checked out \033[32mcombo\033[00m and \0= 33[36mbranch\033[00m as part of the command prompt') + print('For example, instead of:\n') + print('\033[01;32muser@machine\033[00m:\033[01;34mEdk2\033[00m$ ') + print('\nThe command prompt would look like:\n') + print('\033[01;32muser@machine\033[00m:\033[01;34mEdk2\033[00m \033[32= m[Edk2Master]\033[36m (master)\033[00m$ ') + print('') + while True: + print('Would you like the combo and branch shown on the command pr= ompt? [y/N] ') + key =3D get_key(120) + if key: + if key =3D=3D 'y' or key =3D=3D 'Y': + print('Y') + __add_prompt_customization =3D True + return True + if key =3D=3D 'n' or key =3D=3D 'N': + print('N') + __add_prompt_customization =3D False + return False + else: + print('No response after 2min... assuming no.') + __add_prompt_customization =3D False + return False + def get_installed_packages(python_command): pip_cmd =3D [def_python, '-m', 'pip', 'list', '--legacy'] try: @@ -146,6 +239,176 @@ def set_execute_permissions(): stat_data =3D os.stat(py_file) os.chmod(py_file, stat_data.st_mode | stat.S_IEXEC) =20 +bash_prompt_customization =3D r''' +# Add EdkRepo & git to the prompt +ps1len=3D"${#PS1}" +let "pos3 =3D ps1len - 3" +let "pos2 =3D ps1len - 2" +if [ "${PS1:pos3}" =3D=3D "\\$ " ]; then + newps1=3D"${PS1:0:pos3}" + prompt_suffix=3D"\\$ " +elif [ "${PS1:pos3}" =3D=3D " $ " ]; then + newps1=3D"${PS1:0:pos3}" + prompt_suffix=3D" $ " +elif [ "${PS1:pos2}" =3D=3D "$ " ]; then + newps1=3D"${PS1:0:pos2}" + prompt_suffix=3D"$ " +else + newps1=3D"$PS1" + prompt_suffix=3D"" +fi + +# EdkRepo combo in prompt. +if [ -x "$(command -v edkrepo)" ] && [ -x "$(command -v command_completion= _edkrepo)" ]; then + newps1=3D"$newps1\[\033[32m\]\$current_edkrepo_combo" + current_edkrepo_combo=3D$(command_completion_edkrepo current-combo) + + # Determining the current Edkrepo combo requires invoking Python and par= sing + # manifest XML, which is a relatively expensive operation to do every ti= me + # the user presses . + # As a performance optimization, only do this if the present working dir= ectory + # changed + if [[ ! -z ${PROMPT_COMMAND+x} ]] && [[ "$PROMPT_COMMAND" !=3D "edkrepo_= combo_chpwd" ]]; then + old_prompt_command=3D$PROMPT_COMMAND + fi + old_pwd=3D$(pwd) + edkrepo_combo_chpwd() { + if [[ "$(pwd)" !=3D "$old_pwd" ]]; then + old_pwd=3D$(pwd) + current_edkrepo_combo=3D$(command_completion_edkrepo current-combo) + fi + if [[ ! -z ${PROMPT_COMMAND+x} ]]; then + eval $old_prompt_command + fi + } + PROMPT_COMMAND=3Dedkrepo_combo_chpwd +fi + +# Git branch in prompt. +parse_git_branch() { + git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/ (\1)/' +} + +PS1=3D"$newps1\[\033[36m\]\$(parse_git_branch)\[\033[00m\]$prompt_suffix" +''' + +zsh_prompt_customization =3D r''' +# Add EdkRepo & git to the prompt +prompt_length=3D"${#PROMPT}" +let "pos4 =3D prompt_length - 3" +let "pos3 =3D prompt_length - 2" +if [ "${PROMPT[$pos4,$prompt_length]}" =3D ' %# ' ]; then + new_prompt=3D"${PROMPT[1,$pos4-1]}" + prompt_suffix=3D" %# " +elif [ "${PROMPT[$pos3,$prompt_length]}" =3D "%# " ]; then + new_prompt=3D"${PROMPT[1,$pos3-1]}" + prompt_suffix=3D"%# " +else + new_prompt=3D"$PROMPT" + prompt_suffix=3D"" +fi + +# EdkRepo combo in prompt. +if [ -x "$(command -v edkrepo)" ] && [ -x "$(command -v command_completion= _edkrepo)" ]; then + new_prompt=3D"$new_prompt%{$fg[green]%}\$current_edkrepo_combo%{$reset_c= olor%}" + current_edkrepo_combo=3D$(command_completion_edkrepo current-combo) + + # Determining the current Edkrepo combo requires invoking Python and par= sing + # manifest XML, which is a relatively expensive operation to do every ti= me + # the user presses . + # As a performance optimization, only do this if the present working dir= ectory + # changed + function edkrepo_combo_chpwd() { + current_edkrepo_combo=3D$(command_completion_edkrepo current-combo) + } + chpwd_functions=3D(${chpwd_functions[@]} "edkrepo_combo_chpwd") +fi + +# Load version control information +autoload -Uz vcs_info +precmd() { vcs_info } + +# Format the vcs_info_msg_0_ variable +zstyle ':vcs_info:git:*' formats " %{$fg[cyan]%}(%b)%{$reset_color%}" + +# Set up the prompt (with git branch name) +setopt PROMPT_SUBST +eval "PROMPT=3D'$new_prompt\${vcs_info_msg_0_}\$prompt_suffix'" +''' + +def add_command_to_startup_script(script_file, regex, command, username): + script =3D '' + if os.path.isfile(script_file): + with open(script_file, 'r') as f: + script =3D f.read().strip() + data =3D regex.search(script) + if not data: + if script =3D=3D '': + script =3D command + else: + script =3D '{}\n{}'.format(script, command) + with open(script_file, 'w') as f: + f.write(script) + +def add_command_comment_to_startup_script(script_file, regex, command, com= ment, username): + script =3D '' + if os.path.isfile(script_file): + with open(script_file, 'r') as f: + script =3D f.read().strip() + (new_script, subs) =3D re.subn(regex, command, script) + if subs =3D=3D 0: + command =3D '\n{1}\n{0}\n'.format(command, comment) + if script =3D=3D '': + new_script =3D command + else: + new_script =3D '{}\n{}'.format(script, command) + if new_script !=3D script: + with open(script_file, 'w') as f: + f.write(new_script) + shutil.chown(script_file, user=3Dusername) + os.chmod(script_file, 0o644) + +def add_command_completions_to_shell(command_completion_script, args, user= name, user_home_dir): + # Add "source ~/.bashrc" to ~/.bash_profile if it does not have it alr= eady + bash_profile_file =3D os.path.join(user_home_dir, '.bash_profile') + bash_profile =3D '' + if os.path.isfile(bash_profile_file): + with open(bash_profile_file, 'r') as f: + bash_profile =3D f.read().strip() + profile_source_regex =3D re.compile(r"source\s+~/\.bashrc") + profile_source_regex2 =3D re.compile(r".\s+~/\.bashrc") + data =3D profile_source_regex.search(bash_profile) + if not data: + data =3D profile_source_regex2.search(bash_profile) + if not data: + if bash_profile =3D=3D '': + bash_profile =3D 'source ~/.bashrc\n' + else: + bash_profile =3D '{}\nsource ~/.bashrc\n'.format(bash_prof= ile) + with open(bash_profile_file, 'w') as f: + f.write(bash_profile) + shutil.chown(bash_profile_file, user=3Dusername) + os.chmod(bash_profile_file, 0o644) + + # Add edkrepo command completion to ~/.bashrc if it does not have it a= lready + regex =3D r"\[\[\s+-r\s+\"\S*edkrepo_completions.sh\"\s+\]\]\s+&&\s+.\= s+\"\S*edkrepo_completions.sh\"" + new_source_line =3D '[[ -r "{0}" ]] && . "{0}"'.format(command_complet= ion_script) + comment =3D '\n# Add EdkRepo command completions' + bash_rc_file =3D os.path.join(user_home_dir, '.bashrc') + add_command_comment_to_startup_script(bash_rc_file, regex, new_source_= line, comment, username) + if get_add_prompt_customization(args, user_home_dir): + add_command_to_startup_script(bash_rc_file, prompt_regex, bash_pro= mpt_customization, username) + zsh_rc_file =3D os.path.join(user_home_dir, '.zshrc') + add_command_to_startup_script(zsh_rc_file, zsh_autoload_compinit_regex= , zsh_autoload_compinit, username) + add_command_to_startup_script(zsh_rc_file, zsh_autoload_bashcompinit_r= egex, zsh_autoload_bashcompinit, username) + add_command_to_startup_script(zsh_rc_file, zsh_autoload_colors_regex, = zsh_autoload_colors, username) + add_command_to_startup_script(zsh_rc_file, zsh_colors_regex, zsh_color= s, username) + add_command_to_startup_script(zsh_rc_file, zsh_compinit_regex, zsh_com= pinit, username) + add_command_to_startup_script(zsh_rc_file, zsh_bashcompinit_regex, zsh= _bashcompinit, username) + add_command_comment_to_startup_script(zsh_rc_file, regex, new_source_l= ine, comment, username) + if get_add_prompt_customization(args, user_home_dir): + add_command_to_startup_script(zsh_rc_file, prompt_regex, zsh_promp= t_customization, username) + def do_install(): global def_python org_python =3D None @@ -209,6 +472,7 @@ def do_install(): log.info('- Unable to determine users home directory') return 1 default_cfg_dir =3D os.path.join(user_home_dir, cfg_dir) + get_add_prompt_customization(args, user_home_dir) log.info('+ System information collected') =20 # Display current system information. @@ -348,7 +612,7 @@ def do_install(): #Delete obsolete dependencies if updating_edkrepo: installed_packages =3D get_installed_packages(def_python) - for whl_name in ['smmap2', 'gitdb2']: + for whl_name in ['smmap2', 'gitdb2', 'edkrepo-internal']: if whl_name in installed_packages: try: res =3D default_run([def_python, '-m', 'pip', 'uni= nstall', '--yes', whl_name]) @@ -375,6 +639,23 @@ def do_install(): set_execute_permissions() log.info('+ Marked scripts as executable') =20 + + #Install the command completion script + if shutil.which('edkrepo') is not None: + if args.local: + command_completion_script =3D os.path.join(default_cfg_dir, 'e= dkrepo_completions.sh') + else: + command_completion_script =3D os.path.join('/', 'etc', 'profil= e.d', 'edkrepo_completions.sh') + try: + res =3D default_run(['edkrepo', 'generate-command-completion-s= cript', command_completion_script]) + if args.local: + shutil.chown(command_completion_script, user=3Dusername) + os.chmod(command_completion_script, 0o644) + add_command_completions_to_shell(command_completion_script, ar= gs, username, user_home_dir) + except: + log.info('- Failed to configure edkrepo command completion') + if args.verbose: + traceback.print_exc() log.log(logging.PRINT, '\nInstallation complete\n') =20 return 0 --=20 2.26.0.windows.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#56961): https://edk2.groups.io/g/devel/message/56961 Mute This Topic: https://groups.io/mt/72761908/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-