Skip to main content

ralph_workflow/git_helpers/
mod.rs

1//! Git Helper Functions
2//!
3//! Provides git hooks management, a git wrapper for blocking commits during the
4//! agent phase, and basic repository utilities.
5//!
6//! All git operations use libgit2 directly - no git CLI required.
7//!
8//! # Module Structure
9//!
10//! - `hooks` - Git hooks installation and removal
11//! - [`identity`] - Git identity resolution with comprehensive fallback chain
12//! - `repo` - Basic git repository operations (add, commit, snapshot)
13//! - `start_commit` - Starting commit tracking for incremental diffs
14//! - `review_baseline` - Per-review-cycle baseline tracking
15//! - `wrapper` - Agent phase git wrapper for safe concurrent execution
16//! - [`branch`] - Branch detection and default branch resolution
17//! - `rebase` - Rebase operations with fault tolerance
18
19#![deny(unsafe_code)]
20
21use std::io;
22
23/// Convert git2 errors to std::io errors for consistent error handling.
24pub(crate) fn git2_to_io_error(err: &git2::Error) -> io::Error {
25    // Fall back to mapping git2 error codes to a best-effort io::ErrorKind.
26    let kind = match err.code() {
27        git2::ErrorCode::NotFound => io::ErrorKind::NotFound,
28        git2::ErrorCode::Exists => io::ErrorKind::AlreadyExists,
29        git2::ErrorCode::Auth => io::ErrorKind::PermissionDenied,
30        git2::ErrorCode::Certificate => io::ErrorKind::PermissionDenied,
31        git2::ErrorCode::Invalid => io::ErrorKind::InvalidInput,
32        git2::ErrorCode::Eof => io::ErrorKind::UnexpectedEof,
33        git2::ErrorCode::UnbornBranch => io::ErrorKind::NotFound,
34        _ => io::ErrorKind::Other,
35    };
36
37    io::Error::new(kind, err.to_string())
38}
39
40pub mod branch;
41mod hooks;
42pub mod identity;
43mod rebase;
44
45#[cfg(any(test, feature = "test-utils"))]
46pub mod rebase_checkpoint;
47
48#[cfg(any(test, feature = "test-utils"))]
49pub mod rebase_state_machine;
50
51mod repo;
52mod review_baseline;
53mod start_commit;
54mod wrapper;
55
56#[cfg(any(test, feature = "test-utils"))]
57pub use branch::get_default_branch_at;
58pub use branch::{get_default_branch, is_main_or_master_branch};
59pub use hooks::uninstall_hooks;
60#[cfg(any(test, feature = "test-utils"))]
61pub use hooks::{file_contains_marker_with_workspace, verify_hook_integrity_with_workspace};
62pub use rebase::{
63    abort_rebase, continue_rebase, get_conflict_markers_for_file, get_conflicted_files,
64    rebase_in_progress, rebase_onto, RebaseResult,
65};
66
67// Types that are part of the public API but not used in binary
68#[cfg(any(test, feature = "test-utils"))]
69pub use rebase::{CleanupResult, ConcurrentOperation};
70
71#[cfg(any(test, feature = "test-utils"))]
72pub use rebase::{
73    attempt_automatic_recovery, cleanup_stale_rebase_state, detect_concurrent_git_operations,
74    is_dirty_tree_cli, rebase_in_progress_cli, validate_rebase_preconditions,
75    verify_rebase_completed,
76};
77
78pub use rebase::RebaseErrorKind;
79
80#[cfg(any(test, feature = "test-utils"))]
81pub use rebase_checkpoint::RebasePhase;
82
83#[cfg(any(test, feature = "test-utils"))]
84pub use rebase_state_machine::{RebaseLock, RebaseStateMachine};
85pub use repo::{
86    get_git_diff_for_review_with_workspace, get_git_diff_from_start,
87    get_git_diff_from_start_with_workspace, get_repo_root, git_add_all, git_add_all_in_repo,
88    git_commit, git_commit_in_repo, git_diff, git_diff_from, git_snapshot, require_git_repo,
89    CommitResultFallback, DiffReviewContent, DiffTruncationLevel,
90};
91#[cfg(any(test, feature = "test-utils"))]
92pub use review_baseline::load_review_baseline_with_workspace;
93pub use review_baseline::update_review_baseline_with_workspace;
94pub use review_baseline::{
95    get_baseline_summary, get_review_baseline_info, load_review_baseline, update_review_baseline,
96    ReviewBaseline,
97};
98#[cfg(any(test, feature = "test-utils"))]
99pub use start_commit::load_start_point_with_workspace;
100pub use start_commit::{
101    get_current_head_oid, get_start_commit_summary, load_start_point, reset_start_commit,
102    save_start_commit, save_start_commit_with_workspace, StartPoint,
103};
104pub use wrapper::{
105    cleanup_agent_phase_silent, cleanup_orphaned_marker, disable_git_wrapper, end_agent_phase,
106    start_agent_phase, GitHelpers,
107};
108
109// Workspace-aware variants (used by tests and by code paths that must operate
110// without requiring a real git repository).
111pub use wrapper::{
112    cleanup_orphaned_marker_with_workspace, create_marker_with_workspace,
113    marker_exists_with_workspace, remove_marker_with_workspace,
114};
115
116// Re-export checkpoint and recovery action for tests only
117#[cfg(any(test, feature = "test-utils"))]
118pub use rebase_checkpoint::RebaseCheckpoint;
119
120#[cfg(any(test, feature = "test-utils"))]
121pub use rebase_state_machine::RecoveryAction;
122
123#[cfg(test)]
124mod tests;