| Crates.io | blame-rs |
| lib.rs | blame-rs |
| version | 0.1.7 |
| created_at | 2025-10-18 12:05:36.716707+00 |
| updated_at | 2026-01-04 17:58:33.125494+00 |
| description | Line-by-line authorship tracking for revisioned text |
| homepage | https://github.com/levish0/blame-rs |
| repository | https://github.com/levish0/blame-rs |
| max_upload_size | |
| id | 1889155 |
| size | 51,915 |
blame-rs is a Rust library for line-by-line authorship tracking in revisioned text.
Track which revision introduced each line in your documents with a flexible in-memory API.
similar crate&str references (no string allocations)Rc<T> (single clone per revision instead of per line)Add to your Cargo.toml:
[dependencies]
blame-rs = "0.1.0"
use blame_rs::{blame, BlameRevision};
use std::rc::Rc;
#[derive(Debug)]
struct CommitInfo {
hash: String,
author: String,
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let revisions = vec![
BlameRevision {
content: "line 1\nline 2",
metadata: Rc::new(CommitInfo {
hash: "abc123".to_string(),
author: "Alice".to_string(),
}),
},
BlameRevision {
content: "line 1\nline 2\nline 3",
metadata: Rc::new(CommitInfo {
hash: "def456".to_string(),
author: "Bob".to_string(),
}),
},
];
let result = blame(&revisions)?;
for line in result.lines() {
println!(
"Line {}: {} (from {})",
line.line_number,
line.content.trim(),
line.revision_metadata.author
);
}
Ok(())
}
Output:
Line 0: line 1 (from Alice)
Line 1: line 2 (from Alice)
Line 2: line 3 (from Bob)
use blame_rs::{blame_with_options, BlameOptions, BlameRevision, DiffAlgorithm};
let options = BlameOptions {
algorithm: DiffAlgorithm::Patience,
};
let result = blame_with_options(&revisions, options)?;
for line in result.lines() {
println!(
"{:<6} {:<10} {:<15} {}",
line.line_number + 1,
&line.revision_metadata.hash[..6],
line.revision_metadata.author,
line.content.trim_end()
);
}
The algorithm works by:
This forward-tracking approach ensures accurate line attribution even when lines are moved, modified, or deleted across multiple revisions.
Rev 0 (Alice): Rev 1 (Bob): Rev 2 (Charlie):
fn main() { fn main() { fn main() {
println!("Hello"); println!("Hello"); println!("Rust!"); โ Changed
} println!("World"); println!("World");
} }
Result:
Line 0: fn main() { โ Alice (unchanged since Rev 0)
Line 1: println!("Rust!"); โ Charlie (changed in Rev 2)
Line 2: println!("World"); โ Bob (added in Rev 1)
Line 3: } โ Alice (unchanged since Rev 0)
See the examples/ directory for detailed usage:
basic_usage.rs: Demonstrates blame with multiple revisions and formatted table outputdebug_example.rs: Shows detailed blame output with revision content for debuggingRun examples with:
cargo run --example basic_usage
cargo run --example debug_example
The library includes extensive testing with:
tests/fixtures/# Run all tests
cargo test
# Run tests with detailed output
cargo test -- --nocapture
# Run specific fixture test
cargo test test_multiple_revisions_myers -- --nocapture --exact
================================================================================
Testing: multiple_revisions (Algorithm: Myers)
================================================================================
Revisions:
Rev 0: "a\nb"
Rev 1: "a\nb\nc"
Rev 2: "a\nb\nc\nd"
Blame Results:
Line Revision Content
------------------------------------------------------------
0 Rev 0 a
1 Rev 0 b
2 Rev 1 c
3 Rev 2 d
โ multiple_revisions (Myers) passed
Generate and view the full API documentation:
cargo doc --open
Key types:
BlameRevision<'a, T>: Represents a revision with content (&'a str) and metadata (Rc<T>)
content: &'a str - Zero-copy reference to revision contentmetadata: Rc<T> - Shared reference-counted metadata (no T: Clone required)BlameLine<'a, T>: A single line with its origin information
content: &'a str - Zero-copy reference to the original linerevision_metadata: Rc<T> - Shared reference to revision metadataBlameResult<'a, T>: Collection of blamed linesBlameOptions: Configuration for the blame operationDiffAlgorithm: Myers or Patience algorithm selectionNote: The library uses zero-copy string slices (&str) and shared metadata (Rc<T>) for optimal performance. Metadata types don't need to implement Clone.
similar (2.7.0) โ Text diffing algorithmsthiserror (2.0.17) โ Error handlingblame-rs