diff --git a/data/helpers.d/utils b/data/helpers.d/utils index 3389101a6..0a820505c 100644 --- a/data/helpers.d/utils +++ b/data/helpers.d/utils @@ -507,6 +507,7 @@ 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= ) @@ -514,18 +515,43 @@ ynh_read_var_in_file() { local key # Manage arguments with getopts ynh_handle_getopts_args "$@" + set +o xtrace + local filename="$(basename -- "$file")" + local ext="${filename##*.}" + local endline=',;' + local assign="=>|:|=" + local comments="#" + local string="\"'" + if [[ "yaml yml toml ini env" =~ *"$ext"* ]]; then + endline='#' + 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*' - local var_part='^[ \t]*\$?(\w*\[)?[ \t]*["'"']?${key}['"'"]?[ \t]*\]?[ \t]*[:=]>?[ \t]*' + # Extract the part after assignation sign + local expression_with_comment="$(grep -i -o -P $var_part'\K.*$' ${file} || echo YNH_NULL | head -n1)" + if [[ "$expression_with_comment" == "YNH_NULL" ]]; then + echo YNH_NULL + return 0 + fi - local crazy_value="$(grep -i -o -P '^[ \t]*\$?(\w*\[)?[ \t]*["'"']?${key}['"'"]?[ \t]*\]?[ \t]*[:=]>?[ \t]*\K.*(?=[ \t,\n;]*$)' ${file} || echo YNH_NULL | head -n1)" + # Remove comments if needed + local expression="$(echo "$expression_with_comment" | sed "s@$comments[^$string]*\$@@" | sed "s@\s*[$endline]*\s*]*\$@@")" - local first_char="${crazy_value:0:1}" + local first_char="${expression:0:1}" if [[ "$first_char" == '"' ]] ; then - echo "$crazy_value" | grep -m1 -o -P '"\K([^"](\\")?)*[^\\](?=")' | head -n1 | sed 's/\\"/"/g' + echo "$expression" | grep -m1 -o -P '"\K([^"](\\")?)*[^\\](?=")' | head -n1 | sed 's/\\"/"/g' elif [[ "$first_char" == "'" ]] ; then - echo "$crazy_value" | grep -m1 -o -P "'\K([^'](\\\\')?)*[^\\\\](?=')" | head -n1 | sed "s/\\\\'/'/g" + echo "$expression" | grep -m1 -o -P "'\K([^'](\\\\')?)*[^\\\\](?=')" | head -n1 | sed "s/\\\\'/'/g" else - echo "$crazy_value" + echo "$expression" fi } @@ -538,6 +564,7 @@ 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=) @@ -546,9 +573,10 @@ ynh_write_var_in_file() { local value # Manage arguments with getopts ynh_handle_getopts_args "$@" - local var_part='[ \t]*\$?(\w*\[)?[ \t]*["'"']?${key}['"'"]?[ \t]*\]?[ \t]*[:=]>?[ \t]*' + set +o xtrace + local var_part='\s*\$?([\w.]*\[)?\s*["'"']?${key}['"'"]?\s*\]?\s*[:=]>?\s*' - local crazy_value="$(grep -i -o -P '^[ \t]*\$?(\w*\[)?[ \t]*["'"']?${key}['"'"]?[ \t]*\]?[ \t]*[:=]>?[ \t]*\K.*(?=[ \t,\n;]*$)' ${file} | head -n1)" + 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}" delimiter=$'\001' @@ -556,13 +584,13 @@ ynh_write_var_in_file() { # \ 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}"'")([^"]|\\")*("[ \t;,]*)$'$delimiter'\1'"${value}"'\4'$delimiter'i' ${file} + sed -ri s$delimiter'^('"${var_part}"'")([^"]|\\")*("[\s;,]*)$'$delimiter'\1'"${value}"'\4'$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}')([^']|\\')*('"'[ \t,;]*)$'$delimiter'\1'"${value}"'\4'$delimiter'i' ${file} + sed -ri "s$delimiter^(${var_part}')([^']|\\')*('"'[\s,;]*)$'$delimiter'\1'"${value}"'\4'$delimiter'i' ${file} else if [[ "$value" == *"'"* ]] || [[ "$value" == *'"'* ]] ; then value='\"'"$(echo "$value" | sed 's/"/\\\\"/g')"'\"' diff --git a/tests/test_helpers.d/ynhtest_config.sh b/tests/test_helpers.d/ynhtest_config.sh index 7b749adf5..36165e3ac 100644 --- a/tests/test_helpers.d/ynhtest_config.sh +++ b/tests/test_helpers.d/ynhtest_config.sh @@ -27,11 +27,13 @@ ENABLED = False # TITLE = "Old title" TITLE = "Lorem Ipsum" THEME = "colib'ris" -EMAIL = "root@example.com" -PORT = 1234 +EMAIL = "root@example.com" # This is a comment without quotes +PORT = 1234 # This is a comment without quotes URL = 'https://yunohost.org' DICT = {} DICT['ldap_base'] = "ou=users,dc=yunohost,dc=org" +DICT['ldap_conf'] = {} +DICT['ldap_conf']['user'] = "camille" EOF test "$(_read_py "$file" "FOO")" == "None" @@ -56,6 +58,8 @@ EOF test "$(ynh_read_var_in_file "$file" "URL")" == "https://yunohost.org" test "$(ynh_read_var_in_file "$file" "ldap_base")" == "ou=users,dc=yunohost,dc=org" + + test "$(ynh_read_var_in_file "$file" "user")" == "camille" ! _read_py "$file" "NONEXISTENT" test "$(ynh_read_var_in_file "$file" "NONEXISTENT")" == "YNH_NULL" @@ -64,7 +68,7 @@ EOF test "$(ynh_read_var_in_file "$file" "ENABLE")" == "YNH_NULL" } -ynhtest_config_write_py() { +nhtest_config_write_py() { local dummy_dir="$(mktemp -d -p $VAR_WWW)" file="$dummy_dir/dummy.py" @@ -75,8 +79,8 @@ ENABLED = False # TITLE = "Old title" TITLE = "Lorem Ipsum" THEME = "colib'ris" -EMAIL = "root@example.com" -PORT = 1234 +EMAIL = "root@example.com" // This is a comment without quotes +PORT = 1234 // This is a comment without quotes URL = 'https://yunohost.org' DICT = {} DICT['ldap_base'] = "ou=users,dc=yunohost,dc=org" @@ -141,7 +145,7 @@ _read_ini() { ynhtest_config_read_ini() { local dummy_dir="$(mktemp -d -p $VAR_WWW)" - file="$dummy_dir/dummy.yml" + file="$dummy_dir/dummy.ini" cat << EOF > $file # Some comment @@ -152,8 +156,8 @@ enabled = False # title = Old title title = Lorem Ipsum theme = colib'ris -email = root@example.com -port = 1234 +email = root@example.com # This is a comment without quotes +port = 1234 # This is a comment without quotes url = https://yunohost.org [dict] ldap_base = ou=users,dc=yunohost,dc=org @@ -190,7 +194,7 @@ EOF } -ynhtest_config_write_ini() { +nhtest_config_write_ini() { local dummy_dir="$(mktemp -d -p $VAR_WWW)" file="$dummy_dir/dummy.ini" @@ -203,8 +207,8 @@ enabled = False # title = Old title title = Lorem Ipsum theme = colib'ris -email = root@example.com -port = 1234 +email = root@example.com # This is a comment without quotes +port = 1234 # This is a comment without quotes url = https://yunohost.org [dict] ldap_base = ou=users,dc=yunohost,dc=org @@ -280,8 +284,8 @@ enabled: false # title: old title title: Lorem Ipsum theme: colib'ris -email: root@example.com -port: 1234 +email: root@example.com # This is a comment without quotes +port: 1234 # This is a comment without quotes url: https://yunohost.org dict: ldap_base: ou=users,dc=yunohost,dc=org @@ -318,7 +322,7 @@ EOF } -ynhtest_config_write_yaml() { +nhtest_config_write_yaml() { local dummy_dir="$(mktemp -d -p $VAR_WWW)" file="$dummy_dir/dummy.yml" @@ -329,8 +333,8 @@ enabled: false # title: old title title: Lorem Ipsum theme: colib'ris -email: root@example.com -port: 1234 +email: root@example.com # This is a comment without quotes +port: 1234 # This is a comment without quotes url: https://yunohost.org dict: ldap_base: ou=users,dc=yunohost,dc=org @@ -415,10 +419,10 @@ EOF test "$(_read_json "$file" "foo")" == "None" - test "$(ynh_read_var_in_file "$file" "foo")" == "null," # FIXME FIXME FIXME trailing , + test "$(ynh_read_var_in_file "$file" "foo")" == "null" test "$(_read_json "$file" "enabled")" == "False" - test "$(ynh_read_var_in_file "$file" "enabled")" == "false," # FIXME FIXME FIXME trailing , + test "$(ynh_read_var_in_file "$file" "enabled")" == "false" test "$(_read_json "$file" "title")" == "Lorem Ipsum" test "$(ynh_read_var_in_file "$file" "title")" == "Lorem Ipsum" @@ -430,7 +434,7 @@ EOF test "$(ynh_read_var_in_file "$file" "email")" == "root@example.com" test "$(_read_json "$file" "port")" == "1234" - test "$(ynh_read_var_in_file "$file" "port")" == "1234," # FIXME FIXME FIXME trailing , + test "$(ynh_read_var_in_file "$file" "port")" == "1234" test "$(_read_json "$file" "url")" == "https://yunohost.org" test "$(ynh_read_var_in_file "$file" "url")" == "https://yunohost.org" @@ -445,7 +449,7 @@ EOF } -ynhtest_config_write_json() { +nhtest_config_write_json() { local dummy_dir="$(mktemp -d -p $VAR_WWW)" file="$dummy_dir/dummy.json" @@ -538,20 +542,23 @@ ynhtest_config_read_php() { // \$title = "old title"; \$title = "Lorem Ipsum"; \$theme = "colib'ris"; - \$email = "root@example.com"; - \$port = 1234; + \$email = "root@example.com"; // This is a comment without quotes + \$port = 1234; // This is a second comment without quotes \$url = "https://yunohost.org"; \$dict = [ 'ldap_base' => "ou=users,dc=yunohost,dc=org", + 'ldap_conf' => [] ]; + \$dict['ldap_conf']['user'] = 'camille'; + const DB_HOST = 'localhost'; ?> EOF test "$(_read_php "$file" "foo")" == "NULL" - test "$(ynh_read_var_in_file "$file" "foo")" == "NULL;" # FIXME FIXME FIXME trailing ; + test "$(ynh_read_var_in_file "$file" "foo")" == "NULL" test "$(_read_php "$file" "enabled")" == "false" - test "$(ynh_read_var_in_file "$file" "enabled")" == "false;" # FIXME FIXME FIXME trailing ; + test "$(ynh_read_var_in_file "$file" "enabled")" == "false" test "$(_read_php "$file" "title")" == "Lorem Ipsum" test "$(ynh_read_var_in_file "$file" "title")" == "Lorem Ipsum" @@ -563,12 +570,16 @@ EOF test "$(ynh_read_var_in_file "$file" "email")" == "root@example.com" test "$(_read_php "$file" "port")" == "1234" - test "$(ynh_read_var_in_file "$file" "port")" == "1234;" # FIXME FIXME FIXME trailing ; + test "$(ynh_read_var_in_file "$file" "port")" == "1234" test "$(_read_php "$file" "url")" == "https://yunohost.org" test "$(ynh_read_var_in_file "$file" "url")" == "https://yunohost.org" 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" "DB_HOST")" == "localhost" ! _read_php "$file" "nonexistent" test "$(ynh_read_var_in_file "$file" "nonexistent")" == "YNH_NULL" @@ -578,7 +589,7 @@ EOF } -ynhtest_config_write_php() { +nhtest_config_write_php() { local dummy_dir="$(mktemp -d -p $VAR_WWW)" file="$dummy_dir/dummy.php" @@ -590,8 +601,8 @@ ynhtest_config_write_php() { // \$title = "old title"; \$title = "Lorem Ipsum"; \$theme = "colib'ris"; - \$email = "root@example.com"; - \$port = 1234; + \$email = "root@example.com"; // This is a comment without quotes + \$port = 1234; // This is a comment without quotes \$url = "https://yunohost.org"; \$dict = [ 'ldap_base' => "ou=users,dc=yunohost,dc=org",