Skip to main content

outpost_core/ops/
merge.rs

1use crate::{Outpost, OutpostError, OutpostResult, Reporter, SourceRemoteRef, StepKind};
2
3pub struct MergeOptions {
4    pub source_ref: SourceRemoteRef,
5}
6
7pub struct MergeReport {
8    pub source_ref: SourceRemoteRef,
9}
10
11pub fn run(
12    outpost: &Outpost,
13    opts: MergeOptions,
14    reporter: &mut dyn Reporter,
15) -> OutpostResult<MergeReport> {
16    outpost.current_branch().map_err(|err| match err {
17        OutpostError::BranchNotFound { .. } => OutpostError::NoUpstreamTracking {
18            branch: "HEAD".to_owned(),
19        },
20        other => other,
21    })?;
22    validate_source_remote(outpost, &opts.source_ref)?;
23
24    reporter.step(
25        StepKind::OutpostFetch,
26        &format!(
27            "fetching source {} branch {} into outpost {}",
28            outpost.metadata().source_repo.display(),
29            opts.source_ref.branch.as_str(),
30            outpost.work_tree().display()
31        ),
32    );
33    let remote_tracking_ref = fetch_source_ref(outpost, &opts.source_ref)?;
34    outpost.git().run_check(["merge", &remote_tracking_ref])?;
35
36    Ok(MergeReport {
37        source_ref: opts.source_ref,
38    })
39}
40
41fn validate_source_remote(outpost: &Outpost, source_ref: &SourceRemoteRef) -> OutpostResult<()> {
42    if source_ref.remote == outpost.metadata().remote_name {
43        Ok(())
44    } else {
45        Err(OutpostError::InvalidRefName {
46            name: format!(
47                "{}/{}",
48                source_ref.remote.as_str(),
49                source_ref.branch.as_str()
50            ),
51        })
52    }
53}
54
55fn fetch_source_ref(outpost: &Outpost, source_ref: &SourceRemoteRef) -> OutpostResult<String> {
56    let remote_tracking_ref = format!(
57        "refs/remotes/{}/{}",
58        source_ref.remote.as_str(),
59        source_ref.branch.as_str()
60    );
61    let fetch_refspec = format!("{}:{remote_tracking_ref}", source_ref.branch.as_str());
62    outpost
63        .git()
64        .run_check(["fetch", source_ref.remote.as_str(), &fetch_refspec])?;
65    Ok(remote_tracking_ref)
66}