Skip to content

Commit

Permalink
Merge pull request #1230 from Barsik-sus/willbe_publish_diff
Browse files Browse the repository at this point in the history
READY : (willbe): Add "publish_diff" command and related functions
  • Loading branch information
Wandalen authored Mar 21, 2024
2 parents e2cb41a + d243fe1 commit 635f8fd
Show file tree
Hide file tree
Showing 8 changed files with 241 additions and 1 deletion.
16 changes: 16 additions & 0 deletions module/core/process_tools/src/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,22 @@ pub( crate ) mod private

report.out = out;

let err = String::from_utf8( output.stderr )
.context( "Found invalid UTF-8" )
.map_err( | e |
{
report.error = Err( e.into() );
Err::< (), () >( () )
});

if err.is_err()
{
return Err( report );
}
let err = err.unwrap();

report.err = err;

if output.status.success()
{
Ok( report )
Expand Down
2 changes: 2 additions & 0 deletions module/move/willbe/src/action/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ crate::mod_interface!
layer main_header;
/// Publish packages.
layer publish;
/// Return the differences between a local and remote package versions.
layer publish_diff;
/// Generates health table in main Readme.md file of workspace.
// aaa : for Petro : give high quality explanations
// aaa : add more details to description
Expand Down
38 changes: 38 additions & 0 deletions module/move/willbe/src/action/publish_diff.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/// Internal namespace.
mod private
{
use crate::*;

use std::path::PathBuf;
use crates_tools::CrateArchive;

use _path::AbsolutePath;
use wtools::error::for_app::Result;
use diff::{ DiffReport, crate_diff };

/// Return the differences between a local and remote package versions.
#[ cfg_attr( feature = "tracing", tracing::instrument ) ]
pub fn publish_diff( path : PathBuf ) -> Result< DiffReport >
{
let path = AbsolutePath::try_from( path )?;
let dir = CrateDir::try_from( path )?;

let package = package::Package::try_from( dir.clone() )?;
let name = &package.name()?;
let version = &package.version()?;

_ = cargo::pack( cargo::PackOptions::former().path( dir.as_ref() ).dry( false ).form() )?;
let l = CrateArchive::read( packed_crate::local_path( name, version, dir )? )?;
let r = CrateArchive::download_crates_io( name, version ).unwrap();

Ok( crate_diff( &l, &r ) )
}
}

//

crate::mod_interface!
{
/// Publishes the difference between the local and published versions of a package.
orphan use publish_diff;
}
13 changes: 13 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,17 @@ pub( crate ) mod private
.routine( command::publish )
.end()

.command( "publish.diff" )
.hint( "Display the differences between a local and remote package versions." )
.long_hint( "Following this command, you will immediately get a comparison between the local and remote packages. It looks at each file, identifying those added, removed, or modified. A full report will then be generated where you can quickly and easily see the differences." )
.subject()
.hint( "Provide path to the package that you want to check.\n\t The path should point to a directory that contains a `Cargo.toml` file." )
.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 +248,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
39 changes: 39 additions & 0 deletions module/move/willbe/src/command/publish_diff.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
mod private
{
use crate::*;

use std::path::PathBuf;
use wca::Args;

use wtools::error::Result;

/// Command to display the differences between a local and remote package versions.
///
/// # Arguments
///
/// * `args` - Command line arguments.
///
/// # Returns
///
/// Returns a `Result` indicating success or failure.
///
/// # Errors
///
/// Returns an error if there is an issue with the command.
pub fn publish_diff( args : Args ) -> Result< () >
{
let path : PathBuf = args.get_owned( 0 ).unwrap_or( std::env::current_dir()? );

println!( "{}", action::publish_diff( path )? );

Ok( () )
}
}

//

crate::mod_interface!
{
/// Publishes the difference between the local and published versions of a package.
orphan use publish_diff;
}
113 changes: 113 additions & 0 deletions module/move/willbe/src/entity/diff.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
mod private
{
use crate::*;

use std::
{
collections::HashSet,
fmt::Formatter,
path::PathBuf,
};
use colored::Colorize;
use crates_tools::CrateArchive;

use wtools::iter::Itertools;

/// The `Diff` enum is designed to represent differences between two versions
/// of some kind of item identified.
#[ derive( Debug ) ]
pub enum Diff< T >
{
/// This variant represents items that are identical or same in both versions.
Same( T ),
/// This variant represents items that exists in both versions but have been modified.
Modified( T ),
/// This variant represents items that were added.
Add( T ),
/// This variant represents items that were removed.
Rem( T ),
}

/// The `DiffReport` struct represents a diff report containing a list of `Diff` objects.
#[ derive( Debug, Default ) ]
pub struct DiffReport( Vec< Diff< PathBuf > > );

impl std::fmt::Display for DiffReport
{
fn fmt( &self, f : &mut Formatter< '_ > ) -> std::fmt::Result
{
for diff in self.0.iter()
.sorted_by_key( | d | match d { Diff::Modified( df ) | Diff::Same( df ) | Diff::Rem( df ) | Diff::Add( df ) => df } )
{
match diff
{
Diff::Same( t ) => writeln!( f, "{}", t.display() )?,
Diff::Modified( t ) => writeln!( f, "~ {}", t.to_string_lossy().yellow() )?,
Diff::Add( t ) => writeln!( f, "+ {}", t.to_string_lossy().green() )?,
Diff::Rem( t ) => writeln!( f, "- {}", t.to_string_lossy().red() )?,
};
}

Ok( () )
}
}

/// Compare two crate archives and create a difference report.
///
/// # Arguments
///
/// * `left` - A reference to the left crate archive.
/// * `right` - A reference to the right crate archive.
///
/// # Returns
///
/// A `DiffReport` struct representing the difference between the two crate archives.
pub 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.push( Diff::Add( path.to_path_buf() ) );
}

for &path in remote_only
{
report.0.push( Diff::Rem( path.to_path_buf() ) );
}

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();

if local == remote
{
report.0.push( Diff::Same( path.to_path_buf() ) );
}
else
{
report.0.push( Diff::Modified( path.to_path_buf() ) );
}
}

report
}
}

//

crate::mod_interface!
{
protected use Diff;
protected use DiffReport;
protected use crate_diff;
}
4 changes: 4 additions & 0 deletions module/move/willbe/src/entity/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
crate::mod_interface!
{

/// Compare two crate archives and create a difference report.
layer diff;
orphan use super::diff;

/// Operation with features
layer features;
orphan use super::features;
Expand Down
17 changes: 16 additions & 1 deletion module/move/willbe/src/entity/package.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,22 @@ mod private
}
}

impl TryFrom< CrateDir > for Package
{
type Error = PackageError;

fn try_from( value : CrateDir ) -> Result< Self, Self::Error >
{
let manifest = manifest::open( value.absolute_path().join( "Cargo.toml" ) )?;
if !manifest.package_is()?
{
return Err( PackageError::NotAPackage );
}

Ok( Self::Manifest( manifest ) )
}
}

impl TryFrom< Manifest > for Package
{
// qqq : make better errors
Expand Down Expand Up @@ -744,7 +760,6 @@ mod private

Ok( !is_same )
}

}

//
Expand Down

0 comments on commit 635f8fd

Please sign in to comment.