From f287cbbdebc3fcccf1137bc896bac757dc849056 Mon Sep 17 00:00:00 2001 From: SupperZum Date: Tue, 24 Jun 2025 13:46:06 +0300 Subject: [PATCH 1/2] rollback willbe to 0.20 and fix willbe --- Cargo.toml | 2 +- module/core/component_model/Readme.md | 12 +-- module/core/component_model/src/lib.rs | 3 - module/core/component_model_meta/Readme.md | 2 +- .../src/derive_former/former_enum.rs | 30 +++---- .../former_enum/common_emitters.rs | 6 +- .../former_enum/struct_multi_fields_scalar.rs | 6 +- .../struct_multi_fields_subform.rs | 6 +- .../former_enum/struct_single_field_scalar.rs | 2 +- .../struct_single_field_subform.rs | 65 ++++++++------ .../former_enum/struct_zero_fields_handler.rs | 6 +- .../former_enum/tuple_single_field_scalar.rs | 4 +- .../former_enum/tuple_single_field_subform.rs | 5 +- .../former_enum/tuple_zero_fields_handler.rs | 18 ++-- .../former_enum/unit_variant_handler.rs | 9 +- .../src/derive_former/struct_attrs.rs | 24 ++--- module/core/macro_tools/src/ident.rs | 54 ++++++----- module/core/pth/src/path/absolute_path.rs | 4 +- module/core/pth/src/path/canonical_path.rs | 2 +- module/core/pth/src/path/native_path.rs | 2 +- module/move/willbe/Cargo.toml | 2 +- module/move/willbe/src/action/cicd_renew.rs | 2 +- module/move/willbe/src/action/crate_doc.rs | 20 ++--- module/move/willbe/src/action/list.rs | 4 +- module/move/willbe/src/action/publish.rs | 6 -- module/move/willbe/src/action/publish_diff.rs | 3 +- module/move/willbe/src/command/mod.rs | 15 ---- module/move/willbe/src/command/publish.rs | 12 +-- .../move/willbe/src/command/publish_diff.rs | 13 +-- module/move/willbe/src/entity/diff.rs | 34 +------ .../move/willbe/src/entity/files/crate_dir.rs | 2 +- .../willbe/src/entity/files/manifest_file.rs | 4 +- module/move/willbe/src/entity/package.rs | 4 +- module/move/willbe/src/entity/publish.rs | 89 +++++++------------ module/move/willbe/src/tool/graph.rs | 3 +- module/move/willbe/tests/inc/entity/diff.rs | 4 +- module/move/willbe/tests/inc/package.rs | 2 - 37 files changed, 196 insertions(+), 285 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 911dfcaed0..dd7995daf8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -478,7 +478,7 @@ path = "module/move/wcensor" ## willbe [workspace.dependencies.willbe] -version = "~0.21.0" +version = "~0.20.0" path = "module/move/willbe" diff --git a/module/core/component_model/Readme.md b/module/core/component_model/Readme.md index d3c6e9109c..da35c2daa9 100644 --- a/module/core/component_model/Readme.md +++ b/module/core/component_model/Readme.md @@ -1,6 +1,6 @@ -# Module :: component_model +# Module :: `component_model` [![experimental](https://raster.shields.io/static/v1?label=&message=experimental&color=orange)](https://github.com/emersion/stability-badges#experimental) [![rust-status](https://github.com/Wandalen/wTools/actions/workflows/module_component_model_push.yml/badge.svg)](https://github.com/Wandalen/wTools/actions/workflows/module_component_model_push.yml) @@ -47,19 +47,19 @@ where } } -fn main() { +//fn main() { let mut person = Person::default(); person.assign(42); person.assign("Alice"); assert_eq!(person, Person { age: 42, name: "Alice".to_string() }); -} +//} ``` ## API Overview -- **Assign**: Generic trait for assigning values to struct fields by type. -- **AssignWithType**: Trait for assigning values with explicit type annotation. -- **ComponentsAssign**: Trait for assigning multiple components at once. +- **`Assign`**: Generic trait for assigning values to struct fields by type. +- **`AssignWithType`**: Trait for assigning values with explicit type annotation. +- **`ComponentsAssign`**: Trait for assigning multiple components at once. See [component_model_types documentation](https://docs.rs/component_model_types) for details. diff --git a/module/core/component_model/src/lib.rs b/module/core/component_model/src/lib.rs index 3936f30cfb..6b567e81a2 100644 --- a/module/core/component_model/src/lib.rs +++ b/module/core/component_model/src/lib.rs @@ -26,10 +26,7 @@ pub mod dependency #[ cfg( feature = "enabled" ) ] pub use own::*; -#[ allow( unused_imports ) ] -#[ cfg( feature = "enabled" ) ] // Former macro is intentionally not re-exported; all coupling with "former" is removed. - /// Own namespace of the module. #[ cfg( feature = "enabled" ) ] #[ allow( unused_imports ) ] diff --git a/module/core/component_model_meta/Readme.md b/module/core/component_model_meta/Readme.md index 19689cde07..4945def390 100644 --- a/module/core/component_model_meta/Readme.md +++ b/module/core/component_model_meta/Readme.md @@ -5,7 +5,7 @@ [![experimental](https://raster.shields.io/static/v1?label=&message=experimental&color=orange)](https://github.com/emersion/stability-badges#experimental) [![rust-status](https://github.com/Wandalen/wTools/actions/workflows/module_component_model_meta_push.yml/badge.svg)](https://github.com/Wandalen/wTools/actions/workflows/module_component_model_meta_push.yml) [![docs.rs](https://img.shields.io/docsrs/component_model_meta?color=e3e8f0&logo=docs.rs)](https://docs.rs/component_model_meta) [![discord](https://img.shields.io/discord/872391416519737405?color=eee&logo=discord&logoColor=eee&label=ask)](https://discord.gg/m3YfbXpUUY) -A flexible implementation of the Builder pattern supporting nested builders and collection-specific subcomponent_models. Implementation of its derive macro. Should not be used independently, instead use `module::component_model` which relies on the module. +A flexible implementation of the Builder pattern supporting nested builders and collection-specific `subcomponent_models`. Implementation of its derive macro. Should not be used independently, instead use `module::component_model` which relies on the module. Not intended to be used without runtime. This module and runtime is aggregate in `module::component_model` is [here](https://github.com/Wandalen/wTools/tree/master/module/core/component_model). diff --git a/module/core/former_meta/src/derive_former/former_enum.rs b/module/core/former_meta/src/derive_former/former_enum.rs index c9ef2bcd9c..8f0ef4c397 100644 --- a/module/core/former_meta/src/derive_former/former_enum.rs +++ b/module/core/former_meta/src/derive_former/former_enum.rs @@ -148,7 +148,7 @@ pub(super) struct EnumVariantHandlerContext< 'a > pub has_debug : bool, } - +#[allow(clippy::too_many_lines)] pub(super) fn former_for_enum ( ast : &syn::DeriveInput, @@ -211,7 +211,7 @@ pub(super) fn former_for_enum { ast, variant, - struct_attrs : &struct_attrs, + struct_attrs, enum_name, vis, generics, @@ -266,11 +266,11 @@ pub(super) fn former_for_enum { return Err( syn::Error::new_spanned( ctx.variant, "#[subform_scalar] is not allowed on zero-field struct variants." ) ); } - if !ctx.variant_attrs.scalar.is_some() + if ctx.variant_attrs.scalar.is_none() { return Err( syn::Error::new_spanned( ctx.variant, "Zero-field struct variants require `#[scalar]` attribute for direct construction." ) ); } - let generated = struct_zero_fields_handler::handle(&mut ctx)?; + let generated = struct_zero_fields_handler::handle(&mut ctx); ctx.methods.push(generated); // Collect generated tokens } _len => @@ -284,23 +284,21 @@ pub(super) fn former_for_enum } else { - let generated = struct_multi_fields_scalar::handle(&mut ctx)?; + let generated = struct_multi_fields_scalar::handle(&mut ctx); ctx.methods.push(generated); // Collect generated tokens } } + else if fields.named.len() == 1 + { + let generated = struct_single_field_subform::handle(&mut ctx)?; + ctx.methods.push(generated); // Collect generated tokens + } else { - if fields.named.len() == 1 - { - let generated = struct_single_field_subform::handle(&mut ctx)?; - ctx.methods.push(generated); // Collect generated tokens - } - else - { - let generated = struct_multi_fields_subform::handle(&mut ctx)?; - ctx.methods.push(generated); // Collect generated tokens - } + let generated = struct_multi_fields_subform::handle(&mut ctx); + ctx.methods.push(generated); // Collect generated tokens } + } } } // End of match @@ -329,7 +327,7 @@ pub(super) fn former_for_enum if has_debug { - let about = format!( "derive : Former\nenum : {}", enum_name ); + let about = format!( "derive : Former\nenum : {enum_name}" ); diag::report_print( about, original_input, &result ); } diff --git a/module/core/former_meta/src/derive_former/former_enum/common_emitters.rs b/module/core/former_meta/src/derive_former/former_enum/common_emitters.rs index 8343c31e5e..d43427061c 100644 --- a/module/core/former_meta/src/derive_former/former_enum/common_emitters.rs +++ b/module/core/former_meta/src/derive_former/former_enum/common_emitters.rs @@ -1,14 +1,14 @@ // qqq : Implement shared emitter functions use super::*; -use macro_tools::{ Result, quote::{ quote } }; +use macro_tools::{ quote::{ quote } }; use proc_macro2::TokenStream; // Corrected import for TokenStream // use super::EnumVariantHandlerContext; #[allow(dead_code)] // Suppress warning about unused function -pub( crate ) fn generate_direct_constructor_for_variant( _ctx : &EnumVariantHandlerContext< '_ > ) -> Result< TokenStream > +pub( crate ) fn generate_direct_constructor_for_variant( _ctx : &EnumVariantHandlerContext< '_ > ) -> TokenStream { // qqq : Implement - Ok( quote!{} ) + quote!{} } // qqq : Add other placeholder functions as needed \ No newline at end of file diff --git a/module/core/former_meta/src/derive_former/former_enum/struct_multi_fields_scalar.rs b/module/core/former_meta/src/derive_former/former_enum/struct_multi_fields_scalar.rs index 048c21f79c..0ca5b8d1fe 100644 --- a/module/core/former_meta/src/derive_former/former_enum/struct_multi_fields_scalar.rs +++ b/module/core/former_meta/src/derive_former/former_enum/struct_multi_fields_scalar.rs @@ -1,13 +1,13 @@ // qqq : Implement logic for Struct { f1:T1, ... } with #[scalar] use super::*; -use macro_tools::{ Result, quote, syn }; +use macro_tools::{ quote, syn }; use super::EnumVariantHandlerContext; use proc_macro2::TokenStream; // Import TokenStream use convert_case::{ Case, Casing }; // Import Case and Casing from convert_case #[allow(dead_code)] // Suppress warning about unused function -pub( crate ) fn handle( ctx : &mut EnumVariantHandlerContext< '_ > ) -> Result< TokenStream > +pub( crate ) fn handle( ctx : &mut EnumVariantHandlerContext< '_ > ) -> TokenStream { // This handler is specifically for Struct { f1: T1, ... } variants with #[scalar]. // The main dispatch should ensure this is only called for such variants. @@ -73,5 +73,5 @@ pub( crate ) fn handle( ctx : &mut EnumVariantHandlerContext< '_ > ) -> Result< generated_tokens.extend(generated_standalone); } - Ok( generated_tokens ) + generated_tokens } \ No newline at end of file diff --git a/module/core/former_meta/src/derive_former/former_enum/struct_multi_fields_subform.rs b/module/core/former_meta/src/derive_former/former_enum/struct_multi_fields_subform.rs index b6201a4f8e..5dc29af6c9 100644 --- a/module/core/former_meta/src/derive_former/former_enum/struct_multi_fields_subform.rs +++ b/module/core/former_meta/src/derive_former/former_enum/struct_multi_fields_subform.rs @@ -1,13 +1,13 @@ // qqq : Implement logic for Struct { f1:T1, ... } with #[subform_scalar] or default use super::*; -use macro_tools::{ Result, quote, syn }; +use macro_tools::{ quote, syn }; use super::EnumVariantHandlerContext; use proc_macro2::TokenStream; // Import TokenStream use convert_case::{ Case, Casing }; // Import Case and Casing from convert_case #[allow(dead_code)] // Suppress warning about unused function -pub( crate ) fn handle( ctx : &mut EnumVariantHandlerContext< '_ > ) -> Result< TokenStream > +pub( crate ) fn handle( ctx : &mut EnumVariantHandlerContext< '_ > ) -> TokenStream { // This handler is specifically for Struct { f1: T1, ... } variants with #[subform_scalar] or default behavior. // The main dispatch should ensure this is only called for such variants. @@ -55,5 +55,5 @@ pub( crate ) fn handle( ctx : &mut EnumVariantHandlerContext< '_ > ) -> Result< // This will likely involve using common_emitters or dedicated logic here. // For now, just returning the method/constructor tokens. - Ok( generated_tokens ) + generated_tokens } \ No newline at end of file diff --git a/module/core/former_meta/src/derive_former/former_enum/struct_single_field_scalar.rs b/module/core/former_meta/src/derive_former/former_enum/struct_single_field_scalar.rs index d958325824..a30ccd2573 100644 --- a/module/core/former_meta/src/derive_former/former_enum/struct_single_field_scalar.rs +++ b/module/core/former_meta/src/derive_former/former_enum/struct_single_field_scalar.rs @@ -17,7 +17,7 @@ pub( crate ) fn handle( ctx : &mut EnumVariantHandlerContext< '_ > ) -> Result< let vis = &ctx.vis; // Get visibility // Get the single field's type and identifier - let field = ctx.variant_field_info.get(0).ok_or_else(|| { + let field = ctx.variant_field_info.first().ok_or_else(|| { syn::Error::new_spanned(ctx.variant, "Struct variant with #[scalar] must have exactly one field.") })?; let field_ident = &field.ident; diff --git a/module/core/former_meta/src/derive_former/former_enum/struct_single_field_subform.rs b/module/core/former_meta/src/derive_former/former_enum/struct_single_field_subform.rs index 397b34d2d9..49b650a7d0 100644 --- a/module/core/former_meta/src/derive_former/former_enum/struct_single_field_subform.rs +++ b/module/core/former_meta/src/derive_former/former_enum/struct_single_field_subform.rs @@ -18,46 +18,59 @@ pub( crate ) fn handle( ctx : &mut EnumVariantHandlerContext< '_ > ) -> Result< // Decompose generics for use in signatures (impl_generics and ty_generics are needed from local decomposition) let ( _def_generics, impl_generics, ty_generics, _local_where_clause_option_unused ) = // Renamed to avoid confusion - macro_tools::generic_params::decompose(&ctx.generics); + macro_tools::generic_params::decompose( ctx.generics ); // Use merged_where_clause from the context for any top-level item's where clause (like standalone fns or VariantFormer struct) - let top_level_where_clause = match ctx.merged_where_clause { // Use ctx.merged_where_clause - Some(clause) => quote! { where #clause }, // Add `where` keyword if clause exists - None => quote! {}, + let top_level_where_clause = match ctx.merged_where_clause + { // Use ctx.merged_where_clause + Some( clause ) => quote! { where #clause }, // Add `where` keyword if clause exists + None => quote! {}, }; // Get the single field's info - let field_info = ctx.variant_field_info.get(0).ok_or_else(|| { - syn::Error::new_spanned(ctx.variant, "Struct variant with subform behavior must have exactly one field for this handler.") + let field_info = ctx.variant_field_info.first().ok_or_else( + || + { + syn::Error::new_spanned( ctx.variant, "Struct variant with subform behavior must have exactly one field for this handler." ) })?; let field_name_original = &field_info.ident; // This is the original field name from the enum variant let field_ty = &field_info.ty; // Generate the name for the implicit variant former, make it generic if enum is generic - let variant_former_name_str = format!("{}{}Former", enum_ident, variant_ident); - let variant_former_ident = format_ident!("{}", variant_former_name_str); - let variant_former_name_generic = if ctx.generics.params.is_empty() { - quote! { #variant_former_ident } - } else { - quote! { #variant_former_ident< #ty_generics > } + let variant_former_name_str = format!( "{enum_ident}{variant_ident}Former" ); + let variant_former_ident = format_ident!( "{}", variant_former_name_str ); + let variant_former_name_generic = if ctx.generics.params.is_empty() + { + quote! { #variant_former_ident } + } + else + { + quote! { #variant_former_ident< #ty_generics > } }; // Correctly create method_ident for the accessor method, handling raw identifiers - let method_ident = { - let name_str = variant_ident.to_string(); - // Raw identifier check (consistent with other handlers) - if let Some(core_name) = name_str.strip_prefix("r#") { - let snake_core_name = core_name.to_case(Case::Snake); - syn::Ident::new_raw(&snake_core_name, variant_ident.span()) - } else { - let snake_name = name_str.to_case(Case::Snake); - let is_keyword = matches!(snake_name.as_str(), "as" | "async" | "await" | "break" | "const" | "continue" | "crate" | "dyn" | "else" | "enum" | "extern" | "false" | "fn" | "for" | "if" | "impl" | "in" | "let" | "loop" | "match" | "mod" | "move" | "mut" | "pub" | "ref" | "return" | "Self" | "self" | "static" | "struct" | "super" | "trait" | "true" | "type" | "unsafe" | "use" | "where" | "while" | "union" ); - if is_keyword { - syn::Ident::new_raw(&snake_name, variant_ident.span()) - } else { - syn::Ident::new(&snake_name, variant_ident.span()) - } + let method_ident = + { + let name_str = variant_ident.to_string(); + // Raw identifier check (consistent with other handlers) + if let Some( core_name ) = name_str.strip_prefix( "r#" ) + { + let snake_core_name = core_name.to_case( Case::Snake ); + syn::Ident::new_raw( &snake_core_name, variant_ident.span() ) + } + else + { + let snake_name = name_str.to_case( Case::Snake ); + let is_keyword = matches!( snake_name.as_str(), "as" | "async" | "await" | "break" | "const" | "continue" | "crate" | "dyn" | "else" | "enum" | "extern" | "false" | "fn" | "for" | "if" | "impl" | "in" | "let" | "loop" | "match" | "mod" | "move" | "mut" | "pub" | "ref" | "return" | "Self" | "self" | "static" | "struct" | "super" | "trait" | "true" | "type" | "unsafe" | "use" | "where" | "while" | "union" ); + if is_keyword + { + syn::Ident::new_raw( &snake_name, variant_ident.span() ) + } + else + { + syn::Ident::new( &snake_name, variant_ident.span() ) } + } }; // Generate the static method: Enum::variant_name() -> VariantFormer<...> diff --git a/module/core/former_meta/src/derive_former/former_enum/struct_zero_fields_handler.rs b/module/core/former_meta/src/derive_former/former_enum/struct_zero_fields_handler.rs index ed62022706..c25037687e 100644 --- a/module/core/former_meta/src/derive_former/former_enum/struct_zero_fields_handler.rs +++ b/module/core/former_meta/src/derive_former/former_enum/struct_zero_fields_handler.rs @@ -1,11 +1,11 @@ use super::*; -use macro_tools::{ Result, quote }; +use macro_tools::quote; use proc_macro2::TokenStream; // Corrected import for TokenStream // use former_types::FormerDefinition; // Not needed here /// Handles zero-field struct variants with the `#[scalar]` attribute. /// Returns generated tokens for the static method and optionally the standalone constructor. -pub( crate ) fn handle( ctx : &mut EnumVariantHandlerContext< '_ > ) -> Result< TokenStream > +pub( crate ) fn handle( ctx : &mut EnumVariantHandlerContext< '_ > ) -> TokenStream { // This handler is specifically for variants with #[scalar] // The main dispatch should ensure this is only called for scalar zero-field struct variants. @@ -52,5 +52,5 @@ pub( crate ) fn handle( ctx : &mut EnumVariantHandlerContext< '_ > ) -> Result< // and place them in the correct scope (outside the enum impl block). } - Ok( generated_tokens ) + generated_tokens } \ No newline at end of file diff --git a/module/core/former_meta/src/derive_former/former_enum/tuple_single_field_scalar.rs b/module/core/former_meta/src/derive_former/former_enum/tuple_single_field_scalar.rs index 42c06c1dcc..98eef680c0 100644 --- a/module/core/former_meta/src/derive_former/former_enum/tuple_single_field_scalar.rs +++ b/module/core/former_meta/src/derive_former/former_enum/tuple_single_field_scalar.rs @@ -19,7 +19,7 @@ pub( crate ) fn handle( ctx : &mut EnumVariantHandlerContext< '_ > ) -> Result< // Decompose generics for use in signatures (impl_generics and ty_generics are needed) let ( _def_generics, impl_generics, ty_generics, _local_where_clause_option ) = - macro_tools::generic_params::decompose(&ctx.generics); + macro_tools::generic_params::decompose(ctx.generics); // Use merged_where_clause from the context for the standalone constructor's where clause let where_clause = match ctx.merged_where_clause { @@ -28,7 +28,7 @@ pub( crate ) fn handle( ctx : &mut EnumVariantHandlerContext< '_ > ) -> Result< }; // Get the single field's type and identifier - let field = ctx.variant_field_info.get(0).ok_or_else(|| { + let field = ctx.variant_field_info.first().ok_or_else(|| { syn::Error::new_spanned(ctx.variant, "Tuple variant with #[scalar] must have exactly one field.") })?; let field_ty = &field.ty; diff --git a/module/core/former_meta/src/derive_former/former_enum/tuple_single_field_subform.rs b/module/core/former_meta/src/derive_former/former_enum/tuple_single_field_subform.rs index b17fb0773f..defaae9443 100644 --- a/module/core/former_meta/src/derive_former/former_enum/tuple_single_field_subform.rs +++ b/module/core/former_meta/src/derive_former/former_enum/tuple_single_field_subform.rs @@ -13,16 +13,15 @@ pub( crate ) fn handle( ctx : &mut EnumVariantHandlerContext< '_ > ) -> Result< // The main dispatch should ensure this is only called for such variants. let variant_ident = &ctx.variant.ident; - let _enum_ident = &ctx.enum_name; let vis = &ctx.vis; // Get visibility // Get the single field's type - let field = ctx.variant_field_info.get(0).ok_or_else(|| { + let field = ctx.variant_field_info.first().ok_or_else(|| { syn::Error::new_spanned(ctx.variant, "Tuple variant with subform behavior must have exactly one field.") })?; let field_ty = &field.ty; - let type_path_str = quote!{ #field_ty }.to_string().replace(" ", ""); + let type_path_str = quote!{ #field_ty }.to_string().replace(' ', ""); let is_phantom_data_field = type_path_str.starts_with("core::marker::PhantomData") || type_path_str.starts_with("std::marker::PhantomData"); let method_ident_string = variant_ident.to_string().to_case( Case::Snake ); diff --git a/module/core/former_meta/src/derive_former/former_enum/tuple_zero_fields_handler.rs b/module/core/former_meta/src/derive_former/former_enum/tuple_zero_fields_handler.rs index 927b6df7d0..2a6f192f52 100644 --- a/module/core/former_meta/src/derive_former/former_enum/tuple_zero_fields_handler.rs +++ b/module/core/former_meta/src/derive_former/former_enum/tuple_zero_fields_handler.rs @@ -24,7 +24,7 @@ pub( crate ) fn handle( ctx : &mut EnumVariantHandlerContext< '_ > ) -> Result< // Decompose generics (we need impl_generics and ty_generics from this) let ( _def_generics, impl_generics, ty_generics, _local_where_clause_option_unused ) = // Renamed to avoid confusion - macro_tools::generic_params::decompose(&ctx.generics); + macro_tools::generic_params::decompose(ctx.generics); // Use merged_where_clause from the context for the standalone constructor's where clause let top_level_where_clause = match ctx.merged_where_clause { // Use ctx.merged_where_clause @@ -65,15 +65,19 @@ pub( crate ) fn handle( ctx : &mut EnumVariantHandlerContext< '_ > ) -> Result< let fn_signature_generics = if ctx.generics.params.is_empty() { quote!{} } else { quote!{ < #impl_generics > } }; let return_type_generics = if ctx.generics.params.is_empty() { quote!{} } else { quote!{ < #ty_generics > } }; - let enum_path_for_construction = if ctx.generics.params.is_empty() { - quote!{ #enum_ident } - } else { - if ty_generics.is_empty() { quote!{ #enum_ident } } else { quote!{ #enum_ident::< #ty_generics > } } + // FIX: Combine the two conditions with identical blocks using || + let enum_path_for_construction = if ctx.generics.params.is_empty() || ty_generics.is_empty() + { + quote!{ #enum_ident } + } + else + { + quote!{ #enum_ident::< #ty_generics > } }; // Create unique name for standalone constructor: [enum_name]_[variant_snake_case] - let standalone_method_name_str = format!("{}_{}", enum_ident.to_string().to_case(Case::Snake), method_ident.to_string()); - let standalone_method_ident = syn::Ident::new(&standalone_method_name_str, variant_ident.span()); + let standalone_method_name_str = format!( "{}_{}", enum_ident.to_string().to_case( Case::Snake ), method_ident ); + let standalone_method_ident = syn::Ident::new( &standalone_method_name_str, variant_ident.span() ); let generated_standalone = quote! { diff --git a/module/core/former_meta/src/derive_former/former_enum/unit_variant_handler.rs b/module/core/former_meta/src/derive_former/former_enum/unit_variant_handler.rs index 2996959db8..51b28e7755 100644 --- a/module/core/former_meta/src/derive_former/former_enum/unit_variant_handler.rs +++ b/module/core/former_meta/src/derive_former/former_enum/unit_variant_handler.rs @@ -6,8 +6,7 @@ use macro_tools:: generic_params::GenericsRef, // For enhanced generics handling ident, // For proposed ident::new_ident_from_cased_str qt, // For qt! macro, if preferred over quote::quote! - syn, - quote::quote_spanned, // Keep for specific span control if needed, or replace with qt! + syn }; use super::EnumVariantHandlerContext; use convert_case::{ Case, Casing }; // Keep for Case::Snake @@ -23,12 +22,12 @@ pub( crate ) fn handle( ctx : &mut EnumVariantHandlerContext< '_ > ) -> Result< // we might need to iterate attributes here to find the span, or use a broader span. // For this refactoring, we'll assume `FieldAttributes` can provide a span for `subform_scalar` if present. // If not, `ctx.variant.span()` is a fallback. - if let Some( attr_property ) = &ctx.variant_attrs.subform_scalar // Assuming FieldAttributes stores it as Option + if let Some( _attr_property ) = &ctx.variant_attrs.subform_scalar // Assuming FieldAttributes stores it as Option { // If AttributeProperty has a span() method or field: // return diag::return_syn_err!( attr_property.span(), "Attribute `subform_scalar` is not applicable to unit variants" ); // Otherwise, using variant span as a fallback: - return diag::return_syn_err!( ctx.variant.span(), "Attribute `subform_scalar` is not applicable to unit variants" ); + diag::return_syn_err!( ctx.variant.span(), "Attribute `subform_scalar` is not applicable to unit variants" ); } let variant_ident = &ctx.variant.ident; @@ -51,7 +50,7 @@ pub( crate ) fn handle( ctx : &mut EnumVariantHandlerContext< '_ > ) -> Result< // Prepare generics using the proposed (conceptual) GenericsRef enhancements // These will also fail to compile until Increment 6. - let generics_ref = GenericsRef::new_borrowed( &ctx.generics ); + let generics_ref = GenericsRef::new_borrowed( ctx.generics ); let fn_signature_generics = generics_ref.impl_generics_tokens_if_any()?; let return_type_generics = generics_ref.ty_generics_tokens_if_any()?; let enum_path_for_construction = generics_ref.type_path_tokens_if_any( enum_name )?; diff --git a/module/core/former_meta/src/derive_former/struct_attrs.rs b/module/core/former_meta/src/derive_former/struct_attrs.rs index dee59783e3..846968b2cf 100644 --- a/module/core/former_meta/src/derive_former/struct_attrs.rs +++ b/module/core/former_meta/src/derive_former/struct_attrs.rs @@ -16,7 +16,7 @@ use macro_tools:: use component_model_types::{ Assign, OptionExt }; /// Represents the attributes of a struct, including storage fields, mutator, perform, and standalone constructor attributes. // <<< Updated doc -#[ derive( Debug ) ] // Removed Default from derive +#[ derive( Debug, Default ) ] // Removed Default from derive pub struct ItemAttributes { /// Optional attribute for storage-specific fields. @@ -31,24 +31,12 @@ pub struct ItemAttributes pub debug : AttributePropertyDebug, // Added debug field } -// Default impl needs to include the new debug field -impl Default for ItemAttributes { - fn default() -> Self { - Self { - storage_fields: Default::default(), - mutator: Default::default(), - perform: Default::default(), - standalone_constructors: Default::default(), - debug: Default::default(), // Initialize debug - } - } -} impl ItemAttributes { /// Parses attributes from an iterator. - /// This function now expects to find #[former(debug, standalone_constructors, ...)] - /// and also handles top-level #[storage_fields(...)], #[mutator(...)], #[perform(...)] + /// This function now expects to find #[former(debug, `standalone_constructors`, ...)] + /// and also handles top-level #[`storage_fields`(...)], #[mutator(...)], #[perform(...)] pub fn from_attrs< 'a >( attrs_iter : impl Iterator< Item = &'a syn::Attribute > ) -> Result< Self > { let mut result = Self::default(); @@ -441,11 +429,11 @@ impl syn::parse::Parse for ItemAttributes { // Initialize fields that are NOT parsed from inside #[former()] here // to their defaults, as this Parse impl is only for former's args. storage_fields: None, - mutator: Default::default(), + mutator: AttributeMutator::default(), perform: None, // These will be overwritten if found - standalone_constructors: Default::default(), - debug: Default::default(), + standalone_constructors: AttributePropertyOptionalSingletone::default(), + debug: AttributePropertyOptionalSingletone::default(), }; while !input.is_empty() { diff --git a/module/core/macro_tools/src/ident.rs b/module/core/macro_tools/src/ident.rs index 3b475f38d4..5a375689ab 100644 --- a/module/core/macro_tools/src/ident.rs +++ b/module/core/macro_tools/src/ident.rs @@ -51,20 +51,25 @@ mod private /// `syn::Ident::new_raw` is used. Otherwise, `syn::Ident::new` is used. /// /// Returns an error if `cased_name_str` is empty or an invalid identifier. + // FIX: Add # Errors documentation section. + /// # Errors + /// + /// This function will return an error in the following cases: + /// - If `cased_name_str` is an empty string. + /// - If `cased_name_str` contains characters that are not valid for a Rust identifier. + /// - If `cased_name_str` would be an invalid identifier (e.g., starts with a number). pub fn new_ident_from_cased_str ( - cased_name_str: &str, - span: proc_macro2::Span, - source_had_raw_prefix: bool - ) -> Result // Use local Result alias + cased_name_str : &str, + span : proc_macro2::Span, + source_had_raw_prefix : bool + ) -> Result< syn::Ident > // Use local Result alias { - if cased_name_str.is_empty() { - return Err(syn::Error::new(span, "Cannot create identifier from empty string")); - } // Comprehensive list of Rust 2021 keywords that are problematic as idents. // Based on https://doc.rust-lang.org/reference/keywords.html - const RUST_KEYWORDS: &[&str] = &[ + const RUST_KEYWORDS: &[ &str ] = + &[ // Strict keywords "as", "break", "const", "continue", "crate", "else", "enum", "extern", "false", "fn", "for", "if", "impl", "in", "let", "loop", "match", "mod", "move", "mut", "pub", @@ -77,30 +82,39 @@ mod private "dyn", "union", ]; - let is_keyword = RUST_KEYWORDS.contains(&cased_name_str); + if cased_name_str.is_empty() + { + return Err( syn::Error::new( span, "Cannot create identifier from empty string" ) ); + } - if source_had_raw_prefix || is_keyword { + let is_keyword = RUST_KEYWORDS.contains( &cased_name_str ); + + if source_had_raw_prefix || is_keyword + { // Validate if the string is permissible for new_raw, even if it's a keyword. // For example, "123" is not a keyword but also not valid for new_raw("123", span). // A simple validation is to check if it would parse if it *weren't* a keyword. // This is tricky because `syn::parse_str` would fail for actual keywords. // Let's rely on `syn::Ident::new_raw` to do its job, but catch obvious non-ident chars. - if cased_name_str.chars().any(|c| !c.is_alphanumeric() && c != '_') { - if !( cased_name_str.starts_with('_') && cased_name_str.chars().skip(1).all(|c| c.is_alphanumeric() || c == '_') ) && cased_name_str != "_" { - return Err(syn::Error::new(span, format!("Invalid characters in identifier string for raw creation: {}", cased_name_str))); - } + if cased_name_str.chars().any( | c | !c.is_alphanumeric() && c != '_' ) && !( cased_name_str.starts_with( '_' ) && cased_name_str.chars().skip( 1 ).all( | c | c.is_alphanumeric() || c == '_' ) ) && cased_name_str != "_" + { + return Err( syn::Error::new( span, format!( "Invalid characters in identifier string for raw creation: {cased_name_str}" ) ) ); } - Ok(syn::Ident::new_raw(cased_name_str, span)) - } else { + Ok( syn::Ident::new_raw( cased_name_str, span ) ) + } + else + { // Not a keyword and source was not raw. Try to create a normal identifier. // syn::Ident::new would panic on keywords, but we've established it's not a keyword. // It will also panic on other invalid idents like "123" or "with space". // To provide a Result, we attempt to parse it. - match syn::parse_str::(cased_name_str) { - Ok(ident) => Ok(ident), - Err(_e) => { + match syn::parse_str::< syn::Ident >( cased_name_str ) + { + Ok( ident ) => Ok( ident ), + Err( _e ) => + { // Construct a new error, because the error from parse_str might not have the right span or context. - Err(syn::Error::new(span, format!("Invalid identifier string: '{}'", cased_name_str))) + Err( syn::Error::new( span, format!( "Invalid identifier string: '{cased_name_str}'" ) ) ) } } } diff --git a/module/core/pth/src/path/absolute_path.rs b/module/core/pth/src/path/absolute_path.rs index dd0af7a665..0fe344ece1 100644 --- a/module/core/pth/src/path/absolute_path.rs +++ b/module/core/pth/src/path/absolute_path.rs @@ -167,7 +167,7 @@ mod private if !is_absolute( &path ) { - return Err( io::Error::new( io::ErrorKind::Other, format!( "Path expected to be absolute, but it's not {path:?}" ) ) ); + return Err( io::Error::other( format!( "Path expected to be absolute, but it's not {}", path.display() ) ) ); } Ok( Self( path ) ) @@ -260,7 +260,7 @@ mod private #[ inline ] fn try_from( src : &'a AbsolutePath ) -> Result< &'a str, Self::Error > { - src.to_str().ok_or_else( || io::Error::new( io::ErrorKind::Other, format!( "Can't convert &PathBuf into &str {src}" ) ) ) + src.to_str().ok_or_else( || io::Error::other( format!( "Can't convert &PathBuf into &str {src}" ) ) ) } } diff --git a/module/core/pth/src/path/canonical_path.rs b/module/core/pth/src/path/canonical_path.rs index b45be827c0..ab1c26a574 100644 --- a/module/core/pth/src/path/canonical_path.rs +++ b/module/core/pth/src/path/canonical_path.rs @@ -229,7 +229,7 @@ mod private .to_str() .ok_or_else ( - move || io::Error::new( io::ErrorKind::Other, format!( "Can't convert &PathBuf into &str {src}" ) ) + move || io::Error::other( format!( "Can't convert &PathBuf into &str {src}" ) ) ) } } diff --git a/module/core/pth/src/path/native_path.rs b/module/core/pth/src/path/native_path.rs index 56a249c457..3546590d7c 100644 --- a/module/core/pth/src/path/native_path.rs +++ b/module/core/pth/src/path/native_path.rs @@ -243,7 +243,7 @@ mod private .to_str() .ok_or_else ( - move || io::Error::new( io::ErrorKind::Other, format!( "Can't convert &PathBuf into &str {src}" ) ) + move || io::Error::other( format!( "Can't convert &PathBuf into &str {src}" ) ) ) } } diff --git a/module/move/willbe/Cargo.toml b/module/move/willbe/Cargo.toml index ebd0c226d2..8086d5372b 100644 --- a/module/move/willbe/Cargo.toml +++ b/module/move/willbe/Cargo.toml @@ -1,7 +1,7 @@ # module/move/willbe/Cargo.toml [package] name = "willbe" -version = "0.21.0" +version = "0.20.0" edition = "2021" authors = [ "Kostiantyn Wandalen ", diff --git a/module/move/willbe/src/action/cicd_renew.rs b/module/move/willbe/src/action/cicd_renew.rs index cec1aae1c8..e5866f1e0a 100644 --- a/module/move/willbe/src/action/cicd_renew.rs +++ b/module/move/willbe/src/action/cicd_renew.rs @@ -144,7 +144,7 @@ mod private let content = handlebars.render( "module_push", &data )?; file_write( &workflow_file_name, &content )?; - println!( "file_write : {:?}", &workflow_file_name ); + println!( "file_write : {}", &workflow_file_name.display() ); } dbg!( &workflow_root ); diff --git a/module/move/willbe/src/action/crate_doc.rs b/module/move/willbe/src/action/crate_doc.rs index 91f48874a1..864ed984d4 100644 --- a/module/move/willbe/src/action/crate_doc.rs +++ b/module/move/willbe/src/action/crate_doc.rs @@ -104,7 +104,7 @@ mod private /// /// # Errors /// Returns an error if the command arguments are invalid, the workspace cannot be loaded - #[allow(clippy::too_many_lines)] + #[ allow( clippy::too_many_lines, clippy::result_large_err ) ] pub fn doc ( workspace : &Workspace, @@ -123,17 +123,17 @@ mod private // --- Get crate name early for --package argument and file naming --- let manifest_path_for_name = crate_dir.as_ref().join( "Cargo.toml" ); let manifest_content_for_name = fs::read_to_string( &manifest_path_for_name ) - .map_err( CrateDocError::Io ) - .context( format!( "Failed to read Cargo.toml at {}", manifest_path_for_name.display() ) ) - .err_with_report( &report )?; + .map_err( CrateDocError::Io ) + .context( format!( "Failed to read Cargo.toml at {}", manifest_path_for_name.display() ) ) + .err_with_report( &report )?; let manifest_toml_for_name = manifest_content_for_name.parse::< Document >() - .map_err( CrateDocError::Toml ) - .context( format!( "Failed to parse Cargo.toml at {}", manifest_path_for_name.display() ) ) - .err_with_report( &report )?; + .map_err( CrateDocError::Toml ) + .context( format!( "Failed to parse Cargo.toml at {}", manifest_path_for_name.display() ) ) + .err_with_report( &report )?; let crate_name = manifest_toml_for_name[ "package" ][ "name" ] - .as_str() - .ok_or_else( || CrateDocError::MissingPackageName( manifest_path_for_name.clone() ) ) - .err_with_report( &report )?; + .as_str() + .ok_or_else( || CrateDocError::MissingPackageName( manifest_path_for_name.clone() ) ) + .err_with_report( &report )?; // --- End get crate name early --- // Define the arguments for `cargo doc` diff --git a/module/move/willbe/src/action/list.rs b/module/move/willbe/src/action/list.rs index baa74feed0..3ed25a206d 100644 --- a/module/move/willbe/src/action/list.rs +++ b/module/move/willbe/src/action/list.rs @@ -324,10 +324,10 @@ mod private } #[ allow( clippy::trivially_copy_pass_by_ref, clippy::needless_lifetimes ) ] - fn process_package_dependency< 'a > + fn process_package_dependency ( workspace : &Workspace, - package : &WorkspacePackageRef< 'a >, + package : &WorkspacePackageRef< '_ >, args : &ListOptions, dep_rep : &mut tool::ListNodeReport, visited : &mut collection::HashSet< DependencyId > diff --git a/module/move/willbe/src/action/publish.rs b/module/move/willbe/src/action/publish.rs index c926c43063..99d9dd4223 100644 --- a/module/move/willbe/src/action/publish.rs +++ b/module/move/willbe/src/action/publish.rs @@ -110,7 +110,6 @@ mod private /// /// # Arguments /// * `patterns` - A vector of patterns specifying the folders to search for packages. - /// * `exclude_dev_dependencies` - A boolean value indicating whether to exclude dev dependencies from manifest before publish. /// * `dry` - A boolean value indicating whether to perform a dry run. /// * `temp` - A boolean value indicating whether to use a temporary directory. /// @@ -121,8 +120,6 @@ mod private ( patterns : Vec< String >, channel : channel::Channel, - exclude_dev_dependencies : bool, - commit_changes : bool, dry : bool, temp : bool ) @@ -219,7 +216,6 @@ mod private &tmp, &packages_to_publish, dir.clone(), - exclude_dev_dependencies )?; let subgraph = subgraph .map( | _, n | n, | _, e | e ); @@ -239,8 +235,6 @@ mod private .channel( channel ) .workspace_dir( CrateDir::try_from( workspace_root_dir ).unwrap() ) .option_base_temp_dir( dir.clone() ) - .exclude_dev_dependencies( exclude_dev_dependencies ) - .commit_changes( commit_changes ) .dry( dry ) .roots( roots ) .packages( queue ) diff --git a/module/move/willbe/src/action/publish_diff.rs b/module/move/willbe/src/action/publish_diff.rs index f170053773..c204ac5bce 100644 --- a/module/move/willbe/src/action/publish_diff.rs +++ b/module/move/willbe/src/action/publish_diff.rs @@ -22,7 +22,6 @@ mod private pub struct PublishDiffOptions { path : PathBuf, - exclude_dev_dependencies : bool, keep_archive : Option< PathBuf >, } @@ -169,7 +168,7 @@ mod private std::fs::write( local_path, content )?; } } - diffs.insert( path, crate_diff( &l, &r, o.exclude_dev_dependencies ).exclude( diff::PUBLISH_IGNORE_LIST ) ); + diffs.insert( path, crate_diff( &l, &r ).exclude( diff::PUBLISH_IGNORE_LIST ) ); let report = tasks[ current_idx ].info.normal_dependencies.clone(); let printer : Vec< TreePrinter > = report .iter() diff --git a/module/move/willbe/src/command/mod.rs b/module/move/willbe/src/command/mod.rs index 8423756275..bf215440aa 100644 --- a/module/move/willbe/src/command/mod.rs +++ b/module/move/willbe/src/command/mod.rs @@ -27,16 +27,6 @@ mod private .kind( Type::String ) .optional( true ) .end() - .property( "exclude_dev_dependencies" ) - .hint( "Setting this option to true will temporarily remove development dependencies before executing the command, then restore them afterward. Default is `true`." ) - .kind( Type::Bool ) - .optional( true ) - .end() - .property( "commit_changes" ) - .hint( "Indicates whether changes should be committed. Default is `false`." ) - .kind( Type::Bool ) - .optional( true ) - .end() .property( "dry" ) .hint( "Enables 'dry run'. Does not publish, only simulates. Default is `true`." ) .kind( Type::Bool ) @@ -59,11 +49,6 @@ mod private .kind( Type::Path ) .optional( true ) .end() - .property( "exclude_dev_dependencies" ) - .hint( "Setting this option to true will temporarily remove development dependencies before executing the command, then restore them afterward. Default is `true`." ) - .kind( Type::Bool ) - .optional( true ) - .end() .property( "keep_archive" ) .hint( "Save remote package version to the specified path" ) .kind( Type::Path ) diff --git a/module/move/willbe/src/command/publish.rs b/module/move/willbe/src/command/publish.rs index 17622a61a1..004bb3dec8 100644 --- a/module/move/willbe/src/command/publish.rs +++ b/module/move/willbe/src/command/publish.rs @@ -17,10 +17,6 @@ mod private { #[ former( default = Channel::Stable ) ] channel : Channel, - #[ former( default = false ) ] - exclude_dev_dependencies : bool, - #[ former( default = false ) ] - commit_changes : bool, #[ former( default = true ) ] dry : bool, #[ former( default = true ) ] @@ -56,12 +52,10 @@ mod private let PublishProperties { channel, - exclude_dev_dependencies, - commit_changes, dry, temp } = o.props.try_into()?; - let plan = action::publish_plan( patterns, channel, exclude_dev_dependencies, commit_changes, dry, temp ) + let plan = action::publish_plan( patterns, channel, dry, temp ) .context( "Failed to plan the publication process" )?; let mut formatted_plan = String::new(); @@ -116,10 +110,6 @@ mod private else { this }; - this = if let Some( v ) = value - .get_owned( "exclude_dev_dependencies" ) { this.exclude_dev_dependencies::< bool >( v ) } else { this }; - this = if let Some( v ) = value - .get_owned( "commit_changes" ) { this.commit_changes::< bool >( v ) } else { this }; this = if let Some( v ) = value .get_owned( "dry" ) { this.dry::< bool >( v ) } else { this }; this = if let Some( v ) = value diff --git a/module/move/willbe/src/command/publish_diff.rs b/module/move/willbe/src/command/publish_diff.rs index 240dc1e7f8..babfa4a629 100644 --- a/module/move/willbe/src/command/publish_diff.rs +++ b/module/move/willbe/src/command/publish_diff.rs @@ -14,8 +14,6 @@ mod private #[ derive( former::Former ) ] struct PublishDiffProperties { - #[ former( default = false ) ] - exclude_dev_dependencies : bool, keep_archive : Option< PathBuf >, } @@ -38,11 +36,10 @@ mod private pub fn publish_diff( o : VerifiedCommand ) -> error::untyped::Result< () > // qqq : use typed error { let path : PathBuf = o.args.get_owned( 0 ).unwrap_or( std::env::current_dir()? ); - let PublishDiffProperties { keep_archive, exclude_dev_dependencies } = o.props.try_into()?; + let PublishDiffProperties { keep_archive } = o.props.try_into()?; let mut o = action::PublishDiffOptions::former() - .path( path ) - .exclude_dev_dependencies( exclude_dev_dependencies ); + .path( path ); if let Some( k ) = keep_archive.clone() { o = o.keep_archive( k ); } let o = o.form(); @@ -64,12 +61,6 @@ mod private { let mut this = Self::former(); - this = if let Some( v ) = value - .get_owned( "exclude_dev_dependencies" ) - { this.exclude_dev_dependencies::< bool >( v ) } - else - { this }; - this = if let Some( v ) = value .get_owned( "keep_archive" ) { this.keep_archive::< PathBuf >( v ) } diff --git a/module/move/willbe/src/entity/diff.rs b/module/move/willbe/src/entity/diff.rs index 99f7f2e1af..58438896f4 100644 --- a/module/move/willbe/src/entity/diff.rs +++ b/module/move/willbe/src/entity/diff.rs @@ -162,7 +162,7 @@ mod private /// # Panics /// qqq: doc #[ must_use ] - pub fn crate_diff( left : &CrateArchive, right : &CrateArchive, exclude_dev_dependencies : bool ) -> DiffReport + pub fn crate_diff( left : &CrateArchive, right : &CrateArchive ) -> DiffReport { let mut report = DiffReport::default(); @@ -189,38 +189,10 @@ mod private { // unwraps are safe because the paths to the files was compared previously - let mut local = left.content_bytes( path ).unwrap(); - let mut remote = right.content_bytes( path ).unwrap(); + let local = left.content_bytes( path ).unwrap(); + let remote = right.content_bytes( path ).unwrap(); - let ( l, r ) = if path.ends_with( "Cargo.toml.orig" ) && exclude_dev_dependencies - { - - let local = std::str::from_utf8( left.content_bytes( path ).unwrap() ).unwrap(); - let mut local_data = local.parse::< toml_edit::Document >().unwrap(); - local_data.remove( "dev-dependencies" ); - let local = local_data.to_string().as_bytes().to_vec(); - - - let remote = std::str::from_utf8( right.content_bytes( path ).unwrap() ).unwrap(); - let mut remote_data = remote.parse::< toml_edit::Document >().unwrap(); - remote_data.remove( "dev-dependencies" ); - let remote = remote_data.to_string().as_bytes().to_vec(); - - ( local, remote ) - } - else - { - ( vec![], vec![] ) - }; - - - if !l.is_empty() && !r.is_empty() - { - local = l.as_slice(); - remote = r.as_slice(); - } - if local == remote { report.0.insert( path.to_path_buf(), DiffItem::File( Diff::Same( () ) ) ); diff --git a/module/move/willbe/src/entity/files/crate_dir.rs b/module/move/willbe/src/entity/files/crate_dir.rs index eab1ed5a1d..2ac4340956 100644 --- a/module/move/willbe/src/entity/files/crate_dir.rs +++ b/module/move/willbe/src/entity/files/crate_dir.rs @@ -147,7 +147,7 @@ impl TryFrom< AbsolutePath > for CrateDir { if !crate_dir_path.as_ref().join( "Cargo.toml" ).is_file() { - let err = io::Error::new( io::ErrorKind::InvalidData, format!( "Cannot find crate dir at {crate_dir_path:?}" ) ); + let err = io::Error::new( io::ErrorKind::InvalidData, format!( "Cannot find crate dir at {}", crate_dir_path.display() ) ); return Err( PathError::Io( err ) ); } Ok( Self( crate_dir_path ) ) diff --git a/module/move/willbe/src/entity/files/manifest_file.rs b/module/move/willbe/src/entity/files/manifest_file.rs index cb6286647c..ee17d3352b 100644 --- a/module/move/willbe/src/entity/files/manifest_file.rs +++ b/module/move/willbe/src/entity/files/manifest_file.rs @@ -157,13 +157,13 @@ impl TryFrom< AbsolutePath > for ManifestFile if !manifest_file.as_ref().ends_with( "Cargo.toml" ) { - let err = io::Error::new( io::ErrorKind::Other, format!( "File path does not end with Cargo.toml as it should {manifest_file:?}" ) ); + let err = io::Error::other( format!( "File path does not end with Cargo.toml as it should {}", manifest_file.display() ) ); return Err( PathError::Io( err ) ); } if !manifest_file.as_ref().is_file() { - let err = io::Error::new( io::ErrorKind::InvalidData, format!( "Cannot find crate dir at {manifest_file:?}" ) ); + let err = io::Error::new( io::ErrorKind::InvalidData, format!( "Cannot find crate dir at {}", manifest_file.display() ) ); return Err( PathError::Io( err ) ); } Ok( Self( manifest_file ) ) diff --git a/module/move/willbe/src/entity/package.rs b/module/move/willbe/src/entity/package.rs index dc8965e209..b5de716391 100644 --- a/module/move/willbe/src/entity/package.rs +++ b/module/move/willbe/src/entity/package.rs @@ -219,7 +219,7 @@ mod private /// Panics if the package is not loaded or local package is not packed. /// # Errors /// qqq: doc - pub fn publish_need( package : &Package< '_ >, path : Option< path::PathBuf >, exclude_dev_dependencies : bool ) -> Result< bool, PackageError > + pub fn publish_need( package : &Package< '_ >, path : Option< path::PathBuf > ) -> Result< bool, PackageError > { let name = package.name()?; let version = package.version()?; @@ -236,7 +236,7 @@ mod private _ => return Err( PackageError::LoadRemotePackage ), }; - Ok( diff::crate_diff( &local_package, &remote_package, exclude_dev_dependencies ).exclude( diff::PUBLISH_IGNORE_LIST ).has_changes() ) + Ok( diff::crate_diff( &local_package, &remote_package ).exclude( diff::PUBLISH_IGNORE_LIST ).has_changes() ) } } diff --git a/module/move/willbe/src/entity/publish.rs b/module/move/willbe/src/entity/publish.rs index f5e03c4fe7..a34d8e0195 100644 --- a/module/move/willbe/src/entity/publish.rs +++ b/module/move/willbe/src/entity/publish.rs @@ -28,7 +28,7 @@ mod private /// Options for bumping the package version. pub bump : version::BumpOptions, /// Git options related to the package. - pub git_options : Option< entity::git::GitOptions >, + pub git_options : entity::git::GitOptions, /// Options for publishing the package using Cargo. pub publish : cargo::PublishOptions, /// Indicates whether the process should be dry-run (no actual publishing). @@ -45,8 +45,6 @@ mod private channel : channel::Channel, base_temp_dir : Option< path::PathBuf >, #[ former( default = true ) ] - commit_changes : bool, - #[ former( default = true ) ] dry : bool, } @@ -77,16 +75,13 @@ mod private dependencies : dependencies.clone(), dry : self.dry, }; - let git_options = if self.commit_changes + let git_options = entity::git::GitOptions { - Some( entity::git::GitOptions - { - git_root : workspace_root, - items : dependencies.iter().chain( [ &crate_dir ] ).map( | d | d.clone().absolute_path().join( "Cargo.toml" ) ).collect(), - message : format!( "{}-v{}", self.package.name().unwrap(), new_version ), - dry : self.dry, - }) - } else { None }; + git_root : workspace_root, + items : dependencies.iter().chain( [ &crate_dir ] ).map( | d | d.clone().absolute_path().join( "Cargo.toml" ) ).collect(), + message : format!( "{}-v{}", self.package.name().unwrap(), new_version ), + dry : self.dry, + }; let publish = cargo::PublishOptions { path : crate_dir.clone().absolute_path().inner(), @@ -128,14 +123,6 @@ mod private /// Release channels for rust. pub channel : channel::Channel, - /// Setting this option to true will temporarily remove development dependencies before executing the command, then restore them afterward. - #[ allow( dead_code ) ] // former related - pub exclude_dev_dependencies : bool, - - /// Indicates whether changes should be committed. - #[ former( default = true ) ] - pub commit_changes : bool, - /// `dry` - A boolean value indicating whether to do a dry run. If set to `true`, the application performs /// a simulated run without making any actual changes. If set to `false`, the operations are actually executed. /// This property is optional and defaults to `true`. @@ -262,10 +249,6 @@ mod private { plan = plan.dry( dry ); } - if let Some( commit_changes ) = &self.storage.commit_changes - { - plan = plan.commit_changes( *commit_changes ); - } let plan = plan .channel( channel ) .package( package ) @@ -370,7 +353,7 @@ mod private /// /// # Errors /// qqq: doc - #[ allow( clippy::option_map_unit_fn ) ] + #[ allow( clippy::option_map_unit_fn, clippy::result_large_err ) ] pub fn perform_package_publish( instruction : PackagePublishInstruction ) -> ResultWithReport< PublishReport, Error > { let mut report = PublishReport::default(); @@ -385,7 +368,7 @@ mod private } = instruction; pack.dry = dry; bump.dry = dry; - git_options.as_mut().map( | d | d.dry = dry ); + git_options.dry = dry; publish.dry = dry; report.get_info = Some( cargo::pack( pack ).err_with_report( &report )? ); @@ -393,50 +376,38 @@ mod private let bump_report = version::bump( bump ).err_with_report( &report )?; report.bump = Some( bump_report.clone() ); - let git_root = git_options.as_ref().map( | g | g.git_root.clone() ); - if let Some( git_options ) = git_options + let git_root = git_options.git_root.clone(); + let git = match entity::git::perform_git_commit( git_options ) { - let git = match entity::git::perform_git_commit( git_options ) + Ok( git ) => git, + Err( e ) => { - Ok( git ) => git, - Err( e ) => - { - version::revert( &bump_report ) - .map_err( | le | format_err! - ( - "Base error:\n{}\nRevert error:\n{}", e.to_string().replace( '\n', "\n\t" ), le.to_string().replace( '\n', "\n\t" ) - )) - .err_with_report( &report )?; - return Err( ( report, e ) ); - } - }; - report.add = git.add; - report.commit = git.commit; - } + version::revert( &bump_report ) + .map_err( | le | format_err!( "Base error:\n{}\nRevert error:\n{}", e.to_string().replace( '\n', "\n\t" ), le.to_string().replace( '\n', "\n\t" ) ) ) + .err_with_report( &report )?; + return Err( ( report, e ) ); + } + }; + report.add = git.add; + report.commit = git.commit; report.publish = match cargo::publish( publish ) { Ok( publish ) => Some( publish ), Err( e ) => { - if let Some( git_root ) = git_root.as_ref() - { - tool::git::reset( git_root.as_ref(), true, 1, false ) - .map_err - ( - | le | - format_err!( "Base error:\n{}\nRevert error:\n{}", e.to_string().replace( '\n', "\n\t" ), le.to_string().replace( '\n', "\n\t" ) ) - ) - .err_with_report( &report )?; - } + tool::git::reset( git_root.as_ref(), true, 1, false ) + .map_err + ( + | le | + format_err!( "Base error:\n{}\nRevert error:\n{}", e.to_string().replace( '\n', "\n\t" ), le.to_string().replace( '\n', "\n\t" ) ) + ) + .err_with_report( &report )?; return Err( ( report, e ) ); } }; - if let Some( git_root ) = git_root.as_ref() - { - let res = tool::git::push( git_root, dry ).err_with_report( &report )?; - report.push = Some( res ); - } + let res = tool::git::push( &git_root, dry ).err_with_report( &report )?; + report.push = Some( res ); Ok( report ) } diff --git a/module/move/willbe/src/tool/graph.rs b/module/move/willbe/src/tool/graph.rs index 92a4f61ff1..e0ba9bc109 100644 --- a/module/move/willbe/src/tool/graph.rs +++ b/module/move/willbe/src/tool/graph.rs @@ -273,7 +273,6 @@ mod private graph : &Graph< String, String >, roots : &[ String ], temp_path : Option< PathBuf >, - exclude_dev_dependencies : bool, ) -> error::untyped::Result< Graph< String, String > > // qqq : use typed error! @@ -306,7 +305,7 @@ mod private .allow_dirty( true ) .form() )?; - if publish_need( package, temp_path.clone(), exclude_dev_dependencies ).unwrap() + if publish_need( package, temp_path.clone() ).unwrap() { nodes.insert( n ); } diff --git a/module/move/willbe/tests/inc/entity/diff.rs b/module/move/willbe/tests/inc/entity/diff.rs index ec8af5b6e6..9c84aa6cc1 100644 --- a/module/move/willbe/tests/inc/entity/diff.rs +++ b/module/move/willbe/tests/inc/entity/diff.rs @@ -24,7 +24,7 @@ fn no_changes() let right_crate = crate_file_path( &right ); let right_archive = CrateArchive::read( &right_crate ).unwrap(); - let has_changes = crate_diff( &left_archive, &right_archive, false ).exclude( diff::PUBLISH_IGNORE_LIST ).has_changes(); + let has_changes = crate_diff( &left_archive, &right_archive ).exclude( diff::PUBLISH_IGNORE_LIST ).has_changes(); assert!( !has_changes ); } @@ -65,7 +65,7 @@ fn with_changes() CrateArchive::read( &right_crate ).unwrap() }; - let has_changes = crate_diff( &left, &right, false ).exclude( diff::PUBLISH_IGNORE_LIST ).has_changes(); + let has_changes = crate_diff( &left, &right ).exclude( diff::PUBLISH_IGNORE_LIST ).has_changes(); assert!( has_changes ); } diff --git a/module/move/willbe/tests/inc/package.rs b/module/move/willbe/tests/inc/package.rs index c9b84d5a89..0a2a07dd05 100644 --- a/module/move/willbe/tests/inc/package.rs +++ b/module/move/willbe/tests/inc/package.rs @@ -260,8 +260,6 @@ fn kos_plan() channel::Channel::Stable, false, false, - true, - false, ) .unwrap(); From ecfcfb3a070847dbd518fd7f9f5b24408110a3e6 Mon Sep 17 00:00:00 2001 From: SupperZum Date: Wed, 25 Jun 2025 16:40:03 +0300 Subject: [PATCH 2/2] only fix --- Cargo.toml | 2 +- module/move/willbe/Cargo.toml | 2 +- module/move/willbe/src/action/cicd_renew.rs | 2 +- module/move/willbe/src/action/crate_doc.rs | 20 ++--- module/move/willbe/src/action/list.rs | 4 +- module/move/willbe/src/action/publish.rs | 6 ++ module/move/willbe/src/action/publish_diff.rs | 3 +- module/move/willbe/src/command/mod.rs | 15 ++++ module/move/willbe/src/command/publish.rs | 12 ++- .../move/willbe/src/command/publish_diff.rs | 13 ++- module/move/willbe/src/entity/diff.rs | 34 ++++++- .../move/willbe/src/entity/files/crate_dir.rs | 2 +- .../willbe/src/entity/files/manifest_file.rs | 4 +- module/move/willbe/src/entity/package.rs | 4 +- module/move/willbe/src/entity/publish.rs | 89 ++++++++++++------- module/move/willbe/src/tool/graph.rs | 3 +- module/move/willbe/tests/inc/entity/diff.rs | 4 +- module/move/willbe/tests/inc/package.rs | 2 + 18 files changed, 161 insertions(+), 60 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index dd7995daf8..911dfcaed0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -478,7 +478,7 @@ path = "module/move/wcensor" ## willbe [workspace.dependencies.willbe] -version = "~0.20.0" +version = "~0.21.0" path = "module/move/willbe" diff --git a/module/move/willbe/Cargo.toml b/module/move/willbe/Cargo.toml index 8086d5372b..ebd0c226d2 100644 --- a/module/move/willbe/Cargo.toml +++ b/module/move/willbe/Cargo.toml @@ -1,7 +1,7 @@ # module/move/willbe/Cargo.toml [package] name = "willbe" -version = "0.20.0" +version = "0.21.0" edition = "2021" authors = [ "Kostiantyn Wandalen ", diff --git a/module/move/willbe/src/action/cicd_renew.rs b/module/move/willbe/src/action/cicd_renew.rs index e5866f1e0a..cec1aae1c8 100644 --- a/module/move/willbe/src/action/cicd_renew.rs +++ b/module/move/willbe/src/action/cicd_renew.rs @@ -144,7 +144,7 @@ mod private let content = handlebars.render( "module_push", &data )?; file_write( &workflow_file_name, &content )?; - println!( "file_write : {}", &workflow_file_name.display() ); + println!( "file_write : {:?}", &workflow_file_name ); } dbg!( &workflow_root ); diff --git a/module/move/willbe/src/action/crate_doc.rs b/module/move/willbe/src/action/crate_doc.rs index 864ed984d4..91f48874a1 100644 --- a/module/move/willbe/src/action/crate_doc.rs +++ b/module/move/willbe/src/action/crate_doc.rs @@ -104,7 +104,7 @@ mod private /// /// # Errors /// Returns an error if the command arguments are invalid, the workspace cannot be loaded - #[ allow( clippy::too_many_lines, clippy::result_large_err ) ] + #[allow(clippy::too_many_lines)] pub fn doc ( workspace : &Workspace, @@ -123,17 +123,17 @@ mod private // --- Get crate name early for --package argument and file naming --- let manifest_path_for_name = crate_dir.as_ref().join( "Cargo.toml" ); let manifest_content_for_name = fs::read_to_string( &manifest_path_for_name ) - .map_err( CrateDocError::Io ) - .context( format!( "Failed to read Cargo.toml at {}", manifest_path_for_name.display() ) ) - .err_with_report( &report )?; + .map_err( CrateDocError::Io ) + .context( format!( "Failed to read Cargo.toml at {}", manifest_path_for_name.display() ) ) + .err_with_report( &report )?; let manifest_toml_for_name = manifest_content_for_name.parse::< Document >() - .map_err( CrateDocError::Toml ) - .context( format!( "Failed to parse Cargo.toml at {}", manifest_path_for_name.display() ) ) - .err_with_report( &report )?; + .map_err( CrateDocError::Toml ) + .context( format!( "Failed to parse Cargo.toml at {}", manifest_path_for_name.display() ) ) + .err_with_report( &report )?; let crate_name = manifest_toml_for_name[ "package" ][ "name" ] - .as_str() - .ok_or_else( || CrateDocError::MissingPackageName( manifest_path_for_name.clone() ) ) - .err_with_report( &report )?; + .as_str() + .ok_or_else( || CrateDocError::MissingPackageName( manifest_path_for_name.clone() ) ) + .err_with_report( &report )?; // --- End get crate name early --- // Define the arguments for `cargo doc` diff --git a/module/move/willbe/src/action/list.rs b/module/move/willbe/src/action/list.rs index 3ed25a206d..baa74feed0 100644 --- a/module/move/willbe/src/action/list.rs +++ b/module/move/willbe/src/action/list.rs @@ -324,10 +324,10 @@ mod private } #[ allow( clippy::trivially_copy_pass_by_ref, clippy::needless_lifetimes ) ] - fn process_package_dependency + fn process_package_dependency< 'a > ( workspace : &Workspace, - package : &WorkspacePackageRef< '_ >, + package : &WorkspacePackageRef< 'a >, args : &ListOptions, dep_rep : &mut tool::ListNodeReport, visited : &mut collection::HashSet< DependencyId > diff --git a/module/move/willbe/src/action/publish.rs b/module/move/willbe/src/action/publish.rs index 99d9dd4223..c926c43063 100644 --- a/module/move/willbe/src/action/publish.rs +++ b/module/move/willbe/src/action/publish.rs @@ -110,6 +110,7 @@ mod private /// /// # Arguments /// * `patterns` - A vector of patterns specifying the folders to search for packages. + /// * `exclude_dev_dependencies` - A boolean value indicating whether to exclude dev dependencies from manifest before publish. /// * `dry` - A boolean value indicating whether to perform a dry run. /// * `temp` - A boolean value indicating whether to use a temporary directory. /// @@ -120,6 +121,8 @@ mod private ( patterns : Vec< String >, channel : channel::Channel, + exclude_dev_dependencies : bool, + commit_changes : bool, dry : bool, temp : bool ) @@ -216,6 +219,7 @@ mod private &tmp, &packages_to_publish, dir.clone(), + exclude_dev_dependencies )?; let subgraph = subgraph .map( | _, n | n, | _, e | e ); @@ -235,6 +239,8 @@ mod private .channel( channel ) .workspace_dir( CrateDir::try_from( workspace_root_dir ).unwrap() ) .option_base_temp_dir( dir.clone() ) + .exclude_dev_dependencies( exclude_dev_dependencies ) + .commit_changes( commit_changes ) .dry( dry ) .roots( roots ) .packages( queue ) diff --git a/module/move/willbe/src/action/publish_diff.rs b/module/move/willbe/src/action/publish_diff.rs index c204ac5bce..f170053773 100644 --- a/module/move/willbe/src/action/publish_diff.rs +++ b/module/move/willbe/src/action/publish_diff.rs @@ -22,6 +22,7 @@ mod private pub struct PublishDiffOptions { path : PathBuf, + exclude_dev_dependencies : bool, keep_archive : Option< PathBuf >, } @@ -168,7 +169,7 @@ mod private std::fs::write( local_path, content )?; } } - diffs.insert( path, crate_diff( &l, &r ).exclude( diff::PUBLISH_IGNORE_LIST ) ); + diffs.insert( path, crate_diff( &l, &r, o.exclude_dev_dependencies ).exclude( diff::PUBLISH_IGNORE_LIST ) ); let report = tasks[ current_idx ].info.normal_dependencies.clone(); let printer : Vec< TreePrinter > = report .iter() diff --git a/module/move/willbe/src/command/mod.rs b/module/move/willbe/src/command/mod.rs index bf215440aa..8423756275 100644 --- a/module/move/willbe/src/command/mod.rs +++ b/module/move/willbe/src/command/mod.rs @@ -27,6 +27,16 @@ mod private .kind( Type::String ) .optional( true ) .end() + .property( "exclude_dev_dependencies" ) + .hint( "Setting this option to true will temporarily remove development dependencies before executing the command, then restore them afterward. Default is `true`." ) + .kind( Type::Bool ) + .optional( true ) + .end() + .property( "commit_changes" ) + .hint( "Indicates whether changes should be committed. Default is `false`." ) + .kind( Type::Bool ) + .optional( true ) + .end() .property( "dry" ) .hint( "Enables 'dry run'. Does not publish, only simulates. Default is `true`." ) .kind( Type::Bool ) @@ -49,6 +59,11 @@ mod private .kind( Type::Path ) .optional( true ) .end() + .property( "exclude_dev_dependencies" ) + .hint( "Setting this option to true will temporarily remove development dependencies before executing the command, then restore them afterward. Default is `true`." ) + .kind( Type::Bool ) + .optional( true ) + .end() .property( "keep_archive" ) .hint( "Save remote package version to the specified path" ) .kind( Type::Path ) diff --git a/module/move/willbe/src/command/publish.rs b/module/move/willbe/src/command/publish.rs index 004bb3dec8..17622a61a1 100644 --- a/module/move/willbe/src/command/publish.rs +++ b/module/move/willbe/src/command/publish.rs @@ -17,6 +17,10 @@ mod private { #[ former( default = Channel::Stable ) ] channel : Channel, + #[ former( default = false ) ] + exclude_dev_dependencies : bool, + #[ former( default = false ) ] + commit_changes : bool, #[ former( default = true ) ] dry : bool, #[ former( default = true ) ] @@ -52,10 +56,12 @@ mod private let PublishProperties { channel, + exclude_dev_dependencies, + commit_changes, dry, temp } = o.props.try_into()?; - let plan = action::publish_plan( patterns, channel, dry, temp ) + let plan = action::publish_plan( patterns, channel, exclude_dev_dependencies, commit_changes, dry, temp ) .context( "Failed to plan the publication process" )?; let mut formatted_plan = String::new(); @@ -110,6 +116,10 @@ mod private else { this }; + this = if let Some( v ) = value + .get_owned( "exclude_dev_dependencies" ) { this.exclude_dev_dependencies::< bool >( v ) } else { this }; + this = if let Some( v ) = value + .get_owned( "commit_changes" ) { this.commit_changes::< bool >( v ) } else { this }; this = if let Some( v ) = value .get_owned( "dry" ) { this.dry::< bool >( v ) } else { this }; this = if let Some( v ) = value diff --git a/module/move/willbe/src/command/publish_diff.rs b/module/move/willbe/src/command/publish_diff.rs index babfa4a629..240dc1e7f8 100644 --- a/module/move/willbe/src/command/publish_diff.rs +++ b/module/move/willbe/src/command/publish_diff.rs @@ -14,6 +14,8 @@ mod private #[ derive( former::Former ) ] struct PublishDiffProperties { + #[ former( default = false ) ] + exclude_dev_dependencies : bool, keep_archive : Option< PathBuf >, } @@ -36,10 +38,11 @@ mod private pub fn publish_diff( o : VerifiedCommand ) -> error::untyped::Result< () > // qqq : use typed error { let path : PathBuf = o.args.get_owned( 0 ).unwrap_or( std::env::current_dir()? ); - let PublishDiffProperties { keep_archive } = o.props.try_into()?; + let PublishDiffProperties { keep_archive, exclude_dev_dependencies } = o.props.try_into()?; let mut o = action::PublishDiffOptions::former() - .path( path ); + .path( path ) + .exclude_dev_dependencies( exclude_dev_dependencies ); if let Some( k ) = keep_archive.clone() { o = o.keep_archive( k ); } let o = o.form(); @@ -61,6 +64,12 @@ mod private { let mut this = Self::former(); + this = if let Some( v ) = value + .get_owned( "exclude_dev_dependencies" ) + { this.exclude_dev_dependencies::< bool >( v ) } + else + { this }; + this = if let Some( v ) = value .get_owned( "keep_archive" ) { this.keep_archive::< PathBuf >( v ) } diff --git a/module/move/willbe/src/entity/diff.rs b/module/move/willbe/src/entity/diff.rs index 58438896f4..99f7f2e1af 100644 --- a/module/move/willbe/src/entity/diff.rs +++ b/module/move/willbe/src/entity/diff.rs @@ -162,7 +162,7 @@ mod private /// # Panics /// qqq: doc #[ must_use ] - pub fn crate_diff( left : &CrateArchive, right : &CrateArchive ) -> DiffReport + pub fn crate_diff( left : &CrateArchive, right : &CrateArchive, exclude_dev_dependencies : bool ) -> DiffReport { let mut report = DiffReport::default(); @@ -189,10 +189,38 @@ mod private { // unwraps are safe because the paths to the files was compared previously - let local = left.content_bytes( path ).unwrap(); - let remote = right.content_bytes( path ).unwrap(); + let mut local = left.content_bytes( path ).unwrap(); + let mut remote = right.content_bytes( path ).unwrap(); + let ( l, r ) = if path.ends_with( "Cargo.toml.orig" ) && exclude_dev_dependencies + { + + let local = std::str::from_utf8( left.content_bytes( path ).unwrap() ).unwrap(); + let mut local_data = local.parse::< toml_edit::Document >().unwrap(); + local_data.remove( "dev-dependencies" ); + let local = local_data.to_string().as_bytes().to_vec(); + + + let remote = std::str::from_utf8( right.content_bytes( path ).unwrap() ).unwrap(); + let mut remote_data = remote.parse::< toml_edit::Document >().unwrap(); + remote_data.remove( "dev-dependencies" ); + let remote = remote_data.to_string().as_bytes().to_vec(); + + ( local, remote ) + } + else + { + ( vec![], vec![] ) + }; + + + if !l.is_empty() && !r.is_empty() + { + local = l.as_slice(); + remote = r.as_slice(); + } + if local == remote { report.0.insert( path.to_path_buf(), DiffItem::File( Diff::Same( () ) ) ); diff --git a/module/move/willbe/src/entity/files/crate_dir.rs b/module/move/willbe/src/entity/files/crate_dir.rs index 2ac4340956..eab1ed5a1d 100644 --- a/module/move/willbe/src/entity/files/crate_dir.rs +++ b/module/move/willbe/src/entity/files/crate_dir.rs @@ -147,7 +147,7 @@ impl TryFrom< AbsolutePath > for CrateDir { if !crate_dir_path.as_ref().join( "Cargo.toml" ).is_file() { - let err = io::Error::new( io::ErrorKind::InvalidData, format!( "Cannot find crate dir at {}", crate_dir_path.display() ) ); + let err = io::Error::new( io::ErrorKind::InvalidData, format!( "Cannot find crate dir at {crate_dir_path:?}" ) ); return Err( PathError::Io( err ) ); } Ok( Self( crate_dir_path ) ) diff --git a/module/move/willbe/src/entity/files/manifest_file.rs b/module/move/willbe/src/entity/files/manifest_file.rs index ee17d3352b..cb6286647c 100644 --- a/module/move/willbe/src/entity/files/manifest_file.rs +++ b/module/move/willbe/src/entity/files/manifest_file.rs @@ -157,13 +157,13 @@ impl TryFrom< AbsolutePath > for ManifestFile if !manifest_file.as_ref().ends_with( "Cargo.toml" ) { - let err = io::Error::other( format!( "File path does not end with Cargo.toml as it should {}", manifest_file.display() ) ); + let err = io::Error::new( io::ErrorKind::Other, format!( "File path does not end with Cargo.toml as it should {manifest_file:?}" ) ); return Err( PathError::Io( err ) ); } if !manifest_file.as_ref().is_file() { - let err = io::Error::new( io::ErrorKind::InvalidData, format!( "Cannot find crate dir at {}", manifest_file.display() ) ); + let err = io::Error::new( io::ErrorKind::InvalidData, format!( "Cannot find crate dir at {manifest_file:?}" ) ); return Err( PathError::Io( err ) ); } Ok( Self( manifest_file ) ) diff --git a/module/move/willbe/src/entity/package.rs b/module/move/willbe/src/entity/package.rs index b5de716391..dc8965e209 100644 --- a/module/move/willbe/src/entity/package.rs +++ b/module/move/willbe/src/entity/package.rs @@ -219,7 +219,7 @@ mod private /// Panics if the package is not loaded or local package is not packed. /// # Errors /// qqq: doc - pub fn publish_need( package : &Package< '_ >, path : Option< path::PathBuf > ) -> Result< bool, PackageError > + pub fn publish_need( package : &Package< '_ >, path : Option< path::PathBuf >, exclude_dev_dependencies : bool ) -> Result< bool, PackageError > { let name = package.name()?; let version = package.version()?; @@ -236,7 +236,7 @@ mod private _ => return Err( PackageError::LoadRemotePackage ), }; - Ok( diff::crate_diff( &local_package, &remote_package ).exclude( diff::PUBLISH_IGNORE_LIST ).has_changes() ) + Ok( diff::crate_diff( &local_package, &remote_package, exclude_dev_dependencies ).exclude( diff::PUBLISH_IGNORE_LIST ).has_changes() ) } } diff --git a/module/move/willbe/src/entity/publish.rs b/module/move/willbe/src/entity/publish.rs index a34d8e0195..f5e03c4fe7 100644 --- a/module/move/willbe/src/entity/publish.rs +++ b/module/move/willbe/src/entity/publish.rs @@ -28,7 +28,7 @@ mod private /// Options for bumping the package version. pub bump : version::BumpOptions, /// Git options related to the package. - pub git_options : entity::git::GitOptions, + pub git_options : Option< entity::git::GitOptions >, /// Options for publishing the package using Cargo. pub publish : cargo::PublishOptions, /// Indicates whether the process should be dry-run (no actual publishing). @@ -45,6 +45,8 @@ mod private channel : channel::Channel, base_temp_dir : Option< path::PathBuf >, #[ former( default = true ) ] + commit_changes : bool, + #[ former( default = true ) ] dry : bool, } @@ -75,13 +77,16 @@ mod private dependencies : dependencies.clone(), dry : self.dry, }; - let git_options = entity::git::GitOptions + let git_options = if self.commit_changes { - git_root : workspace_root, - items : dependencies.iter().chain( [ &crate_dir ] ).map( | d | d.clone().absolute_path().join( "Cargo.toml" ) ).collect(), - message : format!( "{}-v{}", self.package.name().unwrap(), new_version ), - dry : self.dry, - }; + Some( entity::git::GitOptions + { + git_root : workspace_root, + items : dependencies.iter().chain( [ &crate_dir ] ).map( | d | d.clone().absolute_path().join( "Cargo.toml" ) ).collect(), + message : format!( "{}-v{}", self.package.name().unwrap(), new_version ), + dry : self.dry, + }) + } else { None }; let publish = cargo::PublishOptions { path : crate_dir.clone().absolute_path().inner(), @@ -123,6 +128,14 @@ mod private /// Release channels for rust. pub channel : channel::Channel, + /// Setting this option to true will temporarily remove development dependencies before executing the command, then restore them afterward. + #[ allow( dead_code ) ] // former related + pub exclude_dev_dependencies : bool, + + /// Indicates whether changes should be committed. + #[ former( default = true ) ] + pub commit_changes : bool, + /// `dry` - A boolean value indicating whether to do a dry run. If set to `true`, the application performs /// a simulated run without making any actual changes. If set to `false`, the operations are actually executed. /// This property is optional and defaults to `true`. @@ -249,6 +262,10 @@ mod private { plan = plan.dry( dry ); } + if let Some( commit_changes ) = &self.storage.commit_changes + { + plan = plan.commit_changes( *commit_changes ); + } let plan = plan .channel( channel ) .package( package ) @@ -353,7 +370,7 @@ mod private /// /// # Errors /// qqq: doc - #[ allow( clippy::option_map_unit_fn, clippy::result_large_err ) ] + #[ allow( clippy::option_map_unit_fn ) ] pub fn perform_package_publish( instruction : PackagePublishInstruction ) -> ResultWithReport< PublishReport, Error > { let mut report = PublishReport::default(); @@ -368,7 +385,7 @@ mod private } = instruction; pack.dry = dry; bump.dry = dry; - git_options.dry = dry; + git_options.as_mut().map( | d | d.dry = dry ); publish.dry = dry; report.get_info = Some( cargo::pack( pack ).err_with_report( &report )? ); @@ -376,38 +393,50 @@ mod private let bump_report = version::bump( bump ).err_with_report( &report )?; report.bump = Some( bump_report.clone() ); - let git_root = git_options.git_root.clone(); - let git = match entity::git::perform_git_commit( git_options ) + let git_root = git_options.as_ref().map( | g | g.git_root.clone() ); + if let Some( git_options ) = git_options { - Ok( git ) => git, - Err( e ) => + let git = match entity::git::perform_git_commit( git_options ) { - version::revert( &bump_report ) - .map_err( | le | format_err!( "Base error:\n{}\nRevert error:\n{}", e.to_string().replace( '\n', "\n\t" ), le.to_string().replace( '\n', "\n\t" ) ) ) - .err_with_report( &report )?; - return Err( ( report, e ) ); - } - }; - report.add = git.add; - report.commit = git.commit; + Ok( git ) => git, + Err( e ) => + { + version::revert( &bump_report ) + .map_err( | le | format_err! + ( + "Base error:\n{}\nRevert error:\n{}", e.to_string().replace( '\n', "\n\t" ), le.to_string().replace( '\n', "\n\t" ) + )) + .err_with_report( &report )?; + return Err( ( report, e ) ); + } + }; + report.add = git.add; + report.commit = git.commit; + } report.publish = match cargo::publish( publish ) { Ok( publish ) => Some( publish ), Err( e ) => { - tool::git::reset( git_root.as_ref(), true, 1, false ) - .map_err - ( - | le | - format_err!( "Base error:\n{}\nRevert error:\n{}", e.to_string().replace( '\n', "\n\t" ), le.to_string().replace( '\n', "\n\t" ) ) - ) - .err_with_report( &report )?; + if let Some( git_root ) = git_root.as_ref() + { + tool::git::reset( git_root.as_ref(), true, 1, false ) + .map_err + ( + | le | + format_err!( "Base error:\n{}\nRevert error:\n{}", e.to_string().replace( '\n', "\n\t" ), le.to_string().replace( '\n', "\n\t" ) ) + ) + .err_with_report( &report )?; + } return Err( ( report, e ) ); } }; - let res = tool::git::push( &git_root, dry ).err_with_report( &report )?; - report.push = Some( res ); + if let Some( git_root ) = git_root.as_ref() + { + let res = tool::git::push( git_root, dry ).err_with_report( &report )?; + report.push = Some( res ); + } Ok( report ) } diff --git a/module/move/willbe/src/tool/graph.rs b/module/move/willbe/src/tool/graph.rs index e0ba9bc109..92a4f61ff1 100644 --- a/module/move/willbe/src/tool/graph.rs +++ b/module/move/willbe/src/tool/graph.rs @@ -273,6 +273,7 @@ mod private graph : &Graph< String, String >, roots : &[ String ], temp_path : Option< PathBuf >, + exclude_dev_dependencies : bool, ) -> error::untyped::Result< Graph< String, String > > // qqq : use typed error! @@ -305,7 +306,7 @@ mod private .allow_dirty( true ) .form() )?; - if publish_need( package, temp_path.clone() ).unwrap() + if publish_need( package, temp_path.clone(), exclude_dev_dependencies ).unwrap() { nodes.insert( n ); } diff --git a/module/move/willbe/tests/inc/entity/diff.rs b/module/move/willbe/tests/inc/entity/diff.rs index 9c84aa6cc1..ec8af5b6e6 100644 --- a/module/move/willbe/tests/inc/entity/diff.rs +++ b/module/move/willbe/tests/inc/entity/diff.rs @@ -24,7 +24,7 @@ fn no_changes() let right_crate = crate_file_path( &right ); let right_archive = CrateArchive::read( &right_crate ).unwrap(); - let has_changes = crate_diff( &left_archive, &right_archive ).exclude( diff::PUBLISH_IGNORE_LIST ).has_changes(); + let has_changes = crate_diff( &left_archive, &right_archive, false ).exclude( diff::PUBLISH_IGNORE_LIST ).has_changes(); assert!( !has_changes ); } @@ -65,7 +65,7 @@ fn with_changes() CrateArchive::read( &right_crate ).unwrap() }; - let has_changes = crate_diff( &left, &right ).exclude( diff::PUBLISH_IGNORE_LIST ).has_changes(); + let has_changes = crate_diff( &left, &right, false ).exclude( diff::PUBLISH_IGNORE_LIST ).has_changes(); assert!( has_changes ); } diff --git a/module/move/willbe/tests/inc/package.rs b/module/move/willbe/tests/inc/package.rs index 0a2a07dd05..c9b84d5a89 100644 --- a/module/move/willbe/tests/inc/package.rs +++ b/module/move/willbe/tests/inc/package.rs @@ -260,6 +260,8 @@ fn kos_plan() channel::Channel::Stable, false, false, + true, + false, ) .unwrap();