1use crate::git;
2use crate::ref_name;
3
4pub struct LoadResult {
5 pub name: String,
6 pub conflicts: bool,
7 pub popped: bool,
8 pub auto_stashed: bool,
9}
10
11pub fn run(
12 name: String,
13 pop: bool,
14 theirs: bool,
15 ours: bool,
16 remote: String,
17) -> Result<LoadResult, String> {
18 let user = ref_name::user()?;
19 let name = ref_name::resolve_name(Some(name))?;
20 let wip_ref = ref_name::wip_ref(&name, &user);
21
22 let status = git::git_stdout(&["status", "--porcelain"])?;
24 let auto_stashed = !status.is_empty();
25 if auto_stashed {
26 git::git(&[
27 "stash",
28 "push",
29 "--include-untracked",
30 "-m",
31 "wip-push autostash",
32 ])?;
33 }
34
35 git::git(&["fetch", &remote, &wip_ref])?;
37
38 let mut cp_args = vec!["cherry-pick", "--no-commit", "FETCH_HEAD"];
40 if theirs {
41 cp_args.extend_from_slice(&["--strategy-option", "theirs"]);
42 } else if ours {
43 cp_args.extend_from_slice(&["--strategy-option", "ours"]);
44 }
45
46 let result = git::git_allow_fail(&cp_args)?;
47
48 let conflicts = result.stderr.contains("CONFLICT") || result.stdout.contains("CONFLICT");
49
50 if conflicts {
51 } else if result.stderr.contains("error") {
53 return Err(format!("cherry-pick failed: {}", result.stderr));
54 } else {
55 git::git(&["reset", "HEAD"])?;
57 }
58
59 if auto_stashed && !conflicts {
61 git::git_allow_fail(&["stash", "pop"])?;
62 }
63
64 let popped = if pop {
66 let delete_refspec = format!(":{wip_ref}");
67 git::git(&["push", &remote, &delete_refspec])?;
68 true
69 } else {
70 false
71 };
72
73 Ok(LoadResult {
74 name,
75 conflicts,
76 popped,
77 auto_stashed,
78 })
79}