Skip to content

Commit

Permalink
Add "publish_diff" command and related functions
Browse files Browse the repository at this point in the history
Created a new function called "publish_diff" in publish_diff.rs, registered it as a new command in mod.rs, and added related functions in package.rs. This "publish_diff" feature compares local and published versions of a specific package.
  • Loading branch information
Barsik-sus committed Mar 21, 2024
1 parent fed47e3 commit 2edeb1f
Show file tree
Hide file tree
Showing 3 changed files with 154 additions and 0 deletions.
14 changes: 14 additions & 0 deletions module/move/willbe/src/command/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,18 @@ pub( crate ) mod private
.routine( command::publish )
.end()

// qqq : for Barsik : provide hints
.command( "publish.diff" )
.hint( "---" )
.long_hint( "---" )
.subject()
.hint( "---" )
.kind( Type::Path )
.optional( true )
.end()
.routine( command::publish_diff )
.end()

.command( "list" )
.hint( "list packages from a directory" )
.long_hint( "generates a list of packages based on the provided directory path. The directory must contain a `Cargo.toml` file." )
Expand Down Expand Up @@ -237,6 +249,8 @@ crate::mod_interface!
layer list;
/// Publish packages.
layer publish;
/// Used to compare local and published versions of a specific package.
layer publish_diff;
/// Generates health table in main Readme.md file of workspace.
// aaa : for Petro : what a table??
// aaa : add more details to documentation
Expand Down
28 changes: 28 additions & 0 deletions module/move/willbe/src/command/publish_diff.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
mod private
{
use std::path::PathBuf;
use crate::*;

use { action, wtools };

use wca::{ Args, Props };
use wtools::error::{ for_app::Context, Result };

///
///
///

pub fn publish_diff( args : Args ) -> Result< () >
{
let package : PathBuf = args.get_owned( 0 ).unwrap_or( std::env::current_dir()? );

Ok( () )
}
}

//

crate::mod_interface!
{
orphan use publish_diff;
}
112 changes: 112 additions & 0 deletions module/move/willbe/src/entity/package.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ mod private
use std::hash::Hash;
use std::path::PathBuf;
use cargo_metadata::{ Dependency, DependencyKind, Package as PackageMetadata };
use colored::Colorize;
use toml_edit::value;

use process_tools::process;
Expand All @@ -34,6 +35,7 @@ mod private
};
use action::readme_health_table_renew::Stability;
use former::Former;
use wtools::iter::EitherOrBoth;

///
#[ derive( Debug ) ]
Expand Down Expand Up @@ -745,6 +747,116 @@ mod private
Ok( !is_same )
}

#[ derive( Debug ) ]
enum Diff< T >
{
Same( T ),
Add( T ),
Rem( T ),
}

#[ derive( Debug, Default ) ]
struct DiffReport( HashMap< PathBuf, Vec< Diff< Vec< u8 > > > > );

impl std::fmt::Display for DiffReport
{
fn fmt( &self, f : &mut Formatter< '_ > ) -> std::fmt::Result
{
for ( path, diffs ) in &self.0
{
writeln!( f, "-- begin [{}]", path.display() )?;
for diff in diffs
{
let str = match diff
{
Diff::Same( t ) => String::from_utf8_lossy( t ).into(),
Diff::Add( t ) => format!( "[{}]", String::from_utf8_lossy( t ).green() ),
Diff::Rem( t ) => format!( "{{{}}}", String::from_utf8_lossy( t ).red() ),
};
write!( f, "{str}" )?;
}
writeln!( f, "-- end [{}]", path.display() )?;
}
Ok( () )
}
}

fn crate_diff( left : &CrateArchive, right : &CrateArchive ) -> DiffReport
{
let mut report = DiffReport::default();

let local_package_files : HashSet< _ > = left.list().into_iter().collect();
let remote_package_files : HashSet< _ > = right.list().into_iter().collect();

let local_only = local_package_files.difference( &remote_package_files );
let remote_only = remote_package_files.difference( &local_package_files );
let both = local_package_files.intersection( &remote_package_files );

for &path in local_only
{
report.0.entry( path.to_path_buf() ).or_default().push( Diff::Add( left.content_bytes( path ).unwrap().to_vec() ) );
}

for &path in remote_only
{
report.0.entry( path.to_path_buf() ).or_default().push( Diff::Rem( right.content_bytes( path ).unwrap().to_vec() ) );
}

for &path in both
{
// 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 diffs = Vec::with_capacity( std::cmp::min( local.len(), remote.len() ) );

for pair in local.iter().zip_longest(remote)
{
match pair
{
EitherOrBoth::Both( l, r ) =>
if l == r
{
diffs.push( Diff::Same( *l ) );
}
else
{
diffs.push( Diff::Rem( *r ) );
diffs.push( Diff::Add( *l ) );
}
EitherOrBoth::Left( l ) => diffs.push( Diff::Add( *l ) ),
EitherOrBoth::Right( r ) => diffs.push( Diff::Rem( *r ) ),
}
}
let mut diffs_iter = diffs.iter().peekable();
while let Some( first ) = diffs_iter.next()
{
let mut group = vec![ first ];
while diffs_iter.peek().map_or( false, | &next | std::mem::discriminant( next ) == std::mem::discriminant( &group[ 0 ] ) )
{
group.push( diffs_iter.next().unwrap() );
}
let group = match first
{
Diff::Same( _ ) => Diff::Same( group.into_iter().map( | d | { let Diff::Same( v ) = d else { unreachable!() }; *v } ).collect() ),
Diff::Add( _ ) => Diff::Add( group.into_iter().map( | d | { let Diff::Add( v ) = d else { unreachable!() }; *v } ).collect() ),
Diff::Rem( _ ) => Diff::Rem( group.into_iter().map( | d | { let Diff::Rem( v ) = d else { unreachable!() }; *v } ).collect() ),
};
report.0.entry( path.to_path_buf() ).or_default().push( group );
}
}

report
}

#[ test ]
fn temporary() {
let path = AbsolutePath::try_from(PathBuf::from("../../test/a")).unwrap();
let dir = CrateDir::try_from(path).unwrap();
let l = CrateArchive::read( packed_crate::local_path( "test_experimental_a", "0.3.0", dir ).unwrap() ).unwrap();
let r = CrateArchive::download_crates_io( "test_experimental_a", "0.3.0" ).unwrap();
println!("{}", crate_diff( &l, &r ));
panic!()
}
}

//
Expand Down

0 comments on commit 2edeb1f

Please sign in to comment.