From abf9dd384d5dfbeb057994737c19cb4ce9679d08 Mon Sep 17 00:00:00 2001 From: hasezoey Date: Tue, 5 Sep 2023 12:40:18 +0200 Subject: [PATCH] feat(lib): keep track of what happened to files and also print them in the binary for status --- src/bin/main.rs | 14 +++++++++- src/file.rs | 24 +++++++++++++--- src/lib.rs | 74 ++++++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 103 insertions(+), 9 deletions(-) diff --git a/src/bin/main.rs b/src/bin/main.rs index 57ad5bb3..80c087cf 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -1,5 +1,6 @@ use clap::{CommandFactory, Parser, Subcommand}; use clap_complete::{generate, Shell}; +use dsync::FileChangeStatus; use dsync::{error::IOErrorToError, GenerationConfig, TableOptions}; use std::collections::HashMap; use std::io::{BufWriter, Write}; @@ -144,7 +145,7 @@ fn actual_main() -> dsync::Result<()> { default_table_options = default_table_options.disable_fns(); } - dsync::generate_files( + let changes = dsync::generate_files( &args.input, &args.output, GenerationConfig { @@ -156,6 +157,17 @@ fn actual_main() -> dsync::Result<()> { }, )?; + let mut modified: usize = 0; + + for change in changes { + println!("{} {}", change.status, change.file.to_string_lossy()); + if change.status != FileChangeStatus::Unchanged { + modified += 1; + } + } + + println!("Modified {} files", modified); + Ok(()) } diff --git a/src/file.rs b/src/file.rs index ac2cf0b5..82ceb128 100644 --- a/src/file.rs +++ b/src/file.rs @@ -6,6 +6,7 @@ pub struct MarkedFile { pub file_contents: String, /// Path of the read / to write file pub path: PathBuf, + modified: bool, } impl MarkedFile { @@ -13,8 +14,12 @@ impl MarkedFile { /// /// If the file does not exist, a empty file is created pub fn new(path: PathBuf) -> Result { + let mut modified = false; let file_contents = if !path.exists() { + // TODO: should this really be created empty, instead this should likely only be done on save std::fs::write(&path, "").attach_path_err(&path)?; + // set modified, because a file was written + modified = true; "".to_string() } else { std::fs::read_to_string(&path).attach_path_err(&path)? @@ -22,9 +27,14 @@ impl MarkedFile { Ok(MarkedFile { path, file_contents, + modified, }) } + pub fn is_modified(&self) -> bool { + self.modified + } + pub fn has_use_stmt(&self, use_name: &str) -> bool { self.file_contents.contains(&format!("pub use {use_name};")) } @@ -39,7 +49,8 @@ impl MarkedFile { self.file_contents.push('\n'); } self.file_contents - .push_str(&format!("pub use {use_name};\n")) + .push_str(&format!("pub use {use_name};\n")); + self.modified = true; } pub fn add_mod_stmt(&mut self, mod_name: &str) { @@ -48,7 +59,8 @@ impl MarkedFile { self.file_contents.push('\n'); } self.file_contents - .push_str(&format!("pub mod {mod_name};\n")) + .push_str(&format!("pub mod {mod_name};\n")); + self.modified = true; } pub fn remove_use_stmt(&mut self, mod_name: &str) { @@ -59,6 +71,7 @@ impl MarkedFile { .replace(content_to_remove, "") .trim() .to_string(); + self.modified = true; } } @@ -70,6 +83,7 @@ impl MarkedFile { .replace(content_to_remove, "") .trim() .to_string(); + self.modified = true; } } @@ -112,7 +126,9 @@ impl MarkedFile { std::fs::write(&self.path, &self.file_contents).attach_path_err(&self.path) } - pub fn delete(self) -> Result<()> { - std::fs::remove_file(&self.path).attach_path_err(&self.path) + pub fn delete(self) -> Result { + std::fs::remove_file(&self.path).attach_path_err(&self.path)?; + + Ok(self.path) } } diff --git a/src/lib.rs b/src/lib.rs index 006232e1..d1e11a9d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,7 +9,8 @@ use file::MarkedFile; use parser::ParsedTableMacro; pub use parser::FILE_SIGNATURE; use std::collections::HashMap; -use std::path::Path; +use std::fmt::Display; +use std::path::{Path, PathBuf}; /// Options for a individual table #[derive(Debug, Clone)] @@ -177,6 +178,58 @@ pub fn generate_code( parser::parse_and_generate_code(diesel_schema_file_contents, &config) } +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum FileChangeStatus { + /// Status for unchanged file contents + Unchanged, + /// Status for modified file contents + Modified, + /// Status if the file has been deleted + Deleted, +} + +impl Display for FileChangeStatus { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, + "{}", + match self { + FileChangeStatus::Unchanged => "Unchanged", + FileChangeStatus::Modified => "Modified", + FileChangeStatus::Deleted => "Deleted", + } + ) + } +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct FileChange { + /// File in question + pub file: PathBuf, + /// Status of the file + pub status: FileChangeStatus, +} + +impl FileChange { + pub fn new>(path: P, status: FileChangeStatus) -> Self { + Self { + file: path.as_ref().to_owned(), + status, + } + } +} + +// easily create a [FileChange] from a [MarkedFile] +impl From<&MarkedFile> for FileChange { + fn from(value: &MarkedFile) -> Self { + if value.is_modified() { + Self::new(&value.path, FileChangeStatus::Modified) + } else { + Self::new(&value.path, FileChangeStatus::Unchanged) + } + } +} + /// Generate all Models for a given diesel schema file /// /// Models are saved to disk @@ -184,7 +237,7 @@ pub fn generate_files( input_diesel_schema_file: &Path, output_models_dir: &Path, config: GenerationConfig, -) -> Result<()> { +) -> Result> { let generated = generate_code( &std::fs::read_to_string(input_diesel_schema_file) .attach_path_err(input_diesel_schema_file)?, @@ -200,6 +253,9 @@ pub fn generate_files( )); } + // using generated len, because that is very likely the amount (at least) for files + let mut file_changes = Vec::with_capacity(generated.len()); + // check that the mod.rs file exists let mut mod_rs = MarkedFile::new(output_models_dir.join("mod.rs"))?; @@ -222,9 +278,12 @@ pub fn generate_files( table_generated_rs.file_contents = table.generated_code.clone(); table_generated_rs.write()?; + file_changes.push(FileChange::from(&table_generated_rs)); + table_mod_rs.ensure_mod_stmt("generated"); table_mod_rs.ensure_use_stmt("generated::*"); table_mod_rs.write()?; + file_changes.push(FileChange::from(&table_mod_rs)); mod_rs.ensure_mod_stmt(&table.name.to_string()); } @@ -267,6 +326,10 @@ pub fn generate_files( // this table was deleted, let's delete the generated code std::fs::remove_file(&generated_rs_path).attach_path_err(&generated_rs_path)?; + file_changes.push(FileChange::new( + &generated_rs_path, + FileChangeStatus::Deleted, + )); // remove the mod.rs file if there isn't anything left in there except the use stmt let table_mod_rs_path = item.path().join("mod.rs"); @@ -278,9 +341,11 @@ pub fn generate_files( table_mod_rs.write()?; if table_mod_rs.file_contents.trim().is_empty() { - table_mod_rs.delete()?; + let table_mod_rs = table_mod_rs.delete()?; + file_changes.push(FileChange::new(table_mod_rs, FileChangeStatus::Deleted)); } else { table_mod_rs.write()?; // write the changes we made above + file_changes.push(FileChange::from(&table_mod_rs)); } } @@ -300,6 +365,7 @@ pub fn generate_files( } mod_rs.write()?; + file_changes.push(FileChange::from(&mod_rs)); - Ok(()) + Ok(file_changes) }