tinkerbell / tink

Workflow Engine for provisioning Bare Metal
https://tinkerbell.org
Apache License 2.0
913 stars 134 forks source link

why does setup.sh uses parentheses to declare function bodies? #171

Closed rgl closed 4 years ago

rgl commented 4 years ago

It using parentheses to declare the function body (name() ( ... )) instead of using curly braces (name() { ... }), e.g., at:

https://github.com/tinkerbell/tink/blob/6c66328523c3df28a1625d549ee98d17d668d4f9/setup.sh#L15-L17

Why is that?

grahamc commented 4 years ago

With {}, it is as if the functions did not exist, and all the code was copy/pasted in to the order it ran. With (), the functions get individual scopes. To demonstrate:

#!/bin/sh

foo() {
    set -eux
    example=hello
    cd /
}

bar() {
    echo "example is equal to: «$example»"
    pwd
}

foo
bar

When running bar, the current directory is still /, and set -eux is still configured, and example equals hello:

$ ./test.sh
+ example=hello
+ cd /
+ bar
+ echo example is equal to: «hello»
example is equal to: «hello»
+ pwd
/

Using ()s, the local changes are not leaked:

#!/bin/sh

foo() (
    set -eux
    example=hello
    cd /
)

bar() (
    echo "example is equal to: «$example»"
    pwd
)

foo
bar

produces

$ ./test.sh
+ example=hello
+ cd /
example is equal to: «»
/home/grahamc/projects/github.com/tinkerbell/tink
rgl commented 4 years ago

I never thought that using a subshell as a function body worked. This is so strange! But now I know. Thx!

grahamc commented 4 years ago

Yep! Gladly! To me it feels like taking bash from "meh" to "less meh" :)