forked from extern/nushell
Support Termux (#10013)
This commit is contained in:
parent
487f1a97ea
commit
38f454d5ab
@ -16,5 +16,5 @@ dirs-next = "2.0"
|
|||||||
[target.'cfg(windows)'.dependencies]
|
[target.'cfg(windows)'.dependencies]
|
||||||
omnipath = "0.1"
|
omnipath = "0.1"
|
||||||
|
|
||||||
[target.'cfg(all(unix, not(target_os = "macos")))'.dependencies]
|
[target.'cfg(all(unix, not(target_os = "macos"), not(target_os = "android")))'.dependencies]
|
||||||
pwd = "1.3"
|
pwd = "1.3"
|
||||||
|
@ -1,7 +1,22 @@
|
|||||||
#[cfg(all(unix, not(target_os = "macos")))]
|
#[cfg(all(unix, not(target_os = "macos"), not(target_os = "android")))]
|
||||||
use pwd::Passwd;
|
use pwd::Passwd;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
|
const FALLBACK_USER_HOME_BASE_DIR: &str = "/Users";
|
||||||
|
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
const FALLBACK_USER_HOME_BASE_DIR: &str = "C:\\Users\\";
|
||||||
|
|
||||||
|
#[cfg(all(unix, not(target_os = "macos"), not(target_os = "android")))]
|
||||||
|
const FALLBACK_USER_HOME_BASE_DIR: &str = "/home";
|
||||||
|
|
||||||
|
#[cfg(all(unix, target_os = "android"))]
|
||||||
|
const FALLBACK_USER_HOME_BASE_DIR: &str = "/data";
|
||||||
|
|
||||||
|
#[cfg(target_os = "android")]
|
||||||
|
const TERMUX_HOME: &str = "/data/data/com.termux/files/home";
|
||||||
|
|
||||||
fn expand_tilde_with_home(path: impl AsRef<Path>, home: Option<PathBuf>) -> PathBuf {
|
fn expand_tilde_with_home(path: impl AsRef<Path>, home: Option<PathBuf>) -> PathBuf {
|
||||||
let path = path.as_ref();
|
let path = path.as_ref();
|
||||||
|
|
||||||
@ -45,77 +60,61 @@ fn expand_tilde_with_home(path: impl AsRef<Path>, home: Option<PathBuf>) -> Path
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(unix, not(target_os = "macos")))]
|
fn fallback_home_dir(username: &str) -> PathBuf {
|
||||||
|
PathBuf::from_iter([FALLBACK_USER_HOME_BASE_DIR, username])
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(all(unix, not(target_os = "macos"), not(target_os = "android")))]
|
||||||
fn user_home_dir(username: &str) -> PathBuf {
|
fn user_home_dir(username: &str) -> PathBuf {
|
||||||
let passwd = Passwd::from_name(username);
|
let passwd = Passwd::from_name(username);
|
||||||
match &passwd.ok() {
|
match &passwd.ok() {
|
||||||
Some(Some(dir)) => PathBuf::from(&dir.dir),
|
Some(Some(dir)) => PathBuf::from(&dir.dir),
|
||||||
_ => {
|
_ => fallback_home_dir(username),
|
||||||
let mut file = String::from("/home/");
|
|
||||||
file.push_str(username);
|
|
||||||
PathBuf::from(file)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// PathBuf::from(concat!("/home/", username)),
|
|
||||||
// Returns home dir of user.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(any(target_os = "android", target_os = "windows", target_os = "macos"))]
|
||||||
fn user_home_dir(username: &str) -> PathBuf {
|
fn user_home_dir(username: &str) -> PathBuf {
|
||||||
|
use std::path::Component;
|
||||||
|
|
||||||
match dirs_next::home_dir() {
|
match dirs_next::home_dir() {
|
||||||
None => {
|
None => {
|
||||||
let mut expected_path = String::from("/Users/");
|
// Termux always has the same home directory
|
||||||
expected_path.push_str(username);
|
#[cfg(target_os = "android")]
|
||||||
let path = Path::new(&expected_path);
|
if is_termux() {
|
||||||
let mut home = PathBuf::new();
|
return PathBuf::from(TERMUX_HOME);
|
||||||
home.push(path);
|
}
|
||||||
home
|
|
||||||
|
fallback_home_dir(username)
|
||||||
}
|
}
|
||||||
Some(user) => {
|
Some(user) => {
|
||||||
let mut expected_path = user;
|
let mut expected_path = user;
|
||||||
expected_path.pop();
|
|
||||||
expected_path.push(Path::new(username));
|
if !cfg!(target_os = "android")
|
||||||
|
&& expected_path
|
||||||
|
.components()
|
||||||
|
.last()
|
||||||
|
.map(|last| last != Component::Normal(username.as_ref()))
|
||||||
|
.unwrap_or(false)
|
||||||
|
{
|
||||||
|
expected_path.pop();
|
||||||
|
expected_path.push(Path::new(username));
|
||||||
|
}
|
||||||
|
|
||||||
if expected_path.is_dir() {
|
if expected_path.is_dir() {
|
||||||
expected_path
|
expected_path
|
||||||
} else {
|
} else {
|
||||||
let mut expected_path_as_string = String::from("/Users/");
|
fallback_home_dir(username)
|
||||||
expected_path_as_string.push_str(username);
|
|
||||||
let path = Path::new(&expected_path_as_string);
|
|
||||||
let mut home = PathBuf::new();
|
|
||||||
home.push(path);
|
|
||||||
home
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
/// Returns true if the shell is running inside the Termux terminal emulator
|
||||||
fn user_home_dir(username: &str) -> PathBuf {
|
/// app.
|
||||||
match dirs_next::home_dir() {
|
#[cfg(target_os = "android")]
|
||||||
None => {
|
fn is_termux() -> bool {
|
||||||
let mut expected_path = String::from("C:\\Users\\");
|
std::env::var("TERMUX_VERSION").is_ok()
|
||||||
expected_path.push_str(username);
|
|
||||||
let path = Path::new(&expected_path);
|
|
||||||
let mut home = PathBuf::new();
|
|
||||||
home.push(path);
|
|
||||||
home
|
|
||||||
}
|
|
||||||
Some(user) => {
|
|
||||||
let mut expected_path = user;
|
|
||||||
expected_path.pop();
|
|
||||||
expected_path.push(Path::new(username));
|
|
||||||
if expected_path.is_dir() {
|
|
||||||
expected_path
|
|
||||||
} else {
|
|
||||||
let mut expected_path_as_string = String::from("C:\\Users\\");
|
|
||||||
expected_path_as_string.push_str(username);
|
|
||||||
let path = Path::new(&expected_path_as_string);
|
|
||||||
let mut home = PathBuf::new();
|
|
||||||
home.push(path);
|
|
||||||
home
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expand_tilde_with_another_user_home(path: &Path) -> PathBuf {
|
fn expand_tilde_with_another_user_home(path: &Path) -> PathBuf {
|
||||||
@ -211,4 +210,22 @@ mod tests {
|
|||||||
fn string_with_double_tilde_backslash() {
|
fn string_with_double_tilde_backslash() {
|
||||||
check_expanded("~\\\\test\\test2/test3");
|
check_expanded("~\\\\test\\test2/test3");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// [TODO] Figure out how to reliably test with real users.
|
||||||
|
#[test]
|
||||||
|
fn user_home_dir_fallback() {
|
||||||
|
let user = "nonexistent";
|
||||||
|
let expected_home = PathBuf::from_iter([FALLBACK_USER_HOME_BASE_DIR, user]);
|
||||||
|
|
||||||
|
#[cfg(target_os = "android")]
|
||||||
|
let expected_home = if is_termux() {
|
||||||
|
PathBuf::from(TERMUX_HOME)
|
||||||
|
} else {
|
||||||
|
expected_home
|
||||||
|
};
|
||||||
|
|
||||||
|
let actual_home = super::user_home_dir(user);
|
||||||
|
|
||||||
|
assert_eq!(expected_home, actual_home, "wrong home");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user