@@ -141,40 +141,111 @@ pub fn merge_worktree(
141141 main_branch
142142 } ;
143143
144- // Merge the worktree branch into main
145- let merge = Command :: new ( "git" )
146- . args ( [ "merge" , & branch, "--no-edit" ] )
147- . current_dir ( & project_path)
148- . output ( )
149- . map_err ( |e| format ! ( "Failed to merge: {e}" ) ) ?;
144+ // Check if this thread is linked to a PR
145+ let pr_number = {
146+ let db = state. db . lock ( ) . map_err ( |e| format ! ( "{e}" ) ) ?;
147+ codeforge_persistence:: queries:: get_setting (
148+ db. conn ( ) ,
149+ & format ! ( "pr:{thread_id}" ) ,
150+ )
151+ . ok ( )
152+ . flatten ( )
153+ } ;
150154
151- if !merge. status . success ( ) {
152- return Err ( format ! (
153- "Merge failed (may have conflicts): {}" ,
154- String :: from_utf8_lossy( & merge. stderr)
155- ) ) ;
156- }
155+ if let Some ( _pr_num) = & pr_number {
156+ // PR mode: commit and push the worktree branch (don't merge to main)
157+ // First, commit any uncommitted changes in the worktree
158+ let status = Command :: new ( "git" )
159+ . args ( [ "status" , "--porcelain" ] )
160+ . current_dir ( & worktree_path)
161+ . output ( )
162+ . map_err ( |e| format ! ( "Failed to check status: {e}" ) ) ?;
157163
158- // Remove worktree
159- let _ = Command :: new ( "git" )
160- . args ( [ "worktree" , "remove" , & worktree_path, "--force" ] )
161- . current_dir ( & project_path)
162- . output ( ) ;
164+ let has_changes = !String :: from_utf8_lossy ( & status. stdout ) . trim ( ) . is_empty ( ) ;
163165
164- // Delete the branch
165- let _ = Command :: new ( "git" )
166- . args ( [ "branch " , "-d" , & branch ] )
167- . current_dir ( & project_path )
168- . output ( ) ;
166+ if has_changes {
167+ let _ = Command :: new ( "git" )
168+ . args ( [ "add " , "-A" ] )
169+ . current_dir ( & worktree_path )
170+ . output ( ) ;
169171
170- // Remove setting
171- {
172- let db = state. db . lock ( ) . map_err ( |e| format ! ( "{e}" ) ) ?;
173- let _ = codeforge_persistence:: queries:: delete_setting (
174- db. conn ( ) ,
175- & format ! ( "worktree:{thread_id}" ) ,
176- ) ;
177- }
172+ let _ = Command :: new ( "git" )
173+ . args ( [ "commit" , "-m" , "Changes from CodeForge" ] )
174+ . current_dir ( & worktree_path)
175+ . output ( ) ;
176+ }
177+
178+ // Push the branch
179+ let push = Command :: new ( "git" )
180+ . args ( [ "push" , "origin" , & branch] )
181+ . current_dir ( & worktree_path)
182+ . output ( )
183+ . map_err ( |e| format ! ( "Failed to push: {e}" ) ) ?;
184+
185+ if !push. status . success ( ) {
186+ let stderr = String :: from_utf8_lossy ( & push. stderr ) ;
187+ return Err ( format ! ( "Push failed: {stderr}" ) ) ;
188+ }
189+
190+ // Remove worktree but keep branch (PR is still open)
191+ let _ = Command :: new ( "git" )
192+ . args ( [ "worktree" , "remove" , & worktree_path, "--force" ] )
193+ . current_dir ( & project_path)
194+ . output ( ) ;
195+
196+ // Remove worktree setting
197+ {
198+ let db = state. db . lock ( ) . map_err ( |e| format ! ( "{e}" ) ) ?;
199+ let _ = codeforge_persistence:: queries:: delete_setting (
200+ db. conn ( ) ,
201+ & format ! ( "worktree:{thread_id}" ) ,
202+ ) ;
203+ }
204+
205+ Ok ( format ! ( "Pushed {branch} to origin" ) )
206+ } else {
207+ // Normal mode: merge worktree branch into main
208+ let merge = Command :: new ( "git" )
209+ . args ( [ "merge" , & branch, "--no-edit" ] )
210+ . current_dir ( & project_path)
211+ . output ( )
212+ . map_err ( |e| format ! ( "Failed to merge: {e}" ) ) ?;
213+
214+ if !merge. status . success ( ) {
215+ let stderr = String :: from_utf8_lossy ( & merge. stderr ) . to_string ( ) ;
216+
217+ // Abort the failed merge to leave repo in clean state
218+ let _ = Command :: new ( "git" )
219+ . args ( [ "merge" , "--abort" ] )
220+ . current_dir ( & project_path)
221+ . output ( ) ;
178222
179- Ok ( format ! ( "Merged {branch} into {main_branch}" ) )
223+ return Err ( format ! (
224+ "Merge has conflicts. Resolve them manually in the worktree at {worktree_path} then try again.\n \n Conflict details: {stderr}"
225+ ) ) ;
226+ }
227+
228+ // Remove worktree
229+ let _ = Command :: new ( "git" )
230+ . args ( [ "worktree" , "remove" , & worktree_path, "--force" ] )
231+ . current_dir ( & project_path)
232+ . output ( ) ;
233+
234+ // Delete the branch
235+ let _ = Command :: new ( "git" )
236+ . args ( [ "branch" , "-d" , & branch] )
237+ . current_dir ( & project_path)
238+ . output ( ) ;
239+
240+ // Remove setting
241+ {
242+ let db = state. db . lock ( ) . map_err ( |e| format ! ( "{e}" ) ) ?;
243+ let _ = codeforge_persistence:: queries:: delete_setting (
244+ db. conn ( ) ,
245+ & format ! ( "worktree:{thread_id}" ) ,
246+ ) ;
247+ }
248+
249+ Ok ( format ! ( "Merged {branch} into {main_branch}" ) )
250+ }
180251}
0 commit comments