Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for appending to environment variables #130

Merged
merged 2 commits into from
Dec 4, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 32 additions & 1 deletion ament_package/template/package_level/local_setup.bat.in
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ set "AMENT_CURRENT_PREFIX="
goto:eof


:: Append non-duplicate values to environment variables
:: Append values to environment variables
:: using semicolons as separators and avoiding leading separators.
:: first argument: the name of the result variable
:: second argument: the value
Expand All @@ -45,6 +45,37 @@ goto:eof
)
goto:eof

:: Append non-duplicate values to environment variables
:: using semicolons as separators and avoiding trailing separators.
:: first argument: the name of the result variable
:: second argument: the value
:ament_append_unique_value
setlocal enabledelayedexpansion
:: arguments
set "listname=%~1"
set "value=%~2"
:: expand the list variable
set "list=!%listname%!"
:: check if the list contains the value
set "is_duplicate="
if "%list%" NEQ "" (
for %%v in ("%list:;=";"%") do (
if "%%~v" == "%value%" set "is_duplicate=1"
)
)
:: if it is not a duplicate append it
if "%is_duplicate%" == "" (
:: if not empty, append a semi-colon
if "!list!" NEQ "" set "list=!list!;"
:: append the value
set "list=!list!%value%"
)
endlocal & (
:: set result variable in parent scope
set "%~1=%list%"
)
goto:eof

:: Call the specified batch file and output the name when tracing is requested.
:: first argument: the batch file
:call_file
Expand Down
51 changes: 51 additions & 0 deletions ament_package/template/package_level/local_setup.sh.in
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,57 @@ ament_append_value() {
unset _listname
}

# function to append non-duplicate values to environment variables
# using colons as separators and avoiding leading separators
ament_append_unique_value() {
# arguments
_listname=$1
_value=$2
#echo "listname $_listname"
#eval echo "list value \$$_listname"
#echo "value $_value"

# check if the list contains the value
eval _values=\$$_listname
_duplicate=
_ament_append_unique_value_IFS=$IFS
IFS=":"
if [ "$AMENT_SHELL" = "zsh" ]; then
ament_zsh_to_array _values
fi
for _item in $_values; do
# ignore empty strings
if [ -z "$_item" ]; then
continue
fi
if [ $_item = $_value ]; then
_duplicate=1
fi
done
unset _item

# append only non-duplicates
if [ -z "$_duplicate" ]; then
# avoid leading separator
if [ -z "$_values" ]; then
eval $_listname=\"$_value\"
#eval echo "set list \$$_listname"
else
# field separator must not be a colon
unset IFS
eval $_listname=\"\$$_listname:$_value\"
#eval echo "append list \$$_listname"
fi
fi
IFS=$_ament_append_unique_value_IFS
unset _ament_append_unique_value_IFS
unset _duplicate
unset _values

unset _value
unset _listname
}

# function to prepend non-duplicate values to environment variables
# using colons as separators and avoiding trailing separators
ament_prepend_unique_value() {
Expand Down
42 changes: 37 additions & 5 deletions ament_package/template/prefix_level/_local_setup_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
FORMAT_STR_INVOKE_SCRIPT = None
FORMAT_STR_REMOVE_TRAILING_SEPARATOR = None

DSV_TYPE_APPEND_NON_DUPLICATE = 'append-non-duplicate'
DSV_TYPE_PREPEND_NON_DUPLICATE = 'prepend-non-duplicate'
DSV_TYPE_PREPEND_NON_DUPLICATE_IF_EXISTS = 'prepend-non-duplicate-if-exists'
DSV_TYPE_SET = 'set'
Expand All @@ -27,6 +28,7 @@ def main(argv=sys.argv[1:]): # noqa: D103
global FORMAT_STR_SET_ENV_VAR
global FORMAT_STR_USE_ENV_VAR
global FORMAT_STR_INVOKE_SCRIPT
global FORMAT_STR_REMOVE_LEADING_SEPARATOR
global FORMAT_STR_REMOVE_TRAILING_SEPARATOR

parser = argparse.ArgumentParser(
Expand All @@ -46,6 +48,8 @@ def main(argv=sys.argv[1:]): # noqa: D103
FORMAT_STR_USE_ENV_VAR = '${name}'
FORMAT_STR_INVOKE_SCRIPT = 'AMENT_CURRENT_PREFIX="{prefix}" ' \
'_ament_prefix_sh_source_script "{script_path}"'
FORMAT_STR_REMOVE_LEADING_SEPARATOR = 'if [ "$(echo -n ${name} | ' \
'head -c 1)" = ":" ]; then export {name}=${{{name}#?}} ; fi'
FORMAT_STR_REMOVE_TRAILING_SEPARATOR = 'if [ "$(echo -n ${name} | ' \
'tail -c 1)" = ":" ]; then export {name}=${{{name}%?}} ; fi'
elif args.primary_extension == 'bat':
Expand All @@ -55,6 +59,8 @@ def main(argv=sys.argv[1:]): # noqa: D103
FORMAT_STR_INVOKE_SCRIPT = \
'call:_ament_prefix_bat_call_script "{script_path}"'
# can't use `if` here since each line is being `call`-ed
FORMAT_STR_REMOVE_LEADING_SEPARATOR = \
'call:_ament_prefix_bat_strip_leading_semicolon "{name}"'
FORMAT_STR_REMOVE_TRAILING_SEPARATOR = \
'call:_ament_prefix_bat_strip_trailing_semicolon "{name}"'
else:
Expand All @@ -75,7 +81,7 @@ def main(argv=sys.argv[1:]): # noqa: D103
):
print(line)

for line in _remove_trailing_separators():
for line in _remove_ending_separators():
print(line)


Expand Down Expand Up @@ -300,6 +306,7 @@ def handle_dsv_types_except_source(type_, remainder, prefix):
else:
assert False
elif type_ in (
DSV_TYPE_APPEND_NON_DUPLICATE,
DSV_TYPE_PREPEND_NON_DUPLICATE,
DSV_TYPE_PREPEND_NON_DUPLICATE_IF_EXISTS
):
Expand All @@ -325,6 +332,8 @@ def handle_dsv_types_except_source(type_, remainder, prefix):
f'path: {value}'
commands.append(
FORMAT_STR_COMMENT_LINE.format_map({'comment': comment}))
elif type_ == DSV_TYPE_APPEND_NON_DUPLICATE:
commands += _append_unique_value(env_name, value)
else:
commands += _prepend_unique_value(env_name, value)
else:
Expand All @@ -336,6 +345,28 @@ def handle_dsv_types_except_source(type_, remainder, prefix):
env_state = {}


def _append_unique_value(name, value):
global env_state
if name not in env_state:
if os.environ.get(name):
env_state[name] = set(os.environ[name].split(os.pathsep))
else:
env_state[name] = set()
# append even if the variable has not been set yet, in case a shell script sets the
# same variable without the knowledge of this Python script.
# later _remove_ending_separators() will cleanup any unintentional trailing separator
extend = FORMAT_STR_USE_ENV_VAR.format_map({'name': name}) + os.pathsep
line = FORMAT_STR_SET_ENV_VAR.format_map(
{'name': name, 'value': extend + value})
if value not in env_state[name]:
env_state[name].add(value)
else:
if not _include_comments():
return []
line = FORMAT_STR_COMMENT_LINE.format_map({'comment': line})
return [line]


def _prepend_unique_value(name, value):
global env_state
if name not in env_state:
Expand All @@ -345,7 +376,7 @@ def _prepend_unique_value(name, value):
env_state[name] = set()
# prepend even if the variable has not been set yet, in case a shell script sets the
# same variable without the knowledge of this Python script.
# later _remove_trailing_separators() will cleanup any unintentional trailing separator
# later _remove_ending_separators() will cleanup any unintentional trailing separator
extend = os.pathsep + FORMAT_STR_USE_ENV_VAR.format_map({'name': name})
line = FORMAT_STR_SET_ENV_VAR.format_map(
{'name': name, 'value': value + extend})
Expand All @@ -358,15 +389,16 @@ def _prepend_unique_value(name, value):
return [line]


def _remove_trailing_separators():
def _remove_ending_separators():
global env_state
commands = []
for name in env_state:
# skip variables that already had values before this script started prepending
if name in os.environ:
continue
commands += [FORMAT_STR_REMOVE_TRAILING_SEPARATOR.format_map(
{'name': name})]
commands += [
FORMAT_STR_REMOVE_LEADING_SEPARATOR.format_map({'name': name}),
FORMAT_STR_REMOVE_TRAILING_SEPARATOR.format_map({'name': name})]
return commands


Expand Down
14 changes: 14 additions & 0 deletions ament_package/template/prefix_level/local_setup.bat.in
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,20 @@ goto:eof
goto:eof


:: strip a leading semicolon from an environment variable if applicable
:: first argument: the environment variable name
:_ament_prefix_bat_strip_leading_semicolon
setlocal enabledelayedexpansion
set "name=%~1"
set "value=!%name%!"
if "%value:~0,1%"==";" set "value=%value:~1%"
:: set result variable in parent scope
endlocal & (
set "%~1=%value%"
)
goto:eof


:: strip a trailing semicolon from an environment variable if applicable
:: first argument: the environment variable name
:_ament_prefix_bat_strip_trailing_semicolon
Expand Down