Skip to content

Commit

Permalink
Merge pull request #1146 from SRetip/readme_headers_generate
Browse files Browse the repository at this point in the history
READY (willbe): add `readme.headers.generate` command
  • Loading branch information
Wandalen authored May 31, 2024
2 parents 07d22ed + 5105ac4 commit 6f00d47
Show file tree
Hide file tree
Showing 7 changed files with 355 additions and 46 deletions.
134 changes: 113 additions & 21 deletions module/move/willbe/src/action/main_header.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
mod private
{
use crate::*;
use std::fmt::{ Display, Formatter };
use std::fs::
{
OpenOptions
Expand All @@ -12,9 +13,8 @@ mod private
SeekFrom,
Write
};
use std::path::PathBuf;
use regex::Regex;
use wtools::error::err;
use error_tools::Result;
use wca::wtools::anyhow::Error;
use action::readme_health_table_renew::
{
Expand All @@ -23,19 +23,83 @@ mod private
};
use _path::AbsolutePath;
use { CrateDir, query, url, Workspace, wtools };
use error_tools::for_app::Context;
use wtools::error::anyhow::
use entity::{ CrateDirError, WorkspaceError };
use wtools::error::
{
format_err
anyhow::format_err,
err,
for_app::
{
Result,
Error as wError,
Context,
},
};

use error_tools::
{
dependency::*,
for_lib::Error,
};

static TAGS_TEMPLATE : std::sync::OnceLock< Regex > = std::sync::OnceLock::new();

fn regexes_initialize()
{
TAGS_TEMPLATE.set( Regex::new( r"<!--\{ generate\.main_header\.start(\(\)|\{\}|\(.*?\)|\{.*?\}) \}-->(.|\n|\r\n)+<!--\{ generate\.main_header\.end \}-->" ).unwrap() ).ok();
}

/// Report.
#[ derive( Debug, Default, Clone ) ]
pub struct MainHeaderRenewReport
{
found_file : Option< PathBuf >,
touched_file : PathBuf,
success : bool,
}

impl Display for MainHeaderRenewReport
{
fn fmt( &self, f : &mut Formatter< '_ > ) -> std::fmt::Result
{
if self.success
{
if let Some( file_path ) = self.touched_file.to_str()
{
writeln!( f, "File successful changed : {file_path}." )?;
}
else
{
writeln!( f, "File successful changed but contains non-UTF-8 characters." )?;
}
}
else
{
if let Some( Some( file_path ) ) = self.found_file.as_ref().map( | p | p.to_str() )
{
writeln!( f, "File found but not changed : {file_path}." )?;
}
else
{
writeln!( f, "File not found or contains non-UTF-8 characters." )?;
}
}
Ok( () )
}
}

#[ derive( Debug, Error ) ]
pub enum MainHeaderRenewError
{
#[ error( "Common error: {0}" ) ]
Common(#[ from ] wError ),
#[ error( "I/O error: {0}" ) ]
IO( #[ from ] std::io::Error ),
#[ error( "Workspace error: {0}" ) ]
Workspace( #[ from ] WorkspaceError),
#[ error( "Directory error: {0}" ) ]
Directory( #[ from ] CrateDirError ),
}

/// The `HeaderParameters` structure represents a set of parameters, used for creating url for header.
struct HeaderParameters
{
Expand All @@ -48,7 +112,7 @@ mod private
impl HeaderParameters
{
/// Create `HeaderParameters` instance from the folder where Cargo.toml is stored.
fn from_cargo_toml( workspace : Workspace ) -> Result< Self >
fn from_cargo_toml( workspace : Workspace ) -> Result< Self, MainHeaderRenewError >
{
let repository_url = workspace.repository_url()?.ok_or_else::< Error, _ >( || err!( "repo_url not found in workspace Cargo.toml" ) )?;
let master_branch = workspace.master_branch()?.unwrap_or( "master".into() );
Expand All @@ -68,7 +132,7 @@ mod private
}

/// Convert `Self`to header.
fn to_header( self ) -> Result< String >
fn to_header( self ) -> Result< String, MainHeaderRenewError >
{
let discord = self.discord_url.map( | discord |
format!( "\n[![discord](https://img.shields.io/discord/872391416519737405?color=eee&logo=discord&logoColor=eee&label=ask)]({discord})" )
Expand Down Expand Up @@ -114,21 +178,40 @@ mod private
/// [![docs.rs](https://raster.shields.io/static/v1?label=docs&message=online&color=eee&logo=docsdotrs&logoColor=eee)](https://docs.rs/wtools)
/// <!--{ generate.main_header.end }-->
/// ```
pub fn readme_header_renew( path : AbsolutePath ) -> Result< () >
pub fn readme_header_renew( path : AbsolutePath ) -> Result< MainHeaderRenewReport, ( MainHeaderRenewReport, MainHeaderRenewError ) >
{
let mut report = MainHeaderRenewReport::default();
regexes_initialize();

let mut cargo_metadata = Workspace::with_crate_dir( CrateDir::try_from( path )? )?;
let workspace_root = workspace_root( &mut cargo_metadata )?;
let header_param = HeaderParameters::from_cargo_toml( cargo_metadata )?;
let read_me_path = workspace_root.join( readme_path( &workspace_root ).ok_or_else( || format_err!( "Fail to find README.md" ) )?);
let mut cargo_metadata = Workspace::with_crate_dir
(
CrateDir::try_from( path )
.map_err( | e | ( report.clone(), e.into() ) )?
).map_err( | e | ( report.clone(), e.into() ) )?;

let workspace_root = workspace_root( &mut cargo_metadata )
.map_err( | e | ( report.clone(), e.into() ) )?;

let header_param = HeaderParameters::from_cargo_toml( cargo_metadata )
.map_err( | e | ( report.clone(), e.into() ) )?;

let read_me_path = workspace_root.join
(
readme_path( &workspace_root )
.ok_or_else( || format_err!( "Fail to find README.md" ) )
.map_err( | e | ( report.clone(), e.into() ) )?
);

report.found_file = Some( read_me_path.clone() );

let mut file = OpenOptions::new()
.read( true )
.write( true )
.open( &read_me_path )?;
.open( &read_me_path )
.map_err( | e | ( report.clone(), e.into() ) )?;

let mut content = String::new();
file.read_to_string( &mut content )?;
file.read_to_string( &mut content ).map_err( | e | ( report.clone(), e.into() ) )?;

let raw_params = TAGS_TEMPLATE
.get()
Expand All @@ -140,17 +223,26 @@ mod private

_ = query::parse( raw_params ).context( "Fail to parse arguments" );

let header = header_param.to_header()?;
let content : String = TAGS_TEMPLATE.get().unwrap().replace( &content, &format!( "<!--{{ generate.main_header.start{raw_params} }}-->\n{header}\n<!--{{ generate.main_header.end }}-->" ) ).into();
file.set_len( 0 )?;
file.seek( SeekFrom::Start( 0 ) )?;
file.write_all( content.as_bytes() )?;
Ok( () )
let header = header_param.to_header().map_err( | e | ( report.clone(), e.into() ) )?;
let content : String = TAGS_TEMPLATE.get().unwrap().replace
(
&content,
&format!( "<!--{{ generate.main_header.start{raw_params} }}-->\n{header}\n<!--{{ generate.main_header.end }}-->" )
).into();

file.set_len( 0 ).map_err( | e | ( report.clone(), e.into() ) )?;
file.seek( SeekFrom::Start( 0 ) ).map_err( | e | ( report.clone(), e.into() ) )?;
file.write_all( content.as_bytes() ).map_err( | e | ( report.clone(), e.into() ) )?;
report.touched_file = read_me_path;
report.success = true;
Ok( report )
}
}

crate::mod_interface!
{
/// Generate header.
orphan use readme_header_renew;
/// Report.
orphan use MainHeaderRenewReport;
}
Loading

0 comments on commit 6f00d47

Please sign in to comment.