From 69add611742962eefce4372f056c2289ac4416bf Mon Sep 17 00:00:00 2001 From: NikVolf Date: Sun, 10 Apr 2016 16:12:20 +0300 Subject: [PATCH 1/4] basic upgrade scenario --- Cargo.lock | 1 + Cargo.toml | 2 +- parity/main.rs | 2 ++ parity/upgrade.rs | 84 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 parity/upgrade.rs diff --git a/Cargo.lock b/Cargo.lock index f0f64af94..4a8e6002b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -22,6 +22,7 @@ dependencies = [ "rpassword 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "semver 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/Cargo.toml b/Cargo.toml index 3fe923db7..2f0d0789c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,7 +29,7 @@ ethminer = { path = "miner" } ethcore-devtools = { path = "devtools" } ethcore-rpc = { path = "rpc", optional = true } ethcore-webapp = { path = "webapp", optional = true } - +semver = "0.2" [dependencies.hyper] version = "0.8" diff --git a/parity/main.rs b/parity/main.rs index 8ee9c6f63..b605a9dd4 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -36,6 +36,7 @@ extern crate daemonize; extern crate time; extern crate number_prefix; extern crate rpassword; +extern crate semver; // for price_info.rs #[macro_use] extern crate hyper; @@ -71,6 +72,7 @@ use rpc::Server as RpcServer; use webapp::Listening as WebappServer; mod price_info; +mod upgrade; fn die_with_message(msg: &str) -> ! { println!("ERROR: {}", msg); diff --git a/parity/upgrade.rs b/parity/upgrade.rs new file mode 100644 index 000000000..22ef4a571 --- /dev/null +++ b/parity/upgrade.rs @@ -0,0 +1,84 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +//! Parity upgrade logic + +use semver::Version; +use std::collections::*; +use std::path::*; + +struct Error; + +const CURRENT_VERSION: &'static str = env!("CARGO_PKG_VERSION"); + +#[derive(Hash, PartialEq, Eq)] +struct UpgradeKey { + pub old_version: Version, + pub new_version: Version, +} + +type UpgradeList = HashMap Result<(), Error>>; + +impl UpgradeKey { + // given the following config exist + // ver.lock 1.1 (`previous_version`) + // + // current_version 1.4 (`current_version`) + // + // + //upgrades (set of `UpgradeKey`) + // 1.0 -> 1.1 (u1) + // 1.1 -> 1.2 (u2) + // 1.2 -> 1.3 (u3) + // 1.3 -> 1.4 (u4) + // 1.4 -> 1.5 (u5) + // + // then the following upgrades should be applied: + // u2, u3, u4 + fn is_applicable(&self, previous_version: &Version, current_version: &Version) -> bool { + self.old_version >= *previous_version && self.new_version <= *current_version + } +} + +// dummy upgrade (remove when the first one is in) +fn dummy_upgrade() -> Result<(), Error> { + Ok(()) +} + +fn push_updrades(upgrades: &mut UpgradeList) +{ + // dummy upgrade (remove when the first one is in) + upgrades.insert( + UpgradeKey { old_version: Version::parse("1.0.0").unwrap(), new_version: Version::parse("99.99.0").unwrap() }, + dummy_upgrade); +} + +fn upgrade_from_version(previous_version: &Version) -> Result { + let mut upgrades = HashMap::new(); + push_updrades(&mut upgrades); + + let current_version = Version::parse(CURRENT_VERSION).unwrap(); + + let mut count = 0; + for upgrade_key in upgrades.keys() { + if upgrade_key.is_applicable(previous_version, ¤t_version) { + let upgrade_script = upgrades[upgrade_key]; + try!(upgrade_script()); + count = count + 1; + } + } + Ok(count) +} From d3411a50a4ed056e33361d5f66c1476523f8b67d Mon Sep 17 00:00:00 2001 From: NikVolf Date: Sun, 10 Apr 2016 16:42:33 +0300 Subject: [PATCH 2/4] locked ver.lock upgrade --- parity/upgrade.rs | 47 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/parity/upgrade.rs b/parity/upgrade.rs index 22ef4a571..50861fa91 100644 --- a/parity/upgrade.rs +++ b/parity/upgrade.rs @@ -19,8 +19,14 @@ use semver::Version; use std::collections::*; use std::path::*; +use std::fs::File; +use std::env; +use std::io::{Read, Write}; -struct Error; +pub enum Error { + CannotLockVersionFile, + CannotUpdateVersionFile, +} const CURRENT_VERSION: &'static str = env!("CARGO_PKG_VERSION"); @@ -82,3 +88,42 @@ fn upgrade_from_version(previous_version: &Version) -> Result { } Ok(count) } + +fn with_locked_version(script: F) -> Result + where F: Fn(&Version) -> Result +{ + let mut path = env::home_dir().expect("Applications should have a home dir"); + path.push(".parity"); + path.push("ver.lock"); + + let version: Option = { + match File::open(&path) { + Ok(mut file) => { + let mut version_string = String::new(); + match file.read_to_string(&mut version_string) { + Ok(_) => Some(Version::parse(&version_string).unwrap()), + Err(_) => None + } + }, + Err(_) => None + } + }; + let effective_version = version.unwrap_or_else(|| Version::parse("0.9.0").unwrap()); + + let script_result = { + let mut lock = try!(File::create(&path).map_err(|_| Error::CannotLockVersionFile)); + let result = script(&effective_version); + + let written_version = Version::parse(CURRENT_VERSION).unwrap(); + try!(lock.write_all(written_version.to_string().as_bytes()).map_err(|_| Error::CannotUpdateVersionFile)); + result + }; + + script_result +} + +pub fn upgrade() -> Result { + with_locked_version(|ver| { + upgrade_from_version(ver) + }) +} From 26e23da4c017c67fa836a2faa9c99ef7d505fd15 Mon Sep 17 00:00:00 2001 From: NikVolf Date: Sun, 10 Apr 2016 17:15:40 +0300 Subject: [PATCH 3/4] some newver/oldver logics --- parity/main.rs | 11 +++++++++++ parity/upgrade.rs | 5 +++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/parity/main.rs b/parity/main.rs index b605a9dd4..d625b9ef7 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -780,6 +780,17 @@ fn die_with_io_error(e: std::io::Error) -> ! { } fn main() { + match ::upgrade::upgrade() { + Ok(upgrades_applied) => { + if upgrades_applied > 0 { + println!("Executed {} upgrade scripts - ok", upgrades_applied); + } + }, + Err(e) => { + die!("Error upgrading parity data: {:?}", e); + } + } + Configuration::parse().execute(); } diff --git a/parity/upgrade.rs b/parity/upgrade.rs index 50861fa91..0b41b5892 100644 --- a/parity/upgrade.rs +++ b/parity/upgrade.rs @@ -18,11 +18,11 @@ use semver::Version; use std::collections::*; -use std::path::*; use std::fs::File; use std::env; use std::io::{Read, Write}; +#[derive(Debug)] pub enum Error { CannotLockVersionFile, CannotUpdateVersionFile, @@ -61,6 +61,7 @@ impl UpgradeKey { // dummy upgrade (remove when the first one is in) fn dummy_upgrade() -> Result<(), Error> { + println!("Adding ver.lock"); Ok(()) } @@ -68,7 +69,7 @@ fn push_updrades(upgrades: &mut UpgradeList) { // dummy upgrade (remove when the first one is in) upgrades.insert( - UpgradeKey { old_version: Version::parse("1.0.0").unwrap(), new_version: Version::parse("99.99.0").unwrap() }, + UpgradeKey { old_version: Version::parse("0.9.0").unwrap(), new_version: Version::parse("1.0.0").unwrap() }, dummy_upgrade); } From 8ecbb53e99133d89c7046efd0ab6c309278744d4 Mon Sep 17 00:00:00 2001 From: NikVolf Date: Tue, 12 Apr 2016 06:19:15 +0300 Subject: [PATCH 4/4] reducing code --- parity/upgrade.rs | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/parity/upgrade.rs b/parity/upgrade.rs index 0b41b5892..c9c98e174 100644 --- a/parity/upgrade.rs +++ b/parity/upgrade.rs @@ -97,23 +97,19 @@ fn with_locked_version(script: F) -> Result path.push(".parity"); path.push("ver.lock"); - let version: Option = { - match File::open(&path) { - Ok(mut file) => { + let version = + File::open(&path).ok().and_then(|ref mut file| + { let mut version_string = String::new(); - match file.read_to_string(&mut version_string) { - Ok(_) => Some(Version::parse(&version_string).unwrap()), - Err(_) => None - } - }, - Err(_) => None - } - }; - let effective_version = version.unwrap_or_else(|| Version::parse("0.9.0").unwrap()); + file.read_to_string(&mut version_string) + .ok() + .and_then(|_| Version::parse(&version_string).ok()) + }) + .unwrap_or_else(|| Version::parse("0.9.0").unwrap()); let script_result = { let mut lock = try!(File::create(&path).map_err(|_| Error::CannotLockVersionFile)); - let result = script(&effective_version); + let result = script(&version); let written_version = Version::parse(CURRENT_VERSION).unwrap(); try!(lock.write_all(written_version.to_string().as_bytes()).map_err(|_| Error::CannotUpdateVersionFile));