mirror of
https://github.com/fish-shell/fish-shell.git
synced 2026-06-02 22:21:15 -03:00
Revert "parser: remove unused cwd_fd field"
cwd_fd is crucial to maintain: long-term vision for fish is multiple
threads each with their own CWD with the process-wide CWD used for
nothing at all except transiently (e.g. during fork).
Note this fd is heightenized per open_dir.
This reverts commit 6701b7f6c8.
This commit is contained in:
@@ -12,6 +12,7 @@
|
||||
use errno::Errno;
|
||||
use libc::{EACCES, ELOOP, ENOENT, ENOTDIR, EPERM};
|
||||
use nix::unistd::fchdir;
|
||||
use std::sync::Arc;
|
||||
|
||||
// The cd builtin. Changes the current directory to the one specified or to $HOME if none is
|
||||
// specified. The directory can be relative to any directory in the CDPATH variable.
|
||||
@@ -82,35 +83,42 @@ pub fn cd(parser: &mut Parser, streams: &mut IoStreams, args: &mut [&wstr]) -> B
|
||||
let res = wopen_dir(&norm_dir, BEST_O_SEARCH).map_err(|err| err as i32);
|
||||
|
||||
let res = res.and_then(|fd| {
|
||||
fchdir(&fd).map_err(|_|
|
||||
fchdir(&fd)
|
||||
.map_err(|_|
|
||||
// nix::Result::Err contains nix::errno::Errno, which does not offer an API for
|
||||
// converting to a raw int.
|
||||
errno::errno().0)
|
||||
.map(|()| fd)
|
||||
});
|
||||
|
||||
if let Err(err) = res {
|
||||
// Some errors we skip and only report if nothing worked.
|
||||
// ENOENT in particular is very low priority
|
||||
// - if in another directory there was a *file* by the correct name
|
||||
// we prefer *that* error because it's more specific
|
||||
if err == ENOENT {
|
||||
let tmp = wreadlink(&norm_dir);
|
||||
// clippy doesn't like this is_some/unwrap pair, but using if let is harder to read IMO
|
||||
// TODO: if-let-chains
|
||||
if let Some(tmp) = tmp.filter(|_| broken_symlink.is_empty()) {
|
||||
broken_symlink = norm_dir;
|
||||
broken_symlink_target = tmp;
|
||||
} else if best_errno == 0 {
|
||||
best_errno = errno::errno().0;
|
||||
let fd = match res {
|
||||
Ok(fd) => fd,
|
||||
Err(err) => {
|
||||
// Some errors we skip and only report if nothing worked.
|
||||
// ENOENT in particular is very low priority
|
||||
// - if in another directory there was a *file* by the correct name
|
||||
// we prefer *that* error because it's more specific
|
||||
if err == ENOENT {
|
||||
let tmp = wreadlink(&norm_dir);
|
||||
if let Some(tmp) = tmp.filter(|_| broken_symlink.is_empty()) {
|
||||
broken_symlink = norm_dir;
|
||||
broken_symlink_target = tmp;
|
||||
} else if best_errno == 0 {
|
||||
best_errno = errno::errno().0;
|
||||
}
|
||||
continue;
|
||||
} else if err == ENOTDIR {
|
||||
best_errno = err;
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
} else if err == ENOTDIR {
|
||||
best_errno = err;
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
best_errno = err;
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
// Stash the fd for the cwd in the parser so it stays open.
|
||||
// Eventually fish will support distinct CWDs for different parsers in different threads.
|
||||
parser.libdata_mut().cwd_fd = Some(Arc::new(fd));
|
||||
|
||||
parser.set_var_and_fire(
|
||||
L!("PWD"),
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
},
|
||||
event::{self, Event},
|
||||
expand::{ExpandFlags, ExpandResultCode, expand_string, replace_home_directory_with_tilde},
|
||||
fds::{BEST_O_SEARCH, open_dir},
|
||||
flog, flogf, function,
|
||||
io::IoChain,
|
||||
job_group::MaybeJobId,
|
||||
@@ -25,6 +26,7 @@
|
||||
proc::{InternalJobId, JobGroupRef, JobList, JobRef, Pid, ProcStatus, job_reap},
|
||||
signal::{RawSignal, signal_check_cancel, signal_clear_cancel},
|
||||
wait_handle::WaitHandleStore,
|
||||
wutil::perror_nix,
|
||||
};
|
||||
use assert_matches::assert_matches;
|
||||
use fish_common::{
|
||||
@@ -38,6 +40,7 @@
|
||||
use std::io::Write as _;
|
||||
use std::num::NonZeroU32;
|
||||
use std::ops::DerefMut;
|
||||
use std::os::fd::OwnedFd;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
@@ -271,6 +274,10 @@ pub struct LibraryData {
|
||||
/// the command line.
|
||||
pub transient_commandline: ScopedRefCell<Option<WString>>,
|
||||
|
||||
/// A file descriptor holding the current working directory, for use in openat().
|
||||
/// This is never null and never invalid.
|
||||
pub cwd_fd: Option<Arc<OwnedFd>>,
|
||||
|
||||
/// Variables supporting the "status" builtin.
|
||||
pub status_vars: StatusVars,
|
||||
|
||||
@@ -443,7 +450,7 @@ pub fn user(mode: EnvMode) -> Self {
|
||||
impl Parser {
|
||||
/// Create a parser.
|
||||
pub fn new(variables: EnvStack, cancel_behavior: CancelBehavior) -> Parser {
|
||||
let result = Self {
|
||||
let mut result = Self {
|
||||
interactive_initialized: false,
|
||||
current_node: ScopedRefCell::new(None),
|
||||
current_filename: ScopedRefCell::new(None),
|
||||
@@ -462,6 +469,15 @@ pub fn new(variables: EnvStack, cancel_behavior: CancelBehavior) -> Parser {
|
||||
test_only_suppress_stderr: false,
|
||||
};
|
||||
|
||||
match open_dir(c".", BEST_O_SEARCH) {
|
||||
Ok(fd) => {
|
||||
result.libdata_mut().cwd_fd = Some(Arc::new(fd));
|
||||
}
|
||||
Err(err) => {
|
||||
perror_nix("Unable to open the current working directory", err);
|
||||
}
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user