Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src-tauri/src/git/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ use tauri::State;

use crate::shared::process_core::tokio_command;
use crate::git_utils::{
checkout_branch, commit_to_entry, diff_patch_to_string, diff_stats_for_path,
image_mime_type, list_git_roots as scan_git_roots, parse_github_repo, resolve_git_root,
checkout_branch, commit_to_entry, diff_patch_to_string, diff_stats_for_path, image_mime_type,
list_git_roots as scan_git_roots, parse_github_repo, resolve_git_root,
};
use crate::state::AppState;
use crate::types::{
Expand Down Expand Up @@ -1497,6 +1497,7 @@ pub(crate) async fn create_git_branch(
mod tests {
use super::*;
use std::fs;
use std::path::Path;

fn create_temp_repo() -> (PathBuf, Repository) {
let root = std::env::temp_dir().join(format!(
Expand Down
34 changes: 31 additions & 3 deletions src-tauri/src/git_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,12 @@ pub(crate) fn commit_to_entry(commit: git2::Commit) -> GitLogEntry {

pub(crate) fn checkout_branch(repo: &Repository, name: &str) -> Result<(), git2::Error> {
let refname = format!("refs/heads/{name}");
repo.set_head(&refname)?;
let target = repo.revparse_single(&refname)?;

let mut options = git2::build::CheckoutBuilder::new();
options.safe();
repo.checkout_head(Some(&mut options))?;
repo.checkout_tree(&target, Some(&mut options))?;
repo.set_head(&refname)?;
Ok(())
}

Expand Down Expand Up @@ -90,7 +92,10 @@ pub(crate) fn diff_patch_to_string(patch: &mut git2::Patch) -> Result<String, gi

#[cfg(test)]
mod tests {
use super::image_mime_type;
use super::{checkout_branch, image_mime_type};
use git2::Repository;
use std::fs;
use std::path::Path;

#[test]
fn image_mime_type_detects_known_extensions() {
Expand All @@ -101,6 +106,29 @@ mod tests {
assert_eq!(image_mime_type("readme.txt"), None);
}

#[test]
fn checkout_branch_missing_does_not_change_head() {
let root = std::env::temp_dir().join(format!(
"codex-monitor-git-utils-test-{}",
uuid::Uuid::new_v4()
));
fs::create_dir_all(&root).expect("create temp repo root");
let repo = Repository::init(&root).expect("init repo");

fs::write(root.join("base.txt"), "base\n").expect("write file");
let mut index = repo.index().expect("index");
index.add_path(Path::new("base.txt")).expect("add path");
let tree_id = index.write_tree().expect("write tree");
let tree = repo.find_tree(tree_id).expect("find tree");
let sig = git2::Signature::now("Test", "test@example.com").expect("signature");
repo.commit(Some("HEAD"), &sig, &sig, "init", &tree, &[])
.expect("commit");

let before = repo.head().expect("head").name().unwrap_or("").to_string();
assert!(checkout_branch(&repo, "does-not-exist").is_err());
let after = repo.head().expect("head after").name().unwrap_or("").to_string();
assert_eq!(after, before);
}
}

pub(crate) fn parse_github_repo(remote_url: &str) -> Option<String> {
Expand Down