Skip to main content

grit_lib/diff/
mod.rs

1//! Tree and content diffs, rename detection, merge diffs, and related helpers.
2//!
3//! Library guide: [mod](https://grit-scm.com/docs/library/diff)
4//!
5//! ```rust
6//! use grit_lib::repo::{InitOptions, Repository};
7//! # fn main() -> grit_lib::error::Result<()> {
8//! let dir = tempfile::tempdir()?;
9//! let _repo = Repository::init(dir.path(), &InitOptions::default())?;
10//! let _ = _repo.diff();
11//!
12//! # Ok(())
13//! # }
14//! ```
15mod basename_rename;
16mod changes;
17mod commit_files_many;
18mod core;
19pub(crate) use core::myers_rediff_changed_masks_for_region;
20pub(crate) use core::*;
21pub(crate) use core::{
22    intern_merge_compare_three_way, merge_file_compacted_line_ops, merge_myops_from_preinterned_ids,
23};
24mod detail;
25mod files;
26mod filter;
27mod git_histogram;
28pub(crate) mod handle;
29mod has_changes;
30pub(crate) mod hunk_id;
31mod merge_commit;
32mod no_index;
33mod options;
34mod patch_log;
35pub(crate) mod pickaxe;
36mod posix_ere;
37mod rename_blob_cache;
38mod rename_lines;
39mod stat;
40pub(crate) use core::is_func_line;
41pub(crate) use posix_ere::PosixBre;
42mod targets;
43mod tree_content;
44pub(crate) use tree_content::gitlink_line;
45pub use tree_content::{bytes_for_diff, load_odb_blob_side_for_diff};
46mod unified_emit;
47mod whitespace_mode;
48
49pub use changes::{load_object_changes, FileChange, UncommittedDiff};
50pub use commit_files_many::{CommitFilesManyInput, CommitFilesManyOptions, CommitFilesResult};
51pub use core::structured;
52/// Unified diff for two text sides with default `a/` / `b/` path prefixes.
53#[must_use]
54pub fn unified_diff(
55    old_content: &str,
56    new_content: &str,
57    old_path: &str,
58    new_path: &str,
59    context_lines: usize,
60    indent_heuristic: bool,
61    quote_path_fully: bool,
62) -> String {
63    core::unified_diff(
64        old_content,
65        new_content,
66        old_path,
67        new_path,
68        context_lines,
69        indent_heuristic,
70        quote_path_fully,
71    )
72}
73
74pub use core::{
75    anchored_unified_diff, annotate_unified_diff_no_newline_at_eof, count_changes_with_algorithm,
76    count_git_lines, detect_copies_with_policy, detect_renames_with_policy, diff_commits,
77    diff_commits_with_renames, diff_index_to_tree, diff_index_to_worktree,
78    diff_index_to_worktree_for_staging, diff_index_to_worktree_with_options,
79    diff_index_to_worktree_with_renames, diff_tree_to_worktree, diff_tree_to_worktree_with_git_dir,
80    diff_tree_to_worktree_with_git_dir_and_rules, diff_trees, diff_trees_show_tree_entries,
81    diff_trees_with_renames, empty_blob_oid, format_raw, format_raw_abbrev, hash_worktree_file,
82    index_mtime_for_diff, mode_from_metadata, normalize_ignore_space_change,
83    parse_diff_rename_threshold_percent, postprocess_diff_entries,
84    read_worktree_side_bytes_for_diff, refresh_index_stat_content_verified,
85    rename_similarity_score, resolve_indent_heuristic, sort_entries_by_path, stat_matches,
86    submodule_porcelain_flags, tree_oid_of_commit, unified_diff_histogram_hunks_only,
87    unified_diff_histogram_ignore_with_prefix_and_funcname, unified_diff_with_prefix_and_funcname,
88    unified_diff_with_prefix_and_funcname_and_algorithm, zero_oid, DetectRenamesOptions,
89    DiffEntriesResult, DiffEntry, DiffIndexToWorktreeOptions, DiffPostprocessOptions,
90    DiffPostprocessWorktree, DiffStatus, InexactRenameDetectionSkipped,
91};
92pub use detail::FileDiff as ListedFileDiff;
93pub use detail::{line_change_counts, DiffDetail, DiffTotals, LineStat};
94pub use files::{build_file_diffs, build_file_diffs_streaming, name_status_line, DiffFilesOutput};
95pub use filter::{DiffFilter, InvalidDiffFilter};
96pub use handle::Diff;
97pub use has_changes::text_sides_differ;
98pub use hunk_id::{
99    hunk_ids, hunk_ids_with_duplicate_peers, peer_hunks_by_primary_path, peer_scope_includes_path,
100    DiffSide, HunkId, HunkIdError,
101};
102pub use merge_commit::{combined_structured_patch_body, commit_diff_files, DiffMerges};
103pub use no_index::{diff_paths, write_paths_patch, NoIndexError};
104pub use options::{
105    renames_from_config, DiffAlgorithm, DiffOptions, RenameDetection, UnknownDiffAlgorithm,
106    RENAME_DETECTION_DISABLED, WORD_LEVEL_INLINE_MAX_CHANGED_FILES,
107};
108pub use whitespace_mode::{normalize_ignore_space_change_line, WhitespaceMode};
109
110/// Unified hunk bodies (`@@` …) for two text sides using [`DiffOptions`].
111#[must_use]
112pub fn line_diff_unified_hunk_body(
113    old_content: &str,
114    new_content: &str,
115    options: &DiffOptions,
116) -> String {
117    core::unified_hunk_body_for_diff_options(old_content, new_content, options)
118}
119pub(crate) use core::{imara_unified_hunk_slices, unified_hunk_body_for_diff_options};
120pub use patch_log::{
121    write_commit_header_and_message, write_commit_log_patch, write_commits_log_patch,
122    write_diff_entry_log_patch, write_patch, write_patch_resolved, write_patch_structured,
123    LogPatchBinaryFormat, LogPatchCommitHeader, LogPatchOptions, PatchResolvedSide, PatchSide,
124    PatchTextOptions,
125};
126pub use pickaxe::{Pickaxe, PickaxeError, PickaxeKind};
127pub use stat::{DiffStat, FileStat, StatBar};
128pub use targets::hunk_diff_bundle;
129pub use targets::HunkDiffBundle;
130pub(crate) use targets::{
131    collect_files_for_target, include_file_in_diff, unstaged_file_diffs_with_peer_hunks,
132    unstaged_raw_changes_with_peer_hunks, unstaged_raw_changes_with_peer_hunks_in,
133};
134pub use targets::{
135    resolve_commit_diff_pathspecs, resolve_diff_arguments, resolve_diff_request, DiffArguments,
136    DiffRequest, DiffTarget, FileDiff, ResolveDiffArgumentsError,
137};
138pub use tree_content::{
139    for_each_tree_diff_structured, tree_diff_contents_parallel, tree_diff_stat_parallel,
140    tree_diff_structured_entry, tree_diff_structured_parallel, TreeDiffContent, TreeDiffStructured,
141};
142
143pub(crate) mod bloom {
144    pub(crate) use crate::bloom::*;
145}
146pub mod combined_diff_patch {
147    //! combined_diff_patch API (re-exported at this path).
148    pub use crate::combined_diff_patch::*;
149}
150pub mod combined_tree_diff {
151    //! Combined tree diff helpers for merge commits.
152    pub use crate::combined_tree_diff::*;
153}
154pub mod patch_ids {
155    //! patch_ids API (re-exported at this path).
156    pub use crate::patch_ids::*;
157}
158pub mod userdiff {
159    //! Per-path diff driver (funcname) matching.
160    pub use crate::userdiff::*;
161}
162pub mod merge_diff {
163    //! Combined diff content for octopus merges.
164    pub use crate::merge_diff::*;
165}
166pub mod merge_file {
167    //! merge_file API (re-exported at this path).
168    pub use crate::merge_file::*;
169}
170pub mod merge_trees {
171    //! merge_trees API (re-exported at this path).
172    pub use crate::merge_trees::*;
173}
174pub mod rerere {
175    //! rerere API (re-exported at this path).
176    pub use crate::rerere::*;
177}
178/// Merge commit message formatting from FETCH_HEAD-style input.
179pub mod fmt_merge_msg {
180    pub use crate::fmt_merge_msg::{fmt_merge_msg, FmtMergeMsgOptions};
181}
182pub mod ws {
183    //! ASCII whitespace helpers used by the diff engine.
184    pub use crate::ws::*;
185}