Skip to content

Commit

Permalink
scripts: add version replacer script
Browse files Browse the repository at this point in the history
  • Loading branch information
Br1ght0ne committed Aug 31, 2023
1 parent 151a511 commit 9518df9
Show file tree
Hide file tree
Showing 10 changed files with 150 additions and 4 deletions.
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ members = [
"packages/fuels-test-helpers",
"packages/wasm-tests",
"scripts/check-docs",
"scripts/versions-replacer",
]

[workspace.package]
Expand Down Expand Up @@ -90,3 +91,6 @@ fuels-core = { version = "0.46.0", path = "./packages/fuels-core", default-featu
fuels-macros = { version = "0.46.0", path = "./packages/fuels-macros", default-features = false }
fuels-programs = { version = "0.46.0", path = "./packages/fuels-programs", default-features = false }
fuels-test-helpers = { version = "0.46.0", path = "./packages/fuels-test-helpers", default-features = false }

[workspace.metadata.versions-replacer.external-versions]
fuels-types = "0.35.3"
2 changes: 1 addition & 1 deletion docs/src/types/address.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Address

Like `Bytes32`, `Address` is a wrapper on `[u8; 32]` with similar methods and implements the same traits (see [fuel-types documentation](https://docs.rs/fuel-types/{{versions.fuels_types}}/fuel_types/struct.Address.html)).
Like `Bytes32`, `Address` is a wrapper on `[u8; 32]` with similar methods and implements the same traits (see [fuel-types documentation](https://docs.rs/fuel-types/{{versions.fuels-types}}/fuel_types/struct.Address.html)).

These are the main ways of creating an `Address`:

Expand Down
2 changes: 1 addition & 1 deletion docs/src/types/asset-id.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# AssetId

Like `Bytes32`, `AssetId` is a wrapper on `[u8; 32]` with similar methods and implements the same traits (see [fuel-types documentation](https://docs.rs/fuel-types/{{versions.fuels_types}}/fuel_types/struct.AssetId.html)).
Like `Bytes32`, `AssetId` is a wrapper on `[u8; 32]` with similar methods and implements the same traits (see [fuel-types documentation](https://docs.rs/fuel-types/{{versions.fuels-types}}/fuel_types/struct.AssetId.html)).

These are the main ways of creating an `AssetId`:

Expand Down
2 changes: 1 addition & 1 deletion docs/src/types/bytes32.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@ These are the main ways of creating a `Bytes32`:
{{#include ../../../examples/types/src/lib.rs:bytes32_format}}
```

For a full list of implemented methods and traits, see the [fuel-types documentation](https://docs.rs/fuel-types/{{versions.fuels_types}}/fuel_types/struct.Bytes32.html).
For a full list of implemented methods and traits, see the [fuel-types documentation](https://docs.rs/fuel-types/{{versions.fuels-types}}/fuel_types/struct.Bytes32.html).

> **Note:** In Fuel, there's a special type called `b256`, which is similar to `Bytes32`; also used to represent hashes, and it holds a 256-bit value. In Rust, through the SDK, this is represented as `Bits256(value)` where `value` is a `[u8; 32]`. If your contract method takes a `b256` as input, all you need to do is pass a `Bits256([u8; 32])` when calling it from the SDK.
2 changes: 1 addition & 1 deletion docs/src/types/contract-id.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# ContractId

Like `Bytes32`, `ContractId` is a wrapper on `[u8; 32]` with similar methods and implements the same traits (see [fuel-types documentation](https://docs.rs/fuel-types/{{versions.fuels_types}}/fuel_types/struct.ContractId.html)).
Like `Bytes32`, `ContractId` is a wrapper on `[u8; 32]` with similar methods and implements the same traits (see [fuel-types documentation](https://docs.rs/fuel-types/{{versions.fuels-types}}/fuel_types/struct.ContractId.html)).

These are the main ways of creating a `ContractId`:

Expand Down
21 changes: 21 additions & 0 deletions scripts/versions-replacer/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
[package]
name = "versions-replacer"
publish = false
authors.workspace = true
edition.workspace = true
homepage.workspace = true
readme.workspace = true
license.workspace = true
repository.workspace = true
rust-version.workspace = true
version.workspace = true

[dependencies]
argh = "0.1.12"
cargo_metadata = "0.17.0"
color-eyre = "0.6.2"
once_cell = "1.18.0"
regex = { workspace = true }
serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true }
walkdir = "2.3.3"
2 changes: 2 additions & 0 deletions scripts/versions-replacer/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub mod metadata;
pub mod replace;
55 changes: 55 additions & 0 deletions scripts/versions-replacer/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
use std::path::PathBuf;

use argh::FromArgs;
use color_eyre::{
eyre::{eyre, Context},
Result,
};
use regex::Regex;
use walkdir::WalkDir;

use versions_replacer::{
metadata::collect_versions_from_cargo_toml, replace::replace_versions_in_file,
};

#[derive(FromArgs)]
/// Replace variables like '{{{{versions.fuels}}}}' with correct versions from Cargo.toml.
/// Uses versions from '[workspace.members]' and '[workspace.metadata.versions-replacer.external-versions]'.
struct VersionsReplacer {
/// path to directory with files containing variables
#[argh(positional)]
path: PathBuf,
/// path to Cargo.toml with versions
#[argh(option)]
manifest_path: PathBuf,
/// regex to filter filenames (example: "\.md$")
#[argh(option)]
filename_regex: Option<Regex>,
}

fn main() -> Result<()> {
let args: VersionsReplacer = argh::from_env();
let versions = collect_versions_from_cargo_toml(&args.manifest_path)?;

for entry in WalkDir::new(&args.path) {
let entry = entry.wrap_err("failed to get directory entry")?;

if entry.path().is_file() {
if let Some(filename_regex) = &args.filename_regex {
let file_name = entry
.path()
.file_name()
.ok_or_else(|| eyre!("{:?} has an invalid file name", entry.path()))?
.to_str()
.ok_or_else(|| eyre!("filename is not valid UTF-8"))?;
if !filename_regex.is_match(file_name) {
continue;
}
}

replace_versions_in_file(entry.path(), &versions)
.wrap_err_with(|| format!("failed to replace versions in {:?}", entry.path()))?;
}
}
Ok(())
}
42 changes: 42 additions & 0 deletions scripts/versions-replacer/src/metadata.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
use std::{collections::HashMap, path::Path};

use cargo_metadata::MetadataCommand;
use color_eyre::{eyre::Context, Result};
use serde::Deserialize;

#[derive(Deserialize)]
#[serde(rename_all = "kebab-case")]
pub struct WorkspaceMetadata {
pub versions_replacer: VersionsReplacerMetadata,
}

#[derive(Deserialize)]
#[serde(rename_all = "kebab-case")]
pub struct VersionsReplacerMetadata {
pub external_versions: HashMap<String, String>,
}

pub fn collect_versions_from_cargo_toml(
manifest_path: impl AsRef<Path>,
) -> Result<HashMap<String, String>> {
let metadata = MetadataCommand::new()
.manifest_path(manifest_path.as_ref())
.exec()
.wrap_err("failed to execute 'cargo metadata'")?;
let version_map = metadata
.workspace_members
.iter()
.map(|package_id| {
let package = &metadata[package_id];
(package.name.clone(), package.version.to_string())
})
.chain(
serde_json::from_value::<WorkspaceMetadata>(metadata.workspace_metadata.clone())
.wrap_err("failed to parse '[workspace.metadata]'")?
.versions_replacer
.external_versions
.into_iter(),
)
.collect::<HashMap<_, _>>();
Ok(version_map)
}
22 changes: 22 additions & 0 deletions scripts/versions-replacer/src/replace.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
use std::{collections::HashMap, fs, path::Path};

use color_eyre::{eyre::Context, Result};
use once_cell::sync::Lazy;
use regex::{Captures, Regex};

pub static VERSIONS_REGEX: Lazy<Regex> =
Lazy::new(|| Regex::new(r"\{\{versions\.([\w_-]+)\}\}").unwrap());

pub fn replace_versions_in_file(
path: impl AsRef<Path>,
versions: &HashMap<String, String>,
) -> Result<()> {
let path = path.as_ref();
let contents =
fs::read_to_string(path).wrap_err_with(|| format!("failed to read {:?}", path))?;
let replaced_contents =
VERSIONS_REGEX.replace_all(&contents, |caps: &Captures| &versions[&caps[1]]);
fs::write(path, replaced_contents.as_bytes())
.wrap_err_with(|| format!("failed to write back to {:?}", path))?;
Ok(())
}

0 comments on commit 9518df9

Please sign in to comment.