summaryrefslogtreecommitdiffstats
path: root/extra/git2/src/worktree.rs
diff options
context:
space:
mode:
Diffstat (limited to 'extra/git2/src/worktree.rs')
-rw-r--r--extra/git2/src/worktree.rs331
1 files changed, 0 insertions, 331 deletions
diff --git a/extra/git2/src/worktree.rs b/extra/git2/src/worktree.rs
deleted file mode 100644
index 569b639cf..000000000
--- a/extra/git2/src/worktree.rs
+++ /dev/null
@@ -1,331 +0,0 @@
-use crate::buf::Buf;
-use crate::reference::Reference;
-use crate::repo::Repository;
-use crate::util::{self, Binding};
-use crate::{raw, Error};
-use std::os::raw::c_int;
-use std::path::Path;
-use std::ptr;
-use std::str;
-use std::{marker, mem};
-
-/// An owned git worktree
-///
-/// This structure corresponds to a `git_worktree` in libgit2.
-//
-pub struct Worktree {
- raw: *mut raw::git_worktree,
-}
-
-/// Options which can be used to configure how a worktree is initialized
-pub struct WorktreeAddOptions<'a> {
- raw: raw::git_worktree_add_options,
- _marker: marker::PhantomData<Reference<'a>>,
-}
-
-/// Options to configure how worktree pruning is performed
-pub struct WorktreePruneOptions {
- raw: raw::git_worktree_prune_options,
-}
-
-/// Lock Status of a worktree
-#[derive(PartialEq, Debug)]
-pub enum WorktreeLockStatus {
- /// Worktree is Unlocked
- Unlocked,
- /// Worktree is locked with the optional message
- Locked(Option<String>),
-}
-
-impl Worktree {
- /// Open a worktree of a the repository
- ///
- /// If a repository is not the main tree but a worktree, this
- /// function will look up the worktree inside the parent
- /// repository and create a new `git_worktree` structure.
- pub fn open_from_repository(repo: &Repository) -> Result<Worktree, Error> {
- let mut raw = ptr::null_mut();
- unsafe {
- try_call!(raw::git_worktree_open_from_repository(&mut raw, repo.raw()));
- Ok(Binding::from_raw(raw))
- }
- }
-
- /// Retrieves the name of the worktree
- ///
- /// This is the name that can be passed to repo::Repository::find_worktree
- /// to reopen the worktree. This is also the name that would appear in the
- /// list returned by repo::Repository::worktrees
- pub fn name(&self) -> Option<&str> {
- unsafe {
- crate::opt_bytes(self, raw::git_worktree_name(self.raw))
- .and_then(|s| str::from_utf8(s).ok())
- }
- }
-
- /// Retrieves the path to the worktree
- ///
- /// This is the path to the top-level of the source and not the path to the
- /// .git file within the worktree. This path can be passed to
- /// repo::Repository::open.
- pub fn path(&self) -> &Path {
- unsafe {
- util::bytes2path(crate::opt_bytes(self, raw::git_worktree_path(self.raw)).unwrap())
- }
- }
-
- /// Validates the worktree
- ///
- /// This checks that it still exists on the
- /// filesystem and that the metadata is correct
- pub fn validate(&self) -> Result<(), Error> {
- unsafe {
- try_call!(raw::git_worktree_validate(self.raw));
- }
- Ok(())
- }
-
- /// Locks the worktree
- pub fn lock(&self, reason: Option<&str>) -> Result<(), Error> {
- let reason = crate::opt_cstr(reason)?;
- unsafe {
- try_call!(raw::git_worktree_lock(self.raw, reason));
- }
- Ok(())
- }
-
- /// Unlocks the worktree
- pub fn unlock(&self) -> Result<(), Error> {
- unsafe {
- try_call!(raw::git_worktree_unlock(self.raw));
- }
- Ok(())
- }
-
- /// Checks if worktree is locked
- pub fn is_locked(&self) -> Result<WorktreeLockStatus, Error> {
- let buf = Buf::new();
- unsafe {
- match try_call!(raw::git_worktree_is_locked(buf.raw(), self.raw)) {
- 0 => Ok(WorktreeLockStatus::Unlocked),
- _ => {
- let v = buf.to_vec();
- Ok(WorktreeLockStatus::Locked(match v.len() {
- 0 => None,
- _ => Some(String::from_utf8(v).unwrap()),
- }))
- }
- }
- }
- }
-
- /// Prunes the worktree
- pub fn prune(&self, opts: Option<&mut WorktreePruneOptions>) -> Result<(), Error> {
- // When successful the worktree should be removed however the backing structure
- // of the git_worktree should still be valid.
- unsafe {
- try_call!(raw::git_worktree_prune(self.raw, opts.map(|o| o.raw())));
- }
- Ok(())
- }
-
- /// Checks if the worktree is prunable
- pub fn is_prunable(&self, opts: Option<&mut WorktreePruneOptions>) -> Result<bool, Error> {
- unsafe {
- let rv = try_call!(raw::git_worktree_is_prunable(
- self.raw,
- opts.map(|o| o.raw())
- ));
- Ok(rv != 0)
- }
- }
-}
-
-impl<'a> WorktreeAddOptions<'a> {
- /// Creates a default set of add options.
- ///
- /// By default this will not lock the worktree
- pub fn new() -> WorktreeAddOptions<'a> {
- unsafe {
- let mut raw = mem::zeroed();
- assert_eq!(
- raw::git_worktree_add_options_init(&mut raw, raw::GIT_WORKTREE_ADD_OPTIONS_VERSION),
- 0
- );
- WorktreeAddOptions {
- raw,
- _marker: marker::PhantomData,
- }
- }
- }
-
- /// If enabled, this will cause the newly added worktree to be locked
- pub fn lock(&mut self, enabled: bool) -> &mut WorktreeAddOptions<'a> {
- self.raw.lock = enabled as c_int;
- self
- }
-
- /// reference to use for the new worktree HEAD
- pub fn reference(
- &mut self,
- reference: Option<&'a Reference<'_>>,
- ) -> &mut WorktreeAddOptions<'a> {
- self.raw.reference = if let Some(reference) = reference {
- reference.raw()
- } else {
- ptr::null_mut()
- };
- self
- }
-
- /// Get a set of raw add options to be used with `git_worktree_add`
- pub fn raw(&self) -> *const raw::git_worktree_add_options {
- &self.raw
- }
-}
-
-impl WorktreePruneOptions {
- /// Creates a default set of pruning options
- ///
- /// By defaults this will prune only worktrees that are no longer valid
- /// unlocked and not checked out
- pub fn new() -> WorktreePruneOptions {
- unsafe {
- let mut raw = mem::zeroed();
- assert_eq!(
- raw::git_worktree_prune_options_init(
- &mut raw,
- raw::GIT_WORKTREE_PRUNE_OPTIONS_VERSION
- ),
- 0
- );
- WorktreePruneOptions { raw }
- }
- }
-
- /// Controls whether valid (still existing on the filesystem) worktrees
- /// will be pruned
- ///
- /// Defaults to false
- pub fn valid(&mut self, valid: bool) -> &mut WorktreePruneOptions {
- self.flag(raw::GIT_WORKTREE_PRUNE_VALID, valid)
- }
-
- /// Controls whether locked worktrees will be pruned
- ///
- /// Defaults to false
- pub fn locked(&mut self, locked: bool) -> &mut WorktreePruneOptions {
- self.flag(raw::GIT_WORKTREE_PRUNE_LOCKED, locked)
- }
-
- /// Controls whether the actual working tree on the filesystem is recursively removed
- ///
- /// Defaults to false
- pub fn working_tree(&mut self, working_tree: bool) -> &mut WorktreePruneOptions {
- self.flag(raw::GIT_WORKTREE_PRUNE_WORKING_TREE, working_tree)
- }
-
- fn flag(&mut self, flag: raw::git_worktree_prune_t, on: bool) -> &mut WorktreePruneOptions {
- if on {
- self.raw.flags |= flag as u32;
- } else {
- self.raw.flags &= !(flag as u32);
- }
- self
- }
-
- /// Get a set of raw prune options to be used with `git_worktree_prune`
- pub fn raw(&mut self) -> *mut raw::git_worktree_prune_options {
- &mut self.raw
- }
-}
-
-impl Binding for Worktree {
- type Raw = *mut raw::git_worktree;
- unsafe fn from_raw(ptr: *mut raw::git_worktree) -> Worktree {
- Worktree { raw: ptr }
- }
- fn raw(&self) -> *mut raw::git_worktree {
- self.raw
- }
-}
-
-impl Drop for Worktree {
- fn drop(&mut self) {
- unsafe { raw::git_worktree_free(self.raw) }
- }
-}
-
-#[cfg(test)]
-mod tests {
- use crate::WorktreeAddOptions;
- use crate::WorktreeLockStatus;
-
- use tempfile::TempDir;
-
- #[test]
- fn smoke_add_no_ref() {
- let (_td, repo) = crate::test::repo_init();
-
- let wtdir = TempDir::new().unwrap();
- let wt_path = wtdir.path().join("tree-no-ref-dir");
- let opts = WorktreeAddOptions::new();
-
- let wt = repo.worktree("tree-no-ref", &wt_path, Some(&opts)).unwrap();
- assert_eq!(wt.name(), Some("tree-no-ref"));
- assert_eq!(
- wt.path().canonicalize().unwrap(),
- wt_path.canonicalize().unwrap()
- );
- let status = wt.is_locked().unwrap();
- assert_eq!(status, WorktreeLockStatus::Unlocked);
- }
-
- #[test]
- fn smoke_add_locked() {
- let (_td, repo) = crate::test::repo_init();
-
- let wtdir = TempDir::new().unwrap();
- let wt_path = wtdir.path().join("locked-tree");
- let mut opts = WorktreeAddOptions::new();
- opts.lock(true);
-
- let wt = repo.worktree("locked-tree", &wt_path, Some(&opts)).unwrap();
- // shouldn't be able to lock a worktree that was created locked
- assert!(wt.lock(Some("my reason")).is_err());
- assert_eq!(wt.name(), Some("locked-tree"));
- assert_eq!(
- wt.path().canonicalize().unwrap(),
- wt_path.canonicalize().unwrap()
- );
- assert_eq!(wt.is_locked().unwrap(), WorktreeLockStatus::Locked(None));
- assert!(wt.unlock().is_ok());
- assert!(wt.lock(Some("my reason")).is_ok());
- assert_eq!(
- wt.is_locked().unwrap(),
- WorktreeLockStatus::Locked(Some("my reason".to_string()))
- );
- }
-
- #[test]
- fn smoke_add_from_branch() {
- let (_td, repo) = crate::test::repo_init();
-
- let (wt_top, branch) = crate::test::worktrees_env_init(&repo);
- let wt_path = wt_top.path().join("test");
- let mut opts = WorktreeAddOptions::new();
- let reference = branch.into_reference();
- opts.reference(Some(&reference));
-
- let wt = repo
- .worktree("test-worktree", &wt_path, Some(&opts))
- .unwrap();
- assert_eq!(wt.name(), Some("test-worktree"));
- assert_eq!(
- wt.path().canonicalize().unwrap(),
- wt_path.canonicalize().unwrap()
- );
- let status = wt.is_locked().unwrap();
- assert_eq!(status, WorktreeLockStatus::Unlocked);
- }
-}