Skip to content

Commit

Permalink
Merge pull request #1611 from axodotdev/init-refactor
Browse files Browse the repository at this point in the history
Refactor `dist init` and split out `dist migrate`
  • Loading branch information
duckinator authored Dec 10, 2024
2 parents 49e6359 + c88cfb8 commit 5589242
Show file tree
Hide file tree
Showing 7 changed files with 142 additions and 65 deletions.
5 changes: 5 additions & 0 deletions cargo-dist/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,8 @@ pub enum Commands {
/// also handle updating your project to a new version of dist if you're running one.
#[clap(disable_version_flag = true)]
Init(InitArgs),
/// Migrate to the latest configuration variant.
Migrate(MigrateArgs),
/// Generate one or more pieces of configuration
#[clap(disable_version_flag = true)]
Generate(GenerateArgs),
Expand Down Expand Up @@ -275,6 +277,9 @@ pub struct InitArgs {
pub hosting: Vec<HostingStyle>,
}

#[derive(Args, Clone, Debug)]
pub struct MigrateArgs {}

/// Which style(s) of configuration to generate
#[derive(ValueEnum, Copy, Clone, Debug)]
pub enum GenerateMode {
Expand Down
168 changes: 105 additions & 63 deletions cargo-dist/src/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,90 @@ fn theme() -> dialoguer::theme::ColorfulTheme {
}
}

/// Copy [workspace.metadata.dist] from one workspace to [dist] in another.
fn copy_cargo_workspace_metadata_dist(
new_workspace: &mut toml_edit::DocumentMut,
workspace_toml: toml_edit::DocumentMut,
) {
if let Some(dist) = workspace_toml
.get("workspace")
.and_then(|t| t.get("metadata"))
.and_then(|t| t.get("dist"))
{
new_workspace.insert("dist", dist.to_owned());
}
}

/// Remove [workspace.metadata.dist], if it exists.
fn prune_cargo_workspace_metadata_dist(workspace: &mut toml_edit::DocumentMut) {
workspace
.get_mut("workspace")
.and_then(|ws| ws.get_mut("metadata"))
.and_then(|metadata_item| metadata_item.as_table_mut())
.and_then(|table| table.remove("dist"));
}

/// Create a toml-edit document set up for a cargo workspace.
fn new_workspace() -> toml_edit::DocumentMut {
let mut new_workspace = toml_edit::DocumentMut::new();

// Write generic workspace config
let mut table = toml_edit::table();
if let Some(t) = table.as_table_mut() {
let mut array = toml_edit::Array::new();
array.push("cargo:.");
t["members"] = toml_edit::value(array);
}
new_workspace.insert("workspace", table);

new_workspace
}

fn do_migrate_from_rust_workspace() -> DistResult<()> {
let workspaces = config::get_project()?;
let root_workspace = workspaces.root_workspace();
let initted = has_metadata_table(root_workspace);

if root_workspace.kind != WorkspaceKind::Rust {
// we're not using a Rust workspace, so no migration needed.
return Ok(());
}

if !initted {
// the workspace hasn't been initialized, so no migration needed.
return Ok(());
}

// Load in the root workspace toml to edit and write back
let workspace_toml = config::load_toml(&root_workspace.manifest_path)?;
let mut original_workspace_toml = workspace_toml.clone();

// Generate a new workspace, then populate it using config from Cargo.toml.
let mut new_workspace_toml = new_workspace();
copy_cargo_workspace_metadata_dist(&mut new_workspace_toml, workspace_toml);

// Determine config file location.
let filename = "dist-workspace.toml";
let destination = root_workspace.workspace_dir.join(filename);

// Write new config file.
config::write_toml(&destination, new_workspace_toml)?;

// We've been asked to migrate away from Cargo.toml; delete what
// we've added after writing the new config
prune_cargo_workspace_metadata_dist(&mut original_workspace_toml);
config::write_toml(&root_workspace.manifest_path, original_workspace_toml)?;

Ok(())
}

/// Run `dist migrate`
pub fn do_migrate() -> DistResult<()> {
do_migrate_from_rust_workspace()?;
//do_migrate_from_v0()?;
Ok(())
}

/// Run 'dist init'
pub fn do_init(cfg: &Config, args: &InitArgs) -> DistResult<()> {
// on ctrl-c, dialoguer/console will clean up the rest of its
Expand Down Expand Up @@ -99,38 +183,32 @@ pub fn do_init(cfg: &Config, args: &InitArgs) -> DistResult<()> {

// Load in the root workspace toml to edit and write back
let workspace_toml = config::load_toml(&root_workspace.manifest_path)?;
let mut original_workspace_toml = workspace_toml.clone();
let initted = has_metadata_table(root_workspace);

// Already-initted users should be asked whether to migrate.
if root_workspace.kind == WorkspaceKind::Rust && initted && !args.yes {
let prompt = r#"Would you like to opt in to the new configuration format?
Future versions of dist will feature major changes to the
configuration format, including a new dist-specific configuration file."#;
let is_migrating = dialoguer::Confirm::with_theme(&theme())
.with_prompt(prompt)
.default(false)
.interact()?;

if is_migrating {
do_migrate()?;
return do_init(cfg, args);
}
}

// If this is a Cargo.toml, offer to either write their config to
// a dist-workspace.toml, or migrate existing config there
let mut is_migrating = false;
let mut newly_initted_generic = false;
// Users who haven't initted yet should be opted into the
// new config format by default.
let desired_workspace_kind = if root_workspace.kind == WorkspaceKind::Rust && !initted {
newly_initted_generic = true;
WorkspaceKind::Generic
// Already-initted users should be asked whether to migrate.
} else if root_workspace.kind == WorkspaceKind::Rust {
let prompt = r#"Would you like to opt in to the new configuration format?
Future versions of dist will feature major changes to the
configuration format, including a new dist-specific configuration file."#;
let res = if args.yes {
false
} else {
dialoguer::Confirm::with_theme(&theme())
.with_prompt(prompt)
.default(false)
.interact()?
};

if res {
is_migrating = true;
WorkspaceKind::Generic
} else {
root_workspace.kind
}
} else {
root_workspace.kind
};
Expand All @@ -156,28 +234,8 @@ pub fn do_init(cfg: &Config, args: &InitArgs) -> DistResult<()> {
// If we're migrating, the configuration will be missing the
// generic workspace specification, and will have some
// extraneous cargo-specific stuff that we don't want.
let mut workspace_toml = if is_migrating || newly_initted_generic {
// Always generate a new workspace here for the !initted case
let mut new_workspace = toml_edit::DocumentMut::new();

// Write generic workspace config
let mut table = toml_edit::table();
if let Some(t) = table.as_table_mut() {
let mut array = toml_edit::Array::new();
array.push("cargo:.");
t["members"] = toml_edit::value(array);
}
new_workspace.insert("workspace", table);

if let Some(dist) = workspace_toml
.get("workspace")
.and_then(|t| t.get("metadata"))
.and_then(|t| t.get("dist"))
{
new_workspace.insert("dist", dist.to_owned());
}

new_workspace
let mut workspace_toml = if newly_initted_generic {
new_workspace()
} else {
workspace_toml
};
Expand All @@ -190,13 +248,9 @@ pub fn do_init(cfg: &Config, args: &InitArgs) -> DistResult<()> {

let filename;
let destination;
// If we're migrating, *or* if we're doing a first-time init,
// calculate the filename to write to
if is_migrating || newly_initted_generic {
filename = match desired_workspace_kind {
WorkspaceKind::Rust => "Cargo.toml",
WorkspaceKind::Generic | WorkspaceKind::Javascript => "dist-workspace.toml",
};
if newly_initted_generic {
// Migrations and newly-initted setups always use dist-workspace.toml.
filename = "dist-workspace.toml";
destination = root_workspace.workspace_dir.join(filename);
} else {
filename = root_workspace
Expand All @@ -215,18 +269,6 @@ pub fn do_init(cfg: &Config, args: &InitArgs) -> DistResult<()> {
};
eprintln!("{check} added {key} to your root {filename}");

// We've been asked to migrate away from Cargo.toml; delete what
// we've added after writing the new config
if initted && is_migrating {
original_workspace_toml
.get_mut("workspace")
.and_then(|ws| ws.get_mut("metadata"))
.and_then(|metadata_item| metadata_item.as_table_mut())
.and_then(|table| table.remove("dist"));

config::write_toml(&root_workspace.manifest_path, original_workspace_toml)?;
}

// Now that we've done the stuff that's definitely part of the root Cargo.toml,
// Optionally apply updates to packages
for (_idx, package) in workspaces.all_packages() {
Expand Down
2 changes: 1 addition & 1 deletion cargo-dist/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ use temp_dir::TempDir;
use tracing::info;

use errors::*;
pub use init::{do_init, InitArgs};
pub use init::{do_init, do_migrate, InitArgs};
pub use tasks::*;

pub mod announce;
Expand Down
8 changes: 7 additions & 1 deletion cargo-dist/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use console::Term;
use miette::{miette, IntoDiagnostic};
use net::ClientSettings;

use crate::cli::{BuildArgs, GenerateArgs, GenerateCiArgs, InitArgs, LinkageArgs};
use crate::cli::{BuildArgs, GenerateArgs, GenerateCiArgs, InitArgs, LinkageArgs, MigrateArgs};

mod cli;

Expand Down Expand Up @@ -49,6 +49,7 @@ fn real_main(cli: &axocli::CliApp<Cli>) -> Result<(), miette::Report> {
let config = &cli.config;
match &config.command {
Commands::Init(args) => cmd_init(config, args),
Commands::Migrate(args) => cmd_migrate(config, args),
Commands::Generate(args) => cmd_generate(config, args),
Commands::GenerateCi(args) => cmd_generate_ci(config, args),
Commands::Linkage(args) => cmd_linkage(config, args),
Expand Down Expand Up @@ -418,6 +419,11 @@ fn generate_manifest(
Ok(report)
}

fn cmd_migrate(_cli: &Cli, _args: &MigrateArgs) -> Result<(), miette::Report> {
do_migrate()?;
Ok(())
}

fn cmd_init(cli: &Cli, args: &InitArgs) -> Result<(), miette::Report> {
let config = cargo_dist::config::Config {
tag_settings: cli.tag_settings(false),
Expand Down
2 changes: 2 additions & 0 deletions cargo-dist/tests/snapshots/long-help.snap

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

20 changes: 20 additions & 0 deletions cargo-dist/tests/snapshots/markdown-help.snap

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

2 changes: 2 additions & 0 deletions cargo-dist/tests/snapshots/short-help.snap

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

0 comments on commit 5589242

Please sign in to comment.