Skip to content

Commit f0f7e51

Browse files
moliholyggwpez
andauthored
feat: convert into a library (#34)
* feat: convert into a library * fix test Signed-off-by: Oliver Tale-Yazdi <[email protected]> * fmt Signed-off-by: Oliver Tale-Yazdi <[email protected]> --------- Signed-off-by: Oliver Tale-Yazdi <[email protected]> Co-authored-by: Oliver Tale-Yazdi <[email protected]>
1 parent febe87d commit f0f7e51

File tree

4 files changed

+233
-152
lines changed

4 files changed

+233
-152
lines changed

src/lib.rs

Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
// Copyright (C) Parity Technologies (UK) Ltd.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
16+
//! Polkadot SDK Version Manager Library
17+
//!
18+
//! This library provides functionality to manage and update Polkadot SDK dependencies
19+
//! in Cargo.toml files.
20+
21+
mod tests;
22+
pub mod versions;
23+
24+
use std::{
25+
collections::BTreeMap,
26+
fs,
27+
path::{Path, PathBuf},
28+
};
29+
use toml_edit::DocumentMut;
30+
31+
pub use versions::{
32+
get_orml_crates_and_version, get_polkadot_sdk_versions, get_release_branches_versions,
33+
get_version_mapping_with_fallback, include_orml_crates_in_version_mapping, Repository,
34+
};
35+
36+
pub const DEFAULT_GIT_SERVER: &str = "https://raw.githubusercontent.com";
37+
38+
/// Validates that the provided path points to a valid Cargo.toml file.
39+
///
40+
/// If the path is a directory, it will append "Cargo.toml" to it.
41+
/// Returns an error if the resulting path does not exist.
42+
///
43+
/// # Arguments
44+
///
45+
/// * `path` - A PathBuf that should point to either a Cargo.toml file or a directory containing one
46+
///
47+
/// # Errors
48+
///
49+
/// Returns an error if the Cargo.toml file cannot be found at the specified path.
50+
pub fn validate_workspace_path(mut path: PathBuf) -> Result<PathBuf, Box<dyn std::error::Error>> {
51+
if path.is_dir() {
52+
path = path.join("Cargo.toml");
53+
}
54+
55+
if !path.exists() {
56+
return Err(format!(
57+
"Could not find workspace root Cargo.toml file at {}",
58+
path.display()
59+
)
60+
.into());
61+
}
62+
63+
Ok(path)
64+
}
65+
66+
/// Updates dependencies in a Cargo.toml file based on the provided version mappings.
67+
///
68+
/// # Arguments
69+
///
70+
/// * `cargo_toml_path` - Path to the Cargo.toml file to update
71+
/// * `crates_versions` - A map of crate names to their versions
72+
/// * `overwrite` - If true, will overwrite local path dependencies
73+
/// * `only_check` - If true, only checks if dependencies match without updating
74+
///
75+
/// # Errors
76+
///
77+
/// Returns an error if:
78+
/// - The file cannot be read or written
79+
/// - The TOML content is invalid
80+
/// - `only_check` is true and dependencies are not up to date
81+
pub fn update_dependencies(
82+
cargo_toml_path: &Path,
83+
crates_versions: &BTreeMap<String, String>,
84+
overwrite: bool,
85+
only_check: bool,
86+
) -> Result<(), Box<dyn std::error::Error>> {
87+
let cargo_toml =
88+
update_dependencies_impl(cargo_toml_path, crates_versions, overwrite, only_check)?;
89+
90+
match cargo_toml {
91+
Some(new_content) => {
92+
fs::write(cargo_toml_path, new_content)?;
93+
println!("Updated dependencies in {}", cargo_toml_path.display());
94+
}
95+
None => {
96+
println!(
97+
"Dependencies in {} are already up to date",
98+
cargo_toml_path.display()
99+
);
100+
}
101+
}
102+
103+
Ok(())
104+
}
105+
106+
/// Internal implementation of dependency update logic.
107+
///
108+
/// Returns `Some(String)` with the new content if changes were made,
109+
/// or `None` if no changes were needed.
110+
fn update_dependencies_impl(
111+
cargo_toml_path: &Path,
112+
crates_versions: &BTreeMap<String, String>,
113+
overwrite: bool,
114+
only_check: bool,
115+
) -> Result<Option<String>, Box<dyn std::error::Error>> {
116+
let cargo_toml_content = fs::read_to_string(cargo_toml_path)?;
117+
let mut cargo_toml: DocumentMut = cargo_toml_content.parse()?;
118+
// Check if cargo workspace is defined
119+
let deps = match cargo_toml.as_table_mut().get_mut("workspace") {
120+
Some(toml_edit::Item::Table(table)) => table,
121+
_ => cargo_toml.as_table_mut(),
122+
};
123+
124+
for table in ["dependencies", "dev-dependencies", "build-dependencies"].iter() {
125+
if let Some(toml_edit::Item::Table(dep_table)) = deps.get_mut(table) {
126+
update_table_dependencies(dep_table, crates_versions, overwrite);
127+
}
128+
}
129+
130+
let new_content = cargo_toml.to_string();
131+
if new_content != cargo_toml_content {
132+
if only_check {
133+
Err("Dependencies are not up to date".into())
134+
} else {
135+
Ok(Some(new_content))
136+
}
137+
} else {
138+
Ok(None)
139+
}
140+
}
141+
142+
/// Updates dependencies within a specific TOML table.
143+
///
144+
/// This function modifies the dependency table in-place, updating versions
145+
/// and removing git/path-related fields as appropriate.
146+
///
147+
/// # Arguments
148+
///
149+
/// * `dep_table` - The TOML table containing dependencies
150+
/// * `crates_versions` - A map of crate names to their versions
151+
/// * `overwrite` - If true, will overwrite local path dependencies
152+
pub fn update_table_dependencies(
153+
dep_table: &mut toml_edit::Table,
154+
crates_versions: &BTreeMap<String, String>,
155+
overwrite: bool,
156+
) {
157+
for (dep_key, dep_value) in dep_table.iter_mut() {
158+
let dep_key_str = dep_key.get();
159+
160+
// account for dep renaming:
161+
let lookup_key = if let Some(table) = dep_value.as_table_like() {
162+
table
163+
.get("package")
164+
.and_then(|p| p.as_str())
165+
.unwrap_or(dep_key_str)
166+
} else {
167+
dep_key_str
168+
};
169+
170+
let Some(crate_version) = crates_versions.get(lookup_key) else {
171+
log::debug!("Could not find version for {}", lookup_key);
172+
continue;
173+
};
174+
175+
if let Some(table) = dep_value.as_table_like_mut() {
176+
if !overwrite && table.get("path").is_some() {
177+
continue;
178+
}
179+
180+
table.remove("rev");
181+
table.remove("branch");
182+
table.remove("tag");
183+
table.remove("path");
184+
table.remove("git");
185+
186+
let mut new_table = toml_edit::InlineTable::default();
187+
188+
// Directly create a `toml_edit::Value` for the version
189+
new_table.get_or_insert(
190+
"version",
191+
toml_edit::value(crate_version.clone()).as_value().unwrap(),
192+
);
193+
194+
for (key, value) in table.iter() {
195+
// Ensure we're inserting `Value`s, not `Item`s
196+
if key != "version" && value.is_value() {
197+
new_table.get_or_insert(key, value.as_value().unwrap().clone());
198+
}
199+
}
200+
new_table.fmt();
201+
202+
// Replace the original table-like item with the new inline table
203+
*dep_value = toml_edit::Item::Value(toml_edit::Value::InlineTable(new_table));
204+
} else if dep_value.is_str() {
205+
*dep_value = toml_edit::value(crate_version.clone());
206+
} else {
207+
log::error!("Unexpected dependency value type for {}", dep_key_str);
208+
continue;
209+
}
210+
211+
log::debug!("Setting {} to {}", dep_key_str, crate_version);
212+
}
213+
}

src/main.rs

Lines changed: 5 additions & 149 deletions
Original file line numberDiff line numberDiff line change
@@ -13,23 +13,15 @@
1313
// See the License for the specific language governing permissions and
1414
// limitations under the License.
1515

16-
mod tests;
17-
mod versions;
18-
1916
use clap::Parser;
2017
use env_logger::Env;
21-
use std::{
22-
collections::BTreeMap,
23-
fs,
24-
path::{Path, PathBuf},
25-
};
26-
use toml_edit::DocumentMut;
27-
use versions::{
18+
use psvm::{
2819
get_orml_crates_and_version, get_polkadot_sdk_versions, get_release_branches_versions,
29-
get_version_mapping_with_fallback, include_orml_crates_in_version_mapping, Repository,
20+
get_version_mapping_with_fallback, include_orml_crates_in_version_mapping, update_dependencies,
21+
validate_workspace_path, Repository, DEFAULT_GIT_SERVER,
3022
};
31-
32-
pub const DEFAULT_GIT_SERVER: &str = "https://raw.githubusercontent.com";
23+
use std::collections::BTreeMap;
24+
use std::path::PathBuf;
3325

3426
/// Polkadot SDK Version Manager.
3527
///
@@ -98,139 +90,3 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
9890

9991
Ok(())
10092
}
101-
102-
fn validate_workspace_path(mut path: PathBuf) -> Result<PathBuf, Box<dyn std::error::Error>> {
103-
if path.is_dir() {
104-
path = path.join("Cargo.toml");
105-
}
106-
107-
if !path.exists() {
108-
return Err(format!(
109-
"Could not find workspace root Cargo.toml file at {}",
110-
path.display()
111-
)
112-
.into());
113-
}
114-
115-
Ok(path)
116-
}
117-
118-
fn update_dependencies(
119-
cargo_toml_path: &Path,
120-
crates_versions: &BTreeMap<String, String>,
121-
overwrite: bool,
122-
only_check: bool,
123-
) -> Result<(), Box<dyn std::error::Error>> {
124-
let cargo_toml =
125-
update_dependencies_impl(cargo_toml_path, crates_versions, overwrite, only_check)?;
126-
127-
match cargo_toml {
128-
Some(new_content) => {
129-
fs::write(cargo_toml_path, new_content)?;
130-
println!("Updated dependencies in {}", cargo_toml_path.display());
131-
}
132-
None => {
133-
println!(
134-
"Dependencies in {} are already up to date",
135-
cargo_toml_path.display()
136-
);
137-
}
138-
}
139-
140-
Ok(())
141-
}
142-
143-
fn update_dependencies_impl(
144-
cargo_toml_path: &Path,
145-
crates_versions: &BTreeMap<String, String>,
146-
overwrite: bool,
147-
only_check: bool,
148-
) -> Result<Option<String>, Box<dyn std::error::Error>> {
149-
let cargo_toml_content = fs::read_to_string(cargo_toml_path)?;
150-
let mut cargo_toml: DocumentMut = cargo_toml_content.parse()?;
151-
// Check if cargo workspace is defined
152-
let deps = match cargo_toml.as_table_mut().get_mut("workspace") {
153-
Some(toml_edit::Item::Table(table)) => table,
154-
_ => cargo_toml.as_table_mut(),
155-
};
156-
157-
for table in ["dependencies", "dev-dependencies", "build-dependencies"].iter() {
158-
if let Some(toml_edit::Item::Table(dep_table)) = deps.get_mut(table) {
159-
update_table_dependencies(dep_table, crates_versions, overwrite);
160-
}
161-
}
162-
163-
let new_content = cargo_toml.to_string();
164-
if new_content != cargo_toml_content {
165-
if only_check {
166-
Err("Dependencies are not up to date".into())
167-
} else {
168-
Ok(Some(new_content))
169-
}
170-
} else {
171-
Ok(None)
172-
}
173-
}
174-
175-
pub fn update_table_dependencies(
176-
dep_table: &mut toml_edit::Table,
177-
crates_versions: &BTreeMap<String, String>,
178-
overwrite: bool,
179-
) {
180-
for (dep_key, dep_value) in dep_table.iter_mut() {
181-
let dep_key_str = dep_key.get();
182-
183-
// account for dep renaming:
184-
let lookup_key = if let Some(table) = dep_value.as_table_like() {
185-
table
186-
.get("package")
187-
.and_then(|p| p.as_str())
188-
.unwrap_or(dep_key_str)
189-
} else {
190-
dep_key_str
191-
};
192-
193-
let Some(crate_version) = crates_versions.get(lookup_key) else {
194-
log::debug!("Could not find version for {}", lookup_key);
195-
continue;
196-
};
197-
198-
if let Some(table) = dep_value.as_table_like_mut() {
199-
if !overwrite && table.get("path").is_some() {
200-
continue;
201-
}
202-
203-
table.remove("rev");
204-
table.remove("branch");
205-
table.remove("tag");
206-
table.remove("path");
207-
table.remove("git");
208-
209-
let mut new_table = toml_edit::InlineTable::default();
210-
211-
// Directly create a `toml_edit::Value` for the version
212-
new_table.get_or_insert(
213-
"version",
214-
toml_edit::value(crate_version.clone()).as_value().unwrap(),
215-
);
216-
217-
for (key, value) in table.iter() {
218-
// Ensure we're inserting `Value`s, not `Item`s
219-
if key != "version" && value.is_value() {
220-
new_table.get_or_insert(key, value.as_value().unwrap().clone());
221-
}
222-
}
223-
new_table.fmt();
224-
225-
// Replace the original table-like item with the new inline table
226-
*dep_value = toml_edit::Item::Value(toml_edit::Value::InlineTable(new_table));
227-
} else if dep_value.is_str() {
228-
*dep_value = toml_edit::value(crate_version.clone());
229-
} else {
230-
log::error!("Unexpected dependency value type for {}", dep_key_str);
231-
continue;
232-
}
233-
234-
log::debug!("Setting {} to {}", dep_key_str, crate_version);
235-
}
236-
}

src/testing/orml/notOrml.Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ sp-version = { version = "36.0.0", default-features = false }
6262
pallet-xcm = { version = "15.0.0", default-features = false }
6363
polkadot-parachain-primitives = { version = "13.0.0", default-features = false }
6464
polkadot-runtime-common = { version = "15.0.0", default-features = false }
65-
xcm = { version = "14.0.3", package = "staging-xcm", default-features = false }
65+
xcm = { version = "=14.0.3", package = "staging-xcm", default-features = false }
6666
xcm-builder = { version = "15.0.0", package = "staging-xcm-builder", default-features = false }
6767
xcm-executor = { version = "15.0.0", package = "staging-xcm-executor", default-features = false }
6868

0 commit comments

Comments
 (0)