From 060d5b6dc5118885f69032dd29463e961a5e1ab2 Mon Sep 17 00:00:00 2001 From: ljf Date: Mon, 6 Sep 2021 04:20:35 +0200 Subject: [PATCH] [fix] ynh_write_var_in_file and after option --- data/helpers.d/config | 8 +- data/helpers.d/utils | 94 ++++++++++++++++++----- tests/test_helpers.d/ynhtest_config.sh | 102 +++++++++++++------------ 3 files changed, 136 insertions(+), 68 deletions(-) diff --git a/data/helpers.d/config b/data/helpers.d/config index 5d024442a..e834db041 100644 --- a/data/helpers.d/config +++ b/data/helpers.d/config @@ -124,7 +124,7 @@ _ynh_app_config_apply() { # Save value in app settings elif [[ "$bind" == "settings" ]]; - i then + then ynh_app_setting_set $app $short_setting "${!short_setting}" ynh_print_info "Configuration key '$short_setting' edited in app settings" @@ -143,8 +143,14 @@ _ynh_app_config_apply() { # Set value into a kind of key/value file else + local bind_after="" local bind_key="$(echo "$bind" | cut -d: -f1)" bind_key=${bind_key:-$short_setting} + if [[ "$bind_key" == *">"* ]]; + then + bind_after="$(echo "${bind_key}" | cut -d'>' -f1)" + bind_key="$(echo "${bind_key}" | cut -d'>' -f2)" + fi local bind_file="$(echo "$bind" | cut -d: -f2 | sed s@__FINALPATH__@$final_path@ | sed s/__APP__/$app/)" ynh_backup_if_checksum_is_different --file="$bind_file" diff --git a/data/helpers.d/utils b/data/helpers.d/utils index 97aae12ef..5ecc0cf0b 100644 --- a/data/helpers.d/utils +++ b/data/helpers.d/utils @@ -507,19 +507,30 @@ ynh_replace_vars () { # # Requires YunoHost version 4.3 or higher. ynh_read_var_in_file() { - set +o xtrace # Declare an array to define the options of this helper. - local legacy_args=fk - local -A args_array=( [f]=file= [k]=key= ) + local legacy_args=fka + local -A args_array=( [f]=file= [k]=key= [a]=after=) local file local key + local after # Manage arguments with getopts ynh_handle_getopts_args "$@" - #set +o xtrace - local filename="$(basename -- "$file")" + after="${after:-}" [[ -f $file ]] || ynh_die "File $file does not exists" + # Get the line number after which we search for the variable + local line_number=1 + if [[ -n "$after" ]]; + then + line_number=$(grep -n $after $file | cut -d: -f1) + if [[ -z "$line_number" ]]; + then + return 1 + fi + fi + + local filename="$(basename -- "$file")" local ext="${filename##*.}" local endline=',;' local assign="=>|:|=" @@ -535,14 +546,14 @@ ynh_read_var_in_file() { comments="//" fi local list='\[\s*['$string']?\w+['$string']?\]' - local var_part='^\s*(?:(const|var|let)\s+)?\$?(\w+('$list')*(->|\.|\[))*\s*' + local var_part='^\s*((const|var|let)\s+)?\$?(\w+('$list')*(->|\.|\[))*\s*' var_part+="[$string]?${key}[$string]?" var_part+='\s*\]?\s*' var_part+="($assign)" var_part+='\s*' # Extract the part after assignation sign - local expression_with_comment="$(grep -i -o -P $var_part'\K.*$' ${file} || echo YNH_NULL | head -n1)" + local expression_with_comment="$(tail +$line_number ${file} | grep -i -o -P $var_part'\K.*$' || echo YNH_NULL | head -n1)" if [[ "$expression_with_comment" == "YNH_NULL" ]]; then echo YNH_NULL return 0 @@ -570,40 +581,85 @@ ynh_read_var_in_file() { # # Requires YunoHost version 4.3 or higher. ynh_write_var_in_file() { - set +o xtrace # Declare an array to define the options of this helper. - local legacy_args=fkv - local -A args_array=( [f]=file= [k]=key= [v]=value=) + local legacy_args=fkva + local -A args_array=( [f]=file= [k]=key= [v]=value= [a]=after=) local file local key local value + local after # Manage arguments with getopts ynh_handle_getopts_args "$@" - set +o xtrace - local var_part='\s*\$?([\w.]*\[)?\s*["'"']?${key}['"'"]?\s*\]?\s*[:=]>?\s*' + after="${after:-}" [[ -f $file ]] || ynh_die "File $file does not exists" - local crazy_value="$(grep -i -o -P '^\s*\$?([\w.]*\[)?\s*["'"']?${key}['"'"]?\s*\]?\s*[:=]>?\s*\K.*(?=[\s,;]*$)' ${file} | head -n1)" - # local crazy_value="$(grep -i -o -P "^${var_part}\K.*(?=[ \t,\n;]*\$)" ${file} | head -n1)" - local first_char="${crazy_value:0:1}" + # Get the line number after which we search for the variable + local line_number=1 + if [[ -n "$after" ]]; + then + line_number=$(grep -n $after $file | cut -d: -f1) + if [[ -z "$line_number" ]]; + then + return 1 + fi + fi + local range="${line_number},\$ " + + local filename="$(basename -- "$file")" + local ext="${filename##*.}" + local endline=',;' + local assign="=>|:|=" + local comments="#" + local string="\"'" + if [[ "$ext" =~ ^ini|env|toml|yml|yaml$ ]]; then + endline='#' + fi + if [[ "$ext" =~ ^ini|env$ ]]; then + comments="[;#]" + fi + if [[ "php" == "$ext" ]] || [[ "$ext" == "js" ]]; then + comments="//" + fi + local list='\[\s*['$string']?\w+['$string']?\]' + local var_part='^\s*((const|var|let)\s+)?\$?(\w+('$list')*(->|\.|\[))*\s*' + var_part+="[$string]?${key}[$string]?" + var_part+='\s*\]?\s*' + var_part+="($assign)" + var_part+='\s*' + + # Extract the part after assignation sign + local expression_with_comment="$(tail +$line_number ${file} | grep -i -o -P $var_part'\K.*$' || echo YNH_NULL | head -n1)" + if [[ "$expression_with_comment" == "YNH_NULL" ]]; then + return 1 + fi + + # Remove comments if needed + local expression="$(echo "$expression_with_comment" | sed "s@$comments[^$string]*\$@@g" | sed "s@\s*[$endline]*\s*]*\$@@")" + endline=${expression_with_comment#"$expression"} + endline="$(echo "$endline" | sed 's/\\/\\\\/g')" + value="$(echo "$value" | sed 's/\\/\\\\/g')" + local first_char="${expression:0:1}" delimiter=$'\001' if [[ "$first_char" == '"' ]] ; then # \ and sed is quite complex you need 2 \\ to get one in a sed # So we need \\\\ to go through 2 sed value="$(echo "$value" | sed 's/"/\\\\"/g')" - sed -ri s$delimiter'^('"${var_part}"'")([^"]|\\")*("[\s;,]*)$'$delimiter'\1'"${value}"'\4'$delimiter'i' ${file} + sed -ri "${range}s$delimiter"'(^'"${var_part}"'")([^"]|\\")*("[\s;,]*)(\s*'$comments'.*)?$'$delimiter'\1'"${value}"'"'"${endline}${delimiter}i" ${file} elif [[ "$first_char" == "'" ]] ; then # \ and sed is quite complex you need 2 \\ to get one in a sed # However double quotes implies to double \\ to # So we need \\\\\\\\ to go through 2 sed and 1 double quotes str value="$(echo "$value" | sed "s/'/\\\\\\\\'/g")" - sed -ri "s$delimiter^(${var_part}')([^']|\\')*('"'[\s,;]*)$'$delimiter'\1'"${value}"'\4'$delimiter'i' ${file} + sed -ri "${range}s$delimiter(^${var_part}')([^']|\\')*('"'[\s,;]*)(\s*'$comments'.*)?$'$delimiter'\1'"${value}'${endline}${delimiter}i" ${file} else - if [[ "$value" == *"'"* ]] || [[ "$value" == *'"'* ]] ; then + if [[ "$value" == *"'"* ]] || [[ "$value" == *'"'* ]] || [[ "$ext" =~ ^php|py|json|js$ ]] ; then value='\"'"$(echo "$value" | sed 's/"/\\\\"/g')"'\"' fi - sed -ri "s$delimiter^(${var_part}).*"'$'$delimiter'\1'"${value}"$delimiter'i' ${file} + if [[ "$ext" =~ ^yaml|yml$ ]] ; then + value=" $value" + fi + sed -ri "${range}s$delimiter(^${var_part}).*\$$delimiter\1${value}${endline}${delimiter}i" ${file} fi } diff --git a/tests/test_helpers.d/ynhtest_config.sh b/tests/test_helpers.d/ynhtest_config.sh index 3be72d191..b64943a48 100644 --- a/tests/test_helpers.d/ynhtest_config.sh +++ b/tests/test_helpers.d/ynhtest_config.sh @@ -34,6 +34,8 @@ DICT = {} DICT['ldap_base'] = "ou=users,dc=yunohost,dc=org" DICT['ldap_conf'] = {} DICT['ldap_conf']['user'] = "camille" +# YNH_ICI +DICT['TITLE'] = "Hello world" EOF test "$(_read_py "$file" "FOO")" == "None" @@ -60,6 +62,8 @@ EOF test "$(ynh_read_var_in_file "$file" "ldap_base")" == "ou=users,dc=yunohost,dc=org" test "$(ynh_read_var_in_file "$file" "user")" == "camille" + + test "$(ynh_read_var_in_file "$file" "TITLE" "YNH_ICI")" == "Hello world" ! _read_py "$file" "NONEXISTENT" test "$(ynh_read_var_in_file "$file" "NONEXISTENT")" == "YNH_NULL" @@ -68,7 +72,7 @@ EOF test "$(ynh_read_var_in_file "$file" "ENABLE")" == "YNH_NULL" } -nhtest_config_write_py() { +ynhtest_config_write_py() { local dummy_dir="$(mktemp -d -p $VAR_WWW)" file="$dummy_dir/dummy.py" @@ -84,11 +88,13 @@ PORT = 1234 # This is a comment without quotes URL = 'https://yunohost.org' DICT = {} DICT['ldap_base'] = "ou=users,dc=yunohost,dc=org" +# YNH_ICI +DICT['TITLE'] = "Hello world" EOF - #ynh_write_var_in_file "$file" "FOO" "bar" - #test "$(_read_py "$file" "FOO")" == "bar" # FIXME FIXME FIXME - #test "$(ynh_read_var_in_file "$file" "FOO")" == "bar" + ynh_write_var_in_file "$file" "FOO" "bar" + test "$(_read_py "$file" "FOO")" == "bar" + test "$(ynh_read_var_in_file "$file" "FOO")" == "bar" ynh_write_var_in_file "$file" "ENABLED" "True" test "$(_read_py "$file" "ENABLED")" == "True" @@ -116,12 +122,15 @@ EOF ynh_write_var_in_file "$file" "ldap_base" "ou=users,dc=yunohost,dc=org" test "$(ynh_read_var_in_file "$file" "ldap_base")" == "ou=users,dc=yunohost,dc=org" + + ynh_write_var_in_file "$file" "TITLE" "YOLO" "YNH_ICI" + test "$(ynh_read_var_in_file "$file" "TITLE" "YNH_ICI")" == "YOLO" - ynh_write_var_in_file "$file" "NONEXISTENT" "foobar" + ! ynh_write_var_in_file "$file" "NONEXISTENT" "foobar" ! _read_py "$file" "NONEXISTENT" test "$(ynh_read_var_in_file "$file" "NONEXISTENT")" == "YNH_NULL" - ynh_write_var_in_file "$file" "ENABLE" "foobar" + ! ynh_write_var_in_file "$file" "ENABLE" "foobar" ! _read_py "$file" "ENABLE" test "$(ynh_read_var_in_file "$file" "ENABLE")" == "YNH_NULL" @@ -194,7 +203,7 @@ EOF } -nhtest_config_write_ini() { +ynhtest_config_write_ini() { local dummy_dir="$(mktemp -d -p $VAR_WWW)" file="$dummy_dir/dummy.ini" @@ -231,11 +240,11 @@ EOF test "$(ynh_read_var_in_file "$file" "theme")" == "super-awesome-theme" ynh_write_var_in_file "$file" "email" "sam@domain.tld" - test "$(_read_ini "$file" "email")" == "sam@domain.tld" + test "$(_read_ini "$file" "email")" == "sam@domain.tld # This is a comment without quotes" test "$(ynh_read_var_in_file "$file" "email")" == "sam@domain.tld" ynh_write_var_in_file "$file" "port" "5678" - test "$(_read_ini "$file" "port")" == "5678" + test "$(_read_ini "$file" "port")" == "5678 # This is a comment without quotes" test "$(ynh_read_var_in_file "$file" "port")" == "5678" ynh_write_var_in_file "$file" "url" "https://domain.tld/foobar" @@ -245,11 +254,11 @@ EOF ynh_write_var_in_file "$file" "ldap_base" "ou=users,dc=yunohost,dc=org" test "$(ynh_read_var_in_file "$file" "ldap_base")" == "ou=users,dc=yunohost,dc=org" - ynh_write_var_in_file "$file" "nonexistent" "foobar" + ! ynh_write_var_in_file "$file" "nonexistent" "foobar" ! _read_ini "$file" "nonexistent" test "$(ynh_read_var_in_file "$file" "nonexistent")" == "YNH_NULL" - ynh_write_var_in_file "$file" "enable" "foobar" + ! ynh_write_var_in_file "$file" "enable" "foobar" ! _read_ini "$file" "enable" test "$(ynh_read_var_in_file "$file" "enable")" == "YNH_NULL" @@ -322,7 +331,7 @@ EOF } -nhtest_config_write_yaml() { +ynhtest_config_write_yaml() { local dummy_dir="$(mktemp -d -p $VAR_WWW)" file="$dummy_dir/dummy.yml" @@ -340,10 +349,10 @@ dict: ldap_base: ou=users,dc=yunohost,dc=org EOF - #ynh_write_var_in_file "$file" "foo" "bar" + ynh_write_var_in_file "$file" "foo" "bar" # cat $dummy_dir/dummy.yml # to debug - #! test "$(_read_yaml "$file" "foo")" == "bar" # FIXME FIXME FIXME : writing broke the yaml syntax... "foo:bar" (no space aftr :) - #test "$(ynh_read_var_in_file "$file" "foo")" == "bar" + ! test "$(_read_yaml "$file" "foo")" == "bar" # writing broke the yaml syntax... "foo:bar" (no space aftr :) + test "$(ynh_read_var_in_file "$file" "foo")" == "bar" ynh_write_var_in_file "$file" "enabled" "true" test "$(_read_yaml "$file" "enabled")" == "True" @@ -372,10 +381,10 @@ EOF ynh_write_var_in_file "$file" "ldap_base" "ou=foobar,dc=domain,dc=tld" test "$(ynh_read_var_in_file "$file" "ldap_base")" == "ou=foobar,dc=domain,dc=tld" - ynh_write_var_in_file "$file" "nonexistent" "foobar" + ! ynh_write_var_in_file "$file" "nonexistent" "foobar" test "$(ynh_read_var_in_file "$file" "nonexistent")" == "YNH_NULL" - ynh_write_var_in_file "$file" "enable" "foobar" + ! ynh_write_var_in_file "$file" "enable" "foobar" test "$(ynh_read_var_in_file "$file" "enable")" == "YNH_NULL" test "$(ynh_read_var_in_file "$file" "enabled")" == "true" } @@ -449,7 +458,7 @@ EOF } -nhtest_config_write_json() { +ynhtest_config_write_json() { local dummy_dir="$(mktemp -d -p $VAR_WWW)" file="$dummy_dir/dummy.json" @@ -468,14 +477,15 @@ nhtest_config_write_json() { } EOF - #ynh_write_var_in_file "$file" "foo" "bar" - #cat $file - #test "$(_read_json "$file" "foo")" == "bar" # FIXME FIXME FIXME - #test "$(ynh_read_var_in_file "$file" "foo")" == "bar" + ynh_write_var_in_file "$file" "foo" "bar" + cat $file + test "$(_read_json "$file" "foo")" == "bar" + test "$(ynh_read_var_in_file "$file" "foo")" == "bar" - #ynh_write_var_in_file "$file" "enabled" "true" - #test "$(_read_json "$file" "enabled")" == "True" # FIXME FIXME FIXME - #test "$(ynh_read_var_in_file "$file" "enabled")" == "true" + ynh_write_var_in_file "$file" "enabled" "true" + cat $file + test "$(_read_json "$file" "enabled")" == "true" + test "$(ynh_read_var_in_file "$file" "enabled")" == "true" ynh_write_var_in_file "$file" "title" "Foo Bar" cat $file @@ -492,10 +502,9 @@ EOF test "$(_read_json "$file" "email")" == "sam@domain.tld" test "$(ynh_read_var_in_file "$file" "email")" == "sam@domain.tld" - #ynh_write_var_in_file "$file" "port" "5678" - #cat $file - #test "$(_read_json "$file" "port")" == "5678" # FIXME FIXME FIXME - #test "$(ynh_read_var_in_file "$file" "port")" == "5678" + ynh_write_var_in_file "$file" "port" "5678" + test "$(_read_json "$file" "port")" == "5678" + test "$(ynh_read_var_in_file "$file" "port")" == "5678" ynh_write_var_in_file "$file" "url" "https://domain.tld/foobar" test "$(_read_json "$file" "url")" == "https://domain.tld/foobar" @@ -504,12 +513,12 @@ EOF ynh_write_var_in_file "$file" "ldap_base" "ou=foobar,dc=domain,dc=tld" test "$(ynh_read_var_in_file "$file" "ldap_base")" == "ou=foobar,dc=domain,dc=tld" - ynh_write_var_in_file "$file" "nonexistent" "foobar" + ! ynh_write_var_in_file "$file" "nonexistent" "foobar" test "$(ynh_read_var_in_file "$file" "nonexistent")" == "YNH_NULL" - ynh_write_var_in_file "$file" "enable" "foobar" + ! ynh_write_var_in_file "$file" "enable" "foobar" test "$(ynh_read_var_in_file "$file" "enable")" == "YNH_NULL" - #test "$(ynh_read_var_in_file "$file" "enabled")" == "true" # FIXME + test "$(ynh_read_var_in_file "$file" "enabled")" == "true" } ####################### @@ -589,7 +598,7 @@ EOF } -nhtest_config_write_php() { +ynhtest_config_write_php() { local dummy_dir="$(mktemp -d -p $VAR_WWW)" file="$dummy_dir/dummy.php" @@ -610,15 +619,13 @@ nhtest_config_write_php() { ?> EOF - #ynh_write_var_in_file "$file" "foo" "bar" - #cat $file - #test "$(_read_php "$file" "foo")" == "bar" - #test "$(ynh_read_var_in_file "$file" "foo")" == "bar" # FIXME FIXME FIXME + ynh_write_var_in_file "$file" "foo" "bar" + test "$(_read_php "$file" "foo")" == "bar" + test "$(ynh_read_var_in_file "$file" "foo")" == "bar" - #ynh_write_var_in_file "$file" "enabled" "true" - #cat $file - #test "$(_read_php "$file" "enabled")" == "true" - #test "$(ynh_read_var_in_file "$file" "enabled")" == "true" # FIXME FIXME FIXME + ynh_write_var_in_file "$file" "enabled" "true" + test "$(_read_php "$file" "enabled")" == "true" + test "$(ynh_read_var_in_file "$file" "enabled")" == "true" ynh_write_var_in_file "$file" "title" "Foo Bar" cat $file @@ -635,10 +642,9 @@ EOF test "$(_read_php "$file" "email")" == "sam@domain.tld" test "$(ynh_read_var_in_file "$file" "email")" == "sam@domain.tld" - #ynh_write_var_in_file "$file" "port" "5678" - #cat $file - #test "$(_read_php "$file" "port")" == "5678" # FIXME FIXME FIXME - #test "$(ynh_read_var_in_file "$file" "port")" == "5678" + ynh_write_var_in_file "$file" "port" "5678" + test "$(_read_php "$file" "port")" == "5678" + test "$(ynh_read_var_in_file "$file" "port")" == "5678" ynh_write_var_in_file "$file" "url" "https://domain.tld/foobar" test "$(_read_php "$file" "url")" == "https://domain.tld/foobar" @@ -647,10 +653,10 @@ EOF ynh_write_var_in_file "$file" "ldap_base" "ou=foobar,dc=domain,dc=tld" test "$(ynh_read_var_in_file "$file" "ldap_base")" == "ou=foobar,dc=domain,dc=tld" - ynh_write_var_in_file "$file" "nonexistent" "foobar" + ! ynh_write_var_in_file "$file" "nonexistent" "foobar" test "$(ynh_read_var_in_file "$file" "nonexistent")" == "YNH_NULL" - ynh_write_var_in_file "$file" "enable" "foobar" + ! ynh_write_var_in_file "$file" "enable" "foobar" test "$(ynh_read_var_in_file "$file" "enable")" == "YNH_NULL" - #test "$(ynh_read_var_in_file "$file" "enabled")" == "true" # FIXME + test "$(ynh_read_var_in_file "$file" "enabled")" == "true" }