From d748deffadb2c2eafc62bf5add9fb31394ea9abe Mon Sep 17 00:00:00 2001 From: Bodil Stokke Date: Sun, 2 Sep 2018 23:13:33 +0100 Subject: [PATCH] Rewrite build scripts In Rust. --- .travis.yml | 5 +- Cargo.toml | 1 + Cargo.toml.in | 38 --------- Makefile | 17 ---- Makefile.toml | 196 ++++++++++++++++++++++++++++++++++++++++++++++ VERSION | 1 - build-releases.sh | 38 --------- 7 files changed, 200 insertions(+), 96 deletions(-) delete mode 100644 Cargo.toml.in delete mode 100644 Makefile create mode 100644 Makefile.toml delete mode 100644 VERSION delete mode 100755 build-releases.sh diff --git a/.travis.yml b/.travis.yml index ff017d7..76960cb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,9 +14,10 @@ env: install: - mkdir -p .cargo && echo '[build]' > .cargo/config && echo 'target-dir = "/home/travis/target"' >> .cargo/config - - ./build-releases.sh + - cargo install cargo-make + - cargo make prepare-release -script: cd dist/latest/$CRATE; cargo test +script: cd dist/$CRATE; cargo test matrix: include: diff --git a/Cargo.toml b/Cargo.toml index eb38bf5..9afc49c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,7 @@ readme = "./README.md" categories = ["data-structures"] keywords = ["immutable", "persistent", "hamt", "b-tree", "rrb-tree"] build = "./build.rs" +exclude = ["dist/**", "rc/**", "release.toml", "Makefile.toml", "proptest-regressions/**"] [lib] path = "./src/lib.rs" diff --git a/Cargo.toml.in b/Cargo.toml.in deleted file mode 100644 index 0d5d8e5..0000000 --- a/Cargo.toml.in +++ /dev/null @@ -1,38 +0,0 @@ -[package] -name = "CRATE" -version = "VERSION" -authors = ["Bodil Stokke "] -license = "MPL-2.0+" -description = "DESCRIPTION" -repository = "https://github.com/bodil/im-rs" -documentation = "http://immutable.rs/" -homepage = "http://immutable.rs/" -readme = "BASE/README.md" -categories = ["data-structures"] -keywords = ["immutable", "persistent", "hamt", "b-tree", "rrb-tree"] -build = "BASE/build.rs" - -[lib] -path = "BASE/src/lib.rs" - -[badges] -travis-ci = { repository = "bodil/im-rs" } - -[build-dependencies] -rustc_version = "0.2" - -[dependencies] -typenum = "1.10" -quickcheck = { version = "0.7", optional = true } -proptest = { version = "0.8", optional = true } -serde = { version = "1.0", optional = true } -rayon = { version = "1.0", optional = true } - -[dev-dependencies] -quickcheck = "0.7" -proptest = "0.8" -serde = "1.0" -serde_json = "1.0" -rayon = "1.0" -rand = "0.5" -pretty_assertions = "0.5" diff --git a/Makefile b/Makefile deleted file mode 100644 index f19479b..0000000 --- a/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -update-toml: Cargo.toml rc/Cargo.toml -.PHONY: update-toml - -build-releases: build-releases.sh update-toml - ./build-releases.sh -.PHONY: build-releases - -release: build-releases - cd dist/latest/im && cargo publish - cd dist/latest/im-rc && cargo publish -.PHONY: release - -Cargo.toml: Cargo.toml.in VERSION Makefile - m4 -D BASE=. -D "VERSION=$$(< VERSION)" -D CRATE=im -D DESCRIPTION="Immutable collection datatypes" $< > $@ - -rc/Cargo.toml: Cargo.toml.in VERSION Makefile - m4 -D BASE=.. -D "VERSION=$$(< VERSION)" -D CRATE=im-rc -D DESCRIPTION="Immutable collection datatypes (the fast but not thread safe version)" $< > $@ diff --git a/Makefile.toml b/Makefile.toml new file mode 100644 index 0000000..778d390 --- /dev/null +++ b/Makefile.toml @@ -0,0 +1,196 @@ +[tasks.prepare-release] +dependencies = ["copy-release", "patch-release"] + +[tasks.install-amber] +force = true +command = "cargo" +args = ["install", "-q", "amber"] + +[tasks.patch-release] +dependencies = ["install-amber"] +command = "ambr" +args = ["--no-interactive", "extern crate im", "extern crate im_rc as im", "dist/im-rc"] + +[tasks.copy-release] +dependencies = ["sync"] +script_runner = "@rust" +script = [ +''' +//! ```cargo +//! [dependencies] +//! toml_edit = "0.1" +//! fs_extra = "1.1" +//! glob = "0.2" +//! ``` +extern crate toml_edit; +extern crate fs_extra; +extern crate glob; +use std::fs; +use std::path::{Path, PathBuf}; +use toml_edit::{Document, value}; + +fn read_doc>(name: P) -> Document { + let name: &Path = name.as_ref(); + fs::read_to_string(name).expect(&format!("error reading {:?}", name)) + .parse::() + .expect(&format!("failed to parse TOML in {:?}", name)) +} + +fn make_dist(root: &Path, target: &str, manifest: &str) -> PathBuf { + let path = root.join(target); + fs::create_dir_all(&path); + let mut src = vec!["src".into(), "build.rs".into()]; + for item in glob::glob("*.md").unwrap() { + if let Ok(path) = item { + src.push(path); + } + } + fs_extra::copy_items(&src, &path, &fs_extra::dir::CopyOptions::new()) + .expect(&format!("unable to copy files to {:?} target", target)); + fs::copy(manifest, path.join("Cargo.toml")) + .expect(&format!("unable to copy Cargo.toml to {:?} target", target)); + path +} + +fn main() { + // Prepare target folder + fs::remove_dir_all("dist"); + let path = PathBuf::from("dist"); + + // Copy files into im and im-rc subfolders + make_dist(&path, "im", "Cargo.toml"); + make_dist(&path, "im-rc", "rc/Cargo.toml"); + + // Patch im-rc/Cargo.toml paths + let rc_manifest_path = path.join("im-rc/Cargo.toml"); + let mut doc = read_doc(&rc_manifest_path); + let build = value(doc["package"]["build"].as_str().unwrap()[1..].to_string()); + doc["package"]["build"] = build; + let libpath = value(doc["lib"]["path"].as_str().unwrap()[1..].to_string()); + doc["lib"]["path"] = libpath; + fs::write(&rc_manifest_path, doc.to_string()) + .expect(&format!("unable to write {:?}!", rc_manifest_path)); +} +''' +] + +[tasks.sync] +script_runner = "@rust" +script = [ +''' +//! ```cargo +//! [dependencies] +//! toml_edit = "0.1" +//! ``` +extern crate toml_edit; +use std::{env, process}; +use std::fs::{read_to_string, write}; +use toml_edit::{Document, Item, Table, Value}; + +fn read_doc(name: &str) -> Document { + read_to_string(name).expect(&format!("error reading {:?}", name)) + .parse::() + .expect(&format!("failed to parse TOML in {:?}", name)) +} + +fn compare_values(left: &Value, right: &Value) -> bool { + if left.is_integer() && (left.as_integer() == right.as_integer()) { + return true; + } + if left.is_float() && (left.as_float() == right.as_float()) { + return true; + } + if left.is_bool() && (left.as_bool() == right.as_bool()) { + return true; + } + if left.is_str() && (left.as_str() == right.as_str()) { + return true; + } + if left.is_date_time() && (left.as_date_time() == right.as_date_time()) { + return true; + } + if let (Some(left), Some(right)) = (left.as_array(), right.as_array()) { + if left.len() != right.len() { + return false; + } + for (lvalue, rvalue) in left.iter().zip(right.iter()) { + if !compare_values(lvalue, rvalue) { + return false; + } + } + return true; + } + if let (Some(left), Some(right)) = (left.as_inline_table(), right.as_inline_table()) { + if left.len() != right.len() { + return false; + } + for (key, value) in left.iter() { + if !right.contains_key(key) { + return false; + } + if !compare_values(value, &right.get(key).unwrap()) { + return false; + } + } + return true; + } + false +} + +fn compare_tables(left: &Table, right: &Table) -> bool { + if left.len() != right.len() { + return false; + } + for (key, value) in left.iter() { + if !right.contains_key(key) { + return false; + } + if !compare(value, &right[key]) { + return false; + } + } + true +} + +fn compare(left: &Item, right: &Item) -> bool { + match (left, right) { + (&Item::Value(ref left), &Item::Value(ref right)) => compare_values(left, right), + (&Item::Table(ref left), &Item::Table(ref right)) => compare_tables(left, right), + (&Item::ArrayOfTables(ref left), &Item::ArrayOfTables(ref right)) => { + if left.len() != right.len() { + return false; + } + for (ltable, rtable) in left.iter().zip(right.iter()) { + if !compare_tables(ltable, rtable) { + return false; + } + } + true + } + _ => false + } +} + +fn main() { + let args: Vec = env::args().skip(1).collect(); + let command = args.get(0).cloned().unwrap_or("sync".to_string()); + let src = read_doc("./Cargo.toml"); + let mut out = read_doc("./rc/Cargo.toml"); + if &command == "sync" { + out["package"]["version"] = src["package"]["version"].clone(); + out["dependencies"] = src["dependencies"].clone(); + out["dev-dependencies"] = src["dev-dependencies"].clone(); + out["build-dependencies"] = src["build-dependencies"].clone(); + write("./rc/Cargo.toml", out.to_string()).expect("unable to write rc/Cargo.toml!"); + } else if &command == "check" { + if !compare(&src["package"]["version"], &out["package"]["version"]) + || !compare(&src["dependencies"], &out["dependencies"]) + || !compare(&src["dev-dependencies"], &out["dev-dependencies"]) + || !compare(&src["build-dependencies"], &out["build-dependencies"]) { + eprintln!("*** ERROR: Cargo.toml files are out of sync!\n*** Please run `cargo make sync` and commit the changes."); + process::exit(1); + } + } +} +''' +] diff --git a/VERSION b/VERSION deleted file mode 100644 index 4044f90..0000000 --- a/VERSION +++ /dev/null @@ -1 +0,0 @@ -12.0.0 diff --git a/build-releases.sh b/build-releases.sh deleted file mode 100755 index e0dc4b9..0000000 --- a/build-releases.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env bash - -PROJECT_ROOT=`git rev-parse --show-toplevel` -PREVIOUS_CWD=`pwd` - -VERSION="$1" - -# If no version is given use the same -if [ "x$VERSION" == x ]; then - VERSION=$(perl -ne 'if (/^version = \"(.*)\"/) { print $1 . "\n" }' Cargo.toml) -fi - -cd $PROJECT_ROOT - -# create a release folder -rm -rf "dist/$VERSION" -mkdir -p "dist/$VERSION" -cd "dist/$VERSION" - -# create variations -for VARIATION in im im-rc; do - mkdir $VARIATION - cp -a ../../src ../../build.rs ../../README.md $VARIATION - if [ "$VARIATION" == "im-rc" ]; then - cp -a ../../rc/Cargo.toml $VARIATION - find "$VARIATION" -name '*.rs' -exec perl -pi -e "s/\bextern crate im\b/extern crate im_rc as im/g" "{}" \; - else - cp -a ../../Cargo.toml $VARIATION - fi - perl -pi -e "s/^version = \".*\"/version = \"$VERSION\"/" $VARIATION/Cargo.toml - perl -pi -e "s/\"..\//\"/g" $VARIATION/Cargo.toml -done - -# ln the latest -(cd .. && ln -fs "$VERSION" latest) - -# reset env -cd $PREVIOUS_CWD