aboutsummaryrefslogtreecommitdiff
path: root/src/repo/git/checkout.rs
blob: 418a0afa2538f75ea04d6e4616e486d4f95ac316 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
use super::{Repo, RepoError};

use anyhow::Context;
use gix::{
    clone::checkout::main_worktree::ProgressId, interrupt::IS_INTERRUPTED, progress, remote, Id,
    Progress,
};

use gix_index::{File, State};
use tracing::debug;

impl Repo {
    #[tracing::instrument(level = "trace", skip(progress))]
    pub fn checkout(
        &self,
        remote: remote::Name,
        head: Id,
        progress: &mut dyn progress::DynNestedProgress,
    ) -> Result<(), RepoError> {
        let repo = self.repo()?;

        let workdir = repo.work_dir().ok_or(RepoError::NoWorktree)?;
        let head_tree = head
            .object()
            .context("could not find object HEAD points to")?
            .peel_to_tree()
            .context("failed to peel HEAD object")?
            .id();

        let index = State::from_tree(&head_tree, &repo.objects).context("index from tree")?;
        let mut index = File::from_state(index, repo.index_path());

        let mut files =
            progress.add_child_with_id("checkout".to_string(), ProgressId::CheckoutFiles.into());
        let mut bytes =
            progress.add_child_with_id("writing".to_string(), ProgressId::BytesWritten.into());

        files.init(Some(index.entries().len()), progress::count("files"));
        bytes.init(None, progress::bytes());

        let start = std::time::Instant::now();

        debug!("workdir: {:?}", workdir);
        let opts = gix_worktree_state::checkout::Options::default();
        let outcome = gix_worktree_state::checkout(
            &mut index,
            workdir,
            repo.objects.clone().into_arc().unwrap(),
            &files,
            &bytes,
            &IS_INTERRUPTED,
            opts,
        )
        .context("checkout: failed");

        files.show_throughput(start);
        bytes.show_throughput(start);

        debug!("outcome: {:?}", outcome);
        debug!("is interrupted: {:?}", &gix::interrupt::IS_INTERRUPTED);

        index
            .write(Default::default())
            .context("checkout: write index")?;

        Ok(())
    }
}