History

Squash 11 commits that get started with allowing to checkout a particular branch

FernTheDev committed 2 years ago

Commit 0912a461 parent 2f9f0ac2 files · +68 −4Browse files

Unified · Split

2 files
  1. gix/src/clone/checkout.rs +30 −3
  2. gix/tests/clone/mod.rs +38 −1
gix/src/clone/checkout.rs+30−3
@@ -5,6 +5,8 @@ use crate::{clone::PrepareCheckout, Repository}; · 4 unmodified lines
5pub mod main_worktree {5pub mod main_worktree {
6 use std::{path::PathBuf, sync::atomic::AtomicBool};6 use std::{path::PathBuf, sync::atomic::AtomicBool};
7 7
8 use gix_ref::bstr::BStr;
9
8 use crate::{clone::PrepareCheckout, Progress, Repository};10 use crate::{clone::PrepareCheckout, Progress, Repository};
9 11
10 /// The error returned by [`PrepareCheckout::main_worktree()`].12 /// The error returned by [`PrepareCheckout::main_worktree()`].
@@ -28,6 +30,8 @@ pub mod main_worktree { · 17 unmodified lines
28 CheckoutOptions(#[from] crate::config::checkout_options::Error),30 CheckoutOptions(#[from] crate::config::checkout_options::Error),
29 #[error(transparent)]31 #[error(transparent)]
30 IndexCheckout(#[from] gix_worktree_state::checkout::Error),32 IndexCheckout(#[from] gix_worktree_state::checkout::Error),
33 #[error(transparent)]
34 Peel(#[from] crate::reference::peel::Error),
31 #[error("Failed to reopen object database as Arc (only if thread-safety wasn't compiled in)")]35 #[error("Failed to reopen object database as Arc (only if thread-safety wasn't compiled in)")]
32 OpenArcOdb(#[from] std::io::Error),36 OpenArcOdb(#[from] std::io::Error),
33 #[error("The HEAD reference could not be located")]37 #[error("The HEAD reference could not be located")]
@@ -72,13 +76,29 @@ pub mod main_worktree { · 38 unmodified lines
72 P: gix_features::progress::NestedProgress,76 P: gix_features::progress::NestedProgress,
73 P::SubProgress: gix_features::progress::NestedProgress + 'static,77 P::SubProgress: gix_features::progress::NestedProgress + 'static,
74 {78 {
75 self.main_worktree_inner(&mut progress, should_interrupt)79 self.main_worktree_inner(&mut progress, should_interrupt, None)
80 }
81
82 /// Checkout the a worktree, determining how many threads to use by looking at `checkout.workers`, defaulting to using
83 /// on thread per logical core.
84 pub fn worktree<P>(
85 &mut self,
86 mut progress: P,
87 should_interrupt: &AtomicBool,
88 reference: Option<&BStr>,
89 ) -> Result<(Repository, gix_worktree_state::checkout::Outcome), Error>
90 where
91 P: gix_features::progress::NestedProgress,
92 P::SubProgress: gix_features::progress::NestedProgress + 'static,
93 {
94 self.main_worktree_inner(&mut progress, should_interrupt, reference)
76 }95 }
77 96
78 fn main_worktree_inner(97 fn main_worktree_inner(
79 &mut self,98 &mut self,
80 progress: &mut dyn gix_features::progress::DynNestedProgress,99 progress: &mut dyn gix_features::progress::DynNestedProgress,
81 should_interrupt: &AtomicBool,100 should_interrupt: &AtomicBool,
101 reference: Option<&BStr>,
82 ) -> Result<(Repository, gix_worktree_state::checkout::Outcome), Error> {102 ) -> Result<(Repository, gix_worktree_state::checkout::Outcome), Error> {
83 let _span = gix_trace::coarse!("gix::clone::PrepareCheckout::main_worktree()");103 let _span = gix_trace::coarse!("gix::clone::PrepareCheckout::main_worktree()");
84 let repo = self104 let repo = self
@@ -88,15 +108,22 @@ pub mod main_worktree { · 3 unmodified lines
88 let workdir = repo.work_dir().ok_or_else(|| Error::BareRepository {108 let workdir = repo.work_dir().ok_or_else(|| Error::BareRepository {
89 git_dir: repo.git_dir().to_owned(),109 git_dir: repo.git_dir().to_owned(),
90 })?;110 })?;
91 let root_tree = match repo.head()?.try_peel_to_id_in_place()? {111
112 let root_tree_id = match reference {
113 Some(reference_val) => Some(repo.find_reference(reference_val)?.peel_to_id_in_place()?),
114 None => repo.head()?.try_peel_to_id_in_place()?,
115 };
116
117 let root_tree = match root_tree_id {
92 Some(id) => id.object().expect("downloaded from remote").peel_to_tree()?.id,118 Some(id) => id.object().expect("downloaded from remote").peel_to_tree()?.id,
93 None => {119 None => {
94 return Ok((120 return Ok((
95 self.repo.take().expect("still present"),121 self.repo.take().expect("still present"),
96 gix_worktree_state::checkout::Outcome::default(),122 gix_worktree_state::checkout::Outcome::default(),
97 ))123 ));
98 }124 }
99 };125 };
126
100 let index = gix_index::State::from_tree(&root_tree, &repo.objects, repo.config.protect_options()?)127 let index = gix_index::State::from_tree(&root_tree, &repo.objects, repo.config.protect_options()?)
101 .map_err(|err| Error::IndexFromTree {128 .map_err(|err| Error::IndexFromTree {
102 id: root_tree,129 id: root_tree,
gix/tests/clone/mod.rs+38−1
@@ -5,7 +5,7 @@ mod blocking_io { · 4 unmodified lines
5 use std::{borrow::Cow, sync::atomic::AtomicBool};5 use std::{borrow::Cow, sync::atomic::AtomicBool};
6 6
7 use gix::{7 use gix::{
8 bstr::BString,8 bstr::{BStr, BString},
9 config::tree::{Clone, Core, Init, Key},9 config::tree::{Clone, Core, Init, Key},
10 remote::{10 remote::{
11 fetch::{Shallow, SpecIndex},11 fetch::{Shallow, SpecIndex},
@@ -507,6 +507,43 @@ mod blocking_io { · 495 unmodified lines
507 }507 }
508 Ok(())508 Ok(())
509 }509 }
510 #[test]
511 fn fetch_and_checkout_branch() -> crate::Result {
512 let tmp = gix_testtools::tempfile::TempDir::new()?;
513 let mut prepare = gix::clone::PrepareFetch::new(
514 remote::repo("base").path(),
515 tmp.path(),
516 gix::create::Kind::WithWorktree,
517 Default::default(),
518 restricted(),
519 )?;
520 let (mut checkout, _out) =
521 prepare.fetch_then_checkout(gix::progress::Discard, &std::sync::atomic::AtomicBool::default())?;
522
523 let branch_names = checkout.repo().branch_names();
524 let target_branch: &BStr = "a".into();
525 let branch_result = checkout.repo().find_reference(target_branch);
526
527 assert!(
528 branch_result.is_ok(),
529 "branch {target_branch} not found: {branch_result:?}. Available branches: {branch_names:?}"
530 );
531 let (repo, _) = checkout.worktree(
532 gix::progress::Discard,
533 &std::sync::atomic::AtomicBool::default(),
534 Some("a".into()),
535 )?;
536
537 let index = repo.index()?;
538 assert_eq!(index.entries().len(), 1, "All entries are known as per HEAD tree");
539
540 let work_dir = repo.work_dir().expect("non-bare");
541 for entry in index.entries() {
542 let entry_path = work_dir.join(gix_path::from_bstr(entry.path(&index)));
543 assert!(entry_path.is_file(), "{entry_path:?} not found on disk")
544 }
545 Ok(())
546 }
510 547
511 #[test]548 #[test]
512 fn fetch_and_checkout_empty_remote_repo() -> crate::Result {549 fn fetch_and_checkout_empty_remote_repo() -> crate::Result {