Crate sublime_git_tools

Crate sublime_git_tools 

Source
Expand description

§sublime_git_tools

A high-level Rust interface to Git operations with robust error handling, built on libgit2.

§Overview

sublime_git_tools provides a user-friendly API for working with Git repositories. It wraps the powerful but complex libgit2 library to offer a more ergonomic interface for common Git operations.

This crate is designed for Rust applications that need to:

  • Create, clone, or manipulate Git repositories
  • Manage branches, commits, and tags
  • Track file changes between commits or branches
  • Push/pull with remote repositories
  • Get detailed commit histories
  • Detect changes in specific parts of a repository

§Main Features

§Repository Management

use sublime_git_tools::Repo;

// Create a new repository
let repo = Repo::create("/path/to/new/repo")?;

// Open an existing repository
let repo = Repo::open("./my-project")?;

// Clone a remote repository
let repo = Repo::clone("https://github.com/example/repo.git", "./cloned-repo")?;

§Branch and Commit Operations

use sublime_git_tools::Repo;

// Create a new branch
repo.create_branch("feature/new-feature")?;

// Checkout a branch
repo.checkout("feature/new-feature")?;

// Add files and commit
repo.add("src/main.rs")?;
let commit_id = repo.commit("feat: update main.rs")?;

// Or add all changes and commit in one step
let commit_id = repo.commit_changes("feat: implement new feature")?;

§File Change Detection

use sublime_git_tools::Repo;

// Get all changed files since a tag or commit
let changed_files = repo.get_all_files_changed_since_sha("HEAD~1")?;

// Get all changed files with their status (Added, Modified, Deleted)
let changed_files_with_status = repo
    .get_all_files_changed_since_sha_with_status("HEAD~1")?;

// Get changes in specific packages since a branch
let packages = vec!["packages/pkg1".to_string(), "packages/pkg2".to_string()];
let package_changes = repo
    .get_all_files_changed_since_branch(&packages, "main")?;

§Commit History

use sublime_git_tools::Repo;

// Get all commits since a specific tag
let commits = repo.get_commits_since(
    Some("HEAD~1".to_string()),
    &None
)?;

// Get commits affecting a specific file
let file_commits = repo.get_commits_since(
    None,
    &Some("src/main.rs".to_string())
)?;

§sublime_git_tools API Specification

§Table of Contents

§Overview

sublime_git_tools is a high-level Rust interface to Git operations with robust error handling, built on libgit2. It provides a user-friendly API for working with Git repositories, wrapping the powerful but complex libgit2 library to offer a more ergonomic interface for common Git operations.

This crate is designed for Rust applications that need to:

  • Create, clone, or manipulate Git repositories
  • Manage branches, commits, and tags
  • Track file changes between commits or branches
  • Push/pull with remote repositories
  • Get detailed commit histories
  • Detect changes in specific parts of a repository
  • Handle SSH authentication for remote operations
  • Perform advanced Git operations like merging and status checking

§Repository Management

§Creating and Opening Repositories

§Repo::create

Creates a new Git repository at the specified path with an initial commit on the ‘main’ branch.

pub fn create(path: &str) -> Result<Self, RepoError>

Parameters:

  • path: The path where the repository should be created

Returns:

  • Result<Self, RepoError>: A new Repo instance or an error

Example:

let repo = Repo::create("/path/to/new/repo")?;
println!("Repository created at: {}", repo.get_repo_path().display());

Possible errors:

  • CanonicalPathFailure: Failed to canonicalize the provided path
  • CreateRepoFailure: Failed to initialize the Git repository
§Repo::open

Opens an existing Git repository at the specified path.

pub fn open(path: &str) -> Result<Self, RepoError>

Parameters:

  • path: The path to the existing repository

Returns:

  • Result<Self, RepoError>: A Repo instance or an error

Example:

let repo = Repo::open("./my-project")?;
let branch = repo.get_current_branch()?;
println!("Current branch: {}", branch);

Possible errors:

  • CanonicalPathFailure: Failed to canonicalize the provided path
  • OpenRepoFailure: Failed to open the Git repository
§Repo::clone

Clones a Git repository from a URL to a local path.

pub fn clone(url: &str, path: &str) -> Result<Self, RepoError>

Parameters:

  • url: The URL of the repository to clone
  • path: The local path where the repository should be cloned

Returns:

  • Result<Self, RepoError>: A Repo instance or an error

Example:

let repo = Repo::clone("https://github.com/example/repo.git", "./cloned-repo")?;

Possible errors:

  • CanonicalPathFailure: Failed to canonicalize the provided path
  • CloneRepoFailure: Failed to clone the Git repository
§Repo::clone_with_options

Clones a Git repository from a URL to a local path with advanced options including shallow clone support.

pub fn clone_with_options(
    url: &str,
    path: &str,
    depth: Option<i32>
) -> Result<Self, RepoError>

Parameters:

  • url: The URL of the repository to clone
  • path: The local path where the repository should be cloned
  • depth: Optional depth for shallow clone (e.g., Some(1) for only the latest commit, None for full clone)

Returns:

  • Result<Self, RepoError>: A Repo instance or an error

Examples:

// Full clone (equivalent to Repo::clone)
let repo = Repo::clone_with_options(
    "https://github.com/example/repo.git",
    "./cloned-repo",
    None
)?;

// Shallow clone with depth 1 (only latest commit)
let repo = Repo::clone_with_options(
    "https://github.com/example/large-repo.git",
    "./shallow-clone",
    Some(1)
)?;

// Shallow clone with depth 10 (last 10 commits)
let repo = Repo::clone_with_options(
    "https://github.com/example/repo.git",
    "./partial-clone",
    Some(10)
)?;

Performance Benefits: Shallow clones can significantly reduce:

  • Clone time (especially for repositories with extensive history)
  • Disk space usage
  • Network bandwidth consumption

This is particularly useful for:

  • CI/CD pipelines that only need the latest code
  • Deployment scenarios
  • Quick repository inspection
  • Limited disk space environments

Limitations:

  • Cannot push from a shallow clone without converting to full clone first
  • Some operations requiring full history may fail
  • Can be converted to full clone later using git fetch --unshallow

Possible errors:

  • CanonicalPathFailure: Failed to canonicalize the provided path
  • CloneRepoFailure: Failed to clone the Git repository
  • Network connection failures
  • Authentication failures
  • Insufficient disk space
§Repo::clone_with_progress

Clones a Git repository with real-time progress tracking callbacks.

pub fn clone_with_progress<F>(
    url: &str,
    path: &str,
    depth: Option<i32>,
    progress_cb: F
) -> Result<Self, RepoError>
where
    F: FnMut(usize, usize) + 'static

Parameters:

  • url: The URL of the repository to clone
  • path: The local path where the repository should be cloned
  • depth: Optional depth for shallow clone
  • progress_cb: Callback function that receives (current_objects, total_objects) for progress updates

Returns:

  • Result<Self, RepoError>: A Repo instance or an error

Examples:

use sublime_git_tools::Repo;

// Clone with progress updates
let repo = Repo::clone_with_progress(
    "https://github.com/example/repo.git",
    "./cloned-repo",
    None,
    |current, total| {
        println!("Progress: {}/{} objects ({:.1}%)", 
                 current, total, 
                 (current as f64 / total as f64) * 100.0);
    }
)?;

// Shallow clone with progress
let repo = Repo::clone_with_progress(
    "https://github.com/example/large-repo.git",
    "./shallow",
    Some(1),
    |current, total| {
        if total > 0 {
            let percent = (current as f64 / total as f64) * 100.0;
            print!("\rReceiving objects: {:.0}%", percent);
        }
    }
)?;

Progress Callback Details: The callback is invoked periodically during the clone operation with:

  • current: Number of objects received so far
  • total: Total number of objects to receive (may be 0 initially)

The callback is called during:

  1. Receiving objects from the remote
  2. Resolving deltas
  3. Indexing objects

Possible errors:

  • CanonicalPathFailure: Failed to canonicalize the provided path
  • CloneRepoFailure: Failed to clone the Git repository
  • Network connection failures
  • Authentication failures
  • Insufficient disk space

§Repository Information

§Repo::get_repo_path

Returns the path to the repository root directory.

pub fn get_repo_path(&self) -> &Path

Returns:

  • &Path: Reference to the repository path

Example:

let repo = Repo::open("./my-project")?;
let path = repo.get_repo_path();
println!("Repository path: {}", path.display());

§Configuration

§Repo::config

Sets the Git configuration for username and email in the repository.

pub fn config(&self, username: &str, email: &str) -> Result<&Self, RepoError>

Parameters:

  • username: The Git username to set
  • email: The Git email to set

Returns:

  • Result<&Self, RepoError>: Reference to self for chaining or an error

Example:

repo.config("Jane Doe", "jane@example.com")?;

Possible errors:

  • ConfigError: Failed to access or modify Git configuration
§Repo::list_config

Lists all configuration entries in the repository.

pub fn list_config(&self) -> Result<HashMap<String, String>, RepoError>

Returns:

  • Result<HashMap<String, String>, RepoError>: Map of configuration key-value pairs or an error

Example:

let config_entries = repo.list_config()?;
for (key, value) in config_entries {
    println!("{}: {}", key, value);
}

Possible errors:

  • ConfigError: Failed to access Git configuration
  • ConfigEntriesError: Failed to retrieve configuration entries

§Branch Operations

§Creating and Managing Branches

§Repo::create_branch

Creates a new branch from the current HEAD commit.

pub fn create_branch(&self, branch_name: &str) -> Result<&Self, RepoError>

Parameters:

  • branch_name: The name of the new branch to create

Returns:

  • Result<&Self, RepoError>: Reference to self for chaining or an error

Example:

repo.create_branch("feature/new-feature")?;

Possible errors:

  • HeadError: Failed to get repository HEAD
  • PeelError: Failed to peel HEAD to commit
  • BranchError: Failed to create the branch
§Repo::checkout

Switches to the specified branch.

pub fn checkout(&self, branch_name: &str) -> Result<&Self, RepoError>

Parameters:

  • branch_name: The name of the branch to checkout

Returns:

  • Result<&Self, RepoError>: Reference to self for chaining or an error

Example:

repo.checkout("feature-branch")?;

Possible errors:

  • BranchError: Failed to find the branch
  • CheckoutBranchError: Failed to checkout the branch
  • CheckoutError: Failed to perform checkout

§Branch Information

§Repo::list_branches

Lists all local branches in the repository.

pub fn list_branches(&self) -> Result<Vec<String>, RepoError>

Returns:

  • Result<Vec<String>, RepoError>: Vector of branch names or an error

Example:

let branches = repo.list_branches()?;
for branch in branches {
    println!("Branch: {}", branch);
}

Possible errors:

  • BranchListError: Failed to list branches
  • BranchNameError: Failed to get branch name
§Repo::get_current_branch

Gets the name of the currently checked out branch.

pub fn get_current_branch(&self) -> Result<String, RepoError>

Returns:

  • Result<String, RepoError>: The current branch name or an error

Example:

let current_branch = repo.get_current_branch()?;
println!("Current branch: {}", current_branch);

Possible errors:

  • HeadError: Failed to get repository HEAD
  • BranchNameError: Failed to get branch name from HEAD
§Repo::branch_exists

Checks if a branch exists in the repository.

pub fn branch_exists(&self, branch_name: &str) -> Result<bool, RepoError>

Parameters:

  • branch_name: The name of the branch to check

Returns:

  • Result<bool, RepoError>: True if branch exists, false otherwise, or an error

Example:

if repo.branch_exists("main")? {
    println!("Branch 'main' exists");
}

Possible errors:

  • BranchError: Failed to access branch information
§Repo::get_branch_from_commit

Gets the branch name that contains a specific commit.

pub fn get_branch_from_commit(&self, sha: &str) -> Result<Option<String>, RepoError>

Parameters:

  • sha: The commit SHA to search for

Returns:

  • Result<Option<String>, RepoError>: Branch name if found, None if not found, or an error

Example:

if let Some(branch) = repo.get_branch_from_commit("abcdef123456")? {
    println!("Commit is on branch: {}", branch);
}

Possible errors:

  • CommitOidError: Failed to parse commit SHA
  • BranchListError: Failed to list branches
  • BranchNameError: Failed to get branch name
§Repo::get_branches_containing_commit

Gets all branches that contain a specific commit.

pub fn get_branches_containing_commit(&self, sha: &str) -> Result<Vec<String>, RepoError>

Parameters:

  • sha: The commit SHA to search for

Returns:

  • Result<Vec<String>, RepoError>: Vector of branch names containing the commit or an error

Example:

let branches = repo.get_branches_containing_commit("abcdef123456")?;
for branch in branches {
    println!("Branch {} contains the commit", branch);
}

Possible errors:

  • CommitOidError: Failed to parse commit SHA
  • BranchListError: Failed to list branches
  • GraphError: Failed to perform graph operations

§Commit Operations

§Staging and Committing

§Repo::add

Adds a specific file to the staging area.

pub fn add(&self, file_path: &str) -> Result<&Self, RepoError>

Parameters:

  • file_path: The path to the file to add

Returns:

  • Result<&Self, RepoError>: Reference to self for chaining or an error

Example:

repo.add("src/main.rs")?;

Possible errors:

  • IndexError: Failed to access the index
  • AddFilesError: Failed to add file to index
  • WriteIndexError: Failed to write index
§Repo::add_all

Adds all changed files to the staging area.

pub fn add_all(&self) -> Result<&Self, RepoError>

Returns:

  • Result<&Self, RepoError>: Reference to self for chaining or an error

Example:

repo.add_all()?;

Possible errors:

  • IndexError: Failed to access the index
  • AddFilesError: Failed to add files to index
  • WriteIndexError: Failed to write index
§Repo::commit

Creates a commit with the currently staged changes.

pub fn commit(&self, message: &str) -> Result<String, RepoError>

Parameters:

  • message: The commit message

Returns:

  • Result<String, RepoError>: The commit SHA or an error

Example:

let commit_id = repo.commit("feat: add new functionality")?;
println!("Created commit: {}", commit_id);

Possible errors:

  • SignatureError: Failed to get repository signature
  • HeadError: Failed to get repository HEAD
  • IndexError: Failed to access the index
  • TreeError: Failed to create tree from index
  • CommitError: Failed to create commit
§Repo::commit_changes

Adds all changes and creates a commit in one operation.

pub fn commit_changes(&self, message: &str) -> Result<String, RepoError>

Parameters:

  • message: The commit message

Returns:

  • Result<String, RepoError>: The commit SHA or an error

Example:

let commit_id = repo.commit_changes("fix: resolve authentication issue")?;
println!("Created commit: {}", commit_id);

Possible errors:

  • SignatureError: Failed to get repository signature
  • HeadError: Failed to get repository HEAD
  • IndexError: Failed to access the index
  • AddFilesError: Failed to add files to index
  • WriteIndexError: Failed to write index
  • TreeError: Failed to create tree from index
  • CommitError: Failed to create commit

§Commit Information

§Repo::get_current_sha

Gets the SHA of the current HEAD commit.

pub fn get_current_sha(&self) -> Result<String, RepoError>

Returns:

  • Result<String, RepoError>: The current commit SHA or an error

Example:

let current_sha = repo.get_current_sha()?;
println!("Current commit: {}", current_sha);

Possible errors:

  • HeadError: Failed to get repository HEAD
  • CommitOidError: Failed to get commit OID
§Repo::get_previous_sha

Gets the SHA of the previous commit (parent of HEAD).

pub fn get_previous_sha(&self) -> Result<String, RepoError>

Returns:

  • Result<String, RepoError>: The previous commit SHA or an error

Example:

let previous_sha = repo.get_previous_sha()?;
println!("Previous commit: {}", previous_sha);

Possible errors:

  • HeadError: Failed to get repository HEAD
  • PeelError: Failed to peel HEAD to commit
  • CommitOidError: Failed to get commit OID

§Commit History

§Repo::get_commits_since

Gets commits since a specific reference, optionally filtered by file path.

pub fn get_commits_since(
    &self,
    since: Option<String>,
    path: &Option<String>
) -> Result<Vec<RepoCommit>, RepoError>

Parameters:

  • since: Optional reference (tag, branch, or commit SHA) to start from
  • path: Optional file path to filter commits

Returns:

  • Result<Vec<RepoCommit>, RepoError>: Vector of commits or an error

Example:

// Get all commits since a tag
let commits = repo.get_commits_since(Some("v1.0.0".to_string()), &None)?;

// Get commits affecting a specific file
let file_commits = repo.get_commits_since(None, &Some("src/main.rs".to_string()))?;

Possible errors:

  • RevWalkError: Failed to perform revision walk
  • ReferenceError: Failed to resolve reference
  • CommitOidError: Failed to parse commit
§Repo::get_commits_between

Gets commits between two references (commits in to_ref but not in from_ref).

pub fn get_commits_between(
    &self,
    from_ref: &str,
    to_ref: &str,
    relative: &Option<String>
) -> Result<Vec<RepoCommit>, RepoError>

Parameters:

  • from_ref: Starting reference (commits after this point)
  • to_ref: Ending reference (commits up to this point)
  • relative: Optional file path to filter commits

Returns:

  • Result<Vec<RepoCommit>, RepoError>: Vector of commits between references

Example:

// Get commits between two tags
let commits = repo.get_commits_between("v1.0.0", "v1.1.0", &None)?;

// Get commits between branches affecting specific path
let path_commits = repo.get_commits_between("main", "feature-branch", &Some("src/".to_string()))?;

Possible errors:

  • RevWalkError: Failed to perform revision walk
  • ReferenceError: Failed to resolve reference
  • CommitOidError: Failed to parse commit
  • PeelError: Failed to peel reference to commit

§Tag Operations

§Creating Tags

§Repo::create_tag

Creates a new tag at the current HEAD commit.

pub fn create_tag(&self, tag: &str, message: Option<String>) -> Result<&Self, RepoError>

Parameters:

  • tag: The name of the tag to create
  • message: Optional message for annotated tag (None for lightweight tag)

Returns:

  • Result<&Self, RepoError>: Reference to self for chaining or an error

Example:

// Create annotated tag
repo.create_tag("v1.0.0", Some("Release version 1.0.0".to_string()))?;

// Create lightweight tag
repo.create_tag("v1.0.1", None)?;

Possible errors:

  • SignatureError: Failed to get repository signature
  • HeadError: Failed to get repository HEAD
  • PeelError: Failed to peel HEAD to commit
  • CreateTagError: Failed to create tag

§Tag Information

§Repo::get_last_tag

Gets the most recent tag in the repository.

pub fn get_last_tag(&self) -> Result<String, RepoError>

Returns:

  • Result<String, RepoError>: The most recent tag name or an error

Example:

let last_tag = repo.get_last_tag()?;
println!("Last tag: {}", last_tag);

Possible errors:

  • LastTagError: Failed to get tags or no tags found
§Repo::get_remote_or_local_tags

Gets tags from local or remote repositories.

pub fn get_remote_or_local_tags(
    &self,
    local: Option<bool>
) -> Result<Vec<RepoTags>, RepoError>

Parameters:

  • local: Optional flag to specify local (true) or remote (false) tags. None for both.

Returns:

  • Result<Vec<RepoTags>, RepoError>: Vector of tags or an error

Example:

// Get local tags
let local_tags = repo.get_remote_or_local_tags(Some(true))?;

// Get remote tags
let remote_tags = repo.get_remote_or_local_tags(Some(false))?;

// Get all tags
let all_tags = repo.get_remote_or_local_tags(None)?;

Possible errors:

  • TagError: Failed to retrieve tags
  • RemoteError: Failed to access remote (for remote tags)

§File Status and Change Detection

§Repository Status

§Repo::status_porcelain

Gets the repository status in porcelain format (simple, parseable format).

pub fn status_porcelain(&self) -> Result<Vec<String>, RepoError>

Returns:

  • Result<Vec<String>, RepoError>: Vector of status lines or an error

Example:

let status_lines = repo.status_porcelain()?;
for line in status_lines {
    println!("{}", line);
}

Possible errors:

  • StatusError: Failed to get repository status
§Repo::get_status_detailed

Gets detailed status information for all files in the repository.

pub fn get_status_detailed(&self) -> Result<Vec<GitChangedFile>, RepoError>

Returns:

  • Result<Vec<GitChangedFile>, RepoError>: Vector of file status information or an error

Example:

let detailed_status = repo.get_status_detailed()?;
for file in detailed_status {
    println!("File: {}, Status: {:?}, Staged: {}, Workdir: {}",
        file.path, file.status, file.staged, file.workdir);
}

Possible errors:

  • StatusError: Failed to get repository status
§Repo::get_staged_files

Gets a list of files that are currently staged for commit.

pub fn get_staged_files(&self) -> Result<Vec<String>, RepoError>

Returns:

  • Result<Vec<String>, RepoError>: Vector of staged file paths or an error

Example:

let staged_files = repo.get_staged_files()?;
println!("Files ready for commit: {:?}", staged_files);

Possible errors:

  • StatusError: Failed to get repository status

§Changed Files

§Repo::get_all_files_changed_since_sha_with_status

Gets all files that changed since a specific commit/reference with their status information.

pub fn get_all_files_changed_since_sha_with_status(
    &self,
    git_ref: &str
) -> Result<Vec<GitChangedFile>, RepoError>

Parameters:

  • git_ref: The reference (commit SHA, tag, or branch) to compare against

Returns:

  • Result<Vec<GitChangedFile>, RepoError>: Vector of changed files with status or an error

Example:

let changed_files = repo.get_all_files_changed_since_sha_with_status("v1.0.0")?;
for file in changed_files {
    println!("Changed file: {} ({:?})", file.path, file.status);
}

Possible errors:

  • ReferenceError: Failed to resolve reference
  • DiffError: Failed to perform diff operation
  • CommitOidError: Failed to parse commit
§Repo::get_all_files_changed_since_sha

Gets a simple list of files that changed since a specific commit/reference.

pub fn get_all_files_changed_since_sha(&self, git_ref: &str) -> Result<Vec<String>, RepoError>

Parameters:

  • git_ref: The reference (commit SHA, tag, or branch) to compare against

Returns:

  • Result<Vec<String>, RepoError>: Vector of changed file paths or an error

Example:

let changed_files = repo.get_all_files_changed_since_sha("v1.0.0")?;
for file in changed_files {
    println!("Changed: {}", file);
}

Possible errors:

  • ReferenceError: Failed to resolve reference
  • DiffError: Failed to perform diff operation
§Repo::get_files_changed_between

Gets files changed between two references.

pub fn get_files_changed_between(&self, from_ref: &str, to_ref: &str) -> Result<Vec<GitChangedFile>, RepoError>

Parameters:

  • from_ref: The starting reference
  • to_ref: The ending reference

Returns:

  • Result<Vec<GitChangedFile>, RepoError>: Vector of changed files with status or an error

Example:

let files = repo.get_files_changed_between("main", "feature-branch")?;
for file in files {
    println!("File: {}, Status: {:?}", file.path, file.status);
}

Possible errors:

  • ReferenceError: Failed to resolve references
  • DiffError: Failed to perform diff operation
§Repo::get_files_changed_in_commit

Gets files changed in a specific commit.

pub fn get_files_changed_in_commit(&self, commit_hash: &str) -> Result<Vec<GitChangedFile>, RepoError>

Parameters:

  • commit_hash: The commit hash to analyze

Returns:

  • Result<Vec<GitChangedFile>, RepoError>: Vector of changed files with status or an error

Example:

let files = repo.get_files_changed_in_commit("abc123")?;
for file in files {
    println!("File: {}, Status: {:?}", file.path, file.status);
}

Possible errors:

  • ReferenceError: Failed to resolve commit reference
  • CommitError: Failed to access commit
  • TreeError: Failed to access tree
  • DiffError: Failed to perform diff operation

§Package-specific Changes

§Repo::get_all_files_changed_since_branch

Gets files changed in specific package directories since a branch.

pub fn get_all_files_changed_since_branch(
    &self,
    packages_paths: &[String],
    branch: &str
) -> Result<Vec<String>, RepoError>

Parameters:

  • packages_paths: Vector of package directory paths to check
  • branch: The branch to compare against

Returns:

  • Result<Vec<String>, RepoError>: Vector of changed files in the specified packages or an error

Example:

let packages = vec!["packages/pkg1".to_string(), "packages/pkg2".to_string()];
let package_changes = repo.get_all_files_changed_since_branch(&packages, "main")?;
for file in package_changes {
    println!("Package change: {}", file);
}

Possible errors:

  • ReferenceError: Failed to resolve branch reference
  • DiffError: Failed to perform diff operation

§Remote Operations

§Pushing and Pulling

§Repo::push

Pushes the current branch to a remote repository.

pub fn push(&self, remote_name: &str, follow_tags: Option<bool>) -> Result<bool, RepoError>

Parameters:

  • remote_name: The name of the remote (e.g., “origin”)
  • follow_tags: Optional flag to push tags along with commits

Returns:

  • Result<bool, RepoError>: True if push was successful, or an error

Example:

// Push without tags
let success = repo.push("origin", Some(false))?;

// Push with tags
repo.push("origin", Some(true))?;

Possible errors:

  • HeadError: Failed to get repository HEAD
  • BranchNameError: Failed to get branch name
  • RemoteError: Failed to find or access remote
  • PushError: Failed to push to remote
§Repo::pull

Pulls changes from a remote repository.

pub fn pull(&self, remote_name: &str, branch_name: Option<&str>) -> Result<bool, RepoError>

Parameters:

  • remote_name: The name of the remote (e.g., “origin”)
  • branch_name: Optional specific branch to pull (current branch if None)

Returns:

  • Result<bool, RepoError>: True if pull was successful, or an error

Example:

// Pull current branch
let success = repo.pull("origin", None)?;

// Pull specific branch
repo.pull("origin", Some("feature-branch"))?;

Possible errors:

  • RemoteError: Failed to find or access remote
  • HeadError: Failed to get repository HEAD
  • MergeError: Failed to merge pulled changes

§Fetching

§Repo::fetch

Fetches changes from a remote repository without merging.

pub fn fetch(
    &self,
    remote_name: &str,
    refspecs: Option<&[&str]>,
    prune: bool
) -> Result<bool, RepoError>

Parameters:

  • remote_name: The name of the remote (e.g., “origin”)
  • refspecs: Optional reference specs to fetch (all refs if None)
  • prune: Whether to prune deleted remote branches

Returns:

  • Result<bool, RepoError>: True if fetch was successful, or an error

Example:

// Fetch all refs
repo.fetch("origin", None, false)?;

// Fetch specific refspecs with pruning
repo.fetch("origin", Some(&["refs/heads/main:refs/remotes/origin/main"]), true)?;

Possible errors:

  • RemoteError: Failed to find or access remote
  • GitFailure: Failed to fetch from remote

§SSH Operations

§Repo::push_with_ssh_config

Pushes to a remote repository using SSH authentication with custom key paths.

pub fn push_with_ssh_config(
    &self,
    remote_name: &str,
    follow_tags: Option<bool>,
    ssh_key_paths: Vec<PathBuf>
) -> Result<bool, RepoError>

Parameters:

  • remote_name: The name of the remote (e.g., “origin”)
  • follow_tags: Optional flag to push tags along with commits
  • ssh_key_paths: Vector of SSH key file paths to try in order

Returns:

  • Result<bool, RepoError>: True if push was successful, or an error

Example:

use std::path::PathBuf;

let key_paths = vec![
    PathBuf::from("/home/user/.ssh/id_ed25519"),
    PathBuf::from("/home/user/.ssh/id_rsa"),
];
let success = repo.push_with_ssh_config("origin", Some(true), key_paths)?;

Possible errors:

  • HeadError: Failed to get repository HEAD
  • BranchNameError: Failed to get branch name
  • RemoteError: Failed to find or access remote
  • PushError: Failed to push to remote

§Advanced Git Operations

§Merging

§Repo::merge

Merges a branch into the current branch.

pub fn merge(&self, branch_name: &str) -> Result<(), RepoError>

Parameters:

  • branch_name: The name of the branch to merge

Returns:

  • Result<(), RepoError>: Success or an error

Example:

match repo.merge("feature-branch") {
    Ok(_) => println!("Merge completed successfully"),
    Err(RepoError::MergeConflictError(_)) => {
        println!("Merge conflicts detected");
    },
    Err(e) => println!("Merge failed: {}", e),
}

Possible errors:

  • HeadError: Failed to get repository HEAD
  • BranchError: Failed to find branch
  • MergeError: Failed to perform merge
  • MergeConflictError: Merge conflicts detected

§Repository Analysis

§Repo::get_merge_base

Finds the merge base (common ancestor) between two branches.

pub fn get_merge_base(&self, branch1: &str, branch2: &str) -> Result<String, RepoError>

Parameters:

  • branch1: The first branch name
  • branch2: The second branch name

Returns:

  • Result<String, RepoError>: The merge base commit SHA or an error

Example:

let merge_base = repo.get_merge_base("main", "feature-branch")?;
println!("Merge base: {}", merge_base);

Possible errors:

  • ReferenceError: Failed to resolve branch references
  • GraphError: Failed to find merge base
  • CommitOidError: Failed to get commit OID
§Repo::get_diverged_commit

Finds the common ancestor commit between the current branch and a reference.

pub fn get_diverged_commit(&self, git_ref: &str) -> Result<String, RepoError>

Parameters:

  • git_ref: The reference to compare against (branch, tag, or commit SHA)

Returns:

  • Result<String, RepoError>: The common ancestor commit SHA or an error

Example:

let diverged_commit = repo.get_diverged_commit("feature-branch")?;
println!("Common ancestor: {}", diverged_commit);

Possible errors:

  • ReferenceError: Failed to resolve reference
  • HeadError: Failed to get repository HEAD
  • GraphError: Failed to find common ancestor
  • CommitOidError: Failed to get commit OID

§Types Reference

§Repository Types

§Repo

The main repository struct that wraps libgit2 functionality.

pub struct Repo {
    repo: Repository,
    local_path: PathBuf,
}

Fields:

  • repo: Internal libgit2 repository handle
  • local_path: Path to the repository root directory

§File Status Types

§GitFileStatus

Represents the status of a file in Git.

pub enum GitFileStatus {
    Added,
    Modified,
    Deleted,
    Untracked,
}

Variants:

  • Added: File has been added to the repository
  • Modified: File has been modified
  • Deleted: File has been deleted
  • Untracked: File is not tracked by Git
§GitChangedFile

Represents a changed file with detailed status information.

pub struct GitChangedFile {
    pub path: String,
    pub status: GitFileStatus,
    pub staged: bool,
    pub workdir: bool,
}

Fields:

  • path: The path to the changed file
  • status: The status of the file (Added, Modified, Deleted, or Untracked)
  • staged: Whether the file is staged in the index
  • workdir: Whether the file has changes in the working directory

§Commit and Tag Types

§RepoCommit

Represents a commit in the Git repository.

pub struct RepoCommit {
    pub hash: String,
    pub author_name: String,
    pub author_email: String,
    pub author_date: String,
    pub message: String,
}

Fields:

  • hash: The commit hash (SHA)
  • author_name: The name of the commit author
  • author_email: The email of the commit author
  • author_date: The date of the commit in RFC2822 format
  • message: The commit message
§RepoTags

Represents a tag in the Git repository.

pub struct RepoTags {
    pub hash: String,
    pub tag: String,
}

Fields:

  • hash: The hash of the commit that the tag points to
  • tag: The name of the tag

§Error Types

§RepoError

Comprehensive error type for all Git operations.

pub enum RepoError {
    CanonicalPathFailure(std::io::Error),
    GitFailure(git2::Error),
    CreateRepoFailure(git2::Error),
    OpenRepoFailure(git2::Error),
    CloneRepoFailure(git2::Error),
    ConfigError(git2::Error),
    ConfigEntriesError(git2::Error),
    HeadError(git2::Error),
    PeelError(git2::Error),
    BranchError(git2::Error),
    SignatureError(git2::Error),
    IndexError(git2::Error),
    AddFilesError(git2::Error),
    WriteIndexError(git2::Error),
    TreeError(git2::Error),
    CommitError(git2::Error),
    WriteTreeError(git2::Error),
    BranchListError(git2::Error),
    BranchNameError(git2::Error),
    CheckoutBranchError(git2::Error),
    CheckoutError(git2::Error),
    LastTagError(git2::Error),
    CreateTagError(git2::Error),
    StatusError(git2::Error),
    CommitOidError(git2::Error),
    GraphError(git2::Error),
    PushError(git2::Error),
    RemoteError(git2::Error),
    ReferenceError(git2::Error),
    DiffError(git2::Error),
    RevWalkError(git2::Error),
    TagError(git2::Error),
    MergeError(git2::Error),
    MergeConflictError(git2::Error),
}

§Error Handling

All operations return Result<T, RepoError> to provide comprehensive error information. The error types are specific to the operation that failed, allowing for targeted error handling:

use sublime_git_tools::{Repo, RepoError};

match repo.checkout("feature-branch") {
    Ok(_) => println!("Switched to feature-branch"),
    Err(RepoError::BranchNameError(_)) => println!("Branch does not exist"),
    Err(RepoError::CheckoutBranchError(_)) => println!("Failed to checkout branch"),
    Err(e) => println!("Other error: {}", e),
}

§Examples

§Basic Workflow

use sublime_git_tools::Repo;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Create or open repository
    let repo = Repo::create("/tmp/example-repo")?;
    
    // Configure repository
    repo.config("John Doe", "john@example.com")?;
    
    // Create and commit changes
    std::fs::write("/tmp/example-repo/README.md", "# Example Project")?;
    repo.add("README.md")?;
    let commit_id = repo.commit("Initial commit")?;
    
    println!("Created commit: {}", commit_id);
    Ok(())
}

§Branch Management

use sublime_git_tools::Repo;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let repo = Repo::open("./my-project")?;
    
    // Create and switch to feature branch
    repo.create_branch("feature/new-feature")?;
    repo.checkout("feature/new-feature")?;
    
    // Make changes and commit
    repo.add_all()?;
    repo.commit("Add new feature")?;
    
    // Switch back to main and merge
    repo.checkout("main")?;
    repo.merge("feature/new-feature")?;
    
    // List all branches
    let branches = repo.list_branches()?;
    for branch in branches {
        println!("Branch: {}", branch);
    }
    
    Ok(())
}

§Tracking Changes

use sublime_git_tools::Repo;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let repo = Repo::open("./my-project")?;
    
    // Get last tag
    let last_tag = repo.get_last_tag()?;
    println!("Last release: {}", last_tag);
    
    // Get changes since last release
    let changed_files = repo.get_all_files_changed_since_sha_with_status(&last_tag)?;
    println!("Changes since {}:", last_tag);
    
    for file in changed_files {
        let status_char = match file.status {
            GitFileStatus::Added => "+",
            GitFileStatus::Modified => "M",
            GitFileStatus::Deleted => "-",
            GitFileStatus::Untracked => "?",
        };
        println!("{} {}", status_char, file.path);
    }
    
    // Get commit history
    let commits = repo.get_commits_since(Some(last_tag), &None)?;
    println!("\nCommits since last release:");
    for commit in commits {
        println!("- {} ({})", commit.message, &commit.hash[0..7]);
    }
    
    Ok(())
}

§Remote Operations Examples

use sublime_git_tools::Repo;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Clone a repository
    let repo = Repo::clone("https://github.com/example/repo.git", "/tmp/cloned-repo")?;
    
    // Configure the repository
    repo.config("Jane Doe", "jane@example.com")?;
    
    // Create a new branch with changes
    repo.create_branch("feature/remote-example")?;
    repo.checkout("feature/remote-example")?;
    
    // Make and commit changes
    std::fs::write("/tmp/cloned-repo/example.txt", "Example content")?;
    repo.add_all()?;
    repo.commit("feat: add example file")?;
    
    // Push the branch to remote
    repo.push("origin", None)?;
    
    // Fetch and pull from remote
    repo.fetch("origin", None, false)?;
    repo.checkout("main")?;
    repo.pull("origin", None)?;
    
    // List remote tags
    let remote_tags = repo.get_remote_or_local_tags(Some(false))?;
    println!("Remote tags:");
    for tag in remote_tags {
        println!("- {} ({})", tag.tag, &tag.hash[0..7]);
    }
    
    Ok(())
}

§sublime_git_tools

A high-level Rust interface to Git operations with robust error handling, built on libgit2.

§Overview

sublime_git_tools provides a user-friendly API for working with Git repositories. It wraps the powerful but complex libgit2 library to offer a more ergonomic interface for common Git operations.

This crate is designed for Rust applications that need to:

  • Create, clone, or manipulate Git repositories
  • Manage branches, commits, and tags
  • Track file changes between commits or branches
  • Push/pull with remote repositories
  • Get detailed commit histories
  • Detect changes in specific parts of a repository
  • Handle SSH authentication for remote operations
  • Perform advanced Git operations like merging and status checking

§Table of Contents

§API Reference

For complete API documentation with detailed method signatures, parameters, return types, and comprehensive examples, see the SPEC.md file.

§Repository Management

§Creating, Opening, and Cloning Repositories

use sublime_git_tools::Repo;

// Create a new repository
let repo = Repo::create("/path/to/new/repo")?;
println!("Repository created at: {}", repo.get_repo_path().display());

// Open an existing repository
let repo = Repo::open("./my-project")?;

// Clone a remote repository
let repo = Repo::clone("https://github.com/example/repo.git", "./cloned-repo")?;

// Get repository path
let repo_path = repo.get_repo_path();
println!("Repository is located at: {}", repo_path.display());

§Configuration

§Setting and Viewing Git Configuration

use sublime_git_tools::Repo;

let repo = Repo::open("./my-project")?;

// Configure user name and email
repo.config("Jane Doe", "jane@example.com")?;

// List all configuration entries
let config_entries = repo.list_config()?;
for (key, value) in config_entries {
    println!("{}: {}", key, value);
}

§Branch Operations

§Creating and Managing Branches

use sublime_git_tools::Repo;

let repo = Repo::open("./my-project")?;

// Create a new branch
repo.create_branch("feature/new-feature")?;

// Check if a branch exists
if repo.branch_exists("feature/new-feature")? {
    println!("Branch exists!");
}

// Checkout a branch
repo.checkout("feature/new-feature")?;

// Get current branch name
let current_branch = repo.get_current_branch()?;
println!("Currently on branch: {}", current_branch);

// List all branches
let branches = repo.list_branches()?;
for branch in branches {
    println!("Branch: {}", branch);
}

§Advanced Branch Information

use sublime_git_tools::Repo;

let repo = Repo::open("./my-project")?;

// Get branch from a specific commit
let commit_sha = "abcdef123456";
if let Some(branch) = repo.get_branch_from_commit(commit_sha)? {
    println!("Commit {} is on branch: {}", commit_sha, branch);
}

// Get all branches containing a commit
let branches = repo.get_branches_containing_commit(commit_sha)?;
for branch in branches {
    println!("Branch {} contains commit {}", branch, commit_sha);
}

// Find merge base between branches
let merge_base = repo.get_merge_base("main", "feature/new-feature")?;
println!("Merge base: {}", merge_base);

§Commit Operations

§Staging and Committing

use sublime_git_tools::Repo;

let repo = Repo::open("./my-project")?;

// Add a specific file
repo.add("src/main.rs")?;

// Add all changes
repo.add_all()?;

// Commit staged changes
let commit_id = repo.commit("feat: add new functionality")?;
println!("Created commit: {}", commit_id);

// Add all changes and commit in one step
let commit_id = repo.commit_changes("fix: resolve issue with authentication")?;
println!("Created commit: {}", commit_id);

§Commit Information

use sublime_git_tools::Repo;

let repo = Repo::open("./my-project")?;

// Get current commit SHA
let current_sha = repo.get_current_sha()?;
println!("Current commit: {}", current_sha);

// Get previous commit SHA
let previous_sha = repo.get_previous_sha()?;
println!("Previous commit: {}", previous_sha);

// Get commit history since a specific reference
let commits = repo.get_commits_since(Some("v1.0.0".to_string()), &None)?;
for commit in commits {
    println!("{}: {} (by {} on {})",
        commit.hash,
        commit.message,
        commit.author_name,
        commit.author_date
    );
}

// Get commits affecting a specific file
let file_commits = repo.get_commits_since(None, &Some("src/main.rs".to_string()))?;
for commit in file_commits {
    println!("Commit {} modified src/main.rs: {}", commit.hash, commit.message);
}

§Tag Operations

§Creating and Managing Tags

use sublime_git_tools::Repo;

let repo = Repo::open("./my-project")?;

// Create an annotated tag
repo.create_tag("v1.0.0", Some("Release version 1.0.0".to_string()))?;

// Create a lightweight tag
repo.create_tag("v1.0.1", None)?;

// Get the last tag
let last_tag = repo.get_last_tag()?;
println!("Last tag: {}", last_tag);

// Get all local tags
let local_tags = repo.get_remote_or_local_tags(Some(true))?;
for tag in local_tags {
    println!("Local tag: {} -> {}", tag.tag, tag.hash);
}

// Get all remote tags
let remote_tags = repo.get_remote_or_local_tags(Some(false))?;
for tag in remote_tags {
    println!("Remote tag: {} -> {}", tag.tag, tag.hash);
}

§File Status and Change Detection

§Repository Status

use sublime_git_tools::{Repo, GitFileStatus};

let repo = Repo::open("./my-project")?;

// Get porcelain status (simple format)
let status_lines = repo.status_porcelain()?;
for line in status_lines {
    println!("{}", line);
}

// Get detailed status with file information
let detailed_status = repo.get_status_detailed()?;
for file in detailed_status {
    println!("File: {}, Status: {:?}, Staged: {}, Workdir: {}",
        file.path,
        file.status,
        file.staged,
        file.workdir
    );
}

// Get only staged files
let staged_files = repo.get_staged_files()?;
for file in staged_files {
    println!("Staged: {}", file);
}

§Change Detection Between References

use sublime_git_tools::Repo;

let repo = Repo::open("./my-project")?;

// Get all changed files since a commit/tag with status
let changed_files = repo.get_all_files_changed_since_sha_with_status("v1.0.0")?;
for file in changed_files {
    println!("Changed file: {} ({:?})", file.path, file.status);
}

// Get simple list of changed files since a commit/tag
let changed_files = repo.get_all_files_changed_since_sha("v1.0.0")?;
for file in changed_files {
    println!("Changed: {}", file);
}

// Get files changed between two references
let files = repo.get_files_changed_between("main", "feature-branch")?;
for file in files {
    println!("File: {}, Status: {:?}, Staged: {}, Workdir: {}",
        file.path, file.status, file.staged, file.workdir);
}

// Get changes in specific packages/directories since a branch
let packages = vec!["packages/pkg1".to_string(), "packages/pkg2".to_string()];
let package_changes = repo.get_all_files_changed_since_branch(&packages, "main")?;
for file in package_changes {
    println!("Package change: {}", file);
}

§Remote Operations

§Basic Remote Operations

use sublime_git_tools::Repo;
use std::path::PathBuf;

let repo = Repo::open("./my-project")?;

// Push to remote (without tags)
let success = repo.push("origin", Some(false))?;
if success {
    println!("Push completed successfully");
}

// Push with tags
repo.push("origin", Some(true))?;

// Fetch from remote
repo.fetch("origin", None, false)?;

// Fetch a specific branch
repo.fetch("origin", Some("feature-branch"), false)?;

// Pull from remote (current branch)
let success = repo.pull("origin", None)?;
if success {
    println!("Pull completed successfully");
}

// Pull a specific branch
repo.pull("origin", Some("feature-branch"))?;

§SSH Authentication

use sublime_git_tools::Repo;
use std::path::PathBuf;

let repo = Repo::open("./my-project")?;

// Push using SSH key paths (tries multiple keys in order)
let ssh_key_paths = vec![
    PathBuf::from("/home/user/.ssh/id_ed25519"),
    PathBuf::from("/home/user/.ssh/id_rsa"),
];

let success = repo.push_with_ssh_config("origin", Some(true), ssh_key_paths)?;
if success {
    println!("SSH push completed successfully");
}

§Advanced Git Operations

§Merging

use sublime_git_tools::{Repo, RepoError};

let repo = Repo::open("./my-project")?;

// Merge a branch
match repo.merge("feature-branch") {
    Ok(_) => println!("Merge completed successfully"),
    Err(RepoError::MergeConflictError(_)) => {
        println!("Merge conflicts detected - manual resolution required");
        // Handle conflicts...
    },
    Err(e) => println!("Merge failed: {}", e),
}

// Find diverged commit (common ancestor)
let diverged_commit = repo.get_diverged_commit("feature-branch")?;
println!("Common ancestor: {}", diverged_commit);

§Error Handling

The crate uses a comprehensive error type (RepoError) that provides detailed information about Git operation failures:

use sublime_git_tools::{Repo, RepoError};

match Repo::open("/non/existent/path") {
    Ok(repo) => {
        // Repository operations...
        match repo.checkout("non-existent-branch") {
            Ok(_) => println!("Switched to branch successfully"),
            Err(RepoError::BranchNameError(_)) => {
                println!("Branch does not exist");
            },
            Err(RepoError::CheckoutBranchError(e)) => {
                println!("Failed to checkout branch: {}", e);
            },
            Err(e) => println!("Other checkout error: {}", e),
        }
    },
    Err(RepoError::OpenRepoFailure(e)) => {
        println!("Failed to open repository: {}", e);
    },
    Err(e) => println!("Other error: {}", e),
}

// Handle merge conflicts
match repo.merge("feature-branch") {
    Ok(_) => println!("Merge successful"),
    Err(RepoError::MergeConflictError(_)) => {
        println!("Merge conflicts require manual resolution");
        // Get conflicted files
        let status = repo.get_status_detailed()?;
        for file in status {
            if matches!(file.status, GitFileStatus::Modified) && file.staged && file.workdir {
                println!("Conflict in: {}", file.path);
            }
        }
    },
    Err(RepoError::MergeError(e)) => {
        println!("Merge failed: {}", e);
    },
    Err(e) => println!("Unexpected error: {}", e),
}

§Available Error Types

The RepoError enum provides specific error variants for different Git operations:

  • CreateRepoFailure - Repository creation errors
  • OpenRepoFailure - Repository opening errors
  • CloneRepoFailure - Repository cloning errors
  • BranchError / BranchNameError / CheckoutBranchError - Branch operation errors
  • CommitError / CommitOidError - Commit operation errors
  • MergeError / MergeConflictError - Merge operation errors
  • PushError / RemoteError - Remote operation errors
  • TagError / CreateTagError / LastTagError - Tag operation errors
  • ConfigError / ConfigEntriesError - Configuration errors
  • StatusError / DiffError - Status and diff errors
  • And many more for comprehensive error coverage

§Data Types

§Repository Types

use sublime_git_tools::{Repo, RepoCommit, RepoTags, GitChangedFile, GitFileStatus};

// RepoCommit - represents a commit
let commit = RepoCommit {
    hash: "abcdef123456".to_string(),
    author_name: "John Doe".to_string(),
    author_email: "john@example.com".to_string(),
    author_date: "Wed, 01 Jan 2023 12:00:00 +0000".to_string(),
    message: "feat: add new feature".to_string(),
};

// RepoTags - represents a tag
let tag = RepoTags {
    hash: "abcdef123456".to_string(),
    tag: "v1.0.0".to_string(),
};

// GitChangedFile - represents a file with change information
let changed_file = GitChangedFile {
    path: "src/main.rs".to_string(),
    status: GitFileStatus::Modified,
    staged: true,
    workdir: false,
};

// GitFileStatus - file status enumeration
match changed_file.status {
    GitFileStatus::Added => println!("File was added"),
    GitFileStatus::Modified => println!("File was modified"),
    GitFileStatus::Deleted => println!("File was deleted"),
    GitFileStatus::Untracked => println!("File is untracked"),
}

§Common Workflows

§Feature Branch Workflow

use sublime_git_tools::Repo;

let repo = Repo::open("./my-project")?;

// 1. Create and switch to feature branch
repo.create_branch("feature/user-authentication")?;
repo.checkout("feature/user-authentication")?;

// 2. Make changes and commit
repo.add("src/auth.rs")?;
repo.commit("feat: add user authentication module")?;

// 3. Push feature branch
repo.push("origin", Some(false))?;

// 4. Switch back to main and merge
repo.checkout("main")?;
repo.merge("feature/user-authentication")?;

// 5. Tag the release
repo.create_tag("v1.1.0", Some("Add user authentication".to_string()))?;
repo.push("origin", Some(true))?; // Push with tags

§Change Detection Workflow

use sublime_git_tools::Repo;

let repo = Repo::open("./my-project")?;

// Check what changed since last release
let last_tag = repo.get_last_tag()?;
let changed_files = repo.get_all_files_changed_since_sha_with_status(&last_tag)?;

println!("Changes since {}: ", last_tag);
for file in changed_files {
    match file.status {
        GitFileStatus::Added => println!("+ {}", file.path),
        GitFileStatus::Modified => println!("M {}", file.path),
        GitFileStatus::Deleted => println!("- {}", file.path),
        GitFileStatus::Untracked => println!("? {}", file.path),
    }
}

// Get commits for changelog
let commits = repo.get_commits_since(Some(last_tag), &None)?;
for commit in commits {
    println!("- {} ({})", commit.message, commit.hash[..8].to_string());
}

§Cross-Platform Support

The crate is designed to work on all major platforms:

  • Windows - Full support with vendored OpenSSL and libgit2
  • macOS - Full support with vendored dependencies
  • Linux - Full support with vendored dependencies

SSH operations are supported across all platforms with the vendored SSH implementation.

§Performance Considerations

  • The crate uses vendored libgit2 for consistent behavior across platforms
  • Repository operations are optimized for common use cases
  • Large repositories may benefit from specific Git configuration tuning
  • File change detection operations scale with repository size

§License

This crate is licensed under the terms specified in the workspace configuration.

§Contributing

Please see the workspace-level contribution guidelines for information on how to contribute to this crate.

Structs§

GitChangedFile
Represents a changed file in the Git repository with staging information
GitDiffStats
Represents diff statistics for a file
Repo
Represents a Git repository with high-level operation methods
RepoCommit
Represents a commit in the Git repository
RepoTags
Represents a tag in the Git repository
SystemEnvProvider
System environment provider using std::env::var

Enums§

GitFileStatus
Represents the status of a file in Git
RepoError
Errors that can occur when working with Git repositories

Traits§

EnvProvider
Trait for accessing environment variables

Type Aliases§

Result
Result type alias for git operations.