changeset_operations/providers/
manifest.rs1use std::path::Path;
2use std::process::Command;
3
4use changeset_manifest::{InitConfig, MetadataSection};
5use semver::Version;
6
7use crate::Result;
8use crate::error::OperationError;
9use crate::traits::{
10 InheritedVersionChecker, LockfileUpdater, ManifestDependencyWriter, ManifestMetadataWriter,
11 ManifestVersionWriter, WorkspaceVersionManager,
12};
13
14pub struct FileSystemManifestWriter;
15
16impl FileSystemManifestWriter {
17 #[must_use]
18 pub fn new() -> Self {
19 Self
20 }
21}
22
23impl Default for FileSystemManifestWriter {
24 fn default() -> Self {
25 Self::new()
26 }
27}
28
29impl InheritedVersionChecker for FileSystemManifestWriter {
30 fn has_inherited_version(&self, manifest_path: &Path) -> Result<bool> {
31 Ok(changeset_manifest::has_inherited_version(manifest_path)?)
32 }
33}
34
35impl ManifestVersionWriter for FileSystemManifestWriter {
36 fn write_version(&self, manifest_path: &Path, new_version: &Version) -> Result<()> {
37 Ok(changeset_manifest::write_version(
38 manifest_path,
39 new_version,
40 )?)
41 }
42
43 fn verify_version(&self, manifest_path: &Path, expected: &Version) -> Result<()> {
44 Ok(changeset_manifest::verify_version(manifest_path, expected)?)
45 }
46}
47
48impl ManifestDependencyWriter for FileSystemManifestWriter {
49 fn update_dependency_version(
50 &self,
51 manifest_path: &Path,
52 dependency_name: &str,
53 new_version: &Version,
54 ) -> Result<bool> {
55 Ok(changeset_manifest::update_dependency_version(
56 manifest_path,
57 dependency_name,
58 new_version,
59 )?)
60 }
61}
62
63impl WorkspaceVersionManager for FileSystemManifestWriter {
64 fn read_workspace_version(&self, manifest_path: &Path) -> Result<Option<Version>> {
65 match changeset_manifest::read_workspace_version(manifest_path) {
66 Ok(version) => Ok(Some(version)),
67 Err(changeset_manifest::ManifestError::MissingField { .. }) => Ok(None),
68 Err(e) => Err(e.into()),
69 }
70 }
71
72 fn remove_workspace_version(&self, manifest_path: &Path) -> Result<()> {
73 Ok(changeset_manifest::remove_workspace_version(manifest_path)?)
74 }
75
76 fn write_workspace_version(&self, manifest_path: &Path, version: &Version) -> Result<()> {
77 Ok(changeset_manifest::write_workspace_version(
78 manifest_path,
79 version,
80 )?)
81 }
82}
83
84impl LockfileUpdater for FileSystemManifestWriter {
85 fn update_lockfile(&self, project_root: &Path) -> Result<()> {
86 let output = Command::new("cargo")
87 .args(["update", "--workspace"])
88 .current_dir(project_root)
89 .output()
90 .map_err(|source| OperationError::LockfileGeneration {
91 path: project_root.to_path_buf(),
92 source,
93 })?;
94
95 if !output.status.success() {
96 return Err(OperationError::LockfileCommandFailed {
97 stderr: String::from_utf8_lossy(&output.stderr).into_owned(),
98 });
99 }
100
101 Ok(())
102 }
103
104 fn read_lockfile(&self, project_root: &Path) -> Result<Option<Vec<u8>>> {
105 let lockfile_path = project_root.join("Cargo.lock");
106 if lockfile_path.exists() {
107 let content =
108 std::fs::read(&lockfile_path).map_err(|source| OperationError::LockfileRead {
109 path: lockfile_path,
110 source,
111 })?;
112 Ok(Some(content))
113 } else {
114 Ok(None)
115 }
116 }
117
118 fn restore_lockfile(&self, project_root: &Path, content: &[u8]) -> Result<()> {
119 let lockfile_path = project_root.join("Cargo.lock");
120 std::fs::write(&lockfile_path, content).map_err(|source| {
121 OperationError::LockfileWrite {
122 path: lockfile_path,
123 source,
124 }
125 })?;
126 Ok(())
127 }
128
129 fn remove_lockfile(&self, project_root: &Path) -> Result<()> {
130 let lockfile_path = project_root.join("Cargo.lock");
131 if lockfile_path.exists() {
132 std::fs::remove_file(&lockfile_path).map_err(|source| {
133 OperationError::LockfileWrite {
134 path: lockfile_path,
135 source,
136 }
137 })?;
138 }
139 Ok(())
140 }
141}
142
143impl ManifestMetadataWriter for FileSystemManifestWriter {
144 fn write_metadata(
145 &self,
146 manifest_path: &Path,
147 section: MetadataSection,
148 config: &InitConfig,
149 ) -> Result<()> {
150 Ok(changeset_manifest::write_metadata_section(
151 manifest_path,
152 section,
153 config,
154 )?)
155 }
156}