Skip to content

Commit 8600d67

Browse files
committed
feat: Existing strings are overridable on presence of var
If `BASH_OBJECT_FORCE_SET` is `yes`, then do not print an error if the user is attempting to set a non-string to a string (within objects an arrays). Instead, override the string with that object or string. Later, this will be implemented for objects and arrays, but only strings are implemented for now since the former two involved careful deallocation.
1 parent 778ccd3 commit 8600d67

File tree

3 files changed

+196
-4
lines changed

3 files changed

+196
-4
lines changed

examples/script2.sh

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#!/usr/bin/env bash
2+
set -eo pipefail
3+
4+
eval "$(basalt-package-init)"
5+
basalt.package-init
6+
basalt.package-load
7+
8+
BASH_OBJECT_FORCE_SET=yes
9+
VERIFY_BASH_OBJECT=
10+
11+
declare -A root_object=()
12+
declare -a tl_arr=()
13+
declare -a arr_0=(1 2 3 4 5 6)
14+
declare -a arr_1=(1 2 4 8 this_will_be_replaced_too 32)
15+
declare -a arr_1_2=(0 1 0)
16+
declare -A obj_1_4=([and]=epic [so]=cool [this]=is)
17+
declare -a arr_2=(1 10 100 1000 10000 100000)
18+
19+
bobject set-array --ref root_object '.arr' 'tl_arr'
20+
bobject set-array --ref root_object '.["arr"].[0]' 'arr_0'
21+
bobject set-array --ref root_object '.["arr"].[1]' 'arr_1'
22+
bobject set-array --ref root_object '.["arr"].[1].[2]' 'arr_1_2'
23+
bobject set-object --ref root_object '.["arr"].[1].[4]' 'obj_1_4'
24+
bobject set-array --ref root_object '.["arr"].[2]' 'arr_2'
25+
26+
bobject.print 'root_object'

pkg/src/traverse-set.sh

+52-4
Original file line numberDiff line numberDiff line change
@@ -422,11 +422,59 @@ bash_object.traverse-set() {
422422
elif ((i+1 == ${#REPLY_QUERYTREE[@]})); then
423423
local value="${__current_object[$key]}"
424424
if [ "$final_value_type" = object ]; then
425-
bash_object.util.die 'ERROR_ARGUMENTS_INCORRECT_TYPE' "Assigning an $final_value_type, but found existing string '$value'"
426-
return
425+
if [ "$BASH_OBJECT_FORCE_SET" = 'yes' ]; then
426+
bash_object.util.generate_vobject_name "$root_object_name" "$querytree_stack_string"
427+
local global_object_name="$REPLY"
428+
429+
if bash_object.ensure.variable_does_not_exist "$global_object_name"; then :; else
430+
return
431+
fi
432+
433+
if ! declare -gA "$global_object_name"; then
434+
bash_object.util.die 'ERROR_INTERNAL' "Could not declare variable '$global_object_name'"
435+
return
436+
fi
437+
local -n global_object="$global_object_name"
438+
global_object=()
439+
440+
__current_object["$key"]=$'\x1C\x1D'"type=object;&$global_object_name"
441+
442+
local -n ___object_to_copy_from="$final_value"
443+
444+
for key in "${!___object_to_copy_from[@]}"; do
445+
# shellcheck disable=SC2034
446+
global_object["$key"]="${___object_to_copy_from[$key]}"
447+
done
448+
else
449+
bash_object.util.die 'ERROR_ARGUMENTS_INCORRECT_TYPE' "Assigning an $final_value_type, but found existing string '$value'"
450+
return
451+
fi
427452
elif [ "$final_value_type" = array ]; then
428-
bash_object.util.die 'ERROR_ARGUMENTS_INCORRECT_TYPE' "Assigning an $final_value_type, but found existing string '$value'"
429-
return
453+
if [ "$BASH_OBJECT_FORCE_SET" = 'yes' ]; then
454+
bash_object.util.generate_vobject_name "$root_object_name" "$querytree_stack_string"
455+
local global_array_name="$REPLY"
456+
457+
if bash_object.ensure.variable_does_not_exist "$global_array_name"; then :; else
458+
return
459+
fi
460+
461+
if ! declare -ga "$global_array_name"; then
462+
bash_object.util.die 'ERROR_INTERNAL' "Could not declare variable $global_object_name"
463+
return
464+
fi
465+
local -n global_array="$global_array_name"
466+
global_array=()
467+
468+
__current_object["$key"]=$'\x1C\x1D'"type=array;&$global_array_name"
469+
470+
local -n ___array_to_copy_from="$final_value"
471+
472+
# shellcheck disable=SC2034
473+
global_array=("${___array_to_copy_from[@]}")
474+
else
475+
bash_object.util.die 'ERROR_ARGUMENTS_INCORRECT_TYPE' "Assigning an $final_value_type, but found existing string '$value'"
476+
return
477+
fi
430478
elif [ "$final_value_type" = string ]; then
431479
local -n ___string_to_copy_from="$final_value"
432480
__current_object["$key"]="$___string_to_copy_from"

tests/set-force.bats

+118
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
#!/usr/bin/env bats
2+
3+
load './util/init.sh'
4+
5+
@test "Correctly force set object on string within array" {
6+
BASH_OBJECT_FORCE_SET=yes
7+
8+
declare -A root_object=()
9+
declare -a arr=(y z)
10+
declare -A obj=([key1]=value1 [key2]=value2)
11+
12+
bobject set-array --ref root_object '.a' 'arr'
13+
bobject set-object --ref root_object '.["a"].[1]' 'obj'
14+
15+
bobject get-array --value 'root_object' '.["a"]'
16+
assert [ "${#REPLY[@]}" = 2 ]
17+
18+
bobject get-string --value 'root_object' '.["a"].[0]'
19+
assert [ "$REPLY" = y ]
20+
21+
bobject get-object --value 'root_object' '.["a"].[1]'
22+
assert [ "${#REPLY[@]}" = 2 ]
23+
assert [ "${REPLY[key1]}" = value1 ]
24+
assert [ "${REPLY[key2]}" = value2 ]
25+
}
26+
27+
@test "Correctly force set object on string within object" {
28+
BASH_OBJECT_FORCE_SET=yes
29+
30+
declare -A root_object=()
31+
declare -A p_obj=([a]=b [c]=d [e]=f)
32+
declare -A sub_obj=([key1]=value1 [key2]=value2)
33+
34+
bobject set-object --ref root_object '.a' 'p_obj'
35+
bobject set-object --ref root_object '.["a"].["e"]' 'sub_obj'
36+
37+
bobject get-object --value 'root_object' '.["a"]'
38+
assert [ "${#REPLY[@]}" = 3 ]
39+
assert [ "${REPLY[a]}" = b ]
40+
assert [ "${REPLY[c]}" = d ]
41+
42+
bobject get-object --value 'root_object' '.["a"].["e"]'
43+
assert [ "${#REPLY[@]}" = 2 ]
44+
assert [ "${REPLY[key1]}" = value1 ]
45+
assert [ "${REPLY[key2]}" = value2 ]
46+
}
47+
48+
@test "Correctly force set array on string within array" {
49+
BASH_OBJECT_FORCE_SET=yes
50+
51+
declare -A root_object=()
52+
declare -a p_arr=(y z)
53+
declare -a sub_arr=(a b c d e f)
54+
55+
bobject set-array --ref root_object '.a' 'p_arr'
56+
bobject set-array --ref root_object '.["a"].[1]' 'sub_arr'
57+
58+
bobject get-array --value 'root_object' '.["a"]'
59+
assert [ "${#REPLY[@]}" = 2 ]
60+
61+
bobject get-array --value 'root_object' '.["a"].[1]'
62+
assert [ "${#REPLY[@]}" = 6 ]
63+
assert [ "${REPLY[0]}" = a ]
64+
assert [ "${REPLY[1]}" = b ]
65+
assert [ "${REPLY[5]}" = f ]
66+
}
67+
68+
@test "Correctly force set array on string within object" {
69+
BASH_OBJECT_FORCE_SET=yes
70+
71+
declare -A root_object=()
72+
declare -A p_obj=([w]=x [y]=z)
73+
declare -a sub_arr=(a b c d e f)
74+
75+
bobject set-object --ref root_object '.a' 'p_obj'
76+
bobject set-array --ref root_object '.["a"].["w"]' 'sub_arr'
77+
78+
bobject get-object --value 'root_object' '.["a"]'
79+
assert [ "${#REPLY[@]}" = 2 ]
80+
assert [ "${REPLY[y]}" = z ]
81+
82+
bobject get-array --value 'root_object' '.["a"].["w"]'
83+
assert [ "${#REPLY[@]}" = 6 ]
84+
assert [ "${REPLY[0]}" = a ]
85+
assert [ "${REPLY[1]}" = b ]
86+
assert [ "${REPLY[5]}" = f ]
87+
}
88+
89+
@test "Correctly force set nested objects and arrays on string" {
90+
BASH_OBJECT_FORCE_SET=yes
91+
92+
declare -A root_object=()
93+
declare -a tl_arr=()
94+
declare -a arr_0=(1 2 3 4 5 6)
95+
declare -a arr_1=(1 2 4 8 this_will_be_replaced_too 32)
96+
declare -a arr_1_2=(0 1 0)
97+
declare -A obj_1_4=([and]=epic [so]=cool [this]=is)
98+
declare -a arr_2=(1 10 100 1000 10000 100000)
99+
100+
bobject set-array --ref root_object '.arr' 'tl_arr'
101+
bobject set-array --ref root_object '.["arr"].[0]' 'arr_0'
102+
bobject set-array --ref root_object '.["arr"].[1]' 'arr_1'
103+
bobject set-array --ref root_object '.["arr"].[1].[2]' 'arr_1_2'
104+
bobject set-object --ref root_object '.["arr"].[1].[4]' 'obj_1_4'
105+
bobject set-array --ref root_object '.["arr"].[2]' 'arr_2'
106+
107+
bobject get-array --value 'root_object' '.["arr"].[0]'
108+
assert [ "${#REPLY[@]}" = 6 ]
109+
110+
bobject get-string --value 'root_object' '.["arr"].[1].[1]'
111+
assert [ "$REPLY" = 2 ]
112+
113+
bobject get-array --value 'root_object' '.["arr"].[1].[2]'
114+
assert [ "${#REPLY[@]}" = 3 ]
115+
assert [ "${REPLY[0]}" = 0 ]
116+
assert [ "${REPLY[1]}" = 1 ]
117+
assert [ "${REPLY[2]}" = 0 ]
118+
}

0 commit comments

Comments
 (0)