forked from extern/nushell
@ -1,4 +1,3 @@
|
||||
use crate::filesystem::path::canonicalize;
|
||||
use crate::filesystem::utils::FileStructure;
|
||||
use crate::maybe_text_codec::{MaybeTextCodec, StringOrBinary};
|
||||
use crate::shell::shell_args::{CdArgs, CopyArgs, LsArgs, MkdirArgs, MvArgs, RemoveArgs};
|
||||
@ -10,6 +9,7 @@ use crate::{
|
||||
};
|
||||
use encoding_rs::Encoding;
|
||||
use nu_data::config::LocalConfigDiff;
|
||||
use nu_path::canonicalize;
|
||||
use nu_protocol::{CommandAction, ConfigPath, TaggedDictBuilder, Value};
|
||||
use nu_source::{Span, Tag};
|
||||
use nu_stream::{ActionStream, Interruptible, IntoActionStream, OutputStream};
|
||||
|
@ -1,4 +1,3 @@
|
||||
pub(crate) mod dir_info;
|
||||
pub mod filesystem_shell;
|
||||
pub mod path;
|
||||
pub(crate) mod utils;
|
||||
|
@ -1,178 +0,0 @@
|
||||
use std::io;
|
||||
use std::path::{Component, Path, PathBuf};
|
||||
|
||||
pub fn resolve_dots<P>(path: P) -> PathBuf
|
||||
where
|
||||
P: AsRef<Path>,
|
||||
{
|
||||
let mut result = PathBuf::new();
|
||||
|
||||
path.as_ref()
|
||||
.components()
|
||||
.for_each(|component| match component {
|
||||
Component::ParentDir => {
|
||||
result.pop();
|
||||
}
|
||||
Component::CurDir => {}
|
||||
_ => result.push(component),
|
||||
});
|
||||
|
||||
dunce::simplified(&result).to_path_buf()
|
||||
}
|
||||
|
||||
pub fn absolutize<P, Q>(relative_to: P, path: Q) -> PathBuf
|
||||
where
|
||||
P: AsRef<Path>,
|
||||
Q: AsRef<Path>,
|
||||
{
|
||||
let path = if path.as_ref() == Path::new(".") {
|
||||
// Joining a Path with '.' appends a '.' at the end, making the prompt
|
||||
// more ugly - so we don't do anything, which should result in an equal
|
||||
// path on all supported systems.
|
||||
relative_to.as_ref().to_owned()
|
||||
} else if path.as_ref().starts_with("~") {
|
||||
let expanded_path = expand_tilde(path.as_ref());
|
||||
match expanded_path {
|
||||
Some(p) => p,
|
||||
_ => path.as_ref().to_owned(),
|
||||
}
|
||||
} else {
|
||||
relative_to.as_ref().join(path)
|
||||
};
|
||||
|
||||
let (relative_to, path) = {
|
||||
let components: Vec<_> = path.components().collect();
|
||||
let separator = components
|
||||
.iter()
|
||||
.enumerate()
|
||||
.find(|(_, c)| c == &&Component::CurDir || c == &&Component::ParentDir);
|
||||
|
||||
if let Some((index, _)) = separator {
|
||||
let (absolute, relative) = components.split_at(index);
|
||||
let absolute: PathBuf = absolute.iter().collect();
|
||||
let relative: PathBuf = relative.iter().collect();
|
||||
|
||||
(absolute, relative)
|
||||
} else {
|
||||
(
|
||||
relative_to.as_ref().to_path_buf(),
|
||||
components.iter().collect::<PathBuf>(),
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
let path = if path.is_relative() {
|
||||
let mut result = relative_to;
|
||||
path.components().for_each(|component| match component {
|
||||
Component::ParentDir => {
|
||||
result.pop();
|
||||
}
|
||||
Component::Normal(normal) => result.push(normal),
|
||||
_ => {}
|
||||
});
|
||||
|
||||
result
|
||||
} else {
|
||||
path
|
||||
};
|
||||
|
||||
dunce::simplified(&path).to_path_buf()
|
||||
}
|
||||
|
||||
// borrowed from here https://stackoverflow.com/questions/54267608/expand-tilde-in-rust-path-idiomatically
|
||||
pub fn expand_tilde<P: AsRef<Path>>(path_user_input: P) -> Option<PathBuf> {
|
||||
let p = path_user_input.as_ref();
|
||||
if !p.starts_with("~") {
|
||||
return Some(p.to_path_buf());
|
||||
}
|
||||
|
||||
if p == Path::new("~") {
|
||||
return dirs_next::home_dir();
|
||||
}
|
||||
|
||||
dirs_next::home_dir().map(|mut h| {
|
||||
if h == Path::new("/") {
|
||||
// Corner case: `h` root directory;
|
||||
// don't prepend extra `/`, just drop the tilde.
|
||||
p.strip_prefix("~")
|
||||
.expect("cannot strip ~ prefix")
|
||||
.to_path_buf()
|
||||
} else {
|
||||
h.push(p.strip_prefix("~/").expect("cannot strip ~/ prefix"));
|
||||
h
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn canonicalize<P, Q>(relative_to: P, path: Q) -> io::Result<PathBuf>
|
||||
where
|
||||
P: AsRef<Path>,
|
||||
Q: AsRef<Path>,
|
||||
{
|
||||
let absolutized = absolutize(&relative_to, path);
|
||||
let path = match std::fs::read_link(&absolutized) {
|
||||
Ok(resolved) => {
|
||||
let parent = absolutized.parent().unwrap_or(&absolutized);
|
||||
absolutize(parent, resolved)
|
||||
}
|
||||
|
||||
Err(e) => {
|
||||
if absolutized.exists() {
|
||||
absolutized
|
||||
} else {
|
||||
return Err(e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Ok(dunce::simplified(&path).to_path_buf())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::io;
|
||||
|
||||
#[test]
|
||||
fn absolutize_two_dots() {
|
||||
let relative_to = Path::new("/foo/bar");
|
||||
let path = Path::new("..");
|
||||
|
||||
assert_eq!(
|
||||
PathBuf::from("/foo"), // missing path
|
||||
absolutize(relative_to, path)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn absolutize_with_curdir() {
|
||||
let relative_to = Path::new("/foo");
|
||||
let path = Path::new("./bar/./baz");
|
||||
|
||||
assert!(!absolutize(relative_to, path)
|
||||
.to_str()
|
||||
.unwrap()
|
||||
.contains('.'));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn canonicalize_should_succeed() -> io::Result<()> {
|
||||
let relative_to = Path::new("/foo/bar");
|
||||
let path = Path::new("../..");
|
||||
|
||||
assert_eq!(
|
||||
PathBuf::from("/"), // existing path
|
||||
canonicalize(relative_to, path)?,
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn canonicalize_should_fail() {
|
||||
let relative_to = Path::new("/foo/bar/baz"); // '/foo' is missing
|
||||
let path = Path::new("../..");
|
||||
|
||||
assert!(canonicalize(relative_to, path).is_err());
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
use crate::filesystem::path::canonicalize;
|
||||
use nu_errors::ShellError;
|
||||
use nu_path::canonicalize;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
#[derive(Default)]
|
||||
|
@ -29,7 +29,6 @@ pub use crate::evaluation_context::EvaluationContext;
|
||||
pub use crate::example::Example;
|
||||
pub use crate::filesystem::dir_info::{DirBuilder, DirInfo, FileInfo};
|
||||
pub use crate::filesystem::filesystem_shell::FilesystemShell;
|
||||
pub use crate::filesystem::path;
|
||||
pub use crate::from_value::FromValue;
|
||||
pub use crate::maybe_text_codec::{BufCodecReader, MaybeTextCodec, StringOrBinary};
|
||||
pub use crate::print::maybe_print_errors;
|
||||
|
@ -1,9 +1,7 @@
|
||||
use crate::{
|
||||
evaluate::internal::InternalIterator, maybe_print_errors, path::canonicalize, run_block,
|
||||
shell::CdArgs,
|
||||
};
|
||||
use crate::{evaluate::internal::InternalIterator, maybe_print_errors, run_block, shell::CdArgs};
|
||||
use crate::{BufCodecReader, MaybeTextCodec, StringOrBinary};
|
||||
use nu_errors::ShellError;
|
||||
use nu_path::canonicalize;
|
||||
use nu_protocol::hir::{
|
||||
Call, ClassifiedCommand, Expression, ExternalRedirection, InternalCommand, Literal,
|
||||
NamedArguments, SpannedExpression,
|
||||
|
Reference in New Issue
Block a user