-
Notifications
You must be signed in to change notification settings - Fork 70
Description
Description
I've just started using dotter, and first off must say I quite like it! Because I'm new, forgive me if I'm missing something.
I arrived at a need to do this as follows: when using dotter to place in userChrome.css for Firefox, the profile directory is not always name-static. It's located in ~/.mozilla/firefox/$PROFILE_WHATEVER.default/chrome/userChrome.css.
The most straightforward solution is to allow some way for scripting the file targets. This most easily can be done with the pre_deploy.sh script, which also allows for additional user-configurable erorr checking.
Implementation Suggestion
After research into previous issues on this repo and doing some light testing, I've come up with a somewhat clean way to do this. This solution works for unix only, but I'm pretty sure it can be done in Windows too.
This functionality can be achieved as follows:
- Instead of directly executing
pre_deploy.sh, run it through a wrapper - The wrapper should call
pre_deploy.shin such a way to preserve its environment variables- This can be done either with
sourceor the. cmdsyntax insh - This should be done through
shbecause dotter already uses it and it's a POSIX shell thing
- This can be done either with
- Print out the environment variables in such a way that Rust can interpret and forward them to itself
Below is a proof of concept. While it does not get all the edge cases, I've outlined how to avoid all those that I know may exist:
use std::process::Command;
fn main() {
let output = Command::new("sh")
.args(&[
"-c",
"
# this could be pre_deploy.sh
# the . means 'run this as a part of the current shell'
# thus the environment variables will be taken in
. $CARGO_MANIFEST_DIR/src/test.sh 2>&1 >/dev/null
# and just print the environment variables
printenv -0
# note: in a real implementation, instead of using /dev/null:
# 1) Create a pipe FD inside of rust
# 2) Merge the FD number into this string as:
# printenv -0 >&FDNO
# 3) Read back the pipe via rust
# This would preserve pre_deploy.sh output
",
])
.output()
.expect("failed to execute process");
let env_vars = output
.stdout
.into_iter()
.fold(vec![vec![]], |mut acc, c| {
// Because we used printenv -0, everything is separated by null characters
// Just need to separate on those
if c == 0 {
acc.push(vec![]);
} else {
acc.last_mut().unwrap().push(c);
}
acc
})
.into_iter()
.map(|v| {
// Now to separate the names from the values
let envp = std::str::from_utf8(&v).unwrap();
// posix compliance states that the seperator between env names and env values is the '=' character
let i: Vec<_> = envp.splitn(2, "=").collect();
(
i[0].to_string(),
i.get(1).map(|s| s.to_string()).unwrap_or(String::new()),
)
})
.collect::<Vec<_>>();
// As an example, printing out TESTENV
// It's feasible to just use std::env::set_var over an iterator
println!(
"{:?}",
env_vars
.into_iter()
.find(|s| s.0.starts_with("TESTENV"))
.unwrap()
);
}Offer to Contribute
I'd be happy to flesh out the above solution to capture all the edge cases, and contribute it as a full solution to dotter. @SuperCuber you're in charge here -- if you think this feature is reasonable I'll gladly put the effort in. I don't want to waste time if not.