workspacer_bump/
bump_crate.rs1crate::ix!();
3
4#[async_trait]
5impl<T> Bump for T
6where
7 T: ValidateIntegrity<Error = CrateError>
8 + HasCargoToml
9 + HasCargoTomlPathBuf<Error = CrateError>
10 + AsRef<Path>
11 + Send
12 + Sync,
13{
14 type Error = CrateError;
15
16 async fn bump(&mut self, release: ReleaseType) -> Result<(), Self::Error> {
17 trace!("Entered Bump::bump with release={:?}", release);
18
19 let old_version_str = {
21 let cargo_toml_arc = self.cargo_toml();
22 let guard = cargo_toml_arc.lock().await;
23
24 let ver = match guard.version() {
26 Err(CargoTomlError::FileNotFound { missing_file }) => {
27 error!("bump(): mapping 'FileNotFound' to CrateError::IoError");
28 return Err(CrateError::IoError {
29 io_error: Arc::new(std::io::Error::new(
30 std::io::ErrorKind::NotFound,
31 format!("Cargo.toml not found at {}", missing_file.display())
32 )),
33 context: format!("Cannot read Cargo.toml at {:?}", missing_file),
34 });
35 }
36 Err(e) => {
37 error!("bump(): got CargoTomlError => returning CrateError::CargoTomlError({:?})", e);
38 return Err(CrateError::CargoTomlError(e));
39 }
40 Ok(ver_ok) => ver_ok,
41 };
42 let ver_str = ver.to_string();
43 debug!("Current version (before bump) is '{}', about to do integrity check", ver_str);
44 ver_str
45 };
46
47 trace!("Validating crate integrity before proceeding with bump");
49 self.validate_integrity().await?;
50
51 let cargo_toml_path;
53 let new_version_str;
54 {
55 let cargo_toml_arc = self.cargo_toml();
56 let mut guard = cargo_toml_arc.lock().await;
57
58 let mut old_ver = match guard.version() {
60 Err(CargoTomlError::FileNotFound { missing_file }) => {
61 error!("bump(): second read => mapping 'FileNotFound' to IoError");
62 return Err(CrateError::IoError {
63 io_error: Arc::new(std::io::Error::new(
64 std::io::ErrorKind::NotFound,
65 format!("Cargo.toml not found at {}", missing_file.display())
66 )),
67 context: format!("Cannot re-read Cargo.toml at {:?}", missing_file),
68 });
69 }
70 Err(e) => {
71 error!("bump(): second read => CargoTomlError => returning CrateError::CargoTomlError({:?})", e);
72 return Err(CrateError::CargoTomlError(e));
73 }
74 Ok(ver_ok) => ver_ok,
75 };
76 let old_clone = old_ver.clone();
77
78 release.apply_to(&mut old_ver);
80
81 old_ver.build = old_clone.build.clone();
83
84 let bumped = old_ver.to_string();
86 {
87 let pkg = guard.get_package_section_mut()?;
88 if let Some(tbl) = pkg.as_table_mut() {
90 tbl.insert("version".to_owned(), toml::Value::String(bumped.clone()));
91 debug!("Set `package.version` to '{}'", bumped);
92 } else {
93 error!("`package` section was not a TOML table; cannot set version!");
94 return Err(CrateError::CouldNotSetPackageVersionBecausePackageIsNotATable);
95 }
96 }
97
98 cargo_toml_path = self.as_ref().join("Cargo.toml");
99 new_version_str = bumped;
100 } {
104 let cargo_toml_arc = self.cargo_toml();
105 let guard = cargo_toml_arc.lock().await;
106 guard.save_to_disk().await?;
107 }
108
109 info!(
110 "Successfully bumped crate at {:?} from {} to {}",
111 cargo_toml_path, old_version_str, new_version_str
112 );
113 Ok(())
114 }
115}
116
117#[cfg(test)]
118mod test_bump_crate_handle_with_mock {
119 use super::*;
120
121 #[traced_test]
122 async fn test_bump_patch_ok_with_mock() {
123 let mock_crate = MockCrateHandle::fully_valid_config()
125 .to_builder()
126 .crate_name("patch_ok") .build()
128 .unwrap();
129
130 let arc_handle = Arc::new(AsyncMutex::new(mock_crate));
132
133 {
135 let mut guard = arc_handle.lock().await;
136 guard.bump(ReleaseType::Patch).await
137 .expect("Expected patch bump to succeed in a fully-valid mock");
138 }
139
140 {
142 let guard = arc_handle.lock().await;
143 let new_ver = guard.version().expect("Should parse bumped version from mock");
144 assert_eq!(new_ver.to_string(), "1.2.4", "Mock crate's version should become 1.2.4");
145 }
146 }
147
148 #[traced_test]
149 async fn test_bump_fails_if_readme_missing() {
150 let mock_crate = MockCrateHandle::missing_readme_config();
152
153 let arc_handle = Arc::new(AsyncMutex::new(mock_crate));
154
155 let bump_result = {
157 let mut guard = arc_handle.lock().await;
158 guard.bump(ReleaseType::Minor).await
159 };
160
161 match bump_result {
163 Err(crate_error) => {
164 println!("Got expected error: {:?}", crate_error);
165 assert!(format!("{:?}", crate_error).contains("README.md"),
166 "Error should mention missing README file");
167 }
168 Ok(_) => panic!("Expected missing README to cause a bump failure"),
169 }
170 }
171}