mattly / bork

the Bash-Operated Reconciling Kludge
Other
218 stars 27 forks source link

single-quote arguments that would be expanded by eval #80

Closed martinwalsh closed 6 years ago

martinwalsh commented 8 years ago

I'm trying to create a new assertion type for appending a line to a file (e.g. ~/.profile) if it isn't already present. Here's an example invocation:

ok lineinfile 'if which rbenv > /dev/null; then eval "$(rbenv init -)"; fi' ${HOME}/.profile

I won't bore you with the implementation details unless requested, but the above results in errors like ...

PATH="/usr/local/var/rbenv/shims:${PATH}": No such file or directory

... presumably because the $(rbenv init -) part is being expanded somewhere along the way. It appears that's happening in the ok function, where args are re-quoted with double-quotes and then subsequently eval'ed.

Re-quoting quoted_argstr with single-quotes seems to fix the issue for me, and does not break any tests, but admittedly I may be missing some obvious way to escape the input to avoid the problem in the first place.

frdmn commented 8 years ago

Hi Martin,

thanks for the PR! I just tried to pull in your new type and try out the behaviour on my end, but for some reason I can't get it working so far:

bork do ok lineinfile 'if which rbenv > /dev/null; then eval "$(rbenv init -)"; fi' testfile
missing: lineinfile if which rbenv > /dev/null; then eval "$(rbenv init -)"; fi testfile
/private/tmp/bork/types/lineinfile.sh: line 24: [: rbenv: integer expression expected
verifying : lineinfile if which rbenv > /dev/null; then eval "$(rbenv init -)"; fi testfile
* success

Whenever this happens, a file is created called which with the content:


if

Here's the full verbose (set -x) output - perhaps you can figure out what's going on:

http://paste.frd.mn/oxopu.bash

frdmn commented 8 years ago

@martinwalsh Any news on this?

martinwalsh commented 8 years ago

@frdmn very sorry about the delay. Yes, I see the issue you're raising. For what it's worth, I'm also seeing a similar issue against the master branch, too ... in that a which file is created with the content \nif, when the do operation is used. Although, the error output is slightly different as noted in my original comment. There seems to be no mistaking that if is passed as $2 and which is passed as $3 to my custom type when invoked with do.

So it seems the difficulty I'm facing is in preserving the single-quoted argument as a single entity through the various layers of eval, or perhaps I'm missing some other subtlety.

To confuse matters further, my patch does in fact help when the single-quoted argument is passed to ok inside a config-file. For example,

# test-lineinfile.sh
ok lineinfile 'if which rbenv > /dev/null; then eval "$(rbenv init -)"; fi' testfile
$ bash -x bin/bork satisfy test-lineinfile.sh

output: http://paste.frd.mn/coxas.bash

I'm guessing the interactive shell-session do call in your example is enough for us to drop the single-quotes; bash expands them out, I assume. I now understand that passing around quoted arguments is really hard in bash, and at this point, I'm not sure how to work around the issue.

frdmn commented 8 years ago

Got you! I'm out of escaping ideas as well unfortunately. I'll keep this open (unless you want to remove your fork), maybe someone else knows how to improve this.

mattly commented 6 years ago

Thanks; I think this goes a way toward solving #87, which I started tackling over in #126. Basically bork's use (and enforcement of) quoting is inconsistent and this is a first step towards making it less so.

Sorry it took so long for me to look at it, but I was on caring-for-newborn levels of sleep when this came through.