pub struct CommitSaver {
pub repository_url: String,
pub commit_branch_name: String,
pub commit_hash: String,
pub commit_msg: String,
pub commit_datetime: DateTime<Utc>,
}Expand description
Stores Git commit metadata for logging to Obsidian diary entries.
This struct captures all essential information about a single Git commit that will be written as a row in the daily diary table. It’s automatically populated from the current Git repository’s HEAD commit.
§Examples
use rusty_commit_saver::CommitSaver;
// Automatically populated from current Git repository
let saver = CommitSaver::new();
println!("Repository: {}", saver.repository_url);
println!("Branch: {}", saver.commit_branch_name);
println!("Hash: {}", saver.commit_hash);
println!("Message: {}", saver.commit_msg);§See Also
CommitSaver::new()- Create a new instance from current Git repoCommitSaver::append_entry_to_diary()- Write commit to diary file
Fields§
§repository_url: StringThe Git remote origin URL.
Retrieved from the repository’s origin remote. Double quotes are stripped.
§Examples
https://github.com/user/repo.gitgit@github.com:user/repo.githttps://git.sr.ht/~user/repo
commit_branch_name: StringThe current Git branch name.
Retrieved from the repository’s HEAD reference. Double quotes are stripped.
§Examples
maindevelopfeature/add-documentation
commit_hash: StringThe full SHA-1 commit hash (40 characters).
Uniquely identifies the commit in the Git repository.
§Format
Always 40 hexadecimal characters (e.g., abc123def456...)
commit_msg: StringThe formatted commit message for Obsidian display.
The message is processed for safe rendering in Markdown tables:
- Pipe characters (
|) are escaped to\| - Multiple lines are joined with
<br/> - Empty lines are filtered out
- Leading/trailing whitespace is trimmed
§Examples
Original: "feat: add feature\n\nWith details"
Formatted: "feat: add feature<br/>With details"
Original: "fix: issue | problem"
Formatted: "fix: issue \| problem"commit_datetime: DateTime<Utc>The UTC timestamp when the commit was created.
Used for:
- Generating date-based directory paths
- Displaying commit time in diary entries
- Creating frontmatter tags (week number, day of week)
§Format
Stored as DateTime<Utc> from the chrono crate.
Implementations§
Source§impl CommitSaver
impl CommitSaver
Sourcepub fn new() -> Self
pub fn new() -> Self
Creates a new CommitSaver instance by discovering the current Git repository.
This function automatically:
- Discovers the Git repository in the current directory (
.) - Extracts commit metadata from the HEAD commit
- Formats the commit message for Obsidian (escapes pipes, adds
<br/>)
§Panics
Panics if:
- No Git repository is found in the current directory
- The repository has no HEAD (uninitialized repo)
- The HEAD cannot be resolved to a commit
§Examples
use rusty_commit_saver::CommitSaver;
let saver = CommitSaver::new();
println!("Commit hash: {}", saver.commit_hash);Sourcefn prepare_commit_entry_as_string(&mut self, path: &Path) -> String
fn prepare_commit_entry_as_string(&mut self, path: &Path) -> String
Formats commit metadata as a Markdown table row for diary entry.
Generates a single table row containing all commit information in the format expected by the Obsidian diary template. The row includes pipe delimiters and ends with a newline.
§Arguments
path- The current working directory where the commit was made
§Returns
A formatted string representing one table row with these columns:
- FOLDER - Current working directory path
- TIME - Commit timestamp (HH:MM:SS format)
- COMMIT MESSAGE - Escaped and formatted commit message
- REPOSITORY URL - Git remote origin URL
- BRANCH - Current branch name
- COMMIT HASH - Full SHA-1 commit hash
§Format
| /path/to/repo | 14:30:45 | feat: add feature | https://github.com/user/repo.git | main | abc123... |§Note
This is a private helper method called by append_entry_to_diary().
The commit message has already been formatted with escaped pipes and <br/> separators
during struct initialization.
Generates Obsidian-style frontmatter tags based on the commit timestamp.
Creates three metadata tags for organizing diary entries:
- Week tag:
#datetime/week/WW(e.g.,#datetime/week/02for week 2) - Day tag:
#datetime/days/DDDD(e.g.,#datetime/days/Monday) - Category tag:
#diary/commits(constant)
These tags are used in the Obsidian diary file’s YAML frontmatter to enable:
- Filtering commits by week number
- Organizing by day of week
- Cross-referencing with other diary entries
§Returns
A vector of three strings containing formatted Obsidian tags
§Examples
use rusty_commit_saver::CommitSaver;
use chrono::{TimeZone, Utc};
let mut saver = CommitSaver {
repository_url: "https://github.com/example/repo.git".to_string(),
commit_branch_name: "main".to_string(),
commit_hash: "abc123".to_string(),
commit_msg: "feat: add feature".to_string(),
commit_datetime: Utc.with_ymd_and_hms(2025, 1, 13, 10, 30, 0).unwrap(), // Monday
};
let tags = saver.prepare_frontmatter_tags();
assert_eq!(tags.len(), 3);
assert!(tags.contains("week"));
assert!(tags.contains("Monday"));[1]
assert_eq!(tags, "#diary/commits");Sourcepub fn prepare_path_for_commit(
&mut self,
obsidian_commit_path: &Path,
template_commit_date_path: &str,
) -> String
pub fn prepare_path_for_commit( &mut self, obsidian_commit_path: &Path, template_commit_date_path: &str, ) -> String
Constructs the full file path for a diary entry based on the commit timestamp.
Combines the Obsidian commit directory path with a date-formatted subdirectory structure to create the final path where the commit entry should be saved.
§Arguments
obsidian_commit_path- Base directory path for commits (e.g.,Diaries/Commits)template_commit_date_path- Chrono format string for the date hierarchy (e.g.,%Y/%m-%B/%F.md)
§Returns
A formatted path string combining the base directory and formatted date
§Format Specifiers (Chrono)
%Y- Year (e.g.,2025)%m- Month as number (e.g.,01)%B- Full month name (e.g.,January)%F- ISO 8601 date (e.g.,2025-01-14.md)%d- Day of month (e.g.,14)
§Panics
Panics if:
- The
obsidian_commit_pathcannot be converted to a valid UTF-8 string - The path contains invalid characters that cannot be represented as a string
§Examples
use rusty_commit_saver::CommitSaver;
use std::path::PathBuf;
use chrono::{TimeZone, Utc};
let mut saver = CommitSaver {
repository_url: "https://github.com/example/repo.git".to_string(),
commit_branch_name: "main".to_string(),
commit_hash: "abc123".to_string(),
commit_msg: "feat: add feature".to_string(),
commit_datetime: Utc.with_ymd_and_hms(2025, 1, 14, 10, 30, 0).unwrap(),
};
let path = saver.prepare_path_for_commit(
&PathBuf::from("Diaries/Commits"),
"%Y/%m-%B/%F.md"
);
// Returns: "/Diaries/Commits/2025/01-January/2025-01-14.md"
assert!(path.contains("2025"));
assert!(path.contains("January"));
assert!(path.contains("2025-01-14.md"));Sourcefn prepare_date_for_commit_file(&mut self, path_format: &str) -> String
fn prepare_date_for_commit_file(&mut self, path_format: &str) -> String
Formats the commit timestamp using a Chrono date format string.
Applies the given format template to the commit’s datetime to generate a date-based directory path or filename. This enables flexible organization of diary entries by year, month, week, or custom hierarchies.
§Arguments
path_format- Chrono format string (e.g.,%Y/%m-%B/%F.md)
§Returns
A formatted date string suitable for file paths
§Common Format Specifiers
%Y- Year (4 digits, e.g.,2025)%m- Month (2 digits, e.g.,01)%B- Full month name (e.g.,January)%b- Abbreviated month (e.g.,Jan)%d- Day of month (2 digits, e.g.,14)%F- ISO 8601 date format (%Y-%m-%d, e.g.,2025-01-14)%A- Full weekday name (e.g.,Monday)%W- Week number (e.g.,02)
§Examples
// With format "%Y/%m-%B/%F.md" and datetime 2025-01-14:
// Returns: "2025/01-January/2025-01-14.md"
// With format "%Y/week-%W/%F.md" and datetime in week 2:
// Returns: "2025/week-02/2025-01-14.md"§Note
This is a private helper method called by prepare_path_for_commit().
Sourcepub fn append_entry_to_diary(
&mut self,
wiki: &PathBuf,
) -> Result<(), Box<dyn Error>>
pub fn append_entry_to_diary( &mut self, wiki: &PathBuf, ) -> Result<(), Box<dyn Error>>
Appends the current commit as a table row to an Obsidian diary file.
This method writes a formatted commit entry to the specified diary file in append mode. The entry includes: current directory, timestamp, commit message, repository URL, branch, and commit hash.
§Arguments
wiki- Path to the diary file where the commit entry should be appended
§Returns
Ok(())- Successfully appended the commit entry to the fileErr(Box<dyn Error>)- If file operations fail (file doesn’t exist, permission denied, etc.)
§Errors
Returns an error if:
- The diary file cannot be opened for appending
- The current working directory cannot be determined
- File write operations fail (I/O error, permission denied)
§Examples
use rusty_commit_saver::CommitSaver;
use std::path::PathBuf;
let mut saver = CommitSaver::new();
let diary_path = PathBuf::from("/home/user/diary/2025-01-14.md");
match saver.append_entry_to_diary(&diary_path) {
Ok(()) => println!("Commit logged successfully!"),
Err(e) => eprintln!("Failed to log commit: {}", e),
}Trait Implementations§
Source§impl Clone for CommitSaver
impl Clone for CommitSaver
Source§fn clone(&self) -> CommitSaver
fn clone(&self) -> CommitSaver
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for CommitSaver
impl Debug for CommitSaver
Source§impl Default for CommitSaver
Creates a CommitSaver instance with default values from the current Git repository.
impl Default for CommitSaver
Creates a CommitSaver instance with default values from the current Git repository.
This implementation automatically discovers the Git repository in the current directory
and extracts all commit metadata from the HEAD commit. It’s the core logic used by
CommitSaver::new().
§Panics
Panics if:
- No Git repository is found in the current directory or any parent directory
- The repository has no HEAD (uninitialized or corrupted repository)
- The HEAD reference cannot be resolved to a commit
- The remote “origin” doesn’t exist
§Commit Message Processing
The commit message undergoes several transformations:
- Split into individual lines
- Trim whitespace from each line
- Escape pipe characters:
|→\|(for Markdown table compatibility) - Filter out empty lines
- Join with
<br/>separator (for Obsidian rendering)
§Examples
use rusty_commit_saver::CommitSaver;
// Using Default trait directly
let saver = CommitSaver::default();
// Equivalent to:
let saver2 = CommitSaver::new();