@@ -130,54 +130,135 @@ pub async fn run(yes: bool) -> anyhow::Result<()> {
130130 & info. remote . local_remote_alias ,
131131 ) ?;
132132
133- if config. pull_requests . is_empty ( ) {
133+ let has_pull_requests = !config. pull_requests . is_empty ( ) ;
134+ let has_branches = !config. branches . is_empty ( ) ;
135+
136+ if !has_pull_requests && !has_branches {
134137 log:: info!(
135- "You haven't specified any pull requests to fetch in your config, {}" ,
138+ "You haven't specified any pull requests or branches to fetch in your config, {}" ,
136139 display_link(
137140 "see the instructions on how to configure patchy." ,
138141 "https://github.com/nik-rev/patchy?tab=readme-ov-file#config"
139142 )
140143 ) ;
141144 } else {
142- // TODO: make this concurrent, see https://users.rust-lang.org/t/processing-subprocesses-concurrently/79638/3
143- // Git cannot handle multiple threads executing commands in the same repository,
144- // so we can't use threads, but we can run processes in the background
145- for pull_request in & config. pull_requests {
146- let pull_request = ignore_octothorpe ( pull_request) ;
147- let ( pull_request, commit_hash) = parse_if_maybe_hash ( & pull_request, " @ " ) ;
148- // TODO: refactor this to not use such deep nesting
149- match git:: fetch_pull_request ( & config. repo , & pull_request, None , commit_hash. as_ref ( ) )
145+ // Process pull requests
146+ if has_pull_requests {
147+ // TODO: make this concurrent, see https://users.rust-lang.org/t/processing-subprocesses-concurrently/79638/3
148+ // Git cannot handle multiple threads executing commands in the same repository,
149+ // so we can't use threads, but we can run processes in the background
150+ for pull_request in & config. pull_requests {
151+ let pull_request = ignore_octothorpe ( pull_request) ;
152+ let ( pull_request, commit_hash) = parse_if_maybe_hash ( & pull_request, " @ " ) ;
153+ // TODO: refactor this to not use such deep nesting
154+ match git:: fetch_pull_request (
155+ & config. repo ,
156+ & pull_request,
157+ None ,
158+ commit_hash. as_ref ( ) ,
159+ )
150160 . await
151- {
152- Ok ( ( response, info) ) => {
153- match git:: merge_pull_request (
154- & info,
155- & pull_request,
156- & response. title ,
157- & response. html_url ,
158- ) {
159- Ok ( ( ) ) => {
160- success ! (
161- "Merged pull request {}" ,
162- display_link(
163- & format!(
164- "{}{}{}{}" ,
165- "#" . bright_blue( ) ,
166- pull_request. bright_blue( ) ,
167- " " . bright_blue( ) ,
168- & response. title. bright_blue( ) . italic( )
161+ {
162+ Ok ( ( response, info) ) => {
163+ match git:: merge_pull_request (
164+ & info,
165+ & pull_request,
166+ & response. title ,
167+ & response. html_url ,
168+ ) {
169+ Ok ( ( ) ) => {
170+ success ! (
171+ "Merged pull request {}" ,
172+ display_link(
173+ & format!(
174+ "{}{}{}{}" ,
175+ "#" . bright_blue( ) ,
176+ pull_request. bright_blue( ) ,
177+ " " . bright_blue( ) ,
178+ & response. title. bright_blue( ) . italic( )
179+ ) ,
180+ & response. html_url
169181 ) ,
170- & response. html_url
171- ) ,
172- ) ;
173- }
174- Err ( err) => {
175- fail ! ( "{err}" ) ;
182+ ) ;
183+ }
184+ Err ( err) => {
185+ fail ! ( "{err}" ) ;
186+ }
176187 }
177188 }
189+ Err ( err) => {
190+ fail ! ( "Could not fetch branch from remote\n {err}" ) ;
191+ }
178192 }
179- Err ( err) => {
180- fail ! ( "Could not fetch branch from remote\n {err}" ) ;
193+ }
194+ }
195+
196+ // Process branches
197+ if has_branches {
198+ for branch_entry in & config. branches {
199+ let ( branch_path, commit_hash) = parse_if_maybe_hash ( branch_entry, " @ " ) ;
200+
201+ // Parse the branch path into owner/repo/branch format
202+ let parts: Vec < & str > = branch_path. split ( '/' ) . collect ( ) ;
203+ if parts. len ( ) < 3 {
204+ fail ! (
205+ "Invalid branch format: {}. Expected format: owner/repo/branch" ,
206+ branch_path
207+ ) ;
208+ continue ;
209+ }
210+
211+ let owner = parts[ 0 ] ;
212+ let repo = parts[ 1 ] ;
213+ let branch_name = parts[ 2 ..] . join ( "/" ) ;
214+
215+ let remote = crate :: cli:: Remote {
216+ owner : owner. to_string ( ) ,
217+ repo : repo. to_string ( ) ,
218+ branch : branch_name. clone ( ) ,
219+ } ;
220+
221+ match git:: fetch_branch ( & remote, commit_hash. as_ref ( ) ) . await {
222+ Ok ( ( _, info) ) => {
223+ match git:: merge_into_main (
224+ & info. branch . local_branch_name ,
225+ & info. branch . upstream_branch_name ,
226+ ) {
227+ Ok ( _) => {
228+ success ! (
229+ "Merged branch {}/{}/{} {}" ,
230+ owner. bright_blue( ) ,
231+ repo. bright_blue( ) ,
232+ branch_name. bright_blue( ) ,
233+ commit_hash
234+ . map( |hash| format!(
235+ "at commit {}" ,
236+ hash. as_ref( ) . bright_yellow( )
237+ ) )
238+ . unwrap_or_default( )
239+ ) ;
240+
241+ // Clean up the remote branch
242+ if let Err ( err) = git:: delete_remote_and_branch (
243+ & info. remote . local_remote_alias ,
244+ & info. branch . local_branch_name ,
245+ ) {
246+ fail ! ( "Failed to clean up branch: {err}" ) ;
247+ }
248+ }
249+ Err ( err) => {
250+ fail ! ( "{err}" ) ;
251+ }
252+ }
253+ }
254+ Err ( err) => {
255+ fail ! (
256+ "Could not fetch branch {}/{}/{}: {err}" ,
257+ owner,
258+ repo,
259+ branch_name
260+ ) ;
261+ }
181262 }
182263 }
183264 }
0 commit comments