Skip to content

Commit 43b417b

Browse files
authored
Prepare release v0.14.0 "Hakuna Matata" 🐗 🦁 (#3594)
1 parent de94867 commit 43b417b

File tree

7 files changed

+193
-23
lines changed

7 files changed

+193
-23
lines changed

CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,18 @@
2929

3030
### Added
3131

32+
### Changed
33+
34+
### Removed
35+
36+
### Fixed
37+
38+
## Forest v0.14.0 "Hakuna Matata"
39+
40+
### Breaking
41+
42+
### Added
43+
3244
- [#3422](https://github.com/ChainSafe/forest/issues/3422) Add NV21 (Watermelon)
3345
support for calibration network.
3446

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "forest-filecoin"
3-
version = "0.13.0"
3+
version = "0.14.0"
44
authors = ["ChainSafe Systems <[email protected]>"]
55
repository = "https://github.com/ChainSafe/forest"
66
edition = "2021"

src/db/migration/migration_map.rs

Lines changed: 50 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,14 @@ use semver::Version;
1616
use tracing::info;
1717

1818
use super::v0_12_1::Migration0_12_1_0_13_0;
19+
use super::void_migration::MigrationVoid;
1920

2021
/// Migration trait. It is expected that the [`MigrationOperation::migrate`] method will pick up the relevant database
2122
/// existing under `chain_data_path` and create a new migration database in the same directory.
2223
pub(super) trait MigrationOperation {
24+
fn new(from: Version, to: Version) -> Self
25+
where
26+
Self: Sized;
2327
/// Performs pre-migration checks. This is the place to check if the database is in a valid
2428
/// state and if the migration can be performed. Note that some of the higher-level checks
2529
/// (like checking if the database exists) are performed by the [`Migration`].
@@ -32,6 +36,8 @@ pub(super) trait MigrationOperation {
3236
/// Performs post-migration checks. This is the place to check if the migration database is
3337
/// ready to be used by Forest and renamed into a versioned database.
3438
fn post_checks(&self, chain_data_path: &Path) -> anyhow::Result<()>;
39+
/// Returns the name of the temporary database that will be created during the migration.
40+
fn temporary_db_name(&self) -> String;
3541
}
3642

3743
/// Migrations map. The key is the starting version and the value is the tuple of the target version
@@ -48,15 +54,18 @@ type MigrationsMap = MultiMap<Version, (Version, Migrator)>;
4854
/// The usage is:
4955
/// `<FROM version> -> <TO version> @ <Migrator object>`
5056
macro_rules! create_migrations {
51-
($($from:literal -> $to:literal @ $migration:path),* $(,)?) => {
57+
($($from:literal -> $to:literal @ $migration:tt),* $(,)?) => {
5258
pub(super) static MIGRATIONS: Lazy<MigrationsMap> = Lazy::new(|| {
5359
MigrationsMap::from_iter(
5460
[
5561
$((
5662
Version::from_str($from).unwrap(),
5763
(
5864
Version::from_str($to).unwrap(),
59-
Arc::new($migration) as _,
65+
Arc::new($migration::new(
66+
$from.parse().expect("invalid <from> version"),
67+
$to.parse().expect("invalid <to> version")))
68+
as _,
6069
)),
6170
)*
6271
]
@@ -68,6 +77,7 @@ pub(super) static MIGRATIONS: Lazy<MigrationsMap> = Lazy::new(|| {
6877

6978
create_migrations!(
7079
"0.12.1" -> "0.13.0" @ Migration0_12_1_0_13_0,
80+
"0.13.0" -> "0.14.0" @ MigrationVoid,
7181
);
7282

7383
pub struct Migration {
@@ -259,6 +269,17 @@ mod tests {
259269
fn post_checks(&self, _chain_data_path: &Path) -> anyhow::Result<()> {
260270
Ok(())
261271
}
272+
273+
fn new(_from: Version, _to: Version) -> Self
274+
where
275+
Self: Sized,
276+
{
277+
Self {}
278+
}
279+
280+
fn temporary_db_name(&self) -> String {
281+
"".into()
282+
}
262283
}
263284

264285
#[test]
@@ -385,37 +406,54 @@ mod tests {
385406
}
386407
}
387408

388-
struct SimpleMigration0_1_0_0_2_0;
409+
struct SimpleMigration0_1_0_0_2_0 {
410+
from: Version,
411+
to: Version,
412+
}
389413

390414
impl MigrationOperation for SimpleMigration0_1_0_0_2_0 {
391415
fn pre_checks(&self, chain_data_path: &Path) -> anyhow::Result<()> {
392-
let path = chain_data_path.join("0.1.0");
416+
let path = chain_data_path.join(self.from.to_string());
393417
if !path.exists() {
394-
anyhow::bail!("0.1.0 does not exist");
418+
anyhow::bail!("{} does not exist", self.from);
395419
}
396420
Ok(())
397421
}
398422

399423
fn migrate(&self, chain_data_path: &Path) -> anyhow::Result<PathBuf> {
400-
fs::create_dir(chain_data_path.join("migration_0_1_0_0_2_0")).unwrap();
401-
Ok(chain_data_path.join("migration_0_1_0_0_2_0"))
424+
let temp_db_path = chain_data_path.join(self.temporary_db_name());
425+
fs::create_dir(&temp_db_path).unwrap();
426+
Ok(temp_db_path)
402427
}
403428

404429
fn post_checks(&self, chain_data_path: &Path) -> anyhow::Result<()> {
405-
let path = chain_data_path.join("migration_0_1_0_0_2_0");
430+
let path = chain_data_path.join(self.temporary_db_name());
406431
if !path.exists() {
407-
anyhow::bail!("migration_0_1_0_0_2_0 does not exist");
432+
anyhow::bail!("{} does not exist", path.display());
408433
}
409434
Ok(())
410435
}
436+
437+
fn new(from: Version, to: Version) -> Self
438+
where
439+
Self: Sized,
440+
{
441+
Self { from, to }
442+
}
443+
444+
fn temporary_db_name(&self) -> String {
445+
format!("migration_{}_{}", self.from, self.to).replace('.', "_")
446+
}
411447
}
412448

413449
#[test]
414450
fn test_migration_map_migration() {
451+
let from = Version::new(0, 1, 0);
452+
let to = Version::new(0, 2, 0);
415453
let migration = Migration {
416-
from: Version::new(0, 1, 0),
417-
to: Version::new(0, 2, 0),
418-
migrator: Arc::new(SimpleMigration0_1_0_0_2_0),
454+
from: from.clone(),
455+
to: to.clone(),
456+
migrator: Arc::new(SimpleMigration0_1_0_0_2_0::new(from, to)),
419457
};
420458

421459
let temp_dir = TempDir::new().unwrap();

src/db/migration/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@
44
mod db_migration;
55
mod migration_map;
66
mod v0_12_1;
7+
mod void_migration;
78

89
pub use db_migration::DbMigration;

src/db/migration/v0_12_1.rs

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,16 @@
99
//! coming from the rolling database and ParityDb.
1010
1111
use fs_extra::dir::CopyOptions;
12+
use semver::Version;
1213
use std::path::{Path, PathBuf};
1314
use tracing::info;
1415

1516
use super::migration_map::MigrationOperation;
1617

17-
#[derive(Default)]
18-
pub(super) struct Migration0_12_1_0_13_0;
19-
20-
/// Temporary database path for the migration.
21-
const MIGRATION_DB_0_12_1_0_13_0: &str = "migration_0_12_1_to_0_13_0";
18+
pub(super) struct Migration0_12_1_0_13_0 {
19+
from: Version,
20+
to: Version,
21+
}
2222

2323
/// Migrates the database from version 0.12.1 to 0.13.0
2424
/// This migration is needed because the `Settings` column in the `ParityDb` table changed to
@@ -29,9 +29,9 @@ impl MigrationOperation for Migration0_12_1_0_13_0 {
2929
}
3030

3131
fn migrate(&self, chain_data_path: &Path) -> anyhow::Result<PathBuf> {
32-
let source_db = chain_data_path.join("0.12.1");
32+
let source_db = chain_data_path.join(self.from.to_string());
3333

34-
let temp_db_path = chain_data_path.join(MIGRATION_DB_0_12_1_0_13_0);
34+
let temp_db_path = chain_data_path.join(self.temporary_db_name());
3535
if temp_db_path.exists() {
3636
info!(
3737
"removing old temporary database {temp_db_path}",
@@ -137,14 +137,26 @@ impl MigrationOperation for Migration0_12_1_0_13_0 {
137137
}
138138

139139
fn post_checks(&self, chain_data_path: &Path) -> anyhow::Result<()> {
140-
if !chain_data_path.join(MIGRATION_DB_0_12_1_0_13_0).exists() {
140+
let temp_db_name = self.temporary_db_name();
141+
if !chain_data_path.join(&temp_db_name).exists() {
141142
anyhow::bail!(
142143
"migration database {} does not exist",
143-
chain_data_path.join(MIGRATION_DB_0_12_1_0_13_0).display()
144+
chain_data_path.join(temp_db_name).display()
144145
);
145146
}
146147
Ok(())
147148
}
149+
150+
fn new(from: Version, to: Version) -> Self
151+
where
152+
Self: Sized,
153+
{
154+
Self { from, to }
155+
}
156+
157+
fn temporary_db_name(&self) -> String {
158+
format!("migration_{}_{}", self.from, self.to).replace('.', "_")
159+
}
148160
}
149161

150162
/// Database settings from Forest `v0.12.1`

src/db/migration/void_migration.rs

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
// Copyright 2019-2023 ChainSafe Systems
2+
// SPDX-License-Identifier: Apache-2.0, MIT
3+
4+
//! Migration logic from any version that requires no migration logic.
5+
6+
use fs_extra::dir::CopyOptions;
7+
use semver::Version;
8+
use std::path::{Path, PathBuf};
9+
use tracing::info;
10+
11+
use super::migration_map::MigrationOperation;
12+
13+
pub(super) struct MigrationVoid {
14+
from: Version,
15+
to: Version,
16+
}
17+
18+
impl MigrationOperation for MigrationVoid {
19+
fn pre_checks(&self, _chain_data_path: &Path) -> anyhow::Result<()> {
20+
Ok(())
21+
}
22+
23+
fn migrate(&self, chain_data_path: &Path) -> anyhow::Result<PathBuf> {
24+
let source_db = chain_data_path.join(self.from.to_string());
25+
26+
let temp_db_path = chain_data_path.join(self.temporary_db_name());
27+
if temp_db_path.exists() {
28+
info!(
29+
"removing old temporary database {temp_db_path}",
30+
temp_db_path = temp_db_path.display()
31+
);
32+
std::fs::remove_dir_all(&temp_db_path)?;
33+
}
34+
35+
info!(
36+
"copying old database from {source_db} to {temp_db_path}",
37+
source_db = source_db.display(),
38+
temp_db_path = temp_db_path.display()
39+
);
40+
fs_extra::copy_items(
41+
&[source_db.as_path()],
42+
temp_db_path.clone(),
43+
&CopyOptions::default().copy_inside(true),
44+
)?;
45+
46+
Ok(temp_db_path)
47+
}
48+
49+
fn post_checks(&self, chain_data_path: &Path) -> anyhow::Result<()> {
50+
let temp_db_name = self.temporary_db_name();
51+
if !chain_data_path.join(&temp_db_name).exists() {
52+
anyhow::bail!(
53+
"migration database {} does not exist",
54+
chain_data_path.join(temp_db_name).display()
55+
);
56+
}
57+
Ok(())
58+
}
59+
60+
fn new(from: Version, to: Version) -> Self
61+
where
62+
Self: Sized,
63+
{
64+
Self { from, to }
65+
}
66+
67+
fn temporary_db_name(&self) -> String {
68+
format!("migration_{}_{}", self.from, self.to).replace('.', "_")
69+
}
70+
}
71+
72+
#[cfg(test)]
73+
mod test {
74+
use super::*;
75+
use semver::Version;
76+
use tempfile::TempDir;
77+
78+
#[test]
79+
fn test_migration_void() {
80+
let migration = MigrationVoid::new(Version::new(1, 0, 0), Version::new(1, 0, 1));
81+
let chain_data_path = TempDir::new().unwrap();
82+
83+
// create a file in the temporary database directory, under a directory (to ensure that the
84+
// directory is copied recursively).
85+
let content_dir = chain_data_path.path().join("1.0.0").join("R'lyeh");
86+
std::fs::create_dir_all(&content_dir).unwrap();
87+
88+
let content_file = content_dir.join("cthulhu");
89+
let chant = "ph'nglui mglw'nafh Cthulhu R'lyeh wgah'nagl fhtagn";
90+
std::fs::write(content_file, chant).unwrap();
91+
92+
let path = chain_data_path.path();
93+
migration.pre_checks(path).unwrap();
94+
let temp_db_path = migration.migrate(path).unwrap();
95+
migration.post_checks(path).unwrap();
96+
97+
// check that the temporary database directory exists and contains the file with the
98+
// expected content.
99+
let temp_db_content_dir = temp_db_path.join("R'lyeh");
100+
let temp_db_content_file = temp_db_content_dir.join("cthulhu");
101+
assert!(temp_db_content_file.exists());
102+
assert_eq!(
103+
std::fs::read_to_string(temp_db_content_file).unwrap(),
104+
chant
105+
);
106+
}
107+
}

0 commit comments

Comments
 (0)