@@ -425,51 +425,72 @@ class HackorumPatch
425425 return base_commit
426426 end
427427
428- # Fall back to index hash detection
429- puts "Detecting base commit from patch index entries..."
430-
431- first_patch = all_patch_files . first
432- index_hashes = [ ]
433- new_file_count = 0
434- content = File . read ( first_patch )
435- content . scan ( /^index ([0-9a-f]+)\. \. ([0-9a-f]+)/ ) do |before_hash , after_hash |
436- if before_hash =~ /^0+$/
437- new_file_count += 1
438- else
439- index_hashes << before_hash
428+ # Fall back to index hash detection using file paths
429+ puts "Detecting base commit from patch file paths..."
430+
431+ # Extract file paths and their "before" blob hashes from all patches
432+ # Only record the FIRST occurrence of each file - later patches in a series
433+ # will have "before" hashes that are the result of earlier patches, not the original state
434+ file_info = { } # path => before_hash
435+ all_patch_files . each do |patch_file |
436+ content = File . read ( patch_file )
437+ # Format: diff --git a/path b/path followed by index abc123..def456
438+ content . scan ( /^diff --git a\/ (.+?) b\/ \1 \n (?:.*?\n )*?index ([0-9a-f]+)\. \. ([0-9a-f]+)/m ) do |path , before_hash , after_hash |
439+ next if before_hash =~ /^0+$/ # Skip new files
440+ next if file_info . key? ( path ) # Only use first occurrence
441+ file_info [ path ] = before_hash
440442 end
441443 end
442444
443- if index_hashes . empty?
444- puts " No index entries found in first patch ( #{ new_file_count } new files)"
445+ if file_info . empty?
446+ puts " No modified files found in patches (all new files? )"
445447 return detect_default_branch_head
446448 end
447449
448- puts " Found #{ index_hashes . size } index entries in first patch (skipped #{ new_file_count } new files)"
449- puts " Searching for base commit (this may take a moment)..."
450+ puts " Found #{ file_info . size } modified files across #{ all_patch_files . size } patches"
450451
451- candidates = [ ]
452- index_hashes . each_with_index do |hash , idx |
453- puts " Checking index #{ idx + 1 } /#{ index_hashes . size } ..."
452+ default_branch = detect_default_branch_head
454453
455- output = `git log --all --pretty=format:%H --find-object=#{ hash } -n 1 2>/dev/null` . strip
456- if !output . empty? && output =~ /^[0-9a-f]{40}$/
457- candidates << output
458- puts " Found commit: #{ output [ 0 ..7 ] } ..."
459- end
454+ # Check if the "before" hashes match what's at the default branch HEAD
455+ # This confirms HEAD is the correct base
456+ default_head = `git rev-parse #{ default_branch } 2>/dev/null` . strip
457+ all_match = file_info . all? do |path , before_hash |
458+ current_hash = `git rev-parse #{ default_head } :#{ path } 2>/dev/null` . strip
459+ current_hash == before_hash || current_hash . start_with? ( before_hash ) || before_hash . start_with? ( current_hash )
460460 end
461461
462- if candidates . empty?
463- puts " Could not detect base commit from index entries"
464- return detect_default_branch_head
462+ if all_match
463+ puts " All file hashes match #{ default_branch } HEAD"
464+ puts "[OK] Base commit: #{ default_head } (#{ default_branch } )"
465+ puts ""
466+ return default_head
465467 end
466468
467- base_commit = candidates . first
468- puts " Using commit: #{ base_commit [ 0 ..7 ] } ... as base"
469- puts "[OK] Base commit: #{ base_commit } "
470- puts ""
469+ # Hashes don't match HEAD, search history for a matching commit
470+ puts " File hashes don't match HEAD, searching history..."
471+
472+ # Find commits on the default branch that touched these files
473+ paths = file_info . keys . map { |p | Shellwords . escape ( p ) } . join ( " " )
474+ commits = `git log #{ default_branch } --pretty=format:%H -n 50 -- #{ paths } 2>/dev/null` . strip . split ( "\n " )
475+
476+ commits . each do |commit |
477+ next if commit . empty?
478+
479+ matches = file_info . all? do |path , before_hash |
480+ blob_hash = `git rev-parse #{ commit } :#{ path } 2>/dev/null` . strip
481+ blob_hash == before_hash || blob_hash . start_with? ( before_hash ) || before_hash . start_with? ( blob_hash )
482+ end
483+
484+ if matches
485+ puts " Found matching commit: #{ commit [ 0 ..11 ] } ..."
486+ puts "[OK] Base commit: #{ commit } "
487+ puts ""
488+ return commit
489+ end
490+ end
471491
472- base_commit
492+ puts " Could not find matching commit in history"
493+ detect_default_branch_head
473494 end
474495
475496 def detect_base_commit_from_base_line ( patch_files )
@@ -488,7 +509,7 @@ class HackorumPatch
488509 end
489510
490511 def detect_default_branch_head
491- %w[ origin/ master master ] . each do |ref |
512+ %w[ master origin/ master] . each do |ref |
492513 if system ( "git rev-parse --verify #{ ref } > /dev/null 2>&1" )
493514 return ref
494515 end
0 commit comments