From 7c11f85ad6a04cfe1ebe6b35497f2c9e879cba35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ghignatti=20Nicol=C3=B2?= Date: Sat, 11 Oct 2025 21:49:12 +0200 Subject: [PATCH 1/3] Add error propagation & Fix overindentation in RustDoc --- src/functions/add.rs | 31 ++++++++--------- src/functions/commit.rs | 73 ++++++++++++++++++++--------------------- src/functions/mod.rs | 2 +- src/functions/push.rs | 26 +++++---------- src/main.rs | 4 +-- src/types/commands.rs | 12 +++---- src/types/mod.rs | 2 +- src/types/repository.rs | 10 +++--- 8 files changed, 73 insertions(+), 87 deletions(-) diff --git a/src/functions/add.rs b/src/functions/add.rs index e2df0c2..b92b469 100644 --- a/src/functions/add.rs +++ b/src/functions/add.rs @@ -1,5 +1,5 @@ -use git2::{Error, Repository}; use crate::types::repository::get_current_repository; +use git2::{Error, Repository}; /// Adds a list of files to the staging area (index) of a Git repository. /// @@ -11,7 +11,7 @@ use crate::types::repository::get_current_repository; /// /// * `files` - A reference to a vector of strings representing file paths to add. /// * `repo` - An optional reference to a `Repository`. If `None`, the function tries -/// to find the current repository automatically. +/// to find the current repository automatically. /// /// # Errors /// @@ -26,32 +26,29 @@ use crate::types::repository::get_current_repository; /// * `Ok(0)` on success. pub fn add(files: &Vec, repo: Option<&Repository>) -> Result<(), Error> { let owned_repo; - let current_repo = match repo{ + let current_repo = match repo { Some(r) => r, _ => { - owned_repo = get_current_repository().map_err(|e| e)?; + owned_repo = get_current_repository()?; &owned_repo } }; // get the index (staging area) - let mut index = match current_repo.index() { - Ok(index) => index, - Err(e) => return Err(e), - }; + let mut index = current_repo.index()?; let corrected_files: Vec = if files[0] == "." { - vec![files[0].to_string()] + vec![files[0].to_string()] } else { - files.iter() - .map(|f| { - f.strip_prefix(".\\").unwrap_or(f) - .to_string() - }) + files + .iter() + .map(|f| f.strip_prefix(".\\").unwrap_or(f).to_string()) .collect() }; - index.add_all(corrected_files, git2::IndexAddOption::DEFAULT, None).expect("Error while adding all files"); + index + .add_all(corrected_files, git2::IndexAddOption::DEFAULT, None) + .expect("Error while adding all files"); // write index to disk index.write() @@ -61,9 +58,9 @@ pub fn add(files: &Vec, repo: Option<&Repository>) -> Result<(), Error> mod tests { use super::*; use git2::Repository; - use tempfile::tempdir; use std::fs::File; use std::path::Path; + use tempfile::tempdir; #[test] fn test_add() { @@ -83,4 +80,4 @@ mod tests { let index = repo.index().unwrap(); assert!(index.get_path(Path::new("dummy.txt"), 0).is_some()); } -} \ No newline at end of file +} diff --git a/src/functions/commit.rs b/src/functions/commit.rs index 69c63ac..bc2a47e 100644 --- a/src/functions/commit.rs +++ b/src/functions/commit.rs @@ -1,7 +1,7 @@ -use std::io::Write; +use crate::types::repository::get_current_repository; use git2::{Error, ErrorClass, ErrorCode, Oid, Repository, Signature}; use inquire::{InquireError, Select}; -use crate::types::repository::get_current_repository; +use std::io::Write; fn user_input(message: String) -> String { use std::io; @@ -11,8 +11,8 @@ fn user_input(message: String) -> String { let mut input = String::new(); match io::stdin().read_line(&mut input) { - Ok(_goes_into_input_above) => {}, - Err(_no_updates_is_fine) => {}, + Ok(_goes_into_input_above) => {} + Err(_no_updates_is_fine) => {} } input.trim().to_string() } @@ -105,7 +105,7 @@ fn select_emoji() -> Result { /// # Arguments /// /// * `repo` - An optional reference to a `Repository`. If `None`, the function -/// attempts to find the current repository automatically. +/// attempts to find the current repository automatically. /// /// # Errors /// @@ -119,7 +119,7 @@ fn select_emoji() -> Result { /// /// # Returns /// -/// * `Ok(0)` on successful commit. +/// * `Ok(0)` on a successful commit. /// /// # Workflow /// @@ -132,17 +132,14 @@ fn select_emoji() -> Result { /// - Creates a commit with the assembled information. pub fn commit(repo: Option<&Repository>, debug: bool) -> Result { let owned_repo; - let current_repo = match repo{ + let current_repo = match repo { Some(r) => r, _ => { owned_repo = get_current_repository().map_err(|e| e)?; &owned_repo } }; - let repo_configuration = match current_repo.config() { - Ok(config) => config, - Err(e) => return Err(e) - }; + let repo_configuration = current_repo.config()?; let mut commit_message = String::new(); @@ -156,17 +153,23 @@ pub fn commit(repo: Option<&Repository>, debug: bool) -> Result { } _ => "", }, - Err(e) => return Err(Error::new(ErrorCode::NotFound, ErrorClass::Invalid, e.to_string())) + Err(e) => { + return Err(Error::new( + ErrorCode::NotFound, + ErrorClass::Invalid, + e.to_string(), + )); + } }; commit_message.push_str(emoji); let title = user_input("Provide a commit title > ".to_string()); commit_message.push_str(title.as_str()); - commit_message.push_str("\n"); + commit_message.push('\n'); let message = user_input("Provide a commit message > ".to_string()); commit_message.push_str(message.as_str()); - commit_message.push_str("\n"); + commit_message.push('\n'); let breaking_changes = user_input("Provide a breaking changes description > ".to_string()); commit_message.push_str(format!("BREAKING CHANGES: {}\n", breaking_changes).as_str()); } else { @@ -177,27 +180,16 @@ pub fn commit(repo: Option<&Repository>, debug: bool) -> Result { let email = repo_configuration.get_string("user.email")?.to_string(); // get index and write tree - let mut index = match current_repo.index() { - Ok(idx) => idx, - Err(e) => return Err(e) - }; - let tree_oid = match index.write_tree() { - Ok(oid) => oid, - Err(e) => return Err(e) - }; - let tree = match current_repo.find_tree(tree_oid) { - Ok(idx_tree) => idx_tree, - Err(e) => return Err(e) - }; + let mut index = current_repo.index()?; + let tree_oid = index.write_tree()?; + let tree = current_repo.find_tree(tree_oid)?; // get HEAD commit to set as parent let parents = match current_repo.head() { - Ok(head) => { - match head.peel_to_commit() { - Ok(commit) => vec![commit], - Err(e) => return Err(e), - } - } + Ok(head) => match head.peel_to_commit() { + Ok(commit) => vec![commit], + Err(e) => return Err(e), + }, Err(_) => vec![], // Unborn branch, so NO parent }; @@ -208,7 +200,7 @@ pub fn commit(repo: Option<&Repository>, debug: bool) -> Result { Some("HEAD"), &signature, &signature, - &(commit_message.as_str()), + commit_message.as_str(), &tree, &parent_refs, ) @@ -217,11 +209,10 @@ pub fn commit(repo: Option<&Repository>, debug: bool) -> Result { #[cfg(test)] mod tests { use super::*; + use crate::functions::add::add; use git2::Repository; use std::fs::File; use tempfile::tempdir; - use crate::functions::add::add; - #[test] fn test_commit() { @@ -242,7 +233,15 @@ mod tests { let mut index = repo.index().unwrap(); let tree_id = index.write_tree().unwrap(); tree = repo.find_tree(tree_id).unwrap(); - repo.commit(Some("HEAD"), &signature, &signature, "Initial commit", &tree, &[]).unwrap(); + repo.commit( + Some("HEAD"), + &signature, + &signature, + "Initial commit", + &tree, + &[], + ) + .unwrap(); let result = commit(Some(&repo), true); @@ -252,4 +251,4 @@ mod tests { let commit = head.peel_to_commit().unwrap(); assert_eq!(commit.message().unwrap(), "unit testing"); } -} \ No newline at end of file +} diff --git a/src/functions/mod.rs b/src/functions/mod.rs index 4d2f78b..29a4e3a 100644 --- a/src/functions/mod.rs +++ b/src/functions/mod.rs @@ -1,3 +1,3 @@ pub mod add; pub mod commit; -pub mod push; \ No newline at end of file +pub mod push; diff --git a/src/functions/push.rs b/src/functions/push.rs index afea4a4..b32cebf 100644 --- a/src/functions/push.rs +++ b/src/functions/push.rs @@ -31,7 +31,7 @@ fn create_ssh_callbacks() -> RemoteCallbacks<'static> { /// # Arguments /// /// * `repo` - An optional reference to a `Repository`. If `None`, -/// the function tries to find the current repository automatically. +/// the function tries to find the current repository automatically. /// /// # Errors /// @@ -54,37 +54,27 @@ pub fn push(repo: Option<&Repository>) -> Result<(), Error> { } }; - let head = match current_repo.head() { - Ok(h) => h, - Err(e) => return Err(e), - }; + let head = current_repo.head()?; let branch = head.shorthand().unwrap(); let refspec = format!("refs/heads/{}:refs/heads/{}", branch, branch); let mut push_options = PushOptions::new(); - let repo_configuration = match current_repo.config() { - Ok(config) => config, - Err(e) => return Err(e) - }; + let repo_configuration = current_repo.config()?; - let url = repo_configuration.get_string("remote.origin.url")?.to_string(); + let url = repo_configuration + .get_string("remote.origin.url")? + .to_string(); if !url.contains("https") { let callbacks = create_ssh_callbacks(); push_options.remote_callbacks(callbacks); } else { - let config = match current_repo.config() { - Ok(config) => config, - Err(e) => return Err(e) - }; + let config = current_repo.config()?; let callbacks = create_https_callback(config); push_options.remote_callbacks(callbacks); } - let mut origin = match current_repo.find_remote("origin") { - Ok(org) => org, - Err(e) => return Err(e), - }; + let mut origin = current_repo.find_remote("origin")?; origin.push(&[refspec], Some(&mut push_options)) } diff --git a/src/main.rs b/src/main.rs index 9207894..1c31b1a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,11 +1,11 @@ -mod types; mod functions; +mod types; use clap::Parser; -use types::commands::{Cli, Command}; use functions::add::add; use functions::commit::commit; use functions::push::push; +use types::commands::{Cli, Command}; fn main() { let cli = Cli::parse(); diff --git a/src/types/commands.rs b/src/types/commands.rs index 98d89d5..8b55b03 100644 --- a/src/types/commands.rs +++ b/src/types/commands.rs @@ -8,7 +8,7 @@ use clap::{Parser, Subcommand}; /// # Possible values /// /// * `Add` - Adds one or more files to the staging area. -/// Contains a single field: +/// Contains a single field: /// - `files` - A vector of file paths (`Vec`) to add. /// /// * `Commit` - Creates a new commit with a message enriched with emoji. @@ -17,11 +17,9 @@ use clap::{Parser, Subcommand}; /// #[derive(Subcommand, Debug)] pub(crate) enum Command { - Add { - files: Vec - }, + Add { files: Vec }, Commit, - Push + Push, } /// Command-line interface (CLI) argument parser for the `glyphit` tool. @@ -32,7 +30,7 @@ pub(crate) enum Command { /// # Fields /// /// * `command` - The subcommand specified by the user. Determines the -/// operation the CLI will perform. +/// operation the CLI will perform. /// /// # Usage /// @@ -76,4 +74,4 @@ mod test { let cli = Cli::parse_from(args); assert!(matches!(cli.command, Command::Push)); } -} \ No newline at end of file +} diff --git a/src/types/mod.rs b/src/types/mod.rs index b9f9274..4b28d6f 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -1,2 +1,2 @@ pub mod commands; -pub mod repository; \ No newline at end of file +pub mod repository; diff --git a/src/types/repository.rs b/src/types/repository.rs index 1ce1961..064cc07 100644 --- a/src/types/repository.rs +++ b/src/types/repository.rs @@ -8,7 +8,7 @@ use git2::{Error, Repository}; /// # Returns /// /// * `Ok(Repository)` - The discovered Git repository object. -/// * `Err(Error)` - If no repository could be found or an error occurred while accessing it. +/// * `Err(Error)` - If no repository could be found, or an error occurred while accessing it. pub fn get_current_repository() -> Result { Repository::discover(".") } @@ -22,9 +22,11 @@ mod test { match get_current_repository() { Err(e) => panic!("{}", e.message()), Ok(repo) => { - println!("{:?}", repo.workdir().unwrap().file_name().unwrap().to_str()); - assert!(true) + println!( + "{:?}", + repo.workdir().unwrap().file_name().unwrap().to_str() + ); } } } -} \ No newline at end of file +} From 881a6a5025981b3741ca4b7c5102832a2518a0a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ghignatti=20Nicol=C3=B2?= Date: Sat, 11 Oct 2025 21:49:39 +0200 Subject: [PATCH 2/3] Remove file --- gly.zip | Bin 38214 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 gly.zip diff --git a/gly.zip b/gly.zip deleted file mode 100644 index b3beab3cce8ca832bb4d5bc325fe36a50e704cb0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 38214 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 VwI5T!-4(+a;5`83F`Ogt*MH4!XixwE From 1967be3031add169f07330a249c08aad3aae2c50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ghignatti=20Nicol=C3=B2?= Date: Sat, 11 Oct 2025 22:23:59 +0200 Subject: [PATCH 3/3] Renew the README --- README.md | 255 ++---------------------------------------------------- 1 file changed, 8 insertions(+), 247 deletions(-) diff --git a/README.md b/README.md index 930cf48..65c0a15 100644 --- a/README.md +++ b/README.md @@ -1,253 +1,14 @@ -# 🎨 GlyphIt +

Glyphit

-> **Emoji-powered Git commits made simple** +## ❓ What is Glyphit? -GlyphIt is a blazingly fast, Rust-based CLI tool that brings the power of conventional commits with emojis to your Git workflow. Say goodbye to boring commit messages and hello to expressive, standardized commits that communicate intent at a glance. +Is an open source project which aims to standardize the usage of emojis in git commit. -## ✨ Features +Following the footsteps of [Gitmoji](https://gitmoji.dev/), it aims to provide a fast way to structure your commit, according to a conventional standard. -- **🎯 Interactive Emoji Selection** - Choose from a curated list of conventional commit emojis -- **⚡ Lightning Fast** - Built with Rust for maximum performance -- **🔒 Type-Safe** - Leverages Rust's type system for reliability -- **📦 Zero Dependencies** - Self-contained binaries for all major platforms -- **🎨 Gitmoji Compatible** - Follows the popular gitmoji convention -- **🔄 Full Git Integration** - Seamlessly works with your existing Git workflow +## ❓ How to use Glyphit? +For every question about the projects, from the architecture to the download, consult our [documentation](https://nickghignatti.github.io/glyphit/). -## 🚀 Quick Start +## ™️ License -```bash -# Add files to staging -glyphit add file1.txt file2.txt - -# Create an emoji-powered commit -glyphit commit - -# Push to remote -glyphit push -``` - -## 📥 Installation - -### Download Pre-built Binaries - -Download the latest release for your platform from the [Releases page](https://github.com/yourusername/glyphit/releases): - -#### Linux (x86_64) -```bash -# Download and extract -curl -LO https://github.com/yourusername/glyphit/releases/latest/download/glyphit-Linux-musl-x86_64.tar.gz -tar -xzf glyphit-Linux-musl-x86_64.tar.gz - -# Move to PATH -sudo mv glyphit /usr/local/bin/ -``` - -#### Linux (ARM64) -```bash -# Download and extract -curl -LO https://github.com/yourusername/glyphit/releases/latest/download/glyphit-Linux-musl-arm64.tar.gz -tar -xzf glyphit-Linux-musl-arm64.tar.gz - -# Move to PATH -sudo mv glyphit /usr/local/bin/ -``` - -#### macOS (x86_64) -```bash -# Download and extract -curl -LO https://github.com/yourusername/glyphit/releases/latest/download/glyphit-macOS-x86_64.tar.gz -tar -xzf glyphit-macOS-x86_64.tar.gz - -# Move to PATH -sudo mv glyphit /usr/local/bin/ -``` - -#### Windows (x86_64) -Download `glyphit-Windows-msvc-x86_64.zip` from the releases page, extract it, and add the directory to your PATH. - -### Build from Source - -```bash -# Clone the repository -git clone https://github.com/yourusername/glyphit.git -cd glyphit - -# Build with cargo -cargo build --release - -# The binary will be in target/release/glyphit -``` - -## 📖 Usage - -### Adding Files - -Add files to the staging area just like `git add`: - -```bash -glyphit add src/main.rs -glyphit add file1.txt file2.txt file3.txt -``` - -### Creating Commits - -Launch the interactive commit creator: - -```bash -glyphit commit -``` - -You'll be prompted to: -1. **Select an emoji** from the conventional commit types -2. **Enter a commit message** describing your changes -3. **Add breaking changes** (optional) - -**Available Emoji Types:** - -| Emoji | Code | Description | -|-------|------|-------------| -| 🎨 | `:art:` | Improve structure/format of the code | -| ⚡️ | `:zap:` | Improve performance | -| 🔥 | `:fire:` | Remove code or files | -| 🐛 | `:bug:` | Fix a bug | -| ✨ | `:sparkles:` | Introduce new features | - -### Pushing Changes - -Push your commits to the remote repository: - -```bash -glyphit push -``` - -Supports both HTTPS and SSH authentication methods. - -## 🎯 Complete Workflow Example - -```bash -# Make your changes -echo "new feature" > feature.txt - -# Stage the changes -glyphit add feature.txt - -# Create an emoji commit -glyphit commit -# Select: ✨ :sparkles: Introduce new features -# Message: add new user authentication feature -# Breaking: (leave empty) - -# Push to remote -glyphit push -``` - -## 🏗️ Architecture - -GlyphIt is built with modern software engineering principles: - -- **Domain-Driven Design** - Clear separation of concerns with domain types -- **Test-Driven Development** - Comprehensive test coverage for reliability -- **Functional Core** - Pure functions with minimal side effects -- **Type Safety** - Leverages Rust's strong type system - -### Project Structure - -``` -glyphit/ -├── src/ -│ ├── main.rs # Entry point -│ ├── functions/ # Core Git operations -│ │ ├── add.rs # File staging -│ │ ├── commit.rs # Commit creation -│ │ └── push.rs # Remote pushing -│ └── types/ # Domain types -│ ├── commands.rs # CLI command definitions -│ └── repository.rs # Repository utilities -├── docs/ # Documentation -└── .github/workflows/ # CI/CD pipelines -``` - -## 🔧 Configuration - -GlyphIt uses your existing Git configuration: - -```bash -# Set your Git identity (if not already set) -git config --global user.name "Your Name" -git config --global user.email "your.email@example.com" -``` - -## 🤝 Contributing - -Contributions are welcome! Here's how you can help: - -1. **Fork the repository** -2. **Create a feature branch** (`git checkout -b feature/amazing-feature`) -3. **Make your changes** -4. **Run tests** (`cargo test`) -5. **Commit with GlyphIt** (`glyphit commit`) -6. **Push to your fork** (`glyphit push`) -7. **Open a Pull Request** - -### Development Setup - -```bash -# Clone your fork -git clone https://github.com/yourusername/glyphit.git -cd glyphit - -# Install dependencies and build -cargo build - -# Run tests -cargo test - -# Run with debug output -cargo run -- add file.txt -cargo run -- commit -``` - -## 📋 Requirements - -- **Rust Edition**: 2024 -- **Git**: 2.0 or higher -- **Platforms**: Linux (x86_64, ARM64), macOS (x86_64), Windows (x86_64) - -## 🐛 Troubleshooting - -### Authentication Issues - -**HTTPS Authentication:** -```bash -# Configure credential helper -git config --global credential.helper store -``` - -**SSH Authentication:** -```bash -# Ensure SSH agent is running with your key -ssh-add ~/.ssh/id_rsa -``` - -### Repository Not Found - -Make sure you're in a Git repository: -```bash -git status -``` - -## 📄 License - -This project is licensed under the GLPv3 License - see the [LICENSE](LICENSE) file for details. - -## 🙏 Acknowledgments - -- Inspired by [gitmoji](https://gitmoji.dev/) - An emoji guide for commit messages -- Built with [git2-rs](https://github.com/rust-lang/git2-rs) - Rust bindings to libgit2 -- Powered by [clap](https://github.com/clap-rs/clap) - Command line argument parser - -## 🌟 Star History - -If you find GlyphIt useful, please consider giving it a star! ⭐ - ---- \ No newline at end of file +This code is available under the [GPLv3](LICENSE) license.