11//! `run` subcommand
22
3- use crate :: config:: { self , BranchName , Config , PullRequest } ;
3+ use crate :: config:: { self , BranchName , Config , PrNumber , PullRequest } ;
4+ use anyhow:: Result ;
45use std:: ffi:: OsString ;
56use std:: fs:: { self , File } ;
67use std:: io:: Write as _;
@@ -9,7 +10,6 @@ use std::path::PathBuf;
910use anyhow:: { anyhow, bail} ;
1011use colored:: Colorize as _;
1112
12- use crate :: git_high_level;
1313use crate :: github:: { self , Branch , Remote , RemoteBranch } ;
1414use crate :: utils:: { format_pr, format_url, with_uuid} ;
1515use crate :: { commands, confirm_prompt, git} ;
@@ -23,7 +23,7 @@ struct FileBackup {
2323}
2424
2525/// Run patchy, if `yes` then there will be no prompt
26- pub async fn run ( yes : bool , use_gh_cli : bool ) -> anyhow :: Result < ( ) > {
26+ pub async fn run ( yes : bool , use_gh_cli : bool ) -> Result < ( ) > {
2727 let root = config:: ROOT . as_str ( ) ;
2828
2929 let Ok ( config_string) = fs:: read_to_string ( & * config:: FILE_PATH ) else {
@@ -114,7 +114,7 @@ pub async fn run(yes: bool, use_gh_cli: bool) -> anyhow::Result<()> {
114114 } ,
115115 } ;
116116
117- git_high_level :: add_remote_branch ( & info, commit. as_ref ( ) ) ?;
117+ github :: add_remote_branch ( & info, commit. as_ref ( ) ) ?;
118118
119119 // we want to checkout the `branch` of `remote`
120120 let branch = & info. branch . local_branch_name ;
@@ -171,12 +171,9 @@ pub async fn run(yes: bool, use_gh_cli: bool) -> anyhow::Result<()> {
171171 continue ;
172172 } ;
173173
174- if let Err ( err) = git_high_level:: merge_pull_request (
175- & info,
176- * pull_request,
177- & response. title ,
178- & response. html_url ,
179- ) {
174+ if let Err ( err) =
175+ merge_pull_request ( & info, * pull_request, & response. title , & response. html_url )
176+ {
180177 log:: error!( "failed to merge {pull_request}: {err}" ) ;
181178 continue ;
182179 }
@@ -201,7 +198,7 @@ pub async fn run(yes: bool, use_gh_cli: bool) -> anyhow::Result<()> {
201198 continue ;
202199 } ;
203200
204- if let Err ( err) = git_high_level :: merge (
201+ if let Err ( err) = merge (
205202 & info. branch . local_branch_name ,
206203 & info. branch . upstream_branch_name ,
207204 ) {
@@ -327,3 +324,66 @@ pub async fn run(yes: bool, use_gh_cli: bool) -> anyhow::Result<()> {
327324
328325 Ok ( ( ) )
329326}
327+
328+ /// Create a merge commit that merges the `other_branch` into `current_branch`
329+ pub fn merge (
330+ current_branch : & BranchName ,
331+ other_branch : & BranchName ,
332+ ) -> Result < String , anyhow:: Error > {
333+ log:: trace!( "Merging branch {current_branch}" ) ;
334+
335+ if let Err ( err) = git:: merge ( current_branch. as_ref ( ) ) {
336+ git:: nuke_worktree ( ) ?;
337+ bail ! ( "failed to merge {other_branch}\n {err}" ) ;
338+ }
339+
340+ // --squash will NOT commit anything. So we need to make the commit it manually
341+ git:: commit ( & format ! ( "Merge {current_branch}" ) ) ?;
342+
343+ Ok ( format ! ( "Merged {other_branch} successfully" ) )
344+ }
345+
346+ /// Merge the `pull_request` into patchy's branch
347+ pub fn merge_pull_request (
348+ info : & RemoteBranch ,
349+ pull_request : PrNumber ,
350+ pr_title : & str ,
351+ pr_url : & str ,
352+ ) -> Result < ( ) > {
353+ merge (
354+ & info. branch . local_branch_name ,
355+ & info. branch . upstream_branch_name ,
356+ )
357+ . map_err ( |err| {
358+ let pr = format_pr ( pull_request, pr_title, pr_url) ;
359+
360+ let support_url = format_url (
361+ "Merge conflicts (github)" ,
362+ "https://github.com/nik-rev/patchy?tab=readme-ov-file#merge-conflicts" ,
363+ )
364+ . bright_blue ( ) ;
365+
366+ anyhow ! (
367+ "Could not merge branch {} into the current branch for pull request {pr} since the \
368+ merge is non-trivial.\n You will need to merge it yourself:\n {} {0}\n Note: To learn \
369+ how to merge only once and re-use for subsequent invocations of patchy, see \
370+ {support_url}\n Skipping this PR. Error message from git:\n {err}",
371+ & info. branch. local_branch_name. as_ref( ) . bright_cyan( ) ,
372+ "git merge --squash" . bright_blue( )
373+ )
374+ } ) ?;
375+
376+ if git:: is_worktree_dirty ( ) {
377+ git:: commit ( & format ! (
378+ "auto-merge pull request {}" ,
379+ & pr_url. replace( "github.com" , "redirect.github.com" )
380+ ) ) ?;
381+ }
382+
383+ git:: delete_remote_and_branch (
384+ & info. remote . local_remote_alias ,
385+ & info. branch . local_branch_name ,
386+ ) ?;
387+
388+ Ok ( ( ) )
389+ }
0 commit comments