Skip to content

Commit 03f728b

Browse files
fix: pr to gh bug
1 parent ca84b0f commit 03f728b

File tree

1 file changed

+149
-12
lines changed

1 file changed

+149
-12
lines changed

server/tasks.py

Lines changed: 149 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -430,19 +430,14 @@ def create_pull_request(task_id):
430430
# Apply the patch by creating/updating files
431431
logger.info(f"📦 Applying patch with {len(task.get('changed_files', []))} changed files...")
432432

433-
# For now, we'll use a simple approach to apply changes
434-
# In a real implementation, you'd want a more sophisticated patch parser
433+
# Parse and apply the git patch to the repository
435434
patch_content = task['git_patch']
436-
files_updated = []
435+
files_updated = apply_patch_to_github_repo(repo, pr_branch, patch_content, task)
437436

438-
# Simple file update based on changed_files list
439-
for file_path in task.get('changed_files', []):
440-
try:
441-
# This is a simplified approach - in reality you'd parse the patch properly
442-
logger.info(f"📝 Updating file: {file_path}")
443-
files_updated.append(file_path)
444-
except Exception as e:
445-
logger.warning(f"Failed to update {file_path}: {e}")
437+
if not files_updated:
438+
return jsonify({'error': 'Failed to apply patch - no file changes extracted'}), 500
439+
440+
logger.info(f"✅ Applied patch, updated {len(files_updated)} files")
446441

447442
# Create pull request
448443
pr = repo.create_pull(
@@ -520,4 +515,146 @@ def migrate_legacy_tasks():
520515

521516
except Exception as e:
522517
logger.error(f"Error migrating legacy tasks: {str(e)}")
523-
return jsonify({'error': str(e)}), 500
518+
return jsonify({'error': str(e)}), 500
519+
520+
521+
def apply_patch_to_github_repo(repo, branch, patch_content, task):
522+
"""Apply a git patch to a GitHub repository using the GitHub API"""
523+
try:
524+
logger.info(f"🔧 Parsing patch content...")
525+
526+
# Parse git patch format to extract file changes
527+
files_to_update = {}
528+
current_file = None
529+
new_content_lines = []
530+
531+
# This is a simplified patch parser - for production you might want a more robust one
532+
lines = patch_content.split('\n')
533+
i = 0
534+
535+
while i < len(lines):
536+
line = lines[i]
537+
538+
# Look for file headers in patch format
539+
if line.startswith('--- a/') or line.startswith('--- /dev/null'):
540+
# Next line should be +++ b/filename
541+
if i + 1 < len(lines) and lines[i + 1].startswith('+++ b/'):
542+
current_file = lines[i + 1][6:] # Remove '+++ b/'
543+
logger.info(f"📄 Found file change: {current_file}")
544+
545+
# Get the original file content if it exists
546+
try:
547+
file_obj = repo.get_contents(current_file, ref=branch)
548+
original_content = file_obj.decoded_content.decode('utf-8')
549+
logger.info(f"📥 Got original content for {current_file}")
550+
except:
551+
original_content = "" # New file
552+
logger.info(f"📝 New file: {current_file}")
553+
554+
# For simplicity, we'll reconstruct the file from the diff
555+
# Skip to the actual diff content (after @@)
556+
j = i + 2
557+
while j < len(lines) and not lines[j].startswith('@@'):
558+
j += 1
559+
560+
if j < len(lines):
561+
# Apply the diff changes
562+
new_content = apply_diff_to_content(original_content, lines[j:], current_file)
563+
if new_content is not None:
564+
files_to_update[current_file] = new_content
565+
logger.info(f"✅ Prepared update for {current_file}")
566+
567+
i = j
568+
i += 1
569+
570+
# Now update all the files via GitHub API
571+
updated_files = []
572+
commit_message = f"Claude Code: {task.get('prompt', 'Automated changes')[:100]}"
573+
574+
# Get prompt from chat messages if available
575+
if task.get('chat_messages'):
576+
for msg in task['chat_messages']:
577+
if msg.get('role') == 'user':
578+
commit_message = f"Claude Code: {msg.get('content', '')[:100]}"
579+
break
580+
581+
for file_path, new_content in files_to_update.items():
582+
try:
583+
# Check if file exists
584+
try:
585+
file_obj = repo.get_contents(file_path, ref=branch)
586+
# Update existing file
587+
repo.update_file(
588+
path=file_path,
589+
message=commit_message,
590+
content=new_content,
591+
sha=file_obj.sha,
592+
branch=branch
593+
)
594+
logger.info(f"📝 Updated existing file: {file_path}")
595+
except:
596+
# Create new file
597+
repo.create_file(
598+
path=file_path,
599+
message=commit_message,
600+
content=new_content,
601+
branch=branch
602+
)
603+
logger.info(f"🆕 Created new file: {file_path}")
604+
605+
updated_files.append(file_path)
606+
607+
except Exception as file_error:
608+
logger.error(f"❌ Failed to update {file_path}: {file_error}")
609+
610+
return updated_files
611+
612+
except Exception as e:
613+
logger.error(f"💥 Error applying patch: {str(e)}")
614+
return []
615+
616+
617+
def apply_diff_to_content(original_content, diff_lines, filename):
618+
"""Apply diff changes to original content - simplified implementation"""
619+
try:
620+
# For now, let's use a simple approach: reconstruct from + lines
621+
# This is not a complete diff parser, but works for basic cases
622+
623+
result_lines = []
624+
original_lines = original_content.split('\n') if original_content else []
625+
626+
# Find the actual diff content starting from @@ line
627+
diff_start = 0
628+
for i, line in enumerate(diff_lines):
629+
if line.startswith('@@'):
630+
diff_start = i + 1
631+
break
632+
633+
# Simple reconstruction: take context and + lines, skip - lines
634+
for line in diff_lines[diff_start:]:
635+
if line.startswith('+++') or line.startswith('---'):
636+
continue
637+
elif line.startswith('+') and not line.startswith('+++'):
638+
result_lines.append(line[1:]) # Remove the +
639+
elif line.startswith(' '): # Context line
640+
result_lines.append(line[1:]) # Remove the space
641+
elif line.startswith('-'):
642+
continue # Skip removed lines
643+
elif line.strip() == '':
644+
continue # Skip empty lines in diff
645+
else:
646+
# Check if we've reached the next file
647+
if line.startswith('diff --git') or line.startswith('--- a/'):
648+
break
649+
650+
# If we got content, return it, otherwise fall back to using the git diff directly
651+
if result_lines:
652+
return '\n'.join(result_lines)
653+
else:
654+
# Fallback: return original content (no changes applied)
655+
logger.warning(f"⚠️ Could not parse diff for {filename}, keeping original")
656+
return original_content
657+
658+
except Exception as e:
659+
logger.error(f"❌ Error applying diff to {filename}: {str(e)}")
660+
return None

0 commit comments

Comments
 (0)