A tool to help managing forked repos with their own history
1use anyhow::{bail, Context, Result};
2use std::process::Command;
3
4use crate::config::Config;
5use crate::git::{self, SOURCE_DIR};
6
7pub fn run() -> Result<()> {
8 let config = Config::load()?;
9 let repo = git::open_repo()?;
10 git::ensure_on_forkme_branch(&repo)?;
11
12 if !git::is_working_tree_clean(&repo)? {
13 bail!("Working tree has uncommitted changes. Please commit or stash them before updating.");
14 }
15
16 let upstream_branch = &config.upstream.branch;
17
18 println!("Fetching from origin...");
19 let fetch_status = Command::new("git")
20 .args(["fetch", "origin"])
21 .current_dir(SOURCE_DIR)
22 .status()
23 .context("Failed to run git fetch")?;
24
25 if !fetch_status.success() {
26 bail!("git fetch failed");
27 }
28
29 let head_before = repo.head()?.peel_to_commit()?.id();
30
31 // Rebase onto upstream
32 println!("Rebasing onto origin/{}...", upstream_branch);
33 let rebase_status = Command::new("git")
34 .args(["rebase", &format!("origin/{}", upstream_branch)])
35 .current_dir(SOURCE_DIR)
36 .status()
37 .context("Failed to run git rebase")?;
38
39 if !rebase_status.success() {
40 println!();
41 println!("Rebase encountered conflicts.");
42 println!();
43 println!("To resolve:");
44 println!(" 1. cd {}", SOURCE_DIR);
45 println!(" 2. Fix conflicts in the listed files");
46 println!(" 3. git add <fixed files>");
47 println!(" 4. git rebase --continue");
48 println!(" 5. Repeat until rebase is complete");
49 println!(" 6. Run 'forkme sync' to update patches");
50 println!();
51 println!("To abort the rebase: git rebase --abort");
52 return Ok(());
53 }
54
55 // Check if anything changed
56 let repo = git::open_repo()?; // Re-open to get fresh state
57 let head_after = repo.head()?.peel_to_commit()?.id();
58
59 if head_before == head_after {
60 println!("Already up to date.");
61 } else {
62 println!();
63 println!("Rebase successful!");
64 println!("Run 'forkme sync' to update your patches.");
65 }
66
67 Ok(())
68}