//! Builder-pattern objects for configuration various git operations.

use libc::{c_char, c_int, c_uint, c_void, size_t};
use std::ffi::{CStr, CString};
use std::mem;
use std::path::Path;
use std::ptr;

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

/// A builder struct which is used to build configuration for cloning a new git
/// repository.
///
/// # Example
///
/// Cloning using SSH:
///
/// ```no_run
/// use git2::{Cred, Error, RemoteCallbacks};
/// use std::env;
/// use std::path::Path;
///
///   // Prepare callbacks.
///   let mut callbacks = RemoteCallbacks::new();
///   callbacks.credentials(|_url, username_from_url, _allowed_types| {
///     Cred::ssh_key(
///       username_from_url.unwrap(),
///       None,
///       Path::new(&format!("{}/.ssh/id_rsa", env::var("HOME").unwrap())),
///       None,
///     )
///   });
///
///   // Prepare fetch options.
///   let mut fo = git2::FetchOptions::new();
///   fo.remote_callbacks(callbacks);
///
///   // Prepare builder.
///   let mut builder = git2::build::RepoBuilder::new();
///   builder.fetch_options(fo);
///
///   // Clone the project.
///   builder.clone(
///     "git@github.com:rust-lang/git2-rs.git",
///     Path::new("/tmp/git2-rs"),
///   );
/// ```
pub struct RepoBuilder<'cb> {
    bare: bool,
    branch: Option<CString>,
    local: bool,
    hardlinks: bool,
    checkout: Option<CheckoutBuilder<'cb>>,
    fetch_opts: Option<FetchOptions<'cb>>,
    clone_local: Option<CloneLocal>,
    remote_create: Option<Box<RemoteCreate<'cb>>>,
}

/// Type of callback passed to `RepoBuilder::remote_create`.
///
/// The second and third arguments are the remote's name and the remote's url.
pub type RemoteCreate<'cb> =
    dyn for<'a> FnMut(&'a Repository, &str, &str) -> Result<Remote<'a>, Error> + 'cb;

/// A builder struct for git tree updates, for use with `git_tree_create_updated`.
pub struct TreeUpdateBuilder {
    updates: Vec<raw::git_tree_update>,
    paths: Vec<CString>,
}

/// A builder struct for configuring checkouts of a repository.
pub struct CheckoutBuilder<'cb> {
    their_label: Option<CString>,
    our_label: Option<CString>,
    ancestor_label: Option<CString>,
    target_dir: Option<CString>,
    paths: Vec<CString>,
    path_ptrs: Vec<*const c_char>,
    file_perm: Option<i32>,
    dir_perm: Option<i32>,
    disable_filters: bool,
    checkout_opts: u32,
    progress: Option<Box<Progress<'cb>>>,
    notify: Option<Box<Notify<'cb>>>,
    notify_flags: CheckoutNotificationType,
}

/// Checkout progress notification callback.
///
/// The first argument is the path for the notification, the next is the numver
/// of completed steps so far, and the final is the total number of steps.
pub type Progress<'a> = dyn FnMut(Option<&Path>, usize, usize) + 'a;

/// Checkout notifications callback.
///
/// The first argument is the notification type, the next is the path for the
/// the notification, followed by the baseline diff, target diff, and workdir diff.
///
/// The callback must return a bool specifying whether the checkout should
/// continue.
pub type Notify<'a> = dyn FnMut(
        CheckoutNotificationType,
        Option<&Path>,
        Option<DiffFile<'_>>,
        Option<DiffFile<'_>>,
        Option<DiffFile<'_>>,
    ) -> bool
    + 'a;

impl<'cb> Default for RepoBuilder<'cb> {
    fn default() -> Self {
        Self::new()
    }
}

/// Options that can be passed to `RepoBuilder::clone_local`.
#[derive(Clone, Copy)]
pub enum CloneLocal {
    /// Auto-detect (default)
    ///
    /// Here libgit2 will bypass the git-aware transport for local paths, but
    /// use a normal fetch for `file://` urls.
    Auto = raw::GIT_CLONE_LOCAL_AUTO as isize,

    /// Bypass the git-aware transport even for `file://` urls.
    Local = raw::GIT_CLONE_LOCAL as isize,

    /// Never bypass the git-aware transport
    None = raw::GIT_CLONE_NO_LOCAL as isize,

    /// Bypass the git-aware transport, but don't try to use hardlinks.
    NoLinks = raw::GIT_CLONE_LOCAL_NO_LINKS as isize,

    #[doc(hidden)]
    __Nonexhaustive = 0xff,
}

impl<'cb> RepoBuilder<'cb> {
    /// Creates a new repository builder with all of the default configuration.
    ///
    /// When ready, the `clone()` method can be used to clone a new repository
    /// using this configuration.
    pub fn new() -> RepoBuilder<'cb> {
        crate::init();
        RepoBuilder {
            bare: false,
            branch: None,
            local: true,
            clone_local: None,
            hardlinks: true,
            checkout: None,
            fetch_opts: None,
            remote_create: None,
        }
    }

    /// Indicate whether the repository will be cloned as a bare repository or
    /// not.
    pub fn bare(&mut self, bare: bool) -> &mut RepoBuilder<'cb> {
        self.bare = bare;
        self
    }

    /// Specify the name of the branch to check out after the clone.
    ///
    /// If not specified, the remote's default branch will be used.
    pub fn branch(&mut self, branch: &str) -> &mut RepoBuilder<'cb> {
        self.branch = Some(CString::new(branch).unwrap());
        self
    }

    /// Configures options for bypassing the git-aware transport on clone.
    ///
    /// Bypassing it means that instead of a fetch libgit2 will copy the object
    /// database directory instead of figuring out what it needs, which is
    /// faster. If possible, it will hardlink the files to save space.
    pub fn clone_local(&mut self, clone_local: CloneLocal) -> &mut RepoBuilder<'cb> {
        self.clone_local = Some(clone_local);
        self
    }

    /// Set the flag for bypassing the git aware transport mechanism for local
    /// paths.
    ///
    /// If `true`, the git-aware transport will be bypassed for local paths. If
    /// `false`, the git-aware transport will not be bypassed.
    #[deprecated(note = "use `clone_local` instead")]
    #[doc(hidden)]
    pub fn local(&mut self, local: bool) -> &mut RepoBuilder<'cb> {
        self.local = local;
        self
    }

    /// Set the flag for whether hardlinks are used when using a local git-aware
    /// transport mechanism.
    #[deprecated(note = "use `clone_local` instead")]
    #[doc(hidden)]
    pub fn hardlinks(&mut self, links: bool) -> &mut RepoBuilder<'cb> {
        self.hardlinks = links;
        self
    }

    /// Configure the checkout which will be performed by consuming a checkout
    /// builder.
    pub fn with_checkout(&mut self, checkout: CheckoutBuilder<'cb>) -> &mut RepoBuilder<'cb> {
        self.checkout = Some(checkout);
        self
    }

    /// Options which control the fetch, including callbacks.
    ///
    /// The callbacks are used for reporting fetch progress, and for acquiring
    /// credentials in the event they are needed.
    pub fn fetch_options(&mut self, fetch_opts: FetchOptions<'cb>) -> &mut RepoBuilder<'cb> {
        self.fetch_opts = Some(fetch_opts);
        self
    }

    /// Configures a callback used to create the git remote, prior to its being
    /// used to perform the clone operation.
    pub fn remote_create<F>(&mut self, f: F) -> &mut RepoBuilder<'cb>
    where
        F: for<'a> FnMut(&'a Repository, &str, &str) -> Result<Remote<'a>, Error> + 'cb,
    {
        self.remote_create = Some(Box::new(f));
        self
    }

    /// Clone a remote repository.
    ///
    /// This will use the options configured so far to clone the specified url
    /// into the specified local path.
    pub fn clone(&mut self, url: &str, into: &Path) -> Result<Repository, Error> {
        let mut opts: raw::git_clone_options = unsafe { mem::zeroed() };
        unsafe {
            try_call!(raw::git_clone_init_options(
                &mut opts,
                raw::GIT_CLONE_OPTIONS_VERSION
            ));
        }
        opts.bare = self.bare as c_int;
        opts.checkout_branch = self
            .branch
            .as_ref()
            .map(|s| s.as_ptr())
            .unwrap_or(ptr::null());

        if let Some(ref local) = self.clone_local {
            opts.local = *local as raw::git_clone_local_t;
        } else {
            opts.local = match (self.local, self.hardlinks) {
                (true, false) => raw::GIT_CLONE_LOCAL_NO_LINKS,
                (false, _) => raw::GIT_CLONE_NO_LOCAL,
                (true, _) => raw::GIT_CLONE_LOCAL_AUTO,
            };
        }

        if let Some(ref mut cbs) = self.fetch_opts {
            opts.fetch_opts = cbs.raw();
        }

        if let Some(ref mut c) = self.checkout {
            unsafe {
                c.configure(&mut opts.checkout_opts);
            }
        }

        if let Some(ref mut callback) = self.remote_create {
            opts.remote_cb = Some(remote_create_cb);
            opts.remote_cb_payload = callback as *mut _ as *mut _;
        }

        let url = CString::new(url)?;
        // Normal file path OK (does not need Windows conversion).
        let into = into.into_c_string()?;
        let mut raw = ptr::null_mut();
        unsafe {
            try_call!(raw::git_clone(&mut raw, url, into, &opts));
            Ok(Binding::from_raw(raw))
        }
    }
}

extern "C" fn remote_create_cb(
    out: *mut *mut raw::git_remote,
    repo: *mut raw::git_repository,
    name: *const c_char,
    url: *const c_char,
    payload: *mut c_void,
) -> c_int {
    unsafe {
        let repo = Repository::from_raw(repo);
        let code = panic::wrap(|| {
            let name = CStr::from_ptr(name).to_str().unwrap();
            let url = CStr::from_ptr(url).to_str().unwrap();
            let f = payload as *mut Box<RemoteCreate<'_>>;
            match (*f)(&repo, name, url) {
                Ok(remote) => {
                    *out = crate::remote::remote_into_raw(remote);
                    0
                }
                Err(e) => e.raw_code(),
            }
        });
        mem::forget(repo);
        code.unwrap_or(-1)
    }
}

impl<'cb> Default for CheckoutBuilder<'cb> {
    fn default() -> Self {
        Self::new()
    }
}

impl<'cb> CheckoutBuilder<'cb> {
    /// Creates a new builder for checkouts with all of its default
    /// configuration.
    pub fn new() -> CheckoutBuilder<'cb> {
        crate::init();
        CheckoutBuilder {
            disable_filters: false,
            dir_perm: None,
            file_perm: None,
            path_ptrs: Vec::new(),
            paths: Vec::new(),
            target_dir: None,
            ancestor_label: None,
            our_label: None,
            their_label: None,
            checkout_opts: raw::GIT_CHECKOUT_SAFE as u32,
            progress: None,
            notify: None,
            notify_flags: CheckoutNotificationType::empty(),
        }
    }

    /// Indicate that this checkout should perform a dry run by checking for
    /// conflicts but not make any actual changes.
    pub fn dry_run(&mut self) -> &mut CheckoutBuilder<'cb> {
        self.checkout_opts &= !((1 << 4) - 1);
        self.checkout_opts |= raw::GIT_CHECKOUT_NONE as u32;
        self
    }

    /// Take any action necessary to get the working directory to match the
    /// target including potentially discarding modified files.
    pub fn force(&mut self) -> &mut CheckoutBuilder<'cb> {
        self.checkout_opts &= !((1 << 4) - 1);
        self.checkout_opts |= raw::GIT_CHECKOUT_FORCE as u32;
        self
    }

    /// Indicate that the checkout should be performed safely, allowing new
    /// files to be created but not overwriting extisting files or changes.
    ///
    /// This is the default.
    pub fn safe(&mut self) -> &mut CheckoutBuilder<'cb> {
        self.checkout_opts &= !((1 << 4) - 1);
        self.checkout_opts |= raw::GIT_CHECKOUT_SAFE as u32;
        self
    }

    fn flag(&mut self, bit: raw::git_checkout_strategy_t, on: bool) -> &mut CheckoutBuilder<'cb> {
        if on {
            self.checkout_opts |= bit as u32;
        } else {
            self.checkout_opts &= !(bit as u32);
        }
        self
    }

    /// In safe mode, create files that don't exist.
    ///
    /// Defaults to false.
    pub fn recreate_missing(&mut self, allow: bool) -> &mut CheckoutBuilder<'cb> {
        self.flag(raw::GIT_CHECKOUT_RECREATE_MISSING, allow)
    }

    /// In safe mode, apply safe file updates even when there are conflicts
    /// instead of canceling the checkout.
    ///
    /// Defaults to false.
    pub fn allow_conflicts(&mut self, allow: bool) -> &mut CheckoutBuilder<'cb> {
        self.flag(raw::GIT_CHECKOUT_ALLOW_CONFLICTS, allow)
    }

    /// Remove untracked files from the working dir.
    ///
    /// Defaults to false.
    pub fn remove_untracked(&mut self, remove: bool) -> &mut CheckoutBuilder<'cb> {
        self.flag(raw::GIT_CHECKOUT_REMOVE_UNTRACKED, remove)
    }

    /// Remove ignored files from the working dir.
    ///
    /// Defaults to false.
    pub fn remove_ignored(&mut self, remove: bool) -> &mut CheckoutBuilder<'cb> {
        self.flag(raw::GIT_CHECKOUT_REMOVE_IGNORED, remove)
    }

    /// Only update the contents of files that already exist.
    ///
    /// If set, files will not be created or deleted.
    ///
    /// Defaults to false.
    pub fn update_only(&mut self, update: bool) -> &mut CheckoutBuilder<'cb> {
        self.flag(raw::GIT_CHECKOUT_UPDATE_ONLY, update)
    }

    /// Prevents checkout from writing the updated files' information to the
    /// index.
    ///
    /// Defaults to true.
    pub fn update_index(&mut self, update: bool) -> &mut CheckoutBuilder<'cb> {
        self.flag(raw::GIT_CHECKOUT_DONT_UPDATE_INDEX, !update)
    }

    /// Indicate whether the index and git attributes should be refreshed from
    /// disk before any operations.
    ///
    /// Defaults to true,
    pub fn refresh(&mut self, refresh: bool) -> &mut CheckoutBuilder<'cb> {
        self.flag(raw::GIT_CHECKOUT_NO_REFRESH, !refresh)
    }

    /// Skip files with unmerged index entries.
    ///
    /// Defaults to false.
    pub fn skip_unmerged(&mut self, skip: bool) -> &mut CheckoutBuilder<'cb> {
        self.flag(raw::GIT_CHECKOUT_SKIP_UNMERGED, skip)
    }

    /// Indicate whether the checkout should proceed on conflicts by using the
    /// stage 2 version of the file ("ours").
    ///
    /// Defaults to false.
    pub fn use_ours(&mut self, ours: bool) -> &mut CheckoutBuilder<'cb> {
        self.flag(raw::GIT_CHECKOUT_USE_OURS, ours)
    }

    /// Indicate whether the checkout should proceed on conflicts by using the
    /// stage 3 version of the file ("theirs").
    ///
    /// Defaults to false.
    pub fn use_theirs(&mut self, theirs: bool) -> &mut CheckoutBuilder<'cb> {
        self.flag(raw::GIT_CHECKOUT_USE_THEIRS, theirs)
    }

    /// Indicate whether ignored files should be overwritten during the checkout.
    ///
    /// Defaults to true.
    pub fn overwrite_ignored(&mut self, overwrite: bool) -> &mut CheckoutBuilder<'cb> {
        self.flag(raw::GIT_CHECKOUT_DONT_OVERWRITE_IGNORED, !overwrite)
    }

    /// Indicate whether a normal merge file should be written for conflicts.
    ///
    /// Defaults to false.
    pub fn conflict_style_merge(&mut self, on: bool) -> &mut CheckoutBuilder<'cb> {
        self.flag(raw::GIT_CHECKOUT_CONFLICT_STYLE_MERGE, on)
    }

    /// Specify for which notification types to invoke the notification
    /// callback.
    ///
    /// Defaults to none.
    pub fn notify_on(
        &mut self,
        notification_types: CheckoutNotificationType,
    ) -> &mut CheckoutBuilder<'cb> {
        self.notify_flags = notification_types;
        self
    }

    /// Indicates whether to include common ancestor data in diff3 format files
    /// for conflicts.
    ///
    /// Defaults to false.
    pub fn conflict_style_diff3(&mut self, on: bool) -> &mut CheckoutBuilder<'cb> {
        self.flag(raw::GIT_CHECKOUT_CONFLICT_STYLE_DIFF3, on)
    }

    /// Indicate whether to apply filters like CRLF conversion.
    pub fn disable_filters(&mut self, disable: bool) -> &mut CheckoutBuilder<'cb> {
        self.disable_filters = disable;
        self
    }

    /// Set the mode with which new directories are created.
    ///
    /// Default is 0755
    pub fn dir_perm(&mut self, perm: i32) -> &mut CheckoutBuilder<'cb> {
        self.dir_perm = Some(perm);
        self
    }

    /// Set the mode with which new files are created.
    ///
    /// The default is 0644 or 0755 as dictated by the blob.
    pub fn file_perm(&mut self, perm: i32) -> &mut CheckoutBuilder<'cb> {
        self.file_perm = Some(perm);
        self
    }

    /// Add a path to be checked out.
    ///
    /// If no paths are specified, then all files are checked out. Otherwise
    /// only these specified paths are checked out.
    pub fn path<T: IntoCString>(&mut self, path: T) -> &mut CheckoutBuilder<'cb> {
        let path = util::cstring_to_repo_path(path).unwrap();
        self.path_ptrs.push(path.as_ptr());
        self.paths.push(path);
        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).
        self.target_dir = Some(dst.into_c_string().unwrap());
        self
    }

    /// The name of the common ancestor side of conflicts
    pub fn ancestor_label(&mut self, label: &str) -> &mut CheckoutBuilder<'cb> {
        self.ancestor_label = Some(CString::new(label).unwrap());
        self
    }

    /// The name of the common our side of conflicts
    pub fn our_label(&mut self, label: &str) -> &mut CheckoutBuilder<'cb> {
        self.our_label = Some(CString::new(label).unwrap());
        self
    }

    /// The name of the common their side of conflicts
    pub fn their_label(&mut self, label: &str) -> &mut CheckoutBuilder<'cb> {
        self.their_label = Some(CString::new(label).unwrap());
        self
    }

    /// Set a callback to receive notifications of checkout progress.
    pub fn progress<F>(&mut self, cb: F) -> &mut CheckoutBuilder<'cb>
    where
        F: FnMut(Option<&Path>, usize, usize) + 'cb,
    {
        self.progress = Some(Box::new(cb) as Box<Progress<'cb>>);
        self
    }

    /// Set a callback to receive checkout notifications.
    ///
    /// Callbacks are invoked prior to modifying any files on disk.
    /// Returning `false` from the callback will cancel the checkout.
    pub fn notify<F>(&mut self, cb: F) -> &mut CheckoutBuilder<'cb>
    where
        F: FnMut(
                CheckoutNotificationType,
                Option<&Path>,
                Option<DiffFile<'_>>,
                Option<DiffFile<'_>>,
                Option<DiffFile<'_>>,
            ) -> bool
            + 'cb,
    {
        self.notify = Some(Box::new(cb) as Box<Notify<'cb>>);
        self
    }

    /// Configure a raw checkout options based on this configuration.
    ///
    /// This method is unsafe as there is no guarantee that this structure will
    /// outlive the provided checkout options.
    pub unsafe fn configure(&mut self, opts: &mut raw::git_checkout_options) {
        opts.version = raw::GIT_CHECKOUT_OPTIONS_VERSION;
        opts.disable_filters = self.disable_filters as c_int;
        opts.dir_mode = self.dir_perm.unwrap_or(0) as c_uint;
        opts.file_mode = self.file_perm.unwrap_or(0) as c_uint;

        if !self.path_ptrs.is_empty() {
            opts.paths.strings = self.path_ptrs.as_ptr() as *mut _;
            opts.paths.count = self.path_ptrs.len() as size_t;
        }

        if let Some(ref c) = self.target_dir {
            opts.target_directory = c.as_ptr();
        }
        if let Some(ref c) = self.ancestor_label {
            opts.ancestor_label = c.as_ptr();
        }
        if let Some(ref c) = self.our_label {
            opts.our_label = c.as_ptr();
        }
        if let Some(ref c) = self.their_label {
            opts.their_label = c.as_ptr();
        }
        if self.progress.is_some() {
            opts.progress_cb = Some(progress_cb);
            opts.progress_payload = self as *mut _ as *mut _;
        }
        if self.notify.is_some() {
            opts.notify_cb = Some(notify_cb);
            opts.notify_payload = self as *mut _ as *mut _;
            opts.notify_flags = self.notify_flags.bits() as c_uint;
        }
        opts.checkout_strategy = self.checkout_opts as c_uint;
    }
}

extern "C" fn progress_cb(
    path: *const c_char,
    completed: size_t,
    total: size_t,
    data: *mut c_void,
) {
    panic::wrap(|| unsafe {
        let payload = &mut *(data as *mut CheckoutBuilder<'_>);
        let callback = match payload.progress {
            Some(ref mut c) => c,
            None => return,
        };
        let path = if path.is_null() {
            None
        } else {
            Some(util::bytes2path(CStr::from_ptr(path).to_bytes()))
        };
        callback(path, completed as usize, total as usize)
    });
}

extern "C" fn notify_cb(
    why: raw::git_checkout_notify_t,
    path: *const c_char,
    baseline: *const raw::git_diff_file,
    target: *const raw::git_diff_file,
    workdir: *const raw::git_diff_file,
    data: *mut c_void,
) -> c_int {
    // pack callback etc
    panic::wrap(|| unsafe {
        let payload = &mut *(data as *mut CheckoutBuilder<'_>);
        let callback = match payload.notify {
            Some(ref mut c) => c,
            None => return 0,
        };
        let path = if path.is_null() {
            None
        } else {
            Some(util::bytes2path(CStr::from_ptr(path).to_bytes()))
        };

        let baseline = if baseline.is_null() {
            None
        } else {
            Some(DiffFile::from_raw(baseline))
        };

        let target = if target.is_null() {
            None
        } else {
            Some(DiffFile::from_raw(target))
        };

        let workdir = if workdir.is_null() {
            None
        } else {
            Some(DiffFile::from_raw(workdir))
        };

        let why = CheckoutNotificationType::from_bits_truncate(why as u32);
        let keep_going = callback(why, path, baseline, target, workdir);
        if keep_going {
            0
        } else {
            1
        }
    })
    .unwrap_or(2)
}

unsafe impl Send for TreeUpdateBuilder {}

impl Default for TreeUpdateBuilder {
    fn default() -> Self {
        Self::new()
    }
}

impl TreeUpdateBuilder {
    /// Create a new empty series of updates.
    pub fn new() -> Self {
        Self {
            updates: Vec::new(),
            paths: Vec::new(),
        }
    }

    /// Add an update removing the specified `path` from a tree.
    pub fn remove<T: IntoCString>(&mut self, path: T) -> &mut Self {
        let path = util::cstring_to_repo_path(path).unwrap();
        let path_ptr = path.as_ptr();
        self.paths.push(path);
        self.updates.push(raw::git_tree_update {
            action: raw::GIT_TREE_UPDATE_REMOVE,
            id: raw::git_oid {
                id: [0; raw::GIT_OID_RAWSZ],
            },
            filemode: raw::GIT_FILEMODE_UNREADABLE,
            path: path_ptr,
        });
        self
    }

    /// Add an update setting the specified `path` to a specific Oid, whether it currently exists
    /// or not.
    ///
    /// Note that libgit2 does not support an upsert of a previously removed path, or an upsert
    /// that changes the type of an object (such as from tree to blob or vice versa).
    pub fn upsert<T: IntoCString>(&mut self, path: T, id: Oid, filemode: FileMode) -> &mut Self {
        let path = util::cstring_to_repo_path(path).unwrap();
        let path_ptr = path.as_ptr();
        self.paths.push(path);
        self.updates.push(raw::git_tree_update {
            action: raw::GIT_TREE_UPDATE_UPSERT,
            id: unsafe { *id.raw() },
            filemode: u32::from(filemode) as raw::git_filemode_t,
            path: path_ptr,
        });
        self
    }

    /// Create a new tree from the specified baseline and this series of updates.
    ///
    /// The baseline tree must exist in the specified repository.
    pub fn create_updated(&mut self, repo: &Repository, baseline: &Tree<'_>) -> Result<Oid, Error> {
        let mut ret = raw::git_oid {
            id: [0; raw::GIT_OID_RAWSZ],
        };
        unsafe {
            try_call!(raw::git_tree_create_updated(
                &mut ret,
                repo.raw(),
                baseline.raw(),
                self.updates.len(),
                self.updates.as_ptr()
            ));
            Ok(Binding::from_raw(&ret as *const _))
        }
    }
}

#[cfg(test)]
mod tests {
    use super::{CheckoutBuilder, RepoBuilder, TreeUpdateBuilder};
    use crate::{CheckoutNotificationType, FileMode, Repository};
    use std::fs;
    use std::path::Path;
    use tempfile::TempDir;

    #[test]
    fn smoke() {
        let r = RepoBuilder::new().clone("/path/to/nowhere", Path::new("foo"));
        assert!(r.is_err());
    }

    #[test]
    fn smoke2() {
        let td = TempDir::new().unwrap();
        Repository::init_bare(&td.path().join("bare")).unwrap();
        let url = if cfg!(unix) {
            format!("file://{}/bare", td.path().display())
        } else {
            format!(
                "file:///{}/bare",
                td.path().display().to_string().replace("\\", "/")
            )
        };

        let dst = td.path().join("foo");
        RepoBuilder::new().clone(&url, &dst).unwrap();
        fs::remove_dir_all(&dst).unwrap();
        assert!(RepoBuilder::new().branch("foo").clone(&url, &dst).is_err());
    }

    #[test]
    fn smoke_tree_create_updated() {
        let (_tempdir, repo) = crate::test::repo_init();
        let (_, tree_id) = crate::test::commit(&repo);
        let tree = t!(repo.find_tree(tree_id));
        assert!(tree.get_name("bar").is_none());
        let foo_id = tree.get_name("foo").unwrap().id();
        let tree2_id = t!(TreeUpdateBuilder::new()
            .remove("foo")
            .upsert("bar/baz", foo_id, FileMode::Blob)
            .create_updated(&repo, &tree));
        let tree2 = t!(repo.find_tree(tree2_id));
        assert!(tree2.get_name("foo").is_none());
        let baz_id = tree2.get_path(Path::new("bar/baz")).unwrap().id();
        assert_eq!(foo_id, baz_id);
    }

    /// Issue regression test #365
    #[test]
    fn notify_callback() {
        let td = TempDir::new().unwrap();
        let cd = TempDir::new().unwrap();

        {
            let mut opts = crate::RepositoryInitOptions::new();
            opts.initial_head("main");
            let repo = Repository::init_opts(&td.path(), &opts).unwrap();

            let mut config = repo.config().unwrap();
            config.set_str("user.name", "name").unwrap();
            config.set_str("user.email", "email").unwrap();

            let mut index = repo.index().unwrap();
            let p = Path::new(td.path()).join("file");
            println!("using path {:?}", p);
            fs::File::create(&p).unwrap();
            index.add_path(&Path::new("file")).unwrap();
            let id = index.write_tree().unwrap();

            let tree = repo.find_tree(id).unwrap();
            let sig = repo.signature().unwrap();
            repo.commit(Some("HEAD"), &sig, &sig, "initial", &tree, &[])
                .unwrap();
        }

        let repo = Repository::open_bare(&td.path().join(".git")).unwrap();
        let tree = repo
            .revparse_single(&"main")
            .unwrap()
            .peel_to_tree()
            .unwrap();
        let mut index = repo.index().unwrap();
        index.read_tree(&tree).unwrap();

        let mut checkout_opts = CheckoutBuilder::new();
        checkout_opts.target_dir(&cd.path());
        checkout_opts.notify_on(CheckoutNotificationType::all());
        checkout_opts.notify(|_notif, _path, baseline, target, workdir| {
            assert!(baseline.is_none());
            assert_eq!(target.unwrap().path(), Some(Path::new("file")));
            assert!(workdir.is_none());
            true
        });
        repo.checkout_index(Some(&mut index), Some(&mut checkout_opts))
            .unwrap();
    }
}
