Commit 12e1d452 authored by Jack Brown's avatar Jack Brown

fix(rust): refactor; improve updating Cargo.lock

parent 723a9586
......@@ -18,6 +18,8 @@ mod plugins {
// the plugin, lifecycle hooks, and providing a name in order to enable/disable the plugin.
pub trait Plugable {
fn name(&self) -> String;
// check is run first to determine whether a give plugin should be enabled for use
fn check(&self) -> bool;
fn prefix(&self) -> &str;
fn enable(&mut self);
......@@ -197,7 +199,7 @@ impl Verto {
current_versions.sort();
current_versions.dedup();
if current_versions.len() > 1 {
panic!("different current versions detected by different plugins");
panic!("different current versions detected by different plugins; check that all tags have been pushed, and that you've pulled the latest tags. If they still don't match, make sure that you ran a build to update any lockfiles if you bumped the version by hand somewhere");
}
let current_version = current_versions[0];
info!("==> current version: {}", &current_version.to_string());
......
......@@ -3,7 +3,6 @@ use std::path::{Path, PathBuf};
use cargo;
use git2::Error;
use log::debug;
use semver::Version;
use toml::Value;
......@@ -14,6 +13,7 @@ pub struct Plugin {
prefix: String,
enabled: Option<bool>,
manifest: Option<cargo::core::Manifest>,
lockfile: Option<toml::Value>,
}
impl Plugin {
......@@ -23,6 +23,7 @@ impl Plugin {
prefix: String::from(prefix),
enabled: None,
manifest: None,
lockfile: None,
}
}
......@@ -36,12 +37,17 @@ impl Plugin {
fn crate_name(&self) -> String {
match &self.manifest {
Some(man) => {
man.name().to_string()
}
Some(man) => man.name().to_string(),
_ => panic!("unable to read name from manifest"),
}
}
fn crate_version(&self) -> String {
match &self.manifest {
Some(man) => man.version().to_string(),
_ => panic!("unable to read version from manifest"),
}
}
}
impl crate::Plugable for Plugin {
......@@ -80,42 +86,18 @@ impl crate::Plugable for Plugin {
return false;
}
let toml = fs::read_to_string(self.toml_path()).expect("error reading Cargo.toml");
let toml = toml
.parse::<Value>()
.expect("unable to deserialize Cargo.toml");
// Get the package name from Cargo.toml
let name = toml["package"]["name"].to_string();
// Get the version from Cargo.toml
let toml_version = toml["package"]["version"].to_string();
// Get the version from Cargo.lock
let lock = fs::read_to_string(self.lock_path()).expect("error reading Cargo.lock");
let lock = lock
.parse::<Value>()
.expect("unable to deserialize Cargo.lock");
let mut lock_version = String::from("");
for pkg in lock["package"].as_array().unwrap() {
if pkg["name"].to_string() == name {
lock_version = pkg["version"].to_string();
break;
}
}
if lock_version != toml_version {
panic!(
"Cargo.toml has version {}, but Cargo.lock is at version {}",
toml_version, lock_version
);
}
true
}
fn init(&mut self, _branch: &Option<String>) -> Result<(), Error> {
// Read the lockfile
let lock = fs::read_to_string(self.lock_path()).expect("error reading Cargo.lock");
self.lockfile = Some(
lock.parse::<Value>()
.expect("unable to deserialize Cargo.lock"),
);
// Create a default (global) cargo config object, using the defaults
let cfg = cargo::Config::default().unwrap();
......@@ -135,40 +117,43 @@ impl crate::Plugable for Plugin {
match manifest {
cargo::core::EitherManifest::Real(man) => {
self.manifest = Some(man);
Ok(())
}
_ => Err(Error::from_str("unable to parse manifest")),
}
}
fn current_version(&self) -> Option<Version> {
// Create a default (global) cargo config object, using the defaults
let cfg = cargo::Config::default().unwrap();
_ => {
return Err(Error::from_str("unable to parse manifest"))
}
};
// Create a new workspace for the target project, with default configs
let ws = cargo::core::Workspace::new(&self.toml_path(), &cfg).unwrap();
// Get the lockfile for the project/workspace
let lockfile = cargo::ops::load_pkg_lockfile(&ws).unwrap().unwrap();
// Get the lock version for the package with the same name as the crate name
// (Basically, figure out at what version the package is locked. If there's a mismatch
// between the lock version and the Cargo.toml version, it probably means someone bumped
// the version without using verto and didn't run a build)
debug!("package name: {:?}", &self.crate_name());
let lock_version = lockfile.query(&self.crate_name()).unwrap().version();
// Get the package name from Cargo.toml
let name = self.crate_name();
match &self.manifest {
Some(man) => {
let toml_version = man.version();
debug!("crate version: {:?}", &toml_version);
// Get the version from Cargo.toml
let toml_version = self.crate_version();
if lock_version != toml_version {
return None;
// Get the version from Cargo.lock
match &self.lockfile {
Some(l) => {
for pkg in l["package"].as_array().unwrap() {
if pkg["name"].to_string() == name {
if toml_version != pkg["version"].to_string() {
return Err(Error::from_str(&format!(
"Cargo.toml has version {}, but Cargo.lock is at version {}",
toml_version,
pkg["version"].to_string()
)));
}
}
}
Some(Version::parse(&toml_version.to_string()).unwrap())
}
None => None,
_ => {
return Err(Error::from_str("lockfile is None"))
}
}
Ok(())
}
fn current_version(&self) -> Option<Version> {
Some(Version::parse(&self.crate_version()).unwrap())
}
fn write(&self, version: &str) -> Vec<PathBuf> {
......@@ -178,46 +163,21 @@ impl crate::Plugable for Plugin {
.parse::<Value>()
.expect("unable to deserialize Cargo.toml");
// Get the package name from Cargo.toml
let name = config["package"]["name"].to_string();
config["package"]["version"] = Value::String(version.to_string());
// Serialize the Cargo.toml back to a string
let config = toml::ser::to_string_pretty(&config).unwrap();
// Write the file to disk
fs::write(self.toml_path(), &config).expect("error writing Cargo.toml");
// Update Cargo.lock
// Read the lockfile
let lock = fs::read_to_string(self.lock_path()).expect("error reading Cargo.lock");
let mut lock = lock
.parse::<Value>()
.expect("unable to deserialize Cargo.lock");
// Iterate through the packages, and update the version of the current package
for pkg in lock["package"].as_array_mut().unwrap() {
if pkg["name"].to_string() == name {
pkg["version"] = Value::String(version.to_string());
break;
}
}
// Serialize the lock object back to a string
let lock = toml::ser::to_string_pretty(&lock).unwrap();
// Write it to the lockfile
fs::write(self.lock_path(), &lock).expect("error writing Cargo.lock");
// Use the cargo crate to read/write the lockfile to fix formatting
// This is a hack where we just read the lockfile, then write it back to disk using the
// cargo crate's utilities.
// TODO: Somehow update the lockfile via the cargo crate, to avoid this hackery
let cfg = cargo::util::config::Config::default().unwrap();
let ws = cargo::core::Workspace::new(&self.toml_path(), &cfg).unwrap();
let lockfile = cargo::ops::load_pkg_lockfile(&ws).unwrap().unwrap();
let (_, resolve) = cargo::ops::resolve_ws(&ws).unwrap();
// Write the lockfile back to disk
cargo::ops::write_pkg_lockfile(&ws, &lockfile).unwrap();
cargo::ops::write_pkg_lockfile(&ws, &resolve).unwrap();
vec![self.toml_path(), self.lock_path()]
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment