@@ -22,6 +22,7 @@ class HackorumPatch
2222 @temp_dir = nil
2323 @local_archive = nil
2424 @using_local_file = false
25+ @using_diff_mode = false
2526
2627 parse_options! ( argv )
2728
@@ -79,7 +80,11 @@ class HackorumPatch
7980 create_branch ( base_commit )
8081 end
8182
82- apply_patches ( patch_files )
83+ if @using_diff_mode
84+ apply_diffs ( patch_files )
85+ else
86+ apply_patches ( patch_files )
87+ end
8388 cleanup_temp_files
8489
8590 print_success_message ( use_worktree ? worktree_path : nil )
@@ -350,14 +355,7 @@ class HackorumPatch
350355 end
351356
352357 all_files = Dir . glob ( File . join ( @temp_dir , "*" ) ) . sort
353- patch_files = all_files . select { |f | f . end_with? ( ".patch" ) }
354- skipped = all_files . size - patch_files . size
355- msg = "[OK] Downloaded and extracted #{ patch_files . size } patches"
356- msg += " (skipped #{ skipped } non-patch files)" if skipped > 0
357- puts msg
358- puts ""
359-
360- patch_files
358+ categorize_and_report_files ( all_files )
361359 end
362360
363361 def extract_local_patchset
@@ -379,14 +377,32 @@ class HackorumPatch
379377 end
380378
381379 all_files = Dir . glob ( File . join ( @temp_dir , "*" ) ) . sort
380+ categorize_and_report_files ( all_files )
381+ end
382+
383+ def categorize_and_report_files ( all_files )
382384 patch_files = all_files . select { |f | f . end_with? ( ".patch" ) }
383- skipped = all_files . size - patch_files . size
384- msg = "[OK] Extracted #{ patch_files . size } patches"
385- msg += " (skipped #{ skipped } non-patch files)" if skipped > 0
385+ diff_files = all_files . select { |f | f . end_with? ( ".diff" ) }
386+ skipped = all_files . size - patch_files . size - diff_files . size
387+
388+ if !patch_files . empty? && !diff_files . empty?
389+ raise "Mixed patch and diff files detected. Archives must contain only .patch files OR only .diff files, not both."
390+ end
391+
392+ if patch_files . empty? && diff_files . empty?
393+ raise "No patch or diff files found in archive"
394+ end
395+
396+ @using_diff_mode = !diff_files . empty?
397+ files = @using_diff_mode ? diff_files : patch_files
398+ file_type = @using_diff_mode ? "diffs" : "patches"
399+
400+ msg = "[OK] Extracted #{ files . size } #{ file_type } "
401+ msg += " (skipped #{ skipped } other files)" if skipped > 0
386402 puts msg
387403 puts ""
388404
389- patch_files
405+ files
390406 end
391407
392408 def detect_base_commit ( patch_files_dir )
@@ -397,10 +413,12 @@ class HackorumPatch
397413 end
398414
399415 patch_files = Dir . glob ( File . join ( patch_files_dir , "*.patch" ) ) . sort
400- return detect_default_branch_head if patch_files . empty?
416+ diff_files = Dir . glob ( File . join ( patch_files_dir , "*.diff" ) ) . sort
417+ all_patch_files = patch_files + diff_files
418+ return detect_default_branch_head if all_patch_files . empty?
401419
402420 # First, check for base-commit line (from git format-patch --base)
403- base_commit = detect_base_commit_from_base_line ( patch_files )
421+ base_commit = detect_base_commit_from_base_line ( all_patch_files )
404422 if base_commit
405423 puts "[OK] Base commit: #{ base_commit } (from base-commit line)"
406424 puts ""
@@ -410,7 +428,7 @@ class HackorumPatch
410428 # Fall back to index hash detection
411429 puts "Detecting base commit from patch index entries..."
412430
413- first_patch = patch_files . first
431+ first_patch = all_patch_files . first
414432 index_hashes = [ ]
415433 new_file_count = 0
416434 content = File . read ( first_patch )
@@ -563,6 +581,53 @@ class HackorumPatch
563581 puts ""
564582 end
565583
584+ def apply_diffs ( diff_files )
585+ puts "Applying #{ diff_files . size } diff files..."
586+ puts ""
587+
588+ diff_files . each_with_index do |diff_file , idx |
589+ basename = File . basename ( diff_file , ".diff" )
590+ puts " [#{ idx + 1 } /#{ diff_files . size } ] #{ File . basename ( diff_file ) } "
591+
592+ # Apply the diff
593+ output = `git apply --3way #{ Shellwords . escape ( diff_file ) } 2>&1`
594+ success = $?. success?
595+
596+ output . each_line { |line | puts " #{ line } " } unless output . strip . empty?
597+
598+ unless success
599+ puts ""
600+ puts "[FAIL] Failed to apply #{ File . basename ( diff_file ) } "
601+ puts ""
602+ puts "You can resolve conflicts manually and retry."
603+ raise "Diff application failed"
604+ end
605+
606+ # Stage all changes
607+ unless system ( "git add -A > /dev/null 2>&1" )
608+ raise "Failed to stage changes for #{ File . basename ( diff_file ) } "
609+ end
610+
611+ # Commit with simple message
612+ commit_msg = "Apply #{ basename } "
613+ unless system ( "git commit -m #{ Shellwords . escape ( commit_msg ) } > /dev/null 2>&1" )
614+ # Check if there's actually anything to commit
615+ status = `git status --porcelain` . strip
616+ if status . empty?
617+ puts " (no changes to commit)"
618+ else
619+ raise "Failed to commit #{ File . basename ( diff_file ) } "
620+ end
621+ else
622+ puts " Committed: #{ commit_msg } "
623+ end
624+ end
625+
626+ puts ""
627+ puts "[OK] All diffs applied and committed successfully"
628+ puts ""
629+ end
630+
566631 def cleanup_temp_files
567632 FileUtils . rm_rf ( @temp_dir ) if @temp_dir && File . exist? ( @temp_dir )
568633 end
0 commit comments