lib/ghtorrent/ghtorrent.rb
def ensure_fork_point(owner, repo)

      fork = ensure_repo(owner, repo, false)

      if fork[:forked_from].nil?
        warn "Repo #{owner}/#{repo} is not a fork"
        return nil
      end

      # Return commit if already specified
      unless fork[:forked_commit_id].nil?
        commit = db[:commits].where(:id => fork[:forked_commit_id]).first
        return commit unless commit.nil?
      end

      parent = db.from(:projects, :users).\
                where(Sequel.qualify('projects', 'owner_id') => Sequel.qualify('users', 'id')).\
                where(Sequel.qualify('projects', 'id') => fork[:forked_from]).\
                select(Sequel.qualify('users', 'login'), Sequel.qualify('projects','name')).first

      if parent.nil?
        warn "Unknown parent for repo #{owner}/#{repo}"
        return nil
      end

      default_branch = retrieve_default_branch(parent[:login], parent[:name])

      # Retrieve diff between parent and fork master branch
      diff = retrieve_master_branch_diff(owner, repo, default_branch, parent[:login], parent[:name], default_branch)

      if diff.nil? or diff.empty?
        # Try a bit harder by refreshing the default branch
        default_branch = retrieve_default_branch(parent[:login], parent[:name], true)
        diff = retrieve_master_branch_diff(owner, repo, default_branch, parent[:login], parent[:name], default_branch)
      end

      if diff.nil? or diff.empty?
        # This means that the are no common ancestors between the repos
        # This can apparently happen when the parent repo was renamed or force-pushed
        # example: https://github.com/openzipkin/zipkin/compare/master...aa1wi:master
        warn "No common ancestor between #{parent[:login]}/#{parent[:name]} and #{owner}/#{repo}"
        return nil
      else
        debug "Fork #{owner}/#{repo} is #{diff['ahead_by']} commits ahead and #{diff['behind_by']} commits behind #{parent[:login]}/#{parent[:name]}"
      end

      if diff['ahead_by'].to_i > 0
        # This means that the fork has diverged, and we need to search through the fork
        # commit graph for the earliest commit that is shared with the parent. GitHub's
        # diff contains a list of divergent commits. We are sorting those by date
        # and select the earliest one. We do date sort instead of graph walking as this
        # would be prohibetively slow if the commits for the parent did not exist.
        earliest_diverging = diff['commits'].sort_by{|x| x['commit']['author']['date']}.first

        if earliest_diverging['parents'].nil?
          # this means that the repo was forked from the from the parent repo's initial commit. thus, they both share an initial commit.
          # example: https://api.github.com/repos/btakita/pain-point/compare/master...spent:master
          likely_fork_point = ensure_commit(parent[:name], earliest_diverging['sha'], parent['login'])
        else
          # Make sure that all likely fork points exist for the parent project
          # and select the latest of them.
          # https://github.com/gousiosg/github-mirror/compare/master...pombredanne:master
          likely_fork_point = earliest_diverging['parents'].\
              map{ |x| ensure_commit(parent[:name], x['sha'], parent[:login])}.\
              select{|x| !x.nil?}.\
              sort_by { |x| x[:created_at]}.\
              last
        end
        forked_sha  = likely_fork_point[:sha]
      else
        # This means that the fork has not diverged.
        forked_sha = diff['merge_base_commit']['sha']
      end

      forked_commit = ensure_commit(repo, forked_sha, owner);

      debug "Fork commit for #{owner}/#{repo} is #{forked_sha}"

      unless forked_commit.nil?
        db[:projects].filter(:id => fork[:id]).update(:forked_commit_id => forked_commit[:id])
        info "Repo #{owner}/#{repo} was forked at #{parent[:login]}/#{parent[:name]}:#{forked_sha}"
      end

      db[:commits].where(:sha => forked_sha).first
    end
def ensure_fork_point(owner, repo)

      fork = ensure_repo(owner, repo, false)

      if fork[:forked_from].nil?
        warn "Repo #{owner}/#{repo} is not a fork"
        return nil
      end

      # Return commit if already specified
      unless fork[:forked_commit_id].nil?
        commit = db[:commits].where(:id => fork[:forked_commit_id]).first
        return commit unless commit.nil?
      end

      parent = db.from(:projects, :users).\
                where(Sequel.qualify('projects', 'owner_id') => Sequel.qualify('users', 'id')).\
                where(Sequel.qualify('projects', 'id') => fork[:forked_from]).\
                select(Sequel.qualify('users', 'login'), Sequel.qualify('projects','name')).first

      if parent.nil?
        warn "Unknown parent for repo #{owner}/#{repo}"
        return nil
      end

      default_branch = retrieve_default_branch(parent[:login], parent[:name])

      # Retrieve diff between parent and fork master branch
      diff = retrieve_master_branch_diff(owner, repo, default_branch, parent[:login], parent[:name], default_branch)

      if diff.nil? or diff.empty?
        # Try a bit harder by refreshing the default branch
        default_branch = retrieve_default_branch(parent[:login], parent[:name], true)
        diff = retrieve_master_branch_diff(owner, repo, default_branch, parent[:login], parent[:name], default_branch)
      end

      if diff.nil? or diff.empty?
        # This means that the are no common ancestors between the repos
        # This can apparently happen when the parent repo was renamed or force-pushed
        # example: https://github.com/openzipkin/zipkin/compare/master...aa1wi:master
        warn "No common ancestor between #{parent[:login]}/#{parent[:name]} and #{owner}/#{repo}"
        return nil
      else
        debug "Fork #{owner}/#{repo} is #{diff['ahead_by']} commits ahead and #{diff['behind_by']} commits behind #{parent[:login]}/#{parent[:name]}"
      end

      if diff['ahead_by'].to_i > 0
        # This means that the fork has diverged, and we need to search through the fork
        # commit graph for the earliest commit that is shared with the parent. GitHub's
        # diff contains a list of divergent commits. We are sorting those by date
        # and select the earliest one. We do date sort instead of graph walking as this
        # would be prohibetively slow if the commits for the parent did not exist.
        earliest_diverging = diff['commits'].sort_by{|x| x['commit']['author']['date']}.first

        if earliest_diverging['parents'].nil?
          # this means that the repo was forked from the from the parent repo's initial commit. thus, they both share an initial commit.
          # example: https://api.github.com/repos/btakita/pain-point/compare/master...spent:master
          likely_fork_point = ensure_commit(parent[:name], earliest_diverging['sha'], parent['login'])
        else
          # Make sure that all likely fork points exist for the parent project
          # and select the latest of them.
          # https://github.com/gousiosg/github-mirror/compare/master...pombredanne:master
          likely_fork_point = earliest_diverging['parents'].\
              map{ |x| ensure_commit(parent[:name], x['sha'], parent[:login])}.\
              select{|x| !x.nil?}.\
              sort_by { |x| x[:created_at]}.\
              last
        end
        forked_sha  = likely_fork_point[:sha]
      else
        # This means that the fork has not diverged.
        forked_sha = diff['merge_base_commit']['sha']
      end

      forked_commit = ensure_commit(repo, forked_sha, owner);

      debug "Fork commit for #{owner}/#{repo} is #{forked_sha}"

      unless forked_commit.nil?
        db[:projects].filter(:id => fork[:id]).update(:forked_commit_id => forked_commit[:id])
        info "Repo #{owner}/#{repo} was forked at #{parent[:login]}/#{parent[:name]}:#{forked_sha}"
      end

      db[:commits].where(:sha => forked_sha).first
    end
Retrieve and return the commit at which the provided fork was forked at