Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add forc-migrate tool #6790

Merged
merged 18 commits into from
Jan 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ jobs:
cargo install --locked --debug --path ./forc-plugins/forc-doc
cargo install --locked --debug --path ./forc-plugins/forc-tx
cargo install --locked --debug --path ./forc-plugins/forc-crypto
cargo install --locked --debug --path ./forc-plugins/forc-migrate
cargo install --locked --debug forc-explore
- name: Install mdbook-forc-documenter
run: cargo install --locked --debug --path ./scripts/mdbook-forc-documenter
Expand Down
20 changes: 20 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ members = [
"forc-plugins/forc-doc",
"forc-plugins/forc-fmt",
"forc-plugins/forc-lsp",
"forc-plugins/forc-migrate",
"forc-plugins/forc-tx",
"forc-test",
"forc-tracing",
Expand Down
7 changes: 6 additions & 1 deletion docs/book/spell-check-custom-words.txt
Original file line number Diff line number Diff line change
Expand Up @@ -231,4 +231,9 @@ fmt
deallocated
deallocate
destructors
destructor
destructor
semiautomatically
FuelLabs
github
toml
hardcoded
1 change: 1 addition & 0 deletions docs/book/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,3 +105,4 @@
- [forc explore](./forc/plugins/forc_explore.md)
- [forc fmt](./forc/plugins/forc_fmt.md)
- [forc lsp](./forc/plugins/forc_lsp.md)
- [forc migrate](./forc/plugins/forc_migrate.md)
1 change: 1 addition & 0 deletions docs/book/src/forc/plugins/forc_migrate.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# forc migrate
12 changes: 5 additions & 7 deletions forc-plugins/forc-doc/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ forc_util::cli_examples! {
[ Build the docs for a project in the current path and open it in the browser => "forc doc --open" ]
[ Build the docs for a project located in another path => "forc doc --path {path}" ]
[ Build the docs for the current project exporting private types => "forc doc --document-private-items" ]
[ Build the docs offline without downloading any dependency from the network => "forc doc --offline" ]
[ Build the docs offline without downloading any dependencies => "forc doc --offline" ]
}
}

Expand All @@ -35,11 +35,8 @@ pub struct Command {
/// Meaning it will only try to use previously downloaded dependencies.
#[clap(long = "offline")]
pub offline: bool,
/// Silent mode. Don't output any warnings or errors to the command line.
#[clap(long = "silent", short = 's')]
pub silent: bool,
/// Requires that the Forc.lock file is up-to-date. If the lock file is missing, or it
/// needs to be updated, Forc will exit with an error
/// needs to be updated, Forc will exit with an error.
#[clap(long)]
pub locked: bool,
/// Do not build documentation for dependencies.
Expand All @@ -50,10 +47,11 @@ pub struct Command {
/// Possible values: PUBLIC, LOCAL, <GATEWAY_URL>
#[clap(long)]
pub ipfs_node: Option<IPFSNode>,

#[cfg(test)]
pub(crate) doc_path: Option<String>,

#[clap(flatten)]
pub experimental: sway_features::CliFields,
/// Silent mode. Don't output any warnings or errors to the command line.
#[clap(long = "silent", short = 's')]
pub silent: bool,
}
11 changes: 1 addition & 10 deletions forc-plugins/forc-fmt/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use forc_pkg::{
WorkspaceManifestFile,
};
use forc_tracing::{init_tracing_subscriber, println_error, println_green, println_red};
use forc_util::fs_locking::PidFileLocking;
use forc_util::fs_locking::is_file_dirty;
use prettydiff::{basic::DiffOp, diff_lines};
use std::{
default::Default,
Expand Down Expand Up @@ -101,15 +101,6 @@ fn run() -> Result<()> {
Ok(())
}

/// Checks if the specified file is marked as "dirty".
/// This is used to prevent formatting files that are currently open in an editor
/// with unsaved changes.
///
/// Returns `true` if a corresponding "dirty" flag file exists, `false` otherwise.
fn is_file_dirty<X: AsRef<Path>>(path: X) -> bool {
PidFileLocking::lsp(path.as_ref()).is_locked()
}

/// Recursively get a Vec<PathBuf> of subdirectories that contains a Forc.toml.
fn get_sway_dirs(workspace_dir: PathBuf) -> Vec<PathBuf> {
let mut dirs_to_format = vec![];
Expand Down
25 changes: 25 additions & 0 deletions forc-plugins/forc-migrate/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
[package]
name = "forc-migrate"
version.workspace = true
description = "Migrate Sway projects to the next breaking change version of Sway."
authors.workspace = true
edition.workspace = true
homepage.workspace = true
license.workspace = true
repository.workspace = true

[dependencies]
anyhow.workspace = true
clap = { workspace = true, features = ["derive"] }
forc-pkg.workspace = true
forc-tracing.workspace = true
forc-util.workspace = true
itertools.workspace = true
num-bigint.workspace = true
sha2.workspace = true
sway-ast.workspace = true
sway-core.workspace = true
sway-error.workspace = true
sway-features.workspace = true
sway-types.workspace = true
swayfmt.workspace = true
88 changes: 88 additions & 0 deletions forc-plugins/forc-migrate/src/cli/commands/check.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
use clap::Parser;

use crate::{
cli::{
self,
shared::{
compile_package, create_migration_diagnostic, print_features_and_migration_steps,
},
},
get_migration_steps_or_return,
migrations::{DryRun, MigrationStepKind},
};
use anyhow::{Ok, Result};
use forc_util::format_diagnostic;
use itertools::Itertools;
use sway_core::Engines;

forc_util::cli_examples! {
crate::cli::Opt {
[ Check the project in the current path => "forc migrate check"]
[ Check the project located in another path => "forc migrate check --path {path}" ]
}
}

/// Check the project for code that needs to be migrated.
///
/// Dry-runs the migration steps and prints places in code that need to be reviewed or changed.
#[derive(Debug, Parser)]
pub(crate) struct Command {
#[clap(flatten)]
pub check: cli::shared::Compile,
}

pub(crate) fn exec(command: Command) -> Result<()> {
let migration_steps = get_migration_steps_or_return!();
let engines = Engines::default();
let build_instructions = command.check;

let mut program_info = compile_package(&engines, &build_instructions)?;

// Dry-run all the migration steps.
let mut check_result = vec![];
for (feature, migration_steps) in migration_steps.iter() {
for migration_step in migration_steps.iter() {
let migration_point_spans = match migration_step.kind {
MigrationStepKind::Instruction(instruction) => instruction(&program_info)?,
MigrationStepKind::CodeModification(modification, _) => {
modification(&mut program_info.as_mut(), DryRun::Yes)?
}
MigrationStepKind::Interaction(instruction, _, _) => instruction(&program_info)?,
};

check_result.push((feature, migration_step, migration_point_spans));
}
}

// For every migration step, display the found occurrences in code that require migration effort, if any.
for (feature, migration_step, occurrences_spans) in check_result.iter() {
if let Some(diagnostic) =
create_migration_diagnostic(engines.se(), feature, migration_step, occurrences_spans)
{
format_diagnostic(&diagnostic);
}
}

// Display the summary of the migration effort.
let features_and_migration_steps = check_result
.iter()
.chunk_by(|(feature, _, _)| feature)
.into_iter()
.map(|(key, chunk)| {
(
**key,
chunk
.map(|(_, migration_step, migration_point_spans)| {
(*migration_step, Some(migration_point_spans.len()))
})
.collect::<Vec<_>>(),
)
})
.collect::<Vec<_>>();

println!("Migration effort:");
println!();
print_features_and_migration_steps(&features_and_migration_steps);

Ok(())
}
3 changes: 3 additions & 0 deletions forc-plugins/forc-migrate/src/cli/commands/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pub(crate) mod check;
pub(crate) mod run;
pub(crate) mod show;
Loading
Loading