|
1 | 1 | //! foundry.lock handler type. |
2 | 2 |
|
3 | | -use std::{ |
4 | | - collections::hash_map::Entry, |
5 | | - path::{Path, PathBuf}, |
6 | | -}; |
7 | | - |
8 | 3 | use alloy_primitives::map::HashMap; |
9 | 4 | use eyre::{OptionExt, Result}; |
10 | 5 | use foundry_cli::utils::Git; |
11 | 6 | use serde::{Deserialize, Serialize}; |
| 7 | +use std::{ |
| 8 | + collections::{BTreeMap, hash_map::Entry}, |
| 9 | + path::{Path, PathBuf}, |
| 10 | +}; |
12 | 11 |
|
13 | 12 | pub const FOUNDRY_LOCK: &str = "foundry.lock"; |
14 | 13 |
|
@@ -137,7 +136,8 @@ impl<'a> Lockfile<'a> { |
137 | 136 |
|
138 | 137 | /// Writes the lockfile to the project root. |
139 | 138 | pub fn write(&self) -> Result<()> { |
140 | | - foundry_common::fs::write_pretty_json_file(&self.lockfile_path, &self.deps)?; |
| 139 | + let ordered_deps: BTreeMap<_, _> = self.deps.clone().into_iter().collect(); |
| 140 | + foundry_common::fs::write_pretty_json_file(&self.lockfile_path, &ordered_deps)?; |
141 | 141 | trace!(at= ?self.lockfile_path, "wrote lockfile"); |
142 | 142 |
|
143 | 143 | Ok(()) |
@@ -340,6 +340,8 @@ impl std::fmt::Display for DepIdentifier { |
340 | 340 | #[cfg(test)] |
341 | 341 | mod tests { |
342 | 342 | use super::*; |
| 343 | + use std::fs; |
| 344 | + use tempfile::tempdir; |
343 | 345 |
|
344 | 346 | #[test] |
345 | 347 | fn serde_dep_identifier() { |
@@ -382,4 +384,60 @@ mod tests { |
382 | 384 | assert_eq!(tag, tag_de); |
383 | 385 | assert_eq!(rev, rev_de); |
384 | 386 | } |
| 387 | + |
| 388 | + #[test] |
| 389 | + fn test_write_ordered_deps() { |
| 390 | + let dir = tempdir().unwrap(); |
| 391 | + let mut lockfile = Lockfile::new(dir.path()); |
| 392 | + lockfile.insert( |
| 393 | + PathBuf::from("z_dep"), |
| 394 | + DepIdentifier::Rev { rev: "3".to_string(), r#override: false }, |
| 395 | + ); |
| 396 | + lockfile.insert( |
| 397 | + PathBuf::from("a_dep"), |
| 398 | + DepIdentifier::Rev { rev: "1".to_string(), r#override: false }, |
| 399 | + ); |
| 400 | + lockfile.insert( |
| 401 | + PathBuf::from("c_dep"), |
| 402 | + DepIdentifier::Rev { rev: "2".to_string(), r#override: false }, |
| 403 | + ); |
| 404 | + let _ = lockfile.write(); |
| 405 | + let contents = fs::read_to_string(lockfile.lockfile_path).unwrap(); |
| 406 | + let expected = r#"{ |
| 407 | + "a_dep": { |
| 408 | + "rev": "1" |
| 409 | + }, |
| 410 | + "c_dep": { |
| 411 | + "rev": "2" |
| 412 | + }, |
| 413 | + "z_dep": { |
| 414 | + "rev": "3" |
| 415 | + } |
| 416 | +}"#; |
| 417 | + assert_eq!(contents.trim(), expected.trim()); |
| 418 | + |
| 419 | + let mut lockfile = Lockfile::new(dir.path()); |
| 420 | + lockfile.read().unwrap(); |
| 421 | + lockfile.insert( |
| 422 | + PathBuf::from("x_dep"), |
| 423 | + DepIdentifier::Rev { rev: "4".to_string(), r#override: false }, |
| 424 | + ); |
| 425 | + let _ = lockfile.write(); |
| 426 | + let contents = fs::read_to_string(lockfile.lockfile_path).unwrap(); |
| 427 | + let expected = r#"{ |
| 428 | + "a_dep": { |
| 429 | + "rev": "1" |
| 430 | + }, |
| 431 | + "c_dep": { |
| 432 | + "rev": "2" |
| 433 | + }, |
| 434 | + "x_dep": { |
| 435 | + "rev": "4" |
| 436 | + }, |
| 437 | + "z_dep": { |
| 438 | + "rev": "3" |
| 439 | + } |
| 440 | +}"#; |
| 441 | + assert_eq!(contents.trim(), expected.trim()); |
| 442 | + } |
385 | 443 | } |
0 commit comments