Skip to main content

outpost_core/ops/
pull.rs

1use crate::safety;
2use crate::{Outpost, OutpostError, OutpostResult, RefName, Reporter, StepKind, UpstreamRef};
3
4pub struct PullOptions;
5
6pub struct PullReport {
7    pub source_updated: bool,
8    pub outpost_updated: bool,
9}
10
11pub fn run(
12    outpost: &Outpost,
13    _opts: PullOptions,
14    reporter: &mut dyn Reporter,
15) -> OutpostResult<PullReport> {
16    let branch = outpost.current_branch().map_err(|err| match err {
17        OutpostError::BranchNotFound { .. } => OutpostError::NoUpstreamTracking {
18            branch: "HEAD".to_owned(),
19        },
20        other => other,
21    })?;
22    let source = outpost.source_repo()?;
23    if !source.branch_exists(&branch)? {
24        return Err(OutpostError::BranchNotFound {
25            branch: branch.as_str().to_owned(),
26            repo: source.work_tree().to_path_buf(),
27        });
28    }
29
30    reporter.step(
31        StepKind::SourceFetch,
32        &format!(
33            "fast-forwarding source {} branch {} from origin/{}",
34            source.work_tree().display(),
35            branch.as_str(),
36            branch.as_str()
37        ),
38    );
39    let source_branch_ref = format!("refs/heads/{}", branch.as_str());
40    let source_before = source
41        .git()
42        .run_capture(["rev-parse", &source_branch_ref])?;
43    source.fast_forward_branch_from_origin(&branch)?;
44    let source_after = source
45        .git()
46        .run_capture(["rev-parse", &source_branch_ref])?;
47
48    let upstream = UpstreamRef {
49        remote: outpost.metadata().remote_name.clone(),
50        merge_ref: RefName::parse(format!("refs/heads/{}", branch.as_str()))?,
51    };
52    safety::check_no_divergence(outpost, &branch, &upstream)?;
53
54    reporter.step(
55        StepKind::OutpostFetch,
56        &format!(
57            "fast-forwarding outpost {} branch {} from {}/{}",
58            outpost.work_tree().display(),
59            branch.as_str(),
60            upstream.remote.as_str(),
61            branch.as_str()
62        ),
63    );
64    let before = outpost.git().run_capture(["rev-parse", "HEAD"])?;
65    outpost.git().run_check([
66        "pull",
67        "--ff-only",
68        upstream.remote.as_str(),
69        branch.as_str(),
70    ])?;
71    let after = outpost.git().run_capture(["rev-parse", "HEAD"])?;
72
73    Ok(PullReport {
74        source_updated: source_before != source_after,
75        outpost_updated: before != after,
76    })
77}