use super::Mode;
use thiserror::Error;
use yash_env::system::Errno;
use yash_env::{Env, System};
#[derive(Debug, Clone, Eq, Error, PartialEq)]
pub enum Error {
#[error(transparent)]
SystemError(Errno),
}
pub type Result = std::result::Result<String, Error>;
pub fn compute(env: &Env, mode: Mode) -> Result {
match mode {
Mode::Logical => {
if let Some(pwd) = env.get_pwd_if_correct() {
return Ok(format!("{pwd}\n"));
}
}
Mode::Physical => (),
}
let mut cwd = env
.system
.getcwd()
.map_err(Error::SystemError)?
.into_unix_string()
.into_string()
.map_err(|_| Error::SystemError(Errno::EILSEQ))?;
cwd.push('\n');
Ok(cwd)
}
#[cfg(test)]
mod tests {
use super::*;
use std::cell::RefCell;
use std::rc::Rc;
use yash_env::VirtualSystem;
use yash_env::path::PathBuf;
use yash_env::system::r#virtual::FileBody;
use yash_env::system::r#virtual::Inode;
use yash_env::variable::PWD;
use yash_env::variable::Scope::Global;
fn env_with_symlink_to_dir() -> Env {
let mut system = Box::new(VirtualSystem::new());
let mut state = system.state.borrow_mut();
state
.file_system
.save(
"/foo/bar/dir",
Rc::new(RefCell::new(Inode {
body: FileBody::Directory {
files: Default::default(),
},
permissions: Default::default(),
})),
)
.unwrap();
state
.file_system
.save(
"/foo/link",
Rc::new(RefCell::new(Inode {
body: FileBody::Symlink {
target: "bar/dir".into(),
},
permissions: Default::default(),
})),
)
.unwrap();
drop(state);
system
.current_process_mut()
.chdir(PathBuf::from("/foo/bar/dir"));
Env::with_system(system)
}
#[test]
fn logical_with_correct_pwd() {
let mut env = env_with_symlink_to_dir();
env.variables
.get_or_new(PWD, Global)
.assign("/foo/link", None)
.unwrap();
let result = compute(&env, Mode::Logical).unwrap();
assert_eq!(result, "/foo/link\n");
}
#[test]
fn logical_with_wrong_pwd() {
let mut env = env_with_symlink_to_dir();
env.variables
.get_or_new(PWD, Global)
.assign("/foo/./link", None)
.unwrap();
let result = compute(&env, Mode::Logical).unwrap();
assert_eq!(result, "/foo/bar/dir\n");
}
#[test]
fn physical() {
let mut env = env_with_symlink_to_dir();
env.variables
.get_or_new(PWD, Global)
.assign("/foo/link", None)
.unwrap();
let result = compute(&env, Mode::Physical).unwrap();
assert_eq!(result, "/foo/bar/dir\n");
}
}