Skip to content

Commit

Permalink
fix(container): avoid detecting WSL as a systemd-container (#4593)
Browse files Browse the repository at this point in the history
  • Loading branch information
davidkna committed Nov 15, 2022
1 parent 5f9804d commit b47a4fe
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 45 deletions.
100 changes: 85 additions & 15 deletions src/modules/container.rs
Expand Up @@ -10,7 +10,7 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
use super::ModuleConfig;
use crate::configs::container::ContainerConfig;
use crate::formatter::StringFormatter;
use crate::utils::read_file;
use crate::utils::{self, read_file};

pub fn container_name(context: &Context) -> Option<String> {
use crate::utils::context_path;
Expand All @@ -26,7 +26,14 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
return Some("OCI".into());
}

if context_path(context, "/run/systemd/container").exists() {
// WSL with systemd will set the contents of this file to "wsl"
// Avoid showing the container module in that case
let systemd_path = context_path(context, "/run/systemd/container");
if utils::read_file(systemd_path)
.ok()
.filter(|s| s.trim() != "wsl")
.is_some()
{
// systemd
return Some("Systemd".into());
}
Expand Down Expand Up @@ -101,8 +108,9 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
#[cfg(test)]
mod tests {
use crate::test::ModuleRenderer;
use crate::utils;
use nu_ansi_term::Color;
use std::path::PathBuf;
use std::fs;

#[test]
fn test_none_if_disabled() {
Expand All @@ -120,8 +128,6 @@ mod tests {
}

fn containerenv(name: Option<&str>) -> std::io::Result<(Option<String>, Option<String>)> {
use std::io::Write;

let renderer = ModuleRenderer::new("container")
// For a custom config
.config(toml::toml! {
Expand All @@ -131,18 +137,15 @@ mod tests {

let root_path = renderer.root_path();

let mut containerenv = PathBuf::from(root_path);
let containerenv = root_path.join("run/.containerenv");

containerenv.push("run");
std::fs::DirBuilder::new()
.recursive(true)
.create(&containerenv)?;
fs::create_dir_all(containerenv.parent().unwrap())?;

containerenv.push(".containerenv");
let mut file = std::fs::File::create(&containerenv)?;
if let Some(name) = name {
file.write_all(format!("image=\"{name}\"\n").as_bytes())?;
}
let contents = match name {
Some(name) => format!("image=\"{name}\"\n"),
None => String::new(),
};
utils::write_file(&containerenv, contents)?;

// The output of the module
let actual = renderer
Expand Down Expand Up @@ -182,6 +185,73 @@ mod tests {

Ok(())
}
#[test]
#[cfg(target_os = "linux")]
fn test_containerenv_systemd() -> std::io::Result<()> {
let renderer = ModuleRenderer::new("container")
// For a custom config
.config(toml::toml! {
[container]
disabled = false
});

let root_path = renderer.root_path();

let systemd_path = root_path.join("run/systemd/container");

fs::create_dir_all(systemd_path.parent().unwrap())?;
utils::write_file(&systemd_path, "systemd-nspawn\n")?;

// The output of the module
let actual = renderer
// Run the module and collect the output
.collect();

// The value that should be rendered by the module.
let expected = Some(format!(
"{} ",
Color::Red
.bold()
.dimmed()
.paint(format!("⬢ [{}]", "Systemd"))
));

// Assert that the actual and expected values are the same
assert_eq!(actual, expected);

Ok(())
}

#[test]
#[cfg(target_os = "linux")]
fn test_containerenv_wsl() -> std::io::Result<()> {
let renderer = ModuleRenderer::new("container")
// For a custom config
.config(toml::toml! {
[container]
disabled = false
});

let root_path = renderer.root_path();

let systemd_path = root_path.join("run/systemd/container");

fs::create_dir_all(systemd_path.parent().unwrap())?;
utils::write_file(&systemd_path, "wsl\n")?;

// The output of the module
let actual = renderer
// Run the module and collect the output
.collect();

// The value that should be rendered by the module.
let expected = None;

// Assert that the actual and expected values are the same
assert_eq!(actual, expected);

Ok(())
}

#[test]
#[cfg(not(target_os = "linux"))]
Expand Down
20 changes: 5 additions & 15 deletions src/modules/git_metrics.rs
Expand Up @@ -109,11 +109,11 @@ impl<'a> GitDiff<'a> {

#[cfg(test)]
mod tests {
use crate::utils::create_command;
use crate::utils::{create_command, write_file};
use std::ffi::OsStr;
use std::fs::OpenOptions;
use std::io::{self, Error, ErrorKind, Write};
use std::path::{Path, PathBuf};
use std::path::Path;
use std::process::Stdio;

use nu_ansi_term::Color;
Expand Down Expand Up @@ -157,7 +157,7 @@ mod tests {
let path = repo_dir.path();

let file_path = path.join("the_file");
write_file(file_path, "First Line\nSecond Line")?;
write_file(file_path, "First Line\nSecond Line\n")?;

let actual = render_metrics(path);

Expand All @@ -173,7 +173,7 @@ mod tests {
let path = repo_dir.path();

let file_path = path.join("the_file");
write_file(file_path, "\nSecond Line\n\nModified\nAdded")?;
write_file(file_path, "\nSecond Line\n\nModified\nAdded\n")?;

let actual = render_metrics(path);

Expand Down Expand Up @@ -263,16 +263,6 @@ mod tests {
}
}

fn write_file(file: PathBuf, text: &str) -> io::Result<()> {
let mut file = OpenOptions::new()
.write(true)
.create(true)
.truncate(true)
.open(file)?;
writeln!(file, "{text}")?;
file.sync_all()
}

fn create_repo_with_commit() -> io::Result<tempfile::TempDir> {
let repo_dir = tempfile::tempdir()?;
let path = repo_dir.path();
Expand Down Expand Up @@ -312,7 +302,7 @@ mod tests {
)?;

// Write a file on master and commit it
write_file(file, "First Line\nSecond Line\nThird Line")?;
write_file(file, "First Line\nSecond Line\nThird Line\n")?;
run_git_cmd(["add", "the_file"], Some(path), true)?;
run_git_cmd(
["commit", "--message", "Commit A", "--no-gpg-sign"],
Expand Down
20 changes: 5 additions & 15 deletions src/modules/git_state.rs
Expand Up @@ -159,13 +159,12 @@ struct StateDescription<'a> {
mod tests {
use nu_ansi_term::Color;
use std::ffi::OsStr;
use std::fs::OpenOptions;
use std::io::{self, Error, ErrorKind, Write};
use std::io::{self, Error, ErrorKind};
use std::path::Path;
use std::process::Stdio;

use crate::test::ModuleRenderer;
use crate::utils::create_command;
use crate::utils::{create_command, write_file};

#[test]
fn show_nothing_on_empty_dir() -> io::Result<()> {
Expand Down Expand Up @@ -289,15 +288,6 @@ mod tests {
let path = repo_dir.path();
let conflicted_file = repo_dir.path().join("the_file");

let write_file = |text: &str| {
let mut file = OpenOptions::new()
.write(true)
.create(true)
.truncate(true)
.open(&conflicted_file)?;
write!(file, "{text}")
};

// Initialize a new git repo
run_git_cmd(
[
Expand Down Expand Up @@ -332,7 +322,7 @@ mod tests {
)?;

// Write a file on master and commit it
write_file("Version A")?;
write_file(&conflicted_file, "Version A")?;
run_git_cmd(["add", "the_file"], Some(path), true)?;
run_git_cmd(
["commit", "--message", "Commit A", "--no-gpg-sign"],
Expand All @@ -342,7 +332,7 @@ mod tests {

// Switch to another branch, and commit a change to the file
run_git_cmd(["checkout", "-b", "other-branch"], Some(path), true)?;
write_file("Version B")?;
write_file(&conflicted_file, "Version B")?;
run_git_cmd(
["commit", "--all", "--message", "Commit B", "--no-gpg-sign"],
Some(path),
Expand All @@ -351,7 +341,7 @@ mod tests {

// Switch back to master, and commit a third change to the file
run_git_cmd(["checkout", "master"], Some(path), true)?;
write_file("Version C")?;
write_file(conflicted_file, "Version C")?;
run_git_cmd(
["commit", "--all", "--message", "Commit C", "--no-gpg-sign"],
Some(path),
Expand Down
34 changes: 34 additions & 0 deletions src/utils.rs
Expand Up @@ -48,6 +48,40 @@ pub fn read_file<P: AsRef<Path> + Debug>(file_name: P) -> Result<String> {
result
}

/// Write a string to a file
#[cfg(test)]
pub fn write_file<P: AsRef<Path>, S: AsRef<str>>(file_name: P, text: S) -> Result<()> {
use std::io::Write;

let file_name = file_name.as_ref();
let text = text.as_ref();

log::trace!("Trying to write {text:?} to {file_name:?}");
let mut file = match std::fs::OpenOptions::new()
.write(true)
.create(true)
.truncate(true)
.open(file_name)
{
Ok(file) => file,
Err(err) => {
log::warn!("Error creating file: {:?}", err);
return Err(err);
}
};

match file.write_all(text.as_bytes()) {
Ok(_) => {
log::trace!("File {file_name:?} written successfully");
}
Err(err) => {
log::warn!("Error writing to file: {err:?}");
return Err(err);
}
}
file.sync_all()
}

/// Reads command output from stderr or stdout depending on to which stream program streamed it's output
pub fn get_command_string_output(command: CommandOutput) -> String {
if command.stdout.is_empty() {
Expand Down

0 comments on commit b47a4fe

Please sign in to comment.