style: apply cargo fmt and add formatting check to CI (#319)

Runs `cargo fmt --check` in the rust_crate CI action to catch
formatting issues before they land.
This commit is contained in:
Eric Seidel
2026-04-01 19:30:44 -07:00
committed by GitHub
parent 50954da68a
commit 0cb43c6349
10 changed files with 95 additions and 73 deletions
+5
View File
@@ -13,6 +13,11 @@ inputs:
runs:
using: "composite"
steps:
- name: Check Formatting
working-directory: ${{ inputs.working_directory }}
shell: ${{ inputs.shell }}
run: cargo fmt --check
- name: Clippy
working-directory: ${{ inputs.working_directory }}
shell: ${{ inputs.shell }}
+4 -3
View File
@@ -55,9 +55,10 @@ impl Seek for CFile {
};
let result = (self.file_callbacks.seek)(self.handle, offset, whence);
if result < 0 {
Err(std::io::Error::other(
format!("CFile seek failed with error code: {}", result),
))
Err(std::io::Error::other(format!(
"CFile seek failed with error code: {}",
result
)))
} else {
Ok(result as u64)
}
+1 -2
View File
@@ -219,8 +219,7 @@ fn to_update_result(status: anyhow::Result<UpdateStatus>) -> UpdateResult {
let message = status.to_string();
return UpdateResult {
status: status as i32,
message: allocate_c_string(message.as_str())
.unwrap_or(std::ptr::null_mut()),
message: allocate_c_string(message.as_str()).unwrap_or(std::ptr::null_mut()),
};
}
Err(err) => UpdateResult {
+3 -5
View File
@@ -1,5 +1,5 @@
use anyhow::{bail, Context};
use crate::file_errors::{FileOperation, IoResultExt};
use anyhow::{bail, Context};
use serde::{de::DeserializeOwned, Serialize};
use std::{
fs::File,
@@ -24,8 +24,7 @@ where
std::fs::create_dir_all(containing_dir)
.with_file_context(FileOperation::CreateDir, containing_dir)?;
let file = File::create(path)
.with_file_context(FileOperation::CreateFile, path_as_ref)?;
let file = File::create(path).with_file_context(FileOperation::CreateFile, path_as_ref)?;
let writer = BufWriter::new(file);
serde_json::to_writer_pretty(writer, serializable)
.with_context(|| format!("failed to serialize to {:?}", path_as_ref))
@@ -43,8 +42,7 @@ where
bail!("File {} does not exist", path_as_ref.display());
}
let file = File::open(path_as_ref)
.with_file_context(FileOperation::ReadFile, path_as_ref)?;
let file = File::open(path_as_ref).with_file_context(FileOperation::ReadFile, path_as_ref)?;
let reader = BufReader::new(file);
serde_json::from_reader(reader)
.with_context(|| format!("failed to deserialize from {:?}", &path_as_ref))
+5 -3
View File
@@ -1,7 +1,7 @@
use super::{disk_io, signing, PatchInfo};
use crate::file_errors::{FileOperation, IoResultExt};
use crate::yaml::PatchVerificationMode;
use anyhow::{bail, Context, Result};
use crate::file_errors::{FileOperation, IoResultExt};
use core::fmt::Debug;
use serde::{Deserialize, Serialize};
use std::{
@@ -233,7 +233,8 @@ impl PatchManager {
}
let artifact_size_on_disk = std::fs::metadata(&artifact_path)
.with_file_context(FileOperation::GetMetadata, &artifact_path)?.len();
.with_file_context(FileOperation::GetMetadata, &artifact_path)?
.len();
if artifact_size_on_disk != patch.size {
bail!(
"Patch {} has size {} on disk, but expected size {}",
@@ -404,7 +405,8 @@ impl ManagePatches for PatchManager {
let new_patch = PatchMetadata {
number: patch_number,
size: std::fs::metadata(&patch_path)
.with_file_context(FileOperation::GetMetadata, &patch_path)?.len(),
.with_file_context(FileOperation::GetMetadata, &patch_path)?
.len(),
hash: hash.to_owned(),
signature: signature.map(|s| s.to_owned()),
};
+44 -10
View File
@@ -344,12 +344,20 @@ mod tests {
let release_version = state.serialized_state.release_version.clone();
assert!(state.save().is_ok());
let mut state =
UpdaterState::load_or_new_on_error(&state.cache_dir, &release_version, None, PatchVerificationMode::default());
let mut state = UpdaterState::load_or_new_on_error(
&state.cache_dir,
&release_version,
None,
PatchVerificationMode::default(),
);
assert_eq!(state.next_boot_patch().unwrap().number, 1);
let mut next_version_state =
UpdaterState::load_or_new_on_error(&state.cache_dir, "1.0.0+2", None, PatchVerificationMode::default());
let mut next_version_state = UpdaterState::load_or_new_on_error(
&state.cache_dir,
"1.0.0+2",
None,
PatchVerificationMode::default(),
);
assert!(next_version_state.next_boot_patch().is_none());
}
@@ -367,8 +375,18 @@ mod tests {
#[test]
fn creates_updater_state_with_client_id() {
let tmp_dir = TempDir::new().unwrap();
let state = UpdaterState::load_or_new_on_error(tmp_dir.path(), "1.0.0+1", None, PatchVerificationMode::default());
let saved_state = UpdaterState::load_or_new_on_error(tmp_dir.path(), "1.0.0+1", None, PatchVerificationMode::default());
let state = UpdaterState::load_or_new_on_error(
tmp_dir.path(),
"1.0.0+1",
None,
PatchVerificationMode::default(),
);
let saved_state = UpdaterState::load_or_new_on_error(
tmp_dir.path(),
"1.0.0+1",
None,
PatchVerificationMode::default(),
);
assert_eq!(
state.serialized_state.client_id,
saved_state.serialized_state.client_id
@@ -389,7 +407,12 @@ mod tests {
PatchVerificationMode::default(),
);
let new_loaded = UpdaterState::load_or_new_on_error(&state.cache_dir, "1.0.0+2", None, PatchVerificationMode::default());
let new_loaded = UpdaterState::load_or_new_on_error(
&state.cache_dir,
"1.0.0+2",
None,
PatchVerificationMode::default(),
);
assert_eq!(
original_loaded.serialized_state.client_id,
@@ -416,7 +439,8 @@ mod tests {
let new_state_path = new_tmp_dir.path().join(STATE_FILE_NAME);
std::fs::rename(original_state_path, new_state_path).unwrap();
let new_state = UpdaterState::load(new_tmp_dir.path(), None, PatchVerificationMode::default()).unwrap();
let new_state =
UpdaterState::load(new_tmp_dir.path(), None, PatchVerificationMode::default()).unwrap();
assert_eq!(new_state.cache_dir, new_tmp_dir.path());
}
@@ -557,7 +581,12 @@ mod tests {
let tmp_dir = TempDir::new()?;
// Create a new state, add a patch, and save it.
let mut state = UpdaterState::load_or_new_on_error(tmp_dir.path(), "1.0.0+1", None, PatchVerificationMode::default());
let mut state = UpdaterState::load_or_new_on_error(
tmp_dir.path(),
"1.0.0+1",
None,
PatchVerificationMode::default(),
);
let patch = fake_patch(&tmp_dir, 1);
state.install_patch(&patch, "hash", None)?;
state.save()?;
@@ -568,7 +597,12 @@ mod tests {
std::fs::write(&state_file, "corrupt json")?;
// Ensure that, by corrupting the file, we've reset the patches state.
let mut state = UpdaterState::load_or_new_on_error(tmp_dir.path(), "1.0.0+2", None, PatchVerificationMode::default());
let mut state = UpdaterState::load_or_new_on_error(
tmp_dir.path(),
"1.0.0+2",
None,
PatchVerificationMode::default(),
);
assert!(state.next_boot_patch().is_none());
Ok(())
+13 -24
View File
@@ -38,17 +38,8 @@ impl std::fmt::Display for FileOperation {
/// This function takes an IO error and adds context about what operation failed,
/// what path was involved, and provides hints about possible causes based on
/// the error type.
pub fn enhance_io_error(
error: &std::io::Error,
operation: FileOperation,
path: &Path,
) -> String {
let base_message = format!(
"Failed to {} '{}': {}",
operation,
path.display(),
error
);
pub fn enhance_io_error(error: &std::io::Error, operation: FileOperation, path: &Path) -> String {
let base_message = format!("Failed to {} '{}': {}", operation, path.display(), error);
let hint = get_error_hint(error, operation);
@@ -70,9 +61,7 @@ fn get_error_hint(error: &std::io::Error, operation: FileOperation) -> String {
ErrorKind::StorageFull => {
"The device storage is full. Free up space and try again.".to_string()
}
ErrorKind::ReadOnlyFilesystem => {
"The filesystem is mounted as read-only.".to_string()
}
ErrorKind::ReadOnlyFilesystem => "The filesystem is mounted as read-only.".to_string(),
_ => {
// Check raw OS error for cases not covered by ErrorKind
if let Some(os_error) = error.raw_os_error() {
@@ -90,9 +79,7 @@ fn get_permission_denied_hint(operation: FileOperation) -> String {
FileOperation::CreateDir | FileOperation::CreateFile | FileOperation::WriteFile => {
"The app may not have write access to this location.".to_string()
}
FileOperation::ReadFile => {
"The app may not have read access to this file.".to_string()
}
FileOperation::ReadFile => "The app may not have read access to this file.".to_string(),
FileOperation::DeleteFile | FileOperation::DeleteDir => {
"The app may not have permission to delete this item.".to_string()
}
@@ -114,9 +101,7 @@ fn get_not_found_hint(operation: FileOperation) -> String {
FileOperation::RenameFile => {
"The source file or destination directory may not exist.".to_string()
}
_ => {
"The file or directory does not exist.".to_string()
}
_ => "The file or directory does not exist.".to_string(),
}
}
@@ -126,7 +111,9 @@ fn get_os_error_hint(os_error: i32) -> String {
match os_error {
28 => "The device storage is full (ENOSPC). Free up space and try again.".to_string(),
30 => "The filesystem is mounted as read-only (EROFS).".to_string(),
122 => "Disk quota exceeded (EDQUOT). The user's storage quota has been reached.".to_string(),
122 => {
"Disk quota exceeded (EDQUOT). The user's storage quota has been reached.".to_string()
}
_ => String::new(),
}
}
@@ -162,7 +149,10 @@ mod tests {
assert_eq!(format!("{}", FileOperation::DeleteFile), "delete file");
assert_eq!(format!("{}", FileOperation::DeleteDir), "delete directory");
assert_eq!(format!("{}", FileOperation::RenameFile), "rename/move file");
assert_eq!(format!("{}", FileOperation::GetMetadata), "get file metadata");
assert_eq!(
format!("{}", FileOperation::GetMetadata),
"get file metadata"
);
}
// ==================== enhance_io_error Tests ====================
@@ -459,8 +449,7 @@ mod tests {
#[test]
fn test_io_result_ext_preserves_error_chain() {
let result: std::io::Result<i32> =
Err(Error::new(ErrorKind::NotFound, "No such file"));
let result: std::io::Result<i32> = Err(Error::new(ErrorKind::NotFound, "No such file"));
let path = Path::new("/missing/file.txt");
let converted = result.with_file_context(FileOperation::ReadFile, path);
+1 -3
View File
@@ -457,9 +457,7 @@ mod tests {
#[test]
fn handle_network_result_ok() {
let body = ureq::Body::builder()
.mime_type("text/plain")
.data("");
let body = ureq::Body::builder().mime_type("text/plain").data("");
let response = ureq::http::Response::builder()
.status(200)
.body(body)
+2 -2
View File
@@ -36,8 +36,8 @@ pub fn install_fake_patch(patch_number: usize) -> anyhow::Result<()> {
pub fn write_fake_apk(apk_path: &str, libapp_contents: &[u8]) {
use std::io::Write;
let mut zip = zip::ZipWriter::new(std::fs::File::create(apk_path).unwrap());
let options = zip::write::SimpleFileOptions::default()
.compression_method(zip::CompressionMethod::Stored);
let options =
zip::write::SimpleFileOptions::default().compression_method(zip::CompressionMethod::Stored);
let app_path = crate::android::get_relative_lib_path("libapp.so");
zip.start_file(app_path.to_str().unwrap(), options).unwrap();
zip.write_all(libapp_contents).unwrap();
+17 -21
View File
@@ -261,7 +261,9 @@ pub fn check_for_downloadable_update(channel: Option<&str>) -> anyhow::Result<bo
let (request, url, request_fn) = with_config(|config| {
let mut config = config.clone();
if let Some(channel) = channel { config.channel = channel.to_string() }
if let Some(channel) = channel {
config.channel = channel.to_string()
}
Ok((
PatchCheckRequest::new(&config, &client_id),
@@ -657,14 +659,11 @@ const ZSTD_MAGIC: [u8; 4] = [0x28, 0xB5, 0x2F, 0xFD];
/// Validates that a downloaded patch file is a non-empty, valid zstd archive.
fn validate_compressed_patch(patch_path: &Path) -> anyhow::Result<()> {
let metadata = fs::metadata(patch_path)
.with_file_context(FileOperation::GetMetadata, patch_path)?;
let metadata =
fs::metadata(patch_path).with_file_context(FileOperation::GetMetadata, patch_path)?;
let size = metadata.len();
if size == 0 {
bail!(
"Downloaded patch file is empty: {:?}",
patch_path
);
bail!("Downloaded patch file is empty: {:?}", patch_path);
}
// A valid zstd frame is at least 4 bytes (magic number).
if size < 4 {
@@ -674,8 +673,8 @@ fn validate_compressed_patch(patch_path: &Path) -> anyhow::Result<()> {
patch_path
);
}
let mut file = fs::File::open(patch_path)
.with_file_context(FileOperation::ReadFile, patch_path)?;
let mut file =
fs::File::open(patch_path).with_file_context(FileOperation::ReadFile, patch_path)?;
let mut magic = [0u8; 4];
file.read_exact(&mut magic)
.with_file_context(FileOperation::ReadFile, patch_path)?;
@@ -721,9 +720,8 @@ where
// Spawn a thread to run the decompression in parallel to the patching.
// decompress.copy will block on the pipe being full (I think) and then
// when it returns the thread will exit.
let decompress_handle = std::thread::spawn(move || {
decompress.copy(compressed_patch_r, patch_w)
});
let decompress_handle =
std::thread::spawn(move || decompress.copy(compressed_patch_r, patch_w));
// Do the patch, using the uncompressed patch data from the pipe.
let mut fresh_r =
@@ -1422,11 +1420,7 @@ patch_verification: bogus_mode
let err = super::validate_compressed_patch(&patch_path)
.unwrap_err()
.to_string();
assert!(
err.contains("empty"),
"Expected 'empty' in error: {}",
err
);
assert!(err.contains("empty"), "Expected 'empty' in error: {}", err);
}
#[test]
@@ -1511,7 +1505,7 @@ patch_verification: bogus_mode
let mut uncompressed = Vec::new();
uncompressed.extend_from_slice(&0xB1DFu32.to_le_bytes()); // bipatch magic
uncompressed.extend_from_slice(&0x1000u32.to_le_bytes()); // bipatch version
uncompressed.extend_from_slice(&vec![0u8; 1024]); // padding
uncompressed.extend_from_slice(&vec![0u8; 1024]); // padding
// Compress the valid data into one complete zstd frame.
let mut compressed = std::io::Cursor::new(Vec::new());
@@ -1525,7 +1519,7 @@ patch_verification: bogus_mode
// successfully decompress the first frame (delivering the bipatch
// header so Reader::new succeeds), then fail on this corrupt frame.
compressed.extend_from_slice(&[0x28, 0xB5, 0x2F, 0xFD]); // zstd magic
compressed.extend_from_slice(&[0xFF; 64]); // garbage
compressed.extend_from_slice(&[0xFF; 64]); // garbage
let patch_path = tmp_dir.path().join("corrupt_frame.patch");
fs::write(&patch_path, &compressed).unwrap();
@@ -2730,8 +2724,10 @@ mod multi_engine_tests {
use crate::{
network::{testing_set_network_hooks, PatchCheckResponse, UNEXPECTED_DOWNLOAD},
report_launch_start, report_launch_success, test_utils::install_fake_patch,
updater::tests::init_for_testing, with_mut_state, with_state,
report_launch_start, report_launch_success,
test_utils::install_fake_patch,
updater::tests::init_for_testing,
with_mut_state, with_state,
};
/// Sets up no-op network hooks so that the fire-and-forget thread spawned