LCOV - code coverage report
Current view: top level - internal/src - command.rs (source / functions) Hit Total Coverage
Test: unnamed Lines: 33 53 62.3 %
Date: 2024-10-23 19:20:50 Functions: 3 7 42.9 %

          Line data    Source code
       1             : use anyhow::{ensure, Context, Result};
       2             : use std::{
       3             :     ffi::{OsStr, OsString},
       4             :     path::{Path, PathBuf},
       5             :     process::{Command, Output},
       6             : };
       7             : 
       8             : #[allow(clippy::module_name_repetitions)]
       9             : pub trait CommandExt {
      10             :     fn logged_output(&mut self, require_success: bool) -> Result<Output>;
      11             :     fn success(&mut self) -> Result<()>;
      12             : }
      13             : 
      14             : impl CommandExt for Command {
      15             :     #[cfg_attr(dylint_lib = "general", allow(non_local_effect_before_error_return))]
      16             :     #[cfg_attr(dylint_lib = "overscoped_allow", allow(overscoped_allow))]
      17          79 :     fn logged_output(&mut self, require_success: bool) -> Result<Output> {
      18          79 :         log::debug!("{:?}", self.get_envs().collect::<Vec<_>>());
      19          79 :         log::debug!("{:?}", self.get_current_dir());
      20          79 :         log::debug!("{:?}", self);
      21             : 
      22             :         #[allow(clippy::disallowed_methods)]
      23          79 :         let output = self
      24          79 :             .output()
      25          79 :             .with_context(|| format!("Could not get output of `{self:?}`"))?;
      26             : 
      27          79 :         ensure!(
      28          79 :             !require_success || output.status.success(),
      29           0 :             "command failed: {:?}\nstdout: {:?}\nstderr: {:?}",
      30           0 :             self,
      31           0 :             std::str::from_utf8(&output.stdout).unwrap_or_default(),
      32           0 :             std::str::from_utf8(&output.stderr).unwrap_or_default()
      33             :         );
      34             : 
      35          79 :         Ok(output)
      36          79 :     }
      37             : 
      38             :     // smoelius: Why not get the status by calling `self.output()`? Because we don't want stdout and
      39             :     // stderr to be captured.
      40             :     #[cfg_attr(dylint_lib = "general", allow(non_local_effect_before_error_return))]
      41             :     #[cfg_attr(dylint_lib = "overscoped_allow", allow(overscoped_allow))]
      42         127 :     fn success(&mut self) -> Result<()> {
      43         127 :         log::debug!("{:?}", self.get_envs().collect::<Vec<_>>());
      44         127 :         log::debug!("{:?}", self.get_current_dir());
      45         127 :         log::debug!("{:?}", self);
      46             : 
      47         127 :         let status = self
      48         127 :             .status()
      49         127 :             .with_context(|| format!("Could not get status of `{self:?}`"))?;
      50             : 
      51         127 :         ensure!(status.success(), "command failed: {:?}", self);
      52             : 
      53         124 :         Ok(())
      54         127 :     }
      55             : }
      56             : 
      57             : #[allow(unused_variables)]
      58          32 : pub fn driver(toolchain: &str, driver: &Path) -> Result<Command> {
      59          32 :     #[allow(unused_mut)]
      60          32 :     let mut command = Command::new(driver);
      61          32 :     #[cfg(windows)]
      62          32 :     {
      63          32 :         // MinerSebas: To succesfully determine the dylint driver Version on Windows,
      64          32 :         // it is neccesary to add some Libraries to the Path.
      65          32 :         let new_path = prepend_toolchain_path(toolchain)?;
      66          32 :         command.envs(vec![(crate::env::PATH, new_path)]);
      67          32 :     }
      68          32 :     Ok(command)
      69          32 : }
      70             : 
      71           0 : pub fn prepend_toolchain_path(toolchain: impl AsRef<Path>) -> Result<OsString> {
      72           0 :     let rustup_home = crate::env::var(crate::env::RUSTUP_HOME)?;
      73           0 :     prepend_path(
      74           0 :         Path::new(&rustup_home)
      75           0 :             .join("toolchains")
      76           0 :             .join(toolchain)
      77           0 :             .join("bin"),
      78           0 :     )
      79           0 : }
      80             : 
      81           0 : pub fn prepend_path(path: impl AsRef<OsStr>) -> Result<OsString> {
      82           0 :     let old_path = crate::env::var(crate::env::PATH)?;
      83           0 :     let new_path = std::env::join_paths(
      84           0 :         std::iter::once(PathBuf::from(path.as_ref())).chain(std::env::split_paths(&old_path)),
      85           0 :     )?;
      86           0 :     Ok(new_path)
      87           0 : }

Generated by: LCOV version 1.14