Skip to main content

gps/ps/public/
pull.rs

1use super::super::private::config;
2use super::super::private::git;
3use super::super::private::paths;
4use super::super::private::utils;
5use super::super::public::fetch;
6use super::super::public::list;
7
8#[derive(Debug)]
9pub enum PullError {
10    RepositoryMissing,
11    GetHeadBranchNameFailed,
12    GetUpstreamBranchNameFailed,
13    RebaseFailed(utils::ExecuteError),
14    FetchFailed(fetch::FetchError),
15    GetRepoRootPathFailed(paths::PathsError),
16    PathNotUtf8,
17    GetConfigFailed(config::GetConfigError),
18    ListFailed(list::ListError),
19}
20
21impl std::fmt::Display for PullError {
22    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
23        match self {
24            Self::RepositoryMissing => write!(f, "repository missing"),
25            Self::GetHeadBranchNameFailed => write!(f, "get head branch name failed"),
26            Self::GetUpstreamBranchNameFailed => write!(f, "get upstream branch name failed"),
27            Self::RebaseFailed(e) => write!(f, "rebase failed, {}", e),
28            Self::FetchFailed(e) => write!(f, "fetch failed, {}", e),
29            Self::GetRepoRootPathFailed(e) => write!(f, "get repository root path failed, {}", e),
30            Self::PathNotUtf8 => write!(f, "path not utf-8"),
31            Self::GetConfigFailed(e) => write!(f, "get config failed, {}", e),
32            Self::ListFailed(e) => write!(f, "get list failed, {}", e),
33        }
34    }
35}
36
37impl std::error::Error for PullError {
38    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
39        match self {
40            Self::RepositoryMissing => None,
41            Self::GetHeadBranchNameFailed => None,
42            Self::GetUpstreamBranchNameFailed => None,
43            Self::RebaseFailed(e) => Some(e),
44            Self::FetchFailed(e) => Some(e),
45            Self::GetRepoRootPathFailed(e) => Some(e),
46            Self::PathNotUtf8 => None,
47            Self::GetConfigFailed(e) => Some(e),
48            Self::ListFailed(e) => Some(e),
49        }
50    }
51}
52
53pub fn pull(color: bool) -> Result<(), PullError> {
54    let repo = git::create_cwd_repo().map_err(|_| PullError::RepositoryMissing)?;
55
56    let repo_root_path = paths::repo_root_path(&repo).map_err(PullError::GetRepoRootPathFailed)?;
57    let repo_root_str = repo_root_path.to_str().ok_or(PullError::PathNotUtf8)?;
58    let repo_gitdir_path = repo.path();
59    let repo_gitdir_str = repo_gitdir_path.to_str().ok_or(PullError::PathNotUtf8)?;
60    let config =
61        config::get_config(repo_root_str, repo_gitdir_str).map_err(PullError::GetConfigFailed)?;
62
63    let head_ref = repo
64        .head()
65        .map_err(|_| PullError::GetHeadBranchNameFailed)?;
66    let head_branch_shorthand = head_ref
67        .shorthand()
68        .ok_or(PullError::GetHeadBranchNameFailed)?;
69    let head_branch_name = head_ref.name().ok_or(PullError::GetHeadBranchNameFailed)?;
70
71    let upstream_branch_name = git::branch_upstream_name(&repo, head_branch_name)
72        .map_err(|_| PullError::GetUpstreamBranchNameFailed)?;
73
74    println!("Fetching upstream patches...");
75    fetch::fetch(color).map_err(PullError::FetchFailed)?;
76    println!();
77
78    println!("Rebasing...");
79    utils::execute(
80        "git",
81        &[
82            "rebase",
83            "--no-reapply-cherry-picks",
84            "--onto",
85            upstream_branch_name.as_str(),
86            upstream_branch_name.as_str(),
87            head_branch_shorthand,
88        ],
89    )
90    .map_err(PullError::RebaseFailed)?;
91    println!();
92
93    if config.pull.show_list_post_pull {
94        println!("Listing patch stack...");
95        list::list(color).map_err(PullError::ListFailed)?
96    }
97
98    Ok(())
99}