-
Notifications
You must be signed in to change notification settings - Fork 112
Refactor user-defined scripts #1292
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
config/slskd.example.yml
Outdated
| # my_logging_script: | ||
| # run: | ||
| # executable: ~ # if omitted, defaults to your operating system's $SHELL, or cmd.exe on Windows | ||
| # command: data/my_script.sh # the script reads the data from the $SLSKD_SCRIPT_DATA envar |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why is this called command? I understand this is what is usually called args (except it's a single string instead of a list of strings, which is a more typical way of doing it).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and why isn't data/my_script.sh passed in the executable field? not that it would really make a difference...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
my goal was to get to semantics that "just work" as if someone was at their terminal typing in a prompt. i think i still missed the mark because this needs -c or /c as a first argument to work that way.
i'll split this out into shell and a combination of executable and args. shell will use the existing logic to determine the system shell and automatically prepend -c or /c, while the combination of executable and args will give power users maximal control
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure this is the best idea, but if you really think you should, then you should also go into the string quoting headache.
Let's assume you want to do something very simple, like this
echo "The new value is $(echo -n "$SLSKD_SCRIPT_DATA" | jq '.foo[]|.bar')" >> /tmp/slskd-log.txtThis needs two different quoting: one is done by the user, when writing the YAML configuration. It sucks, but it's not your problem as a developer.
The second kind of quoting happens when you want to invoke such a line. I see you can't have ArgumentList, so you're left with a single string. So you would need to do some form of quoting so that ProcessStartInfo splits your command the correct way. (ie: ["/bin/sh", "-c", "whatever I wrote earlier"]). I don't know how that works exactly, and I wouldn't be surprised if that was platform-specific.
| RedirectStandardOutput = true, | ||
| RedirectStandardError = true, | ||
| RedirectStandardInput = true, | ||
| Arguments = args, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know nothing about csharp (so feel free to ignore this comment), but isn't ArgumentList just more practical than Arguments?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it would be but unfortunately there's only Arguments which is a string
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about that? https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.processstartinfo.-ctor?view=net-9.0#system-diagnostics-processstartinfo-ctor(system-string-system-collections-generic-ienumerable((system-string))) Again, sorry if I'm talking gibberish: I really know nothing about the .net environment
config/slskd.example.yml
Outdated
| # args_list: | ||
| # - /c | ||
| # - echo %SLSKD_SCRIPT_DATA% >> downloads.txt |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that's sooo much nicer interface!
is there any case in which using a single string (args) should be recommended for user? shouldn't args_list just be enough for everyone, allowing for the code to be simplified a lot?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My big concern with this is that if args were to take on the behavior of args_list (which I've just renamed to arglist to better match other applications) people would fumble trying to specify a string where an array is expected. YAML formatting errors get really ugly and cryptic error messages and I see users struggle with it a lot, so I'm trying my best to make it as intuitive as possible
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
people would fumble trying to specify a string where an array is expected
I see your point. My experience, as a user, is that I learned why "strings as command arguments don't work" the hard way: I was trying to write commands in similar settings, and that was just repeatedly buggy. And whenever I was asking developers what I should do to handle the n-th level of quoting, the only meaningful tip I got was "just create a wrapper script and invoke that". So, since then, my thought is always: why isn't this just stated upfront since the beginning? Why are examples pointing me in a direction which is fragile and sometimes just not working? Why do people mess with placeholder in argument strings (which are difficult to handle) compared to passing data to stdin (which is straightforward)?
Anyway, back to the case at hand, I see how your concern is an important one, too. I still stand that it would be better to just have args_list. I think you are right in pointing out that users could get confused. Good mitigations are:
- provide clear examples
- provide a clear error message, like "args_list should be a list of arguments, not a string. See link.to/doc/ for examples"
I think you are still headed to have this triple mode merged. I think it's making the code more complex for no real value, but you're the maintainer, so it's your call :)
| RedirectStandardOutput = true, | ||
| RedirectStandardError = true, | ||
| Arguments = run.Command.StartsWith(DefaultCommandPrefix) ? run.Command : $"{DefaultCommandPrefix} {run.Command}", | ||
| Arguments = run.Command.StartsWith(DefaultCommandPrefix) ? run.Command : $"{DefaultCommandPrefix} \"{run.Command}\"", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't this break if the user supplied a command which includes double quotes? ie:
touch "/tmp/notify me"There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it didn't when i was testing on Linux last night. i'm going to test on Windows this morning
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Broke on Windows; I pushed a fix. Thanks for pointing it out.
|
I'm going to push this out to the canary so I can test in a wider variety of scenarios. The final structure is:
I'm going to hold off on updating the docs until I've verified that things are still working as expected. |
|
Thanks @SevereOverfl0w and @boyska for the feedback! Please let me know what you think of the finished product. |
Closes #1278
Documentation to follow once folks have had a chance to confirm functionality
Testing
Linux
Windows