<commit_before>#!/usr/bin/env ruby
#SBATCH --job-name=voldemort_conflict_processing
#SBATCH --time=048:00:00
#SBATCH --output=/work/cse990/knorth/outputs/voldemort_conflict_processing.STDOUT
#SBATCH --error=/work/cse990/knorth/outputs/voldemort_conflict_processing.STDERR
#SBATCH --mem-per-cpu=8192
#SBATCH --ntasks=1

class Conflict
  attr_accessor :start
  attr_accessor :end

  def initialize
  end
end

def get_commit_parents(commit_hash)
  out = `git show #{commit_hash} --format="%P"`.strip
  parents =  out.split('\n')[0].strip.split(' ')
  return parents
end

file = ARGV[0]

graph = File.read(file).split("\n")

Dir.chdir ARGV[1]

commits_in_topological_order = []
all_commit_conflicts = {}
all_parents = {}

commit_regex = /([0-9a-fA-F]+) \| ?([0-9a-fA-F ]*)$/
for row in graph.reverse()
  commit_match = commit_regex.match row
  if commit_match
    commit_hash = commit_match.captures[0]
    commit_conflicts = commit_match.captures[1].split(' ').map {|c| c.strip}
    commit_parents = get_commit_parents(commit_hash)
    commits_in_topological_order.push commit_hash
    all_commit_conflicts[commit_hash] = commit_conflicts
    all_parents[commit_hash] = commit_parents
  end
end

conflicts = []

for commit_hash in commits_in_topological_order
  commit_hash
  commit_parents = all_parents[commit_hash]
  commit_conflicts = all_commit_conflicts[commit_hash] or []

  parent_conflicts = []
  for parent in commit_conflicts
    parent_conflicts = parent_conflicts | all_commit_conflicts[parent]
  end

  potential_conflict_starts = Array.new(commit_conflicts) #deep copy of array
  potential_conflict_starts.delete_if {|c| parent_conflicts.include? c}

  potential_conflict_ends = Array.new(parent_conflicts)
  potential_conflict_ends.delete_if {|c| commit_conflicts.include? c}

  # In many cases, when a commit has a conflict listed that isn't in its parents,
  # that conflict 
  conflict_starts_to_remove = []
  conflict_ends_to_remove = []
  for potential_conflict_start in potential_conflict_starts
    start_parents = all_parents[potential_conflict_start]
    is_conflict_continued = false
    potential_end_to_remove = nil
    for parent in start_parents
      if potential_conflict_ends.include? parent
        is_conflict_continued = true
        potential_end_to_remove = parent
        break
      end
    end

    if not is_conflict_continued
      next
    end

    # Make sure that the conflict end we're removing wasn't actually merged into
    # the commit we're checking. This would mean that we actually resolved one
    # conflict at the same time as starting another conflict on a parallel
    # branch
    if not commit_parents.include? potential_end_to_remove
      potential_conflict_ends.delete potential_end_to_remove
      potential_conflict_starts.delete potential_conflict_start
    end
  end

  # for conflict_end in potential_conflict_ends
  #   conflicts.find {|c| (c.start.eql? conflict_end) and (c.end == nil)}.end = commit_hash
  # end
  # for conflict_start in potential_conflict_starts
  #   new_conflict = Conflict.new
  #   new_conflict.start = commit_hash
  #   new_conflict.end = nil
  #   conflicts.push new_conflict
  # end

  for conflict in conflicts
    if commit_conflicts.include? conflict.end
      conflict.end = commit_hash
    end
  end

  for new_conflict_start in potential_conflict_starts
    new_conflict = Conflict.new
    new_conflict.start = new_conflict_start
    new_conflict.end = commit_hash
    conflicts.push new_conflict
  end
end

for conflict in conflicts
  puts conflict.start + ' ' + conflict.end<commit_msg>Still not working, but much closer<commit_after>#!/usr/bin/env ruby
#SBATCH --job-name=voldemort_conflict_processing
#SBATCH --time=048:00:00
#SBATCH --output=/work/cse990/knorth/outputs/voldemort_conflict_processing.STDOUT
#SBATCH --error=/work/cse990/knorth/outputs/voldemort_conflict_processing.STDERR
#SBATCH --mem-per-cpu=8192
#SBATCH --ntasks=1

class Conflict
  attr_accessor :start
  attr_accessor :end
  attr_accessor :conflicting_commit

  def initialize
  end
end

def get_commit_parents(commit_hash)
  out = `git show #{commit_hash} --format="%P" --no-patch`.strip
  parents =  out.strip.split(' ')
  return parents
end

file = ARGV[0]

graph = File.read(file).split("\n")

Dir.chdir ARGV[1]

commits_in_topological_order = []
all_commit_conflicts = {}
all_parents = {}

commit_regex = /([0-9a-fA-F]+) \| ?([0-9a-fA-F ]*)$/
for row in graph.reverse()
  commit_match = commit_regex.match row
  if commit_match
    commit_hash = commit_match.captures[0]
    commit_conflicts = commit_match.captures[1].split(' ').map {|c| c.strip}
    commit_parents = get_commit_parents(commit_hash)
    commits_in_topological_order.push commit_hash
    all_commit_conflicts[commit_hash] = commit_conflicts
    all_parents[commit_hash] = commit_parents
  end
end

conflicts = []

for commit_hash in commits_in_topological_order
  commit_hash
  commit_parents = all_parents[commit_hash]
  commit_conflicts = all_commit_conflicts[commit_hash] or []

  parent_conflicts = []
  for parent in commit_conflicts
    parent_conflicts = parent_conflicts | all_commit_conflicts[parent]
  end

  new_conflicts = Array.new(commit_conflicts) # deep copy array
  resolved_conflicts = Array.new(parent_conflicts)
  # continued_conflicts = Array.new(parent_conflicts)

  for parent_conflict in parent_conflicts
    if commit_conflicts.include? parent_conflict
      resolved_conflicts.delete parent_conflict
    # else
      # continued_conflicts.delete parent_conflict
    end
  end

  for commit_conflict in commit_conflicts
    if parent_conflicts.include? commit_conflict
      new_conflicts.delete commit_conflict
    end
  end

  for resolved_conflict in resolved_conflicts
    selected_conflicts = conflicts.select {|c| c.conflicting_commit == resolved_conflict}
    for conflict in selected_conflicts
      conflict.end = commit_hash
    end
  end

  for new_conflict in new_conflicts
    conflict = Conflict.new
    conflict.start = commit_hash
    conflict.conflicting_commit = new_conflict
    conflicts.push conflict 
  end
end

for conflict in conflicts
  start_commit = conflict.start
  if start_commit == nil
    start_commit = "nil"
  end
  
  end_commit = conflict.end or "null"
  if end_commit == nil
    end_commit = "nil"
  end

  conflicting_commit = conflict.conflicting_commit
  if conflicting_commit == nil
    conflicting_commit = "nil"
  end

  puts start_commit + ' ' + end_commit + ' | ' + conflicting_commit
{'fraction_non_alphanumeric': 0.08274377114733927, 'fraction_numerical': 0.008151338049830821, 'mean_word_length': 4.23169750603379, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3782292', 'n_tokens_mistral': 2265, 'n_tokens_neox': 2153, 'n_words': 463}