Move current_filename out of LibraryData

The ScopedRefCell wrapping from library_data
is used for two things
1. to allow mutating library_data from a &Parser (for this, a RefCell would be enough)
2. to replace "current_filename" for a scope

A following commit wants to pass parser as "&mut Parser", which
voids reason 1.  It will also remove the ScopedRefCell wrapping
from LibraryData because reason 2 alone is not strong enough.  Move
"current_filename" outside of that, next to "current_node" which is
already a ScopedRefCell.  In future we could maybe consolidate them
into one field, like (or even merging with) ScopedData.
This commit is contained in:
Johannes Altmanninger
2026-04-30 18:54:24 +08:00
parent d35aa3860a
commit d0e47cf58a
5 changed files with 12 additions and 15 deletions

View File

@@ -588,10 +588,8 @@ fn throwing_main() -> i32 {
list.iter().map(|s| s.to_owned()).collect(),
);
let _filename_push = parser
.library_data
.scoped_set(Some(Arc::new(filename.to_owned())), |s| {
&mut s.current_filename
});
.current_filename
.scoped_replace(Some(Arc::new(filename.to_owned())));
res = reader_read(parser, f.as_raw_fd(), &IoChain::new());
if res.is_err() {
flog!(

View File

@@ -317,7 +317,7 @@ pub fn function(
}
// Extract the current filename.
let definition_file = parser.libdata().current_filename.clone();
let definition_file = parser.current_filename.borrow().clone();
// Ensure inherit_vars is unique and then populate it.
opts.inherit_vars.sort_unstable();

View File

@@ -72,8 +72,8 @@ pub fn source(parser: &Parser, streams: &mut IoStreams, args: &mut [&wstr]) -> B
let sb = parser.push_block(Block::source_block(func_filename.clone()));
let _filename_push = parser
.library_data
.scoped_set(Some(func_filename.clone()), |s| &mut s.current_filename);
.current_filename
.scoped_replace(Some(func_filename.clone()));
// Construct argv for the sourced file from our remaining args.
// This is slightly subtle. If this is a bare `source` with no args then `argv + optind` already

View File

@@ -901,7 +901,7 @@ fn exec_external_command(
#[cfg(have_posix_spawn)]
// Prefer to use posix_spawn, since it's faster on some systems like OS X.
if can_use_posix_spawn_for_job(j, &dup2s) {
let file = &parser.libdata().current_filename;
let file = parser.current_filename.borrow();
let count = FORK_COUNT.fetch_add(1, Ordering::Relaxed) + 1; // spawn counts as a fork+exec
let pid = PosixSpawner::new(j, pgroup_policy, &dup2s).and_then(|mut spawner| {

View File

@@ -269,9 +269,6 @@ fn default() -> Self {
/// Miscellaneous data used to avoid recursion and others.
#[derive(Default)]
pub struct LibraryData {
/// The current filename we are evaluating, either from builtin source or on the command line.
pub current_filename: Option<FilenameRef>,
/// A fake value to be returned by builtin_commandline. This is used by the completion
/// machinery when wrapping: e.g. if `tig` wraps `git` then git completions need to see git on
/// the command line.
@@ -383,6 +380,9 @@ pub enum CancelBehavior {
pub struct Parser {
pub interactive_initialized: RelaxedAtomicBool,
/// The current filename we are evaluating, either from builtin source or on the command line.
pub current_filename: ScopedRefCell<Option<FilenameRef>>,
/// The currently executing Node.
current_node: ScopedRefCell<Option<NodeRef<ast::JobPipeline>>>,
@@ -445,6 +445,7 @@ pub fn new(variables: EnvStack, cancel_behavior: CancelBehavior) -> Parser {
let result = Self {
interactive_initialized: RelaxedAtomicBool::new(false),
current_node: ScopedRefCell::new(None),
current_filename: ScopedRefCell::new(None),
job_list: RefCell::default(),
wait_handles: RefCell::default(),
block_list: RefCell::default(),
@@ -604,9 +605,7 @@ pub fn eval_file_wstr(
) -> Result<EvalRes, WString> {
let _interactive_push = self.push_scope(|s| s.is_interactive = false);
let sb = self.push_block(Block::source_block(filename.clone()));
let _filename_push = self
.library_data
.scoped_set(Some(filename), |s| &mut s.current_filename);
let _filename_push = self.current_filename.scoped_replace(Some(filename));
let ret = self.eval_wstr(src, io, job_group, BlockType::Top);
@@ -1200,7 +1199,7 @@ pub fn current_filename(&self) -> Option<FilenameRef> {
Some(BlockData::Source { file, .. }) => Some(file.clone()),
_ => None,
})
.or_else(|| self.libdata().current_filename.clone())
.or_else(|| self.current_filename.borrow().clone())
}
/// Return if we are interactive, which means we are executing a command that the user typed in