From 0b48f4a46d24248e4c012ef37d25b5963c27a78c Mon Sep 17 00:00:00 2001 From: nsfisis Date: Sun, 23 Aug 2026 12:43:10 +0900 Subject: fix(fs): carry file_get_contents results as bytes file_get_contents() and file_get_contents_with_max_length() return Vec instead of a from_utf8_lossy'd String. Call sites whose consumer takes a &str still convert lossily and are marked TODO(bytes). file_get_contents_with_max_length() now reads at most the requested number of bytes instead of the whole file. Co-Authored-By: Claude Opus 5 (1M context) --- crates/shirabe/src/command/require_command.rs | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) (limited to 'crates/shirabe/src/command/require_command.rs') diff --git a/crates/shirabe/src/command/require_command.rs b/crates/shirabe/src/command/require_command.rs index 4f90a532..2dfb140d 100644 --- a/crates/shirabe/src/command/require_command.rs +++ b/crates/shirabe/src/command/require_command.rs @@ -51,11 +51,11 @@ pub struct RequireCommand { first_require: std::cell::Cell, json: std::cell::RefCell>>>, file: std::cell::RefCell, - composer_backup: std::cell::RefCell, + composer_backup: std::cell::RefCell>, /// file name lock: std::cell::RefCell, /// contents before modification if the lock file exists - lock_backup: std::cell::RefCell>, + lock_backup: std::cell::RefCell>>, dependency_resolution_completed: std::rc::Rc>, repos: std::cell::RefCell>, repository_sets: @@ -78,7 +78,7 @@ impl RequireCommand { first_require: std::cell::Cell::new(false), json: std::cell::RefCell::new(None), file: std::cell::RefCell::new(String::new()), - composer_backup: std::cell::RefCell::new(String::new()), + composer_backup: std::cell::RefCell::new(Vec::new()), lock: std::cell::RefCell::new(String::new()), lock_backup: std::cell::RefCell::new(None), dependency_resolution_completed: std::rc::Rc::new(std::cell::Cell::new(false)), @@ -655,7 +655,11 @@ impl RequireCommand { remove_key: &str, sort_packages: bool, ) -> bool { - let contents = file_get_contents(json.borrow().get_path()).unwrap_or_default(); + // TODO(bytes): JsonManipulator takes the JSON as a String. + let contents = String::from_utf8_lossy( + &file_get_contents(json.borrow().get_path()).unwrap_or_default(), + ) + .into_owned(); let mut manipulator = match JsonManipulator::new(contents) { Ok(m) => m, @@ -712,12 +716,9 @@ impl RequireCommand { extra ); self.get_io().write_error3(&msg, true, io_interface::NORMAL); - file_put_contents( - json.borrow().get_path(), - self.composer_backup.borrow().as_bytes(), - ); + file_put_contents(json.borrow().get_path(), &self.composer_backup.borrow()); if let Some(ref lock_backup) = *self.lock_backup.borrow() { - file_put_contents(&lock, lock_backup.as_bytes()); + file_put_contents(&lock, lock_backup); } } } @@ -837,7 +838,7 @@ impl Command for RequireCommand { file_get_contents(json.borrow().get_path()).unwrap_or_default(); let lock = self.lock.borrow().clone(); *self.lock_backup.borrow_mut() = if file_exists(&lock) { - file_get_contents(&lock) + file_get_contents(&lock).ok() } else { None }; @@ -859,7 +860,7 @@ impl Command for RequireCommand { let backup_contents = self.composer_backup.borrow().clone(); if !is_writable(&file) && Silencer::call(|| { - shirabe_php_shim::file_put_contents(&file_path, backup_contents.as_bytes()); + shirabe_php_shim::file_put_contents(&file_path, &backup_contents); Ok::(false) }) .ok() -- cgit v1.3.1-4-g156e