Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions src/install/PackageInstaller.rs
Original file line number Diff line number Diff line change
Expand Up @@ -358,8 +358,7 @@ fn abs_node_modules_path(
&mut rel_buf,
&mut depth_buf,
);
let top = strings::without_trailing_slash(FileSystem::instance().top_level_dir());
let mut abs = AbsPath::from(top).unwrap_or_oom();
let mut abs = AbsPath::init_top_level_dir();
abs.append(rel.as_bytes()).unwrap_or_oom();
abs
}
Expand Down
77 changes: 32 additions & 45 deletions src/install/PackageManager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use bun_event_loop::{self, AnyEventLoop, EventLoopHandle};
use bun_http as http;
use bun_ini as ini;
use bun_paths::resolve_path::{self, PosixToWinNormalizer, platform};
use bun_paths::string_paths::without_trailing_slash_windows_path;
use bun_paths::{DELIMITER, PathBuffer, SEP, SEP_STR};
use bun_semver as Semver;
use bun_sys::{self, Fd};
Expand Down Expand Up @@ -1092,7 +1093,7 @@ fn configure_env_for_scripts_run(
let init_cwd_entry = this.env_mut().map.get_or_put_without_value(b"INIT_CWD")?;
if !init_cwd_entry.found_existing {
*init_cwd_entry.value_ptr = dot_env::HashTableValue {
value: Box::<[u8]>::from(strings::without_trailing_slash(
value: Box::<[u8]>::from(without_trailing_slash_windows_path(
FileSystem::instance().top_level_dir(),
)),
};
Expand Down Expand Up @@ -1472,6 +1473,14 @@ fn overlay_bunfig_install(install: &mut Api::BunInstall, bunfig: Api::BunInstall
);
}

/// Appends `package.json\0` to a directory. A filesystem root already ends in the separator.
fn push_package_json(path: &mut Vec<u8>) {
if !path.last().is_some_and(|&c| bun_paths::is_sep_native(c)) {
path.push(SEP);
}
path.extend_from_slice(b"package.json\0");
}

/// Returns `&'static mut PackageManager` — the process-singleton (held in
/// `holder::RAW_PTR`) is leaked for the process lifetime and `init()` is called
/// exactly once on the single CLI dispatch thread. Every
Expand Down Expand Up @@ -1506,7 +1515,8 @@ pub fn init(
// and seeds `top_level_dir` from `getcwd`.
bun_resolver::fs::FileSystem::init(None)?;
let fs = FileSystem::instance();
let top_level_dir_no_trailing_slash = strings::without_trailing_slash(fs.top_level_dir());
// `C:\` keeps its separator: `C:` is the current directory of drive C, not its root.
let top_level_dir_no_trailing_slash = without_trailing_slash_windows_path(fs.top_level_dir());
// SAFETY: CWD_BUF is a process-global path buffer only touched on the main thread.
// repr(transparent) makes the `*mut PathBuffer → *mut u8` cast sound.
unsafe {
Expand All @@ -1533,19 +1543,12 @@ pub fn init(
let _ = cwd_ptr;
}

// Per-cfg const literal, no runtime alloc.
#[cfg(windows)]
const SEP_PACKAGE_JSON: &[u8] = b"\\package.json";
#[cfg(not(windows))]
const SEP_PACKAGE_JSON: &[u8] = b"/package.json";

let mut original_package_json_path_buf: Vec<u8> =
Vec::with_capacity(top_level_dir_no_trailing_slash.len() + SEP_PACKAGE_JSON.len() + 1);
Vec::with_capacity(top_level_dir_no_trailing_slash.len() + "/package.json".len() + 1);
original_package_json_path_buf.extend_from_slice(top_level_dir_no_trailing_slash);
original_package_json_path_buf.extend_from_slice(SEP_PACKAGE_JSON);
original_package_json_path_buf.push(0);
push_package_json(&mut original_package_json_path_buf);
Comment thread
robobun marked this conversation as resolved.

let path_len = top_level_dir_no_trailing_slash.len() + SEP_PACKAGE_JSON.len();
let path_len = original_package_json_path_buf.len() - 1;
// SAFETY: NUL written at `path_len` above. Not `from_buf`: this borrow is
// intentionally detached — `original_package_json_path_buf` is mutated and
// re-sliced below (the directory-walk rewrites the tail in place), and
Expand All @@ -1554,7 +1557,7 @@ pub fn init(
let mut original_package_json_path =
unsafe { ZStr::from_raw(original_package_json_path_buf.as_ptr(), path_len) };
let original_cwd =
strings::without_suffix_comptime(original_package_json_path.as_bytes(), SEP_PACKAGE_JSON);
&original_package_json_path.as_bytes()[..top_level_dir_no_trailing_slash.len()];
let original_cwd_clone = Box::<[u8]>::from(original_cwd);

let mut workspace_names = Package::WorkspaceMap::WorkspaceMap::init();
Expand Down Expand Up @@ -1584,14 +1587,10 @@ pub fn init(

loop {
let mut package_json_path_buf = bun_paths::path_buffer_pool::get();
package_json_path_buf[..this_cwd.len()].copy_from_slice(this_cwd);
package_json_path_buf[this_cwd.len()..this_cwd.len() + b"/package.json".len()]
.copy_from_slice(b"/package.json");
package_json_path_buf[this_cwd.len() + b"/package.json".len()] = 0;
// SAFETY: NUL written above
let package_json_path = ZStr::from_buf(
&package_json_path_buf[..],
this_cwd.len() + b"/package.json".len(),
let package_json_path = resolve_path::join_abs_string_buf_z::<platform::Auto>(
this_cwd,
&mut package_json_path_buf[..],
&[b"package.json"],
);

match bun_sys::File::openat(
Expand All @@ -1607,7 +1606,7 @@ pub fn init(
Ok(f) => break 'child f,
Err(e) if e.get_errno() == bun_sys::E::ENOENT => {
if let Some(parent) = bun_core::dirname(this_cwd) {
this_cwd = strings::without_trailing_slash(parent);
this_cwd = without_trailing_slash_windows_path(parent);
continue;
} else {
break;
Expand Down Expand Up @@ -1666,11 +1665,9 @@ pub fn init(
true,
));
original_package_json_path_buf.truncate(this_cwd.len());
original_package_json_path_buf.push(SEP);
original_package_json_path_buf.extend_from_slice(b"package.json");
original_package_json_path_buf.push(0);
push_package_json(&mut original_package_json_path_buf);

let new_path_len = this_cwd.len() + "/package.json".len();
let new_path_len = original_package_json_path_buf.len() - 1;
// SAFETY: NUL written above
original_package_json_path =
ZStr::from_buf(&original_package_json_path_buf[..], new_path_len);
Expand All @@ -1680,20 +1677,17 @@ pub fn init(
if subcommand.should_chdir_to_root() {
if !created_package_json && !no_project {
while let Some(parent) = bun_core::dirname(this_cwd) {
let parent_without_trailing_slash = strings::without_trailing_slash(parent);
let mut parent_path_buf = bun_paths::path_buffer_pool::get();
parent_path_buf[..parent_without_trailing_slash.len()]
.copy_from_slice(parent_without_trailing_slash);
parent_path_buf[parent_without_trailing_slash.len()
..parent_without_trailing_slash.len() + b"/package.json".len()]
.copy_from_slice(b"/package.json");
parent_path_buf[parent_without_trailing_slash.len() + b"/package.json".len()] =
0;
let parent_package_json_path =
resolve_path::join_abs_string_buf_z::<platform::Auto>(
parent,
&mut parent_path_buf[..],
&[b"package.json"],
);

let json_file = match bun_sys::File::openat(
bun_sys::Fd::cwd(),
&parent_path_buf
[..parent_without_trailing_slash.len() + b"/package.json".len()],
parent_package_json_path.as_bytes(),
bun_sys::O::RDWR | bun_sys::O::CLOEXEC,
0,
) {
Expand Down Expand Up @@ -2456,16 +2450,9 @@ fn init_with_runtime_once(

// var progress = Progress{};
// var node = progress.start(name: []const u8, estimated_total_items: usize)
let top_level_dir_no_trailing_slash =
strings::without_trailing_slash(FileSystem::instance().top_level_dir());
let mut original_package_json_path =
vec![0u8; top_level_dir_no_trailing_slash.len() + "/package.json".len() + 1];
original_package_json_path[..top_level_dir_no_trailing_slash.len()]
.copy_from_slice(top_level_dir_no_trailing_slash);
original_package_json_path[top_level_dir_no_trailing_slash.len()
..top_level_dir_no_trailing_slash.len() + b"/package.json".len()]
.copy_from_slice(b"/package.json");
// last byte already 0 (sentinel)
without_trailing_slash_windows_path(FileSystem::instance().top_level_dir()).to_vec();
push_package_json(&mut original_package_json_path);

// SAFETY: manager_ptr points to uninitialized memory; fully initialize
// field-by-field via `addr_of_mut!((*p).field).write(..)`. See the PERF
Expand Down
2 changes: 1 addition & 1 deletion src/install/PackageManager/add_catalog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,7 @@ fn collect_root_entries(root: &Expr, group: &[u8], out: &mut Vec<RootEntry>) {
}

fn member_targets(ws: &WorkspaceMembers) -> Vec<WorkspaceTarget> {
let top_level = strings::without_trailing_slash(FileSystem::instance().top_level_dir());
let top_level = FileSystem::instance().top_level_dir();
let mut buf = path_buffer_pool::get();
ws.members
.keys()
Expand Down
4 changes: 2 additions & 2 deletions src/install/PackageManager/add_remove_with_filter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ pub(crate) struct WorkspaceTarget {
}

pub(crate) fn root_package_json_path() -> Box<[u8]> {
let top_level = strings::without_trailing_slash(FileSystem::instance().top_level_dir());
let top_level = FileSystem::instance().top_level_dir();
let mut buf = path_buffer_pool::get();
let path: Box<[u8]> =
join_abs_string_buf::<platform::Auto>(top_level, &mut buf.0, &[b"package.json"]).into();
Expand Down Expand Up @@ -152,7 +152,7 @@ pub(crate) fn select_targets(
manager: &mut PackageManager,
original_cwd: &[u8],
) -> Result<Vec<WorkspaceTarget>, Error> {
let top_level = strings::without_trailing_slash(FileSystem::instance().top_level_dir());
let top_level = FileSystem::instance().top_level_dir();
let WorkspaceMembers {
root_path,
root_name,
Expand Down
4 changes: 2 additions & 2 deletions src/install/PackageManager/package_json_write_back.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use bun_collections::DynamicBitSet;
use bun_collections::bit_set::Range as BitRange;
use bun_core::{Global, strings};
use bun_core::Global;
use bun_paths::path_buffer_pool;
use bun_paths::resolve_path::{join_abs_string_buf, platform};
use bun_sys::{Fd, File};
Expand Down Expand Up @@ -114,7 +114,7 @@ fn edit_update_targets(
edited: &mut Vec<EditedPackageJson>,
exact: bool,
) -> crate::Result<()> {
let top_level = strings::without_trailing_slash(FileSystem::instance().top_level_dir());
let top_level = FileSystem::instance().top_level_dir();
let mut selected: Vec<WorkspaceTarget> = Vec::new();
{
let lockfile: &Lockfile = &manager.lockfile;
Expand Down
17 changes: 4 additions & 13 deletions src/install/PackageManager/updatePackageJSONAndInstall.rs
Original file line number Diff line number Diff line change
Expand Up @@ -513,20 +513,11 @@ fn update_package_json_and_install_with_manager_with_updates(
);
}

// may or may not be the package json we are editing
let top_level_dir_without_trailing_slash =
strings::without_trailing_slash(FileSystem::instance().top_level_dir());

let mut root_package_json_path_buf = bun_paths::path_buffer_pool::get();
// One spelling with `original_package_json_path`: the package.json cache is keyed by path.
let mut root_package_json_path_buf: Vec<u8> = FileSystem::instance().top_level_dir().to_vec();
super::push_package_json(&mut root_package_json_path_buf);
let root_package_json_path: &ZStr = 'root_package_json_path: {
root_package_json_path_buf[..top_level_dir_without_trailing_slash.len()]
.copy_from_slice(top_level_dir_without_trailing_slash);
root_package_json_path_buf[top_level_dir_without_trailing_slash.len()..]
[..b"/package.json".len()]
.copy_from_slice(b"/package.json");
let root_package_json_path_len =
top_level_dir_without_trailing_slash.len() + b"/package.json".len();
root_package_json_path_buf[root_package_json_path_len] = 0;
let root_package_json_path_len = root_package_json_path_buf.len() - 1;
let root_package_json_path = &root_package_json_path_buf[..root_package_json_path_len];

// The lifetime of this pointer is only valid until the next call to `getWithPath`, which can happen after this scope.
Expand Down
2 changes: 1 addition & 1 deletion src/install/audit_fix/package_json_edits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ fn target_for(manager: &PackageManager, owner: PackageID) -> Option<WorkspaceTar
}),
ResolutionTag::Workspace => {
let buf = lockfile.buffers.string_bytes.as_slice();
let top_level = strings::without_trailing_slash(FileSystem::instance().top_level_dir());
let top_level = FileSystem::instance().top_level_dir();
let mut path_buf = path_buffer_pool::get();
Some(WorkspaceTarget {
name: Box::from(lockfile.packages.items_name()[owner as usize].slice(buf)),
Expand Down
4 changes: 3 additions & 1 deletion src/runtime/cli/link_command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,9 @@ fn link(ctx: command::Context) -> crate::Result<()> {
use bun_core::ZStr;
use bun_paths::{platform, resolve_path};
// create the junction
let top_level = FileSystem::instance().top_level_dir_without_trailing_slash();
let top_level = bun_paths::string_paths::without_trailing_slash_windows_path(
FileSystem::instance().top_level_dir(),
);
Comment thread
robobun marked this conversation as resolved.
let mut link_path_buf = bun_paths::path_buffer_pool::get();
link_path_buf.0[..top_level.len()].copy_from_slice(top_level);
link_path_buf.0[top_level.len()] = 0;
Expand Down
2 changes: 1 addition & 1 deletion src/runtime/cli/pack_command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2133,7 +2133,7 @@ pub(crate) fn pack<const FOR_PUBLISH: bool>(
Global::crash();
}

let abs_workspace_path: &[u8] = strings::without_trailing_slash(
let abs_workspace_path: &[u8] = path::string_paths::without_trailing_slash_windows_path(
strings::without_suffix_comptime(abs_package_json_path.as_bytes(), b"package.json"),
);
// SAFETY: `configure_env_for_run` fully initialized `this_transpiler`.
Expand Down
10 changes: 6 additions & 4 deletions src/runtime/cli/publish_command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -672,10 +672,12 @@ impl PublishCommand {
.contains(install::PackageManagerDoStub::RUN_SCRIPTS)
{
let abs_workspace_path: Box<[u8]> =
strings::without_trailing_slash(strings::without_suffix_comptime(
PackageManager::get().original_package_json_path.as_bytes(),
b"package.json",
))
path::string_paths::without_trailing_slash_windows_path(
strings::without_suffix_comptime(
PackageManager::get().original_package_json_path.as_bytes(),
b"package.json",
),
)
.into();
let script_env = context
.script_env
Expand Down
7 changes: 4 additions & 3 deletions src/runtime/cli/run_command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2434,11 +2434,12 @@ impl RunCommand {
temp_script_buffer.extend_from_slice(b"\x00pre");
temp_script_buffer.extend_from_slice(target_name);

let package_json_dir =
strings::without_trailing_slash(strings::without_suffix_comptime(
let package_json_dir = strings::paths::without_trailing_slash_windows_path(
strings::without_suffix_comptime(
package_json.source.path.text,
b"package.json",
));
),
);
bun_core::scoped_log!(
RUN_LOG,
"Running in dir `{}`",
Expand Down
Loading
Loading