xtask: Upgrade xshell to 0.2
This commit is contained in:
parent
bab06ed375
commit
ce715d4c13
@ -16,7 +16,7 @@ serde = { workspace = true }
|
|||||||
serde_json = { workspace = true }
|
serde_json = { workspace = true }
|
||||||
toml = { version = "0.8.2", default-features = false, features = ["parse"] }
|
toml = { version = "0.8.2", default-features = false, features = ["parse"] }
|
||||||
toml_edit = { version = "0.22.22", optional = true }
|
toml_edit = { version = "0.22.22", optional = true }
|
||||||
xshell = "0.1.17"
|
xshell = "0.2.7"
|
||||||
|
|
||||||
[lints]
|
[lints]
|
||||||
workspace = true
|
workspace = true
|
||||||
|
@ -9,8 +9,10 @@ use serde::{de::IgnoredAny, Deserialize};
|
|||||||
#[cfg(feature = "default")]
|
#[cfg(feature = "default")]
|
||||||
use toml_edit::{value, DocumentMut};
|
use toml_edit::{value, DocumentMut};
|
||||||
#[cfg(feature = "default")]
|
#[cfg(feature = "default")]
|
||||||
use xshell::{cmd, pushd, read_file, write_file};
|
use xshell::Shell;
|
||||||
|
|
||||||
|
#[cfg(feature = "default")]
|
||||||
|
use crate::cmd;
|
||||||
use crate::{util::ask_yes_no, Metadata, Result};
|
use crate::{util::ask_yes_no, Metadata, Result};
|
||||||
|
|
||||||
const CRATESIO_API: &str = "https://crates.io/api/v1/crates";
|
const CRATESIO_API: &str = "https://crates.io/api/v1/crates";
|
||||||
@ -74,15 +76,15 @@ impl Package {
|
|||||||
#[cfg(feature = "default")]
|
#[cfg(feature = "default")]
|
||||||
impl Package {
|
impl Package {
|
||||||
/// Update the version of this crate.
|
/// Update the version of this crate.
|
||||||
pub fn update_version(&mut self, version: &Version, dry_run: bool) -> Result<()> {
|
pub fn update_version(&mut self, sh: &Shell, version: &Version, dry_run: bool) -> Result<()> {
|
||||||
println!("Updating {} to version {version}…", self.name);
|
println!("Updating {} to version {version}…", self.name);
|
||||||
|
|
||||||
if !dry_run {
|
if !dry_run {
|
||||||
let mut document = read_file(&self.manifest_path)?.parse::<DocumentMut>()?;
|
let mut document = sh.read_file(&self.manifest_path)?.parse::<DocumentMut>()?;
|
||||||
|
|
||||||
document["package"]["version"] = value(version.to_string());
|
document["package"]["version"] = value(version.to_string());
|
||||||
|
|
||||||
write_file(&self.manifest_path, document.to_string())?;
|
sh.write_file(&self.manifest_path, document.to_string())?;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.version = version.clone();
|
self.version = version.clone();
|
||||||
@ -92,7 +94,12 @@ impl Package {
|
|||||||
|
|
||||||
/// Update the version of this crate in dependant crates' manifests, with the given version
|
/// Update the version of this crate in dependant crates' manifests, with the given version
|
||||||
/// prefix.
|
/// prefix.
|
||||||
pub(crate) fn update_dependants(&self, metadata: &Metadata, dry_run: bool) -> Result<()> {
|
pub(crate) fn update_dependants(
|
||||||
|
&self,
|
||||||
|
sh: &Shell,
|
||||||
|
metadata: &Metadata,
|
||||||
|
dry_run: bool,
|
||||||
|
) -> Result<()> {
|
||||||
if self.name == "ruma" {
|
if self.name == "ruma" {
|
||||||
for package in metadata.packages.iter().filter(|p| {
|
for package in metadata.packages.iter().filter(|p| {
|
||||||
p.manifest_path.starts_with(&metadata.workspace_root)
|
p.manifest_path.starts_with(&metadata.workspace_root)
|
||||||
@ -101,7 +108,8 @@ impl Package {
|
|||||||
println!("Updating dependency in {} crate…", package.name);
|
println!("Updating dependency in {} crate…", package.name);
|
||||||
|
|
||||||
if !dry_run {
|
if !dry_run {
|
||||||
let mut document = read_file(&package.manifest_path)?.parse::<DocumentMut>()?;
|
let mut document =
|
||||||
|
sh.read_file(&package.manifest_path)?.parse::<DocumentMut>()?;
|
||||||
|
|
||||||
let version = if !self.version.pre.is_empty() {
|
let version = if !self.version.pre.is_empty() {
|
||||||
format!("={}", self.version)
|
format!("={}", self.version)
|
||||||
@ -119,12 +127,12 @@ impl Package {
|
|||||||
document[kind][&self.name]["version"] = value(version.as_str());
|
document[kind][&self.name]["version"] = value(version.as_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
write_file(&package.manifest_path, document.to_string())?;
|
sh.write_file(&package.manifest_path, document.to_string())?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let workspace_manifest_path = metadata.workspace_root.join("Cargo.toml");
|
let workspace_manifest_path = metadata.workspace_root.join("Cargo.toml");
|
||||||
let mut document = read_file(&workspace_manifest_path)?.parse::<DocumentMut>()?;
|
let mut document = sh.read_file(&workspace_manifest_path)?.parse::<DocumentMut>()?;
|
||||||
let workspace_deps = &mut document["workspace"]["dependencies"];
|
let workspace_deps = &mut document["workspace"]["dependencies"];
|
||||||
|
|
||||||
println!("Updating workspace dependency…");
|
println!("Updating workspace dependency…");
|
||||||
@ -139,7 +147,7 @@ impl Package {
|
|||||||
|
|
||||||
workspace_deps[&self.name]["version"] = value(version.as_str());
|
workspace_deps[&self.name]["version"] = value(version.as_str());
|
||||||
|
|
||||||
write_file(&workspace_manifest_path, document.to_string())?;
|
sh.write_file(&workspace_manifest_path, document.to_string())?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,7 +157,7 @@ impl Package {
|
|||||||
/// Get the changes for the version.
|
/// Get the changes for the version.
|
||||||
///
|
///
|
||||||
/// If `update` is `true`, update the changelog for the release of the given version.
|
/// If `update` is `true`, update the changelog for the release of the given version.
|
||||||
pub fn changes(&self, update: bool) -> Result<String> {
|
pub fn changes(&self, sh: &Shell, update: bool) -> Result<String> {
|
||||||
if self.name == "ruma-macros" {
|
if self.name == "ruma-macros" {
|
||||||
// ruma-macros doesn't have a changelog and won't create a tag.
|
// ruma-macros doesn't have a changelog and won't create a tag.
|
||||||
return Ok(String::new());
|
return Ok(String::new());
|
||||||
@ -158,7 +166,7 @@ impl Package {
|
|||||||
let mut changelog_path = self.manifest_path.clone();
|
let mut changelog_path = self.manifest_path.clone();
|
||||||
changelog_path.set_file_name("CHANGELOG.md");
|
changelog_path.set_file_name("CHANGELOG.md");
|
||||||
|
|
||||||
let changelog = read_file(&changelog_path)?;
|
let changelog = sh.read_file(&changelog_path)?;
|
||||||
let version = Version {
|
let version = Version {
|
||||||
pre: semver::Prerelease::EMPTY,
|
pre: semver::Prerelease::EMPTY,
|
||||||
build: semver::BuildMetadata::EMPTY,
|
build: semver::BuildMetadata::EMPTY,
|
||||||
@ -196,7 +204,7 @@ impl Package {
|
|||||||
let rest = &changelog[changes_end..];
|
let rest = &changelog[changes_end..];
|
||||||
let changelog = format!("# [unreleased]\n\n# {}\n\n{changes}\n{rest}", self.version);
|
let changelog = format!("# [unreleased]\n\n# {}\n\n{changes}\n{rest}", self.version);
|
||||||
|
|
||||||
write_file(&changelog_path, changelog)?;
|
sh.write_file(&changelog_path, changelog)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(changes.to_owned())
|
Ok(changes.to_owned())
|
||||||
@ -211,16 +219,16 @@ impl Package {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Publish this package on crates.io.
|
/// Publish this package on crates.io.
|
||||||
pub fn publish(&self, client: &Client, dry_run: bool) -> Result<()> {
|
pub fn publish(&self, sh: &Shell, client: &Client, dry_run: bool) -> Result<()> {
|
||||||
println!("Publishing {} {} on crates.io…", self.name, self.version);
|
println!("Publishing {} {} on crates.io…", self.name, self.version);
|
||||||
let _dir = pushd(self.manifest_path.parent().unwrap())?;
|
let _dir = sh.push_dir(self.manifest_path.parent().unwrap());
|
||||||
|
|
||||||
if self.is_published(client)? {
|
if self.is_published(client)? {
|
||||||
if !ask_yes_no("This version is already published. Skip this step and continue?")? {
|
if !ask_yes_no("This version is already published. Skip this step and continue?")? {
|
||||||
return Err("Release interrupted by user.".into());
|
return Err("Release interrupted by user.".into());
|
||||||
}
|
}
|
||||||
} else if !dry_run {
|
} else if !dry_run {
|
||||||
cmd!("cargo publish").run()?;
|
cmd!(sh, "cargo publish").run()?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use clap::{Args, Subcommand};
|
use clap::{Args, Subcommand};
|
||||||
use xshell::pushd;
|
use xshell::Shell;
|
||||||
|
|
||||||
use crate::{cmd, Metadata, Result, NIGHTLY};
|
use crate::{cmd, Metadata, Result, NIGHTLY};
|
||||||
|
|
||||||
@ -81,12 +81,16 @@ pub struct CiTask {
|
|||||||
|
|
||||||
/// The metadata of the workspace.
|
/// The metadata of the workspace.
|
||||||
project_metadata: Metadata,
|
project_metadata: Metadata,
|
||||||
|
|
||||||
|
/// The shell API to use to run commands.
|
||||||
|
sh: Shell,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CiTask {
|
impl CiTask {
|
||||||
pub(crate) fn new(cmd: Option<CiCmd>) -> Result<Self> {
|
pub(crate) fn new(cmd: Option<CiCmd>) -> Result<Self> {
|
||||||
let project_metadata = Metadata::load()?;
|
let sh = Shell::new()?;
|
||||||
Ok(Self { cmd, project_metadata })
|
let project_metadata = Metadata::load(&sh)?;
|
||||||
|
Ok(Self { cmd, sh, project_metadata })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn project_root(&self) -> &Path {
|
fn project_root(&self) -> &Path {
|
||||||
@ -94,7 +98,7 @@ impl CiTask {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn run(self) -> Result<()> {
|
pub(crate) fn run(self) -> Result<()> {
|
||||||
let _p = pushd(self.project_root())?;
|
let _p = self.sh.push_dir(self.project_root());
|
||||||
|
|
||||||
match self.cmd {
|
match self.cmd {
|
||||||
Some(CiCmd::Msrv) => self.msrv()?,
|
Some(CiCmd::Msrv) => self.msrv()?,
|
||||||
@ -147,6 +151,7 @@ impl CiTask {
|
|||||||
/// * xtask (no real reason to enforce an MSRV for it)
|
/// * xtask (no real reason to enforce an MSRV for it)
|
||||||
fn msrv_all(&self) -> Result<()> {
|
fn msrv_all(&self) -> Result<()> {
|
||||||
cmd!(
|
cmd!(
|
||||||
|
&self.sh,
|
||||||
"rustup run {MSRV} cargo check --workspace --all-features
|
"rustup run {MSRV} cargo check --workspace --all-features
|
||||||
--exclude ruma
|
--exclude ruma
|
||||||
--exclude ruma-macros
|
--exclude ruma-macros
|
||||||
@ -159,7 +164,7 @@ impl CiTask {
|
|||||||
|
|
||||||
/// Check ruma crate with default features with the MSRV.
|
/// Check ruma crate with default features with the MSRV.
|
||||||
fn msrv_ruma(&self) -> Result<()> {
|
fn msrv_ruma(&self) -> Result<()> {
|
||||||
cmd!("rustup run {MSRV} cargo check -p ruma").run().map_err(Into::into)
|
cmd!(&self.sh, "rustup run {MSRV} cargo check -p ruma").run().map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Run all the tasks that use the stable version.
|
/// Run all the tasks that use the stable version.
|
||||||
@ -177,6 +182,7 @@ impl CiTask {
|
|||||||
// ruma-macros is pulled in as a dependency, but excluding it on the command line means its
|
// ruma-macros is pulled in as a dependency, but excluding it on the command line means its
|
||||||
// features don't get activated. It has only a single feature, which is nightly-only.
|
// features don't get activated. It has only a single feature, which is nightly-only.
|
||||||
cmd!(
|
cmd!(
|
||||||
|
&self.sh,
|
||||||
"rustup run stable cargo check
|
"rustup run stable cargo check
|
||||||
--workspace --all-features --exclude ruma-macros"
|
--workspace --all-features --exclude ruma-macros"
|
||||||
)
|
)
|
||||||
@ -186,7 +192,7 @@ impl CiTask {
|
|||||||
|
|
||||||
/// Check ruma-client without default features with the stable version.
|
/// Check ruma-client without default features with the stable version.
|
||||||
fn stable_client(&self) -> Result<()> {
|
fn stable_client(&self) -> Result<()> {
|
||||||
cmd!("rustup run stable cargo check -p ruma-client --no-default-features")
|
cmd!(&self.sh, "rustup run stable cargo check -p ruma-client --no-default-features")
|
||||||
.run()
|
.run()
|
||||||
.map_err(Into::into)
|
.map_err(Into::into)
|
||||||
}
|
}
|
||||||
@ -194,6 +200,7 @@ impl CiTask {
|
|||||||
/// Check ruma-common with onjy the required features with the stable version.
|
/// Check ruma-common with onjy the required features with the stable version.
|
||||||
fn stable_common(&self) -> Result<()> {
|
fn stable_common(&self) -> Result<()> {
|
||||||
cmd!(
|
cmd!(
|
||||||
|
&self.sh,
|
||||||
"rustup run stable cargo check -p ruma-common
|
"rustup run stable cargo check -p ruma-common
|
||||||
--no-default-features --features client,server"
|
--no-default-features --features client,server"
|
||||||
)
|
)
|
||||||
@ -203,20 +210,24 @@ impl CiTask {
|
|||||||
|
|
||||||
/// Run tests on all crates with almost all features with the stable version.
|
/// Run tests on all crates with almost all features with the stable version.
|
||||||
fn test_all(&self) -> Result<()> {
|
fn test_all(&self) -> Result<()> {
|
||||||
cmd!("rustup run stable cargo test --tests --features __ci").run().map_err(Into::into)
|
cmd!(&self.sh, "rustup run stable cargo test --tests --features __ci")
|
||||||
|
.run()
|
||||||
|
.map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Run tests on all crates with almost all features and the compat features with the stable
|
/// Run tests on all crates with almost all features and the compat features with the stable
|
||||||
/// version.
|
/// version.
|
||||||
fn test_compat(&self) -> Result<()> {
|
fn test_compat(&self) -> Result<()> {
|
||||||
cmd!("rustup run stable cargo test --tests --features __ci,compat")
|
cmd!(&self.sh, "rustup run stable cargo test --tests --features __ci,compat")
|
||||||
.run()
|
.run()
|
||||||
.map_err(Into::into)
|
.map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Run doctests on all crates with almost all features with the stable version.
|
/// Run doctests on all crates with almost all features with the stable version.
|
||||||
fn test_doc(&self) -> Result<()> {
|
fn test_doc(&self) -> Result<()> {
|
||||||
cmd!("rustup run stable cargo test --doc --features __ci").run().map_err(Into::into)
|
cmd!(&self.sh, "rustup run stable cargo test --doc --features __ci")
|
||||||
|
.run()
|
||||||
|
.map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Run all the tasks that use the nightly version.
|
/// Run all the tasks that use the nightly version.
|
||||||
@ -230,12 +241,14 @@ impl CiTask {
|
|||||||
|
|
||||||
/// Check the formatting with the nightly version.
|
/// Check the formatting with the nightly version.
|
||||||
fn fmt(&self) -> Result<()> {
|
fn fmt(&self) -> Result<()> {
|
||||||
cmd!("rustup run {NIGHTLY} cargo fmt -- --check").run().map_err(Into::into)
|
cmd!(&self.sh, "rustup run {NIGHTLY} cargo fmt -- --check").run().map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check ruma crate with full feature with the nightly version.
|
/// Check ruma crate with full feature with the nightly version.
|
||||||
fn nightly_full(&self) -> Result<()> {
|
fn nightly_full(&self) -> Result<()> {
|
||||||
cmd!("rustup run {NIGHTLY} cargo check -p ruma --features full").run().map_err(Into::into)
|
cmd!(&self.sh, "rustup run {NIGHTLY} cargo check -p ruma --features full")
|
||||||
|
.run()
|
||||||
|
.map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check all crates with all features with the nightly version.
|
/// Check all crates with all features with the nightly version.
|
||||||
@ -243,6 +256,7 @@ impl CiTask {
|
|||||||
/// Also checks that all features that are used in the code exist.
|
/// Also checks that all features that are used in the code exist.
|
||||||
fn nightly_all(&self) -> Result<()> {
|
fn nightly_all(&self) -> Result<()> {
|
||||||
cmd!(
|
cmd!(
|
||||||
|
&self.sh,
|
||||||
"
|
"
|
||||||
rustup run {NIGHTLY} cargo check
|
rustup run {NIGHTLY} cargo check
|
||||||
--workspace --all-features -Z unstable-options
|
--workspace --all-features -Z unstable-options
|
||||||
@ -259,7 +273,7 @@ impl CiTask {
|
|||||||
|
|
||||||
/// Check ruma-common with `ruma_identifiers_storage="Box"`
|
/// Check ruma-common with `ruma_identifiers_storage="Box"`
|
||||||
fn msrv_owned_id_box(&self) -> Result<()> {
|
fn msrv_owned_id_box(&self) -> Result<()> {
|
||||||
cmd!("rustup run {MSRV} cargo check -p ruma-common")
|
cmd!(&self.sh, "rustup run {MSRV} cargo check -p ruma-common")
|
||||||
.env("RUSTFLAGS", "--cfg=ruma_identifiers_storage=\"Box\"")
|
.env("RUSTFLAGS", "--cfg=ruma_identifiers_storage=\"Box\"")
|
||||||
.run()
|
.run()
|
||||||
.map_err(Into::into)
|
.map_err(Into::into)
|
||||||
@ -267,7 +281,7 @@ impl CiTask {
|
|||||||
|
|
||||||
/// Check ruma-common with `ruma_identifiers_storage="Arc"`
|
/// Check ruma-common with `ruma_identifiers_storage="Arc"`
|
||||||
fn msrv_owned_id_arc(&self) -> Result<()> {
|
fn msrv_owned_id_arc(&self) -> Result<()> {
|
||||||
cmd!("rustup run {MSRV} cargo check -p ruma-common")
|
cmd!(&self.sh, "rustup run {MSRV} cargo check -p ruma-common")
|
||||||
.env("RUSTFLAGS", "--cfg=ruma_identifiers_storage=\"Arc\"")
|
.env("RUSTFLAGS", "--cfg=ruma_identifiers_storage=\"Arc\"")
|
||||||
.run()
|
.run()
|
||||||
.map_err(Into::into)
|
.map_err(Into::into)
|
||||||
@ -276,6 +290,7 @@ impl CiTask {
|
|||||||
/// Lint default features with clippy with the nightly version.
|
/// Lint default features with clippy with the nightly version.
|
||||||
fn clippy_default(&self) -> Result<()> {
|
fn clippy_default(&self) -> Result<()> {
|
||||||
cmd!(
|
cmd!(
|
||||||
|
&self.sh,
|
||||||
"
|
"
|
||||||
rustup run {NIGHTLY} cargo clippy
|
rustup run {NIGHTLY} cargo clippy
|
||||||
--workspace --all-targets --features=full -- -D warnings
|
--workspace --all-targets --features=full -- -D warnings
|
||||||
@ -288,6 +303,7 @@ impl CiTask {
|
|||||||
/// Lint ruma with clippy with the nightly version and wasm target.
|
/// Lint ruma with clippy with the nightly version and wasm target.
|
||||||
fn clippy_wasm(&self) -> Result<()> {
|
fn clippy_wasm(&self) -> Result<()> {
|
||||||
cmd!(
|
cmd!(
|
||||||
|
&self.sh,
|
||||||
"
|
"
|
||||||
rustup run {NIGHTLY} cargo clippy --target wasm32-unknown-unknown -p ruma --features
|
rustup run {NIGHTLY} cargo clippy --target wasm32-unknown-unknown -p ruma --features
|
||||||
__unstable-mscs,api,canonical-json,client-api,events,html-matrix,identity-service-api,js,markdown,rand,signatures,unstable-unspecified -- -D warnings
|
__unstable-mscs,api,canonical-json,client-api,events,html-matrix,identity-service-api,js,markdown,rand,signatures,unstable-unspecified -- -D warnings
|
||||||
@ -301,6 +317,7 @@ impl CiTask {
|
|||||||
/// Lint almost all features with clippy with the nightly version.
|
/// Lint almost all features with clippy with the nightly version.
|
||||||
fn clippy_all(&self) -> Result<()> {
|
fn clippy_all(&self) -> Result<()> {
|
||||||
cmd!(
|
cmd!(
|
||||||
|
&self.sh,
|
||||||
"
|
"
|
||||||
rustup run {NIGHTLY} cargo clippy
|
rustup run {NIGHTLY} cargo clippy
|
||||||
--workspace --all-targets --features=__ci,compat -- -D warnings
|
--workspace --all-targets --features=__ci,compat -- -D warnings
|
||||||
@ -324,13 +341,14 @@ impl CiTask {
|
|||||||
|
|
||||||
/// Check the sorting of dependencies with the nightly version.
|
/// Check the sorting of dependencies with the nightly version.
|
||||||
fn dependencies(&self) -> Result<()> {
|
fn dependencies(&self) -> Result<()> {
|
||||||
if cmd!("cargo sort --version").run().is_err() {
|
if cmd!(&self.sh, "cargo sort --version").run().is_err() {
|
||||||
return Err(
|
return Err(
|
||||||
"Could not find cargo-sort. Install it by running `cargo install cargo-sort`"
|
"Could not find cargo-sort. Install it by running `cargo install cargo-sort`"
|
||||||
.into(),
|
.into(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
cmd!(
|
cmd!(
|
||||||
|
&self.sh,
|
||||||
"
|
"
|
||||||
rustup run {NIGHTLY} cargo sort
|
rustup run {NIGHTLY} cargo sort
|
||||||
--workspace --grouped --check
|
--workspace --grouped --check
|
||||||
@ -343,11 +361,11 @@ impl CiTask {
|
|||||||
|
|
||||||
/// Check the typos.
|
/// Check the typos.
|
||||||
fn typos(&self) -> Result<()> {
|
fn typos(&self) -> Result<()> {
|
||||||
if cmd!("typos --version").run().is_err() {
|
if cmd!(&self.sh, "typos --version").run().is_err() {
|
||||||
return Err(
|
return Err(
|
||||||
"Could not find typos. Install it by running `cargo install typos-cli`".into()
|
"Could not find typos. Install it by running `cargo install typos-cli`".into()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
cmd!("typos").run().map_err(Into::into)
|
cmd!(&self.sh, "typos").run().map_err(Into::into)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use clap::Args;
|
use clap::Args;
|
||||||
|
use xshell::Shell;
|
||||||
|
|
||||||
use crate::{cmd, Result, NIGHTLY};
|
use crate::{cmd, Result, NIGHTLY};
|
||||||
|
|
||||||
@ -20,7 +21,8 @@ impl DocTask {
|
|||||||
rustdocflags += " -Dwarnings";
|
rustdocflags += " -Dwarnings";
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut cmd = cmd!("rustup run {NIGHTLY} cargo doc --all-features --no-deps")
|
let sh = Shell::new()?;
|
||||||
|
let mut cmd = cmd!(sh, "rustup run {NIGHTLY} cargo doc --all-features --no-deps")
|
||||||
.env("RUSTDOCFLAGS", rustdocflags);
|
.env("RUSTDOCFLAGS", rustdocflags);
|
||||||
|
|
||||||
if self.open {
|
if self.open {
|
||||||
|
@ -30,6 +30,7 @@ use ci::{CiArgs, CiTask};
|
|||||||
use doc::DocTask;
|
use doc::DocTask;
|
||||||
#[cfg(feature = "default")]
|
#[cfg(feature = "default")]
|
||||||
use release::{ReleaseArgs, ReleaseTask};
|
use release::{ReleaseArgs, ReleaseTask};
|
||||||
|
use xshell::Shell;
|
||||||
|
|
||||||
type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
|
type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
|
||||||
|
|
||||||
@ -75,8 +76,8 @@ struct Metadata {
|
|||||||
|
|
||||||
impl Metadata {
|
impl Metadata {
|
||||||
/// Load a new `Metadata` from the command line.
|
/// Load a new `Metadata` from the command line.
|
||||||
pub fn load() -> Result<Metadata> {
|
pub fn load(sh: &Shell) -> Result<Metadata> {
|
||||||
let metadata_json = cmd!("cargo metadata --no-deps --format-version 1").read()?;
|
let metadata_json = cmd!(sh, "cargo metadata --no-deps --format-version 1").read()?;
|
||||||
Ok(from_json_str(&metadata_json)?)
|
Ok(from_json_str(&metadata_json)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,11 +97,11 @@ struct Config {
|
|||||||
#[cfg(feature = "default")]
|
#[cfg(feature = "default")]
|
||||||
impl Config {
|
impl Config {
|
||||||
/// Load a new `Config` from `config.toml`.
|
/// Load a new `Config` from `config.toml`.
|
||||||
fn load() -> Result<Self> {
|
fn load(sh: &Shell) -> Result<Self> {
|
||||||
use std::{env, path::Path};
|
use std::{env, path::Path};
|
||||||
|
|
||||||
let path = Path::new(&env!("CARGO_MANIFEST_DIR")).join("config.toml");
|
let path = Path::new(&env!("CARGO_MANIFEST_DIR")).join("config.toml");
|
||||||
let config = xshell::read_file(path)?;
|
let config = sh.read_file(path)?;
|
||||||
Ok(toml::from_str(&config)?)
|
Ok(toml::from_str(&config)?)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -117,7 +118,7 @@ struct GithubConfig {
|
|||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! cmd {
|
macro_rules! cmd {
|
||||||
($cmd:tt) => {
|
($sh: expr, $cmd:tt) => {
|
||||||
xshell::cmd!($cmd).echo_cmd(false)
|
xshell::cmd!($sh, $cmd).quiet()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ use clap::Args;
|
|||||||
use reqwest::{blocking::Client, StatusCode};
|
use reqwest::{blocking::Client, StatusCode};
|
||||||
use semver::Version;
|
use semver::Version;
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
|
use xshell::Shell;
|
||||||
|
|
||||||
use crate::{cargo::Package, cmd, util::ask_yes_no, GithubConfig, Metadata, Result};
|
use crate::{cargo::Package, cmd, util::ask_yes_no, GithubConfig, Metadata, Result};
|
||||||
|
|
||||||
@ -40,6 +41,9 @@ pub struct ReleaseTask {
|
|||||||
/// The github configuration required to publish a release.
|
/// The github configuration required to publish a release.
|
||||||
config: GithubConfig,
|
config: GithubConfig,
|
||||||
|
|
||||||
|
/// The shell API to use to run commands.
|
||||||
|
sh: Shell,
|
||||||
|
|
||||||
/// List the steps but don't actually change anything
|
/// List the steps but don't actually change anything
|
||||||
pub dry_run: bool,
|
pub dry_run: bool,
|
||||||
}
|
}
|
||||||
@ -47,7 +51,8 @@ pub struct ReleaseTask {
|
|||||||
impl ReleaseTask {
|
impl ReleaseTask {
|
||||||
/// Create a new `ReleaseTask` with the given `name` and `version`.
|
/// Create a new `ReleaseTask` with the given `name` and `version`.
|
||||||
pub(crate) fn new(name: String, version: Version, dry_run: bool) -> Result<Self> {
|
pub(crate) fn new(name: String, version: Version, dry_run: bool) -> Result<Self> {
|
||||||
let metadata = Metadata::load()?;
|
let sh = Shell::new()?;
|
||||||
|
let metadata = Metadata::load(&sh)?;
|
||||||
|
|
||||||
let package = metadata
|
let package = metadata
|
||||||
.packages
|
.packages
|
||||||
@ -56,11 +61,11 @@ impl ReleaseTask {
|
|||||||
.find(|p| p.name == name)
|
.find(|p| p.name == name)
|
||||||
.ok_or(format!("Package {name} not found in cargo metadata"))?;
|
.ok_or(format!("Package {name} not found in cargo metadata"))?;
|
||||||
|
|
||||||
let config = crate::Config::load()?.github;
|
let config = crate::Config::load(&sh)?.github;
|
||||||
|
|
||||||
let http_client = Client::builder().user_agent("ruma xtask").build()?;
|
let http_client = Client::builder().user_agent("ruma xtask").build()?;
|
||||||
|
|
||||||
Ok(Self { metadata, package, version, http_client, config, dry_run })
|
Ok(Self { metadata, package, version, http_client, config, sh, dry_run })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Run the task to effectively create a release.
|
/// Run the task to effectively create a release.
|
||||||
@ -81,10 +86,10 @@ impl ReleaseTask {
|
|||||||
return Err("This crate version is already released".into());
|
return Err("This crate version is already released".into());
|
||||||
}
|
}
|
||||||
|
|
||||||
let remote = Self::git_remote()?;
|
let remote = self.git_remote()?;
|
||||||
|
|
||||||
println!("Checking status of git repository…");
|
println!("Checking status of git repository…");
|
||||||
if !cmd!("git status -s -uno").read()?.is_empty()
|
if !cmd!(&self.sh, "git status -s -uno").read()?.is_empty()
|
||||||
&& !ask_yes_no("This git repository contains uncommitted changes. Continue?")?
|
&& !ask_yes_no("This git repository contains uncommitted changes. Continue?")?
|
||||||
{
|
{
|
||||||
return Ok(());
|
return Ok(());
|
||||||
@ -101,8 +106,8 @@ impl ReleaseTask {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let create_commit = if self.package.version != self.version {
|
let create_commit = if self.package.version != self.version {
|
||||||
self.package.update_version(&self.version, self.dry_run)?;
|
self.package.update_version(&self.sh, &self.version, self.dry_run)?;
|
||||||
self.package.update_dependants(&self.metadata, self.dry_run)?;
|
self.package.update_dependants(&self.sh, &self.metadata, self.dry_run)?;
|
||||||
true
|
true
|
||||||
} else if !ask_yes_no(&format!(
|
} else if !ask_yes_no(&format!(
|
||||||
"Package is already version {}. Skip creating a commit and continue?",
|
"Package is already version {}. Skip creating a commit and continue?",
|
||||||
@ -113,19 +118,19 @@ impl ReleaseTask {
|
|||||||
false
|
false
|
||||||
};
|
};
|
||||||
|
|
||||||
let changes = &self.package.changes(!prerelease && !self.dry_run)?;
|
let changes = &self.package.changes(&self.sh, !prerelease && !self.dry_run)?;
|
||||||
|
|
||||||
if create_commit {
|
if create_commit {
|
||||||
self.commit()?;
|
self.commit()?;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.package.publish(&self.http_client, self.dry_run)?;
|
self.package.publish(&self.sh, &self.http_client, self.dry_run)?;
|
||||||
|
|
||||||
let branch = cmd!("git rev-parse --abbrev-ref HEAD").read()?;
|
let branch = cmd!(&self.sh, "git rev-parse --abbrev-ref HEAD").read()?;
|
||||||
if publish_only {
|
if publish_only {
|
||||||
println!("Pushing to remote repository…");
|
println!("Pushing to remote repository…");
|
||||||
if !self.dry_run {
|
if !self.dry_run {
|
||||||
cmd!("git push {remote} {branch}").run()?;
|
cmd!(&self.sh, "git push {remote} {branch}").run()?;
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("Crate published successfully!");
|
println!("Crate published successfully!");
|
||||||
@ -135,18 +140,18 @@ impl ReleaseTask {
|
|||||||
let tag = &self.tag_name();
|
let tag = &self.tag_name();
|
||||||
|
|
||||||
println!("Creating git tag '{tag}'…");
|
println!("Creating git tag '{tag}'…");
|
||||||
if cmd!("git tag -l {tag}").read()?.is_empty() {
|
if cmd!(&self.sh, "git tag -l {tag}").read()?.is_empty() {
|
||||||
if !self.dry_run {
|
if !self.dry_run {
|
||||||
cmd!("git tag -s {tag} -m {title} -m {changes}").read()?;
|
cmd!(&self.sh, "git tag -s {tag} -m {title} -m {changes}").read()?;
|
||||||
}
|
}
|
||||||
} else if !ask_yes_no("This tag already exists. Skip this step and continue?")? {
|
} else if !ask_yes_no("This tag already exists. Skip this step and continue?")? {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("Pushing to remote repository…");
|
println!("Pushing to remote repository…");
|
||||||
if cmd!("git ls-remote --tags {remote} {tag}").read()?.is_empty() {
|
if cmd!(&self.sh, "git ls-remote --tags {remote} {tag}").read()?.is_empty() {
|
||||||
if !self.dry_run {
|
if !self.dry_run {
|
||||||
cmd!("git push {remote} {branch} {tag}").run()?;
|
cmd!(&self.sh, "git push {remote} {branch} {tag}").run()?;
|
||||||
}
|
}
|
||||||
} else if !ask_yes_no("This tag has already been pushed. Skip this step and continue?")? {
|
} else if !ask_yes_no("This tag has already been pushed. Skip this step and continue?")? {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
@ -192,9 +197,9 @@ impl ReleaseTask {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Load the GitHub config from the config file.
|
/// Load the GitHub config from the config file.
|
||||||
fn git_remote() -> Result<String> {
|
fn git_remote(&self) -> Result<String> {
|
||||||
let branch = cmd!("git rev-parse --abbrev-ref HEAD").read()?;
|
let branch = cmd!(&self.sh, "git rev-parse --abbrev-ref HEAD").read()?;
|
||||||
let remote = cmd!("git config branch.{branch}.remote").read()?;
|
let remote = cmd!(&self.sh, "git config branch.{branch}.remote").read()?;
|
||||||
|
|
||||||
if remote.is_empty() {
|
if remote.is_empty() {
|
||||||
return Err("Could not get current git remote".into());
|
return Err("Could not get current git remote".into());
|
||||||
@ -229,7 +234,7 @@ impl ReleaseTask {
|
|||||||
return Err("User aborted commit".into());
|
return Err("User aborted commit".into());
|
||||||
}
|
}
|
||||||
"d" | "diff" => {
|
"d" | "diff" => {
|
||||||
cmd!("git diff").run()?;
|
cmd!(&self.sh, "git diff").run()?;
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
println!("Unknown command.");
|
println!("Unknown command.");
|
||||||
@ -247,7 +252,7 @@ impl ReleaseTask {
|
|||||||
println!("Creating commit with message '{message}'…");
|
println!("Creating commit with message '{message}'…");
|
||||||
|
|
||||||
if !self.dry_run {
|
if !self.dry_run {
|
||||||
cmd!("git commit -a -m {message}").read()?;
|
cmd!(&self.sh, "git commit -a -m {message}").read()?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
Loading…
x
Reference in New Issue
Block a user