Skip to content

Commit

Permalink
Add maybe_sudo
Browse files Browse the repository at this point in the history
  • Loading branch information
theory committed Jan 9, 2025
1 parent 8c20357 commit 3d9791d
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 10 deletions.
2 changes: 1 addition & 1 deletion src/pg_config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ impl PgConfig {

/// Returns the `pg_config` value for `cfg`, which should be a lowercase
/// string.
pub fn get(&mut self, cfg: &str) -> Option<&str> {
pub fn get(&self, cfg: &str) -> Option<&str> {
match self.0.get(cfg) {
Some(c) => Some(c.as_str()),
None => None,
Expand Down
2 changes: 1 addition & 1 deletion src/pg_config/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ fn pg_config() -> Result<(), BuildError> {
]);

// Parse its output.
let mut cfg = PgConfig::new(&path)?;
let cfg = PgConfig::new(&path)?;
assert_eq!(&exp, &cfg.0);

// Get lowercase.
Expand Down
25 changes: 17 additions & 8 deletions src/pipeline/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,22 @@ pub(crate) trait Pipeline<P: AsRef<Path>> {
/// Returns the PgConfig passed to [`new`].
fn pg_config(&self) -> &PgConfig;

// maybe_sudo returns a Command that starts with the sudo command if
// `sudo` is true and the `pkglibdir` returned by pg_config isn't
// writeable by the current user.
fn maybe_sudo(&self, cmd: &str, sudo: bool) -> Command {
if sudo {
if let Some(dir) = self.pg_config().get("pkglibdir") {
if !self.is_writeable(dir) {
let mut c = Command::new("sudo");
c.arg(cmd);
return c;
}
}
}
Command::new(cmd)
}

/// Attempts to write a temporary file to `dir` and returns `true` on
/// success and `false` on failure. The temporary file will be deleted.
fn is_writeable<D: AsRef<Path>>(&self, dir: D) -> bool {
Expand All @@ -56,14 +72,7 @@ pub(crate) trait Pipeline<P: AsRef<Path>> {
S: AsRef<std::ffi::OsStr>,
{
// Use `sudo` if the param is set.
let mut cmd = if sudo {
let mut c = Command::new("sudo");
c.arg(cmd);
c
} else {
Command::new(cmd)
};

let mut cmd = self.maybe_sudo(cmd, sudo);
cmd.args(args);
cmd.current_dir(self.dir());
match cmd.output() {
Expand Down
35 changes: 35 additions & 0 deletions src/pipeline/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,3 +110,38 @@ fn is_writeable() -> Result<(), BuildError> {

Ok(())
}

#[test]
fn maybe_sudo() -> Result<(), BuildError> {
let tmp = tempdir()?;
let cfg = PgConfig::from_map(HashMap::from([(
"pkglibdir".to_string(),
tmp.as_ref().display().to_string(),
)]));
let pipe = TestPipeline::new(&tmp, cfg, false);

// Never use sudo when param is false.
let cmd = pipe.maybe_sudo("foo", false);
assert_eq!("foo", cmd.get_program().to_str().unwrap());

// Never use sudo when directory is writeable.
let cmd = pipe.maybe_sudo("foo", true);
assert_eq!("foo", cmd.get_program().to_str().unwrap());

// Use sudo when the directory is not writeable.
let cfg = PgConfig::from_map(HashMap::from([(
"pkglibdir".to_string(),
tmp.path().join("nonesuch").display().to_string(),
)]));
let pipe = TestPipeline::new(&tmp, cfg, true);
let cmd = pipe.maybe_sudo("foo", true);
assert_eq!("sudo", cmd.get_program().to_str().unwrap());
let args: Vec<&std::ffi::OsStr> = cmd.get_args().collect();
assert_eq!(args, &["foo"]);

// Never use sudo when param is false.
let cmd = pipe.maybe_sudo("foo", false);
assert_eq!("foo", cmd.get_program().to_str().unwrap());

Ok(())
}

0 comments on commit 3d9791d

Please sign in to comment.