Skip to content
Open
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
24 changes: 23 additions & 1 deletion src/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use std::path::Path;
use std::ptr;

use crate::util::{self, Binding};
use crate::{panic, raw, Error, FetchOptions, IntoCString, Oid, Repository, Tree};
use crate::{panic, raw, Error, FetchOptions, Index, IntoCString, Oid, Repository, Tree};
use crate::{CheckoutNotificationType, DiffFile, FileMode, Remote};

/// A builder struct which is used to build configuration for cloning a new git
Expand Down Expand Up @@ -83,6 +83,8 @@ pub struct CheckoutBuilder<'cb> {
their_label: Option<CString>,
our_label: Option<CString>,
ancestor_label: Option<CString>,
baseline: Option<&'cb Tree<'cb>>,
baseline_index: Option<&'cb Index>,
target_dir: Option<CString>,
paths: Vec<CString>,
path_ptrs: Vec<*const c_char>,
Expand Down Expand Up @@ -334,6 +336,8 @@ impl<'cb> CheckoutBuilder<'cb> {
file_perm: None,
path_ptrs: Vec::new(),
paths: Vec::new(),
baseline: None,
baseline_index: None,
target_dir: None,
ancestor_label: None,
our_label: None,
Expand Down Expand Up @@ -535,6 +539,18 @@ impl<'cb> CheckoutBuilder<'cb> {
self
}

/// The expected content of the working directory. Overridden by [Self::baseline_index].
pub fn baseline(&mut self, tree: &'cb Tree<'cb>) -> &mut CheckoutBuilder<'cb> {
self.baseline = Some(tree);
self
}

/// The expected content of the working directory. Overrides [Self::baseline].
pub fn baseline_index(&mut self, index: &'cb Index) -> &mut CheckoutBuilder<'cb> {
self.baseline_index = Some(index);
self
}

/// Set the directory to check out to
pub fn target_dir(&mut self, dst: &Path) -> &mut CheckoutBuilder<'cb> {
// Normal file path OK (does not need Windows conversion).
Expand Down Expand Up @@ -606,6 +622,12 @@ impl<'cb> CheckoutBuilder<'cb> {
if let Some(ref c) = self.target_dir {
opts.target_directory = c.as_ptr();
}
if let Some(ref c) = self.baseline {
opts.baseline = c.raw();
}
if let Some(ref c) = self.baseline_index {
opts.baseline_index = c.raw();
}
if let Some(ref c) = self.ancestor_label {
opts.ancestor_label = c.as_ptr();
}
Expand Down
89 changes: 89 additions & 0 deletions src/repo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3658,9 +3658,11 @@ mod tests {
use crate::build::CheckoutBuilder;
use crate::AttrCheckFlags;
use crate::Error;
use crate::Index;
use crate::ObjectFormat;
#[cfg(feature = "unstable-sha256")]
use crate::RepositoryInitOptions;
use crate::Tree;
use crate::{CherrypickOptions, MergeFileOptions};
use crate::{
Config, ObjectType, Oid, Repository, ResetType, Signature, SubmoduleIgnore, SubmoduleUpdate,
Expand All @@ -3669,6 +3671,7 @@ mod tests {
use std::ffi::OsStr;
use std::fs;
use std::path::Path;
use std::path::PathBuf;

use libgit2_sys as raw;
use tempfile::TempDir;
Expand Down Expand Up @@ -3875,6 +3878,92 @@ mod tests {
assert_eq!(format, "sha256");
}

fn setup_checkout_with_baseline<'repo>(
repo: &'repo Repository,
) -> (PathBuf, PathBuf, PathBuf, Tree<'repo>, Tree<'repo>) {
let blank_commit = repo.revparse_single("HEAD").unwrap();

let (tree_a, path_a) = {
let mut index = repo.index().unwrap();
let path = Path::new(repo.workdir().unwrap()).join("file_a");
fs::write(&path, "a").unwrap();
index.add_path(Path::new("file_a")).unwrap();
let id = index.write_tree().unwrap();
(repo.find_tree(id).unwrap(), path)
};

t!(repo.reset(&blank_commit, ResetType::Hard, None));

let (tree_b, path_b) = {
let mut index = repo.index().unwrap();
let path = Path::new(repo.workdir().unwrap()).join("file_b");
fs::write(&path, "b").unwrap();
index.add_path(Path::new("file_b")).unwrap();
let id = index.write_tree().unwrap();
(repo.find_tree(id).unwrap(), path)
};

// Leave file_b in index.

let path_c = {
let mut index = repo.index().unwrap();
let path = Path::new(repo.workdir().unwrap()).join("file_c");
fs::write(&path, "c").unwrap();
index.add_path(Path::new("file_c")).unwrap();
path
};

(path_a, path_b, path_c, tree_a, tree_b)
}

#[test]
fn checkout_with_baseline() {
let (_td, repo) = crate::test::repo_init();
let (path_a, path_b, path_c, tree_a, tree_b) = setup_checkout_with_baseline(&repo);

let mut opts = CheckoutBuilder::new();
opts.baseline(&tree_b);
t!(repo.checkout_tree(&tree_a.into_object(), Some(&mut opts)));

assert!(
fs::exists(&path_a).unwrap(),
"we are checking out a tree that has a"
);
assert!(
!fs::exists(&path_b).unwrap(),
"we are checking out from a baseline that has b to a tree that does not have b"
);
assert!(
fs::exists(&path_c).unwrap(),
"c is related to neither baseline nor tree and is preserved"
);
}

#[test]
fn checkout_with_baseline_index() {
let (_td, repo) = crate::test::repo_init();
let (path_a, path_b, path_c, tree_a, tree_b) = setup_checkout_with_baseline(&repo);

let mut index = Index::new().unwrap();
index.read_tree(&tree_b).unwrap();
let mut opts = CheckoutBuilder::new();
opts.baseline_index(&index);
t!(repo.checkout_tree(&tree_a.into_object(), Some(&mut opts)));

assert!(
fs::exists(&path_a).unwrap(),
"we are checking out a tree that has a"
);
assert!(
!fs::exists(&path_b).unwrap(),
"we are checking out from a baseline that has b to a tree that does not have b"
);
assert!(
fs::exists(&path_c).unwrap(),
"c is related to neither baseline nor tree and is preserved"
);
}

#[test]
fn makes_dirs() {
let td = TempDir::new().unwrap();
Expand Down
Loading