diff options
author | Toby Vincent <tobyv@tobyvin.dev> | 2023-07-15 18:34:02 -0500 |
---|---|---|
committer | Toby Vincent <tobyv@tobyvin.dev> | 2023-07-15 18:34:02 -0500 |
commit | 74793d28cf25ea1cd6203bdc8e27a265175be1c1 (patch) | |
tree | c8fe9934fc6015589bfcadb93a6035d46356bdcd /xtask/src | |
parent | fea9dd1a69968e5857d85f3466f3f9f4d302a17f (diff) |
build: move PKGBUILDs into seperate reposdevelop
Diffstat (limited to 'xtask/src')
-rw-r--r-- | xtask/src/main.rs | 193 |
1 files changed, 143 insertions, 50 deletions
diff --git a/xtask/src/main.rs b/xtask/src/main.rs index 76fca16..42ff2cf 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -6,20 +6,20 @@ //! This binary is integrated into the `cargo` command line by using an alias in //! `.cargo/config`. -use std::path::{Path, PathBuf}; -use std::{fs::File, process::Command}; +use std::{fs::File, io::Write, process::Command}; +use std::{ + io::{BufReader, BufWriter, Read}, + path::{Path, PathBuf}, +}; use anyhow::{anyhow, bail, ensure, Context, Result}; use build_info::BuildInfo; -use bump::{Bump, Level}; -use clap::{Parser, Subcommand}; +use clap::{Parser, Subcommand, ValueEnum}; use flate2::{write::GzEncoder, Compression}; use once_cell::sync::Lazy; -use semver::Version; +use semver::{Prerelease, Version}; use tar::Builder; -mod bump; - const PKG_NAME: &str = "projectr"; const PKG_VER: &str = env!("CARGO_PKG_VERSION"); const PKG_INCLUDE: &[&str] = &[ @@ -34,28 +34,19 @@ fn main() -> Result<()> { match cli.command { Commands::OutDir => println!("{}", out_dir()?.display()), - Commands::Version => match version(cli.pre_release) { + Commands::Version => match version(cli.force) { Ok(v) => println!("{v}"), Err(_) => std::process::exit(1), }, Commands::Dist => { - let version = version(cli.pre_release)?; + let version = version(cli.force)?; let targz = generate_tar_gz(version)?; println!("{}", targz.display()); } - Commands::Release { level } => { - let Bump { prev, next } = release(level, cli.pre_release)?; - - println!("Bumped version: {prev} -> {next}"); - println!(); - println!("Create release commit:"); - println!("git commit -m 'chore: release projectr version {next}'"); - println!(); - println!("Create release tag:"); - println!("git shortlog v{prev}..HEAD | git tag -s v{next} --file -"); - println!(); - println!("Push refs:"); - println!("git push --follow-tags"); + Commands::Bump { level, pre_release } => { + let prev = version(cli.force)?; + let next = bump(prev, level, pre_release)?; + println!("{next}"); } }; @@ -65,9 +56,9 @@ fn main() -> Result<()> { #[derive(Debug, Clone, Parser)] #[command(author, version, about)] struct Cli { - /// Disable version/git tag check and appends `-dev` to the version - #[arg(short, long, global = true, required = false)] - pre_release: bool, + /// Disable version/git tag check + #[arg(short, long, global = true)] + force: bool, #[command(subcommand)] command: Commands, @@ -84,17 +75,43 @@ enum Commands { /// Generate distributable package. Dist, - /// Automation for create a new release. - Release { - /// Level of version bump. - #[arg(required = false)] - level: bump::Level, + /// Bump the version and update version dependant locations in files. + Bump { + /// SemVer field to increment. + #[arg(value_enum, required = false)] + level: Level, + /// Set pre-release field. + #[arg(short, long)] + pre_release: Option<Prerelease>, }, } -fn version(pre_release: bool) -> Result<String> { +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, ValueEnum)] +pub enum Level { + Major, + Minor, + #[default] + Patch, +} + +impl std::str::FromStr for Level { + type Err = anyhow::Error; + + fn from_str(s: &str) -> std::result::Result<Self, Self::Err> { + match s.to_lowercase().as_str() { + "major" => Ok(Level::Major), + "minor" => Ok(Level::Minor), + "patch" => Ok(Level::Patch), + s => Err(anyhow::anyhow!("Invalid bump level: {s}")), + } + } +} + +fn version(force: bool) -> Result<Version> { use build_info::VersionControl::Git; + let version: Version = PKG_VER.parse()?; + let BuildInfo { version_control: Some(Git(git)), .. @@ -102,10 +119,8 @@ fn version(pre_release: bool) -> Result<String> { bail!("Failed to get version control info."); }; - if pre_release { - Ok(format!("{PKG_VER}-dev")) - } else if git.tags.contains(&format!("v{PKG_VER}")) { - Ok(PKG_VER.to_owned()) + if force || git.tags.contains(&format!("v{version}")) { + Ok(version) } else { Err(anyhow!("Failed to find git tag matching package version.")) } @@ -136,7 +151,7 @@ fn out_dir() -> Result<PathBuf> { .context("Failed to find `out` directory for latest build") } -fn generate_tar_gz(version: String) -> Result<PathBuf> { +fn generate_tar_gz(version: Version) -> Result<PathBuf> { let target = build_info::format!("{}", $.target.triple); let dist_pkg = DIST_DIR.join(format!("{PKG_NAME}-v{version}-{target}.tar.gz")); @@ -181,22 +196,22 @@ fn build_binary() -> Result<PathBuf> { Ok(binary) } -pub fn release(level: Level, pre_release: bool) -> Result<Bump> { - let prev = PKG_VER.parse().unwrap_or_else(|_| Version::new(0, 1, 0)); - let mut next = level.bump(&prev); +fn bump(prev: Version, level: Level, pre_release: Option<Prerelease>) -> Result<Version> { + let mut next = prev.clone(); - if pre_release { - next.pre = semver::Prerelease::new("dev")? - } + match level { + Level::Major => next.major += 1, + Level::Minor => next.minor += 1, + Level::Patch => next.patch += 1, + }; - let bump = Bump { next, prev }; + if let Some(pre) = pre_release { + next.pre = pre; + } - bump.bump_file("./Cargo.toml", bump::cargo)?; - bump.bump_file("./README.md", bump::replace)?; - bump.bump_file("./CHANGELOG.md", bump::changelog)?; - bump.bump_file("./pkg/archlinux/projectr/PKGBUILD", bump::replace)?; - bump.bump_file("./pkg/archlinux/projectr-bin/PKGBUILD", bump::replace)?; - bump.bump_file("./pkg/archlinux/projectr-git/PKGBUILD", bump::vsc_pkgbuild)?; + bump_cargo(&next)?; + bump_readme(&prev, &next)?; + bump_changelog(&next)?; let cargo_update = Command::new("cargo") .arg("update") @@ -210,7 +225,85 @@ pub fn release(level: Level, pre_release: bool) -> Result<Bump> { .status()?; anyhow::ensure!(git_added.success(), "Failed to add Cargo.lock to git"); - Ok(bump) + Ok(next) +} + +fn bump_readme(prev: &Version, next: &Version) -> Result<()> { + bump_file("./README.md", |contents| { + Ok(contents.replace(&prev.to_string(), &next.to_string())) + }) +} + +fn bump_changelog(next: &Version) -> Result<()> { + bump_file("./CHANGELOG.md", |contents| { + let date = chrono::Utc::now().format("%Y-%m-%d"); + + let lines: Vec<String> = contents + .lines() + .flat_map(|line| { + if line.starts_with("## [Unreleased]") { + vec![ + line.to_owned(), + "".to_owned(), + format!("## [{next}] - {date}"), + ] + } else if line.starts_with("[Unreleased]: ") { + vec![ + line.to_owned(), + line.replace("[Unreleased]", &format!("[{next}]")) + .replace("HEAD", &format!("v{next}")), + ] + } else { + vec![line.to_owned()] + } + }) + .collect(); + + Ok(lines.join("\n")) + }) +} + +fn bump_cargo(next: &Version) -> Result<()> { + bump_file("./Cargo.toml", |contents| { + let mut cargo_toml: toml_edit::Document = contents.parse()?; + + if cargo_toml["package"]["version"]["workspace"] + .as_bool() + .unwrap_or_default() + { + cargo_toml["workspace"]["package"]["version"] = toml_edit::value(next.to_string()); + } else if cargo_toml["package"]["version"].is_str() { + cargo_toml["package"]["version"] = toml_edit::value(next.to_string()); + } else { + anyhow::bail!("Failed to find version in Cargo.toml"); + }; + + Ok(cargo_toml.to_string()) + }) +} + +fn bump_file<P, F>(path: P, mutator: F) -> Result<()> +where + P: AsRef<Path>, + F: Fn(String) -> Result<String>, +{ + let path = path.as_ref(); + + let mut reader = BufReader::new(File::open(path)?); + let mut buf = String::new(); + reader.read_to_string(&mut buf)?; + + let buf = mutator(buf)?; + + let mut writer = BufWriter::new(File::open(path)?); + writer.write_all(buf.as_bytes())?; + writer.flush()?; + + let git_added = Command::new("git").arg("add").arg(path).status()?; + + anyhow::ensure!(git_added.success(), "Failed to add bumped files to git"); + + Ok(()) } static PROJECT_ROOT: Lazy<PathBuf> = Lazy::new(|| { |