class Grit::GitRuby::FileIndex

Attributes

max_file_size[RW]
files[R]

Public Class Methods

new(repo_path) click to toggle source

initializes index given repo_path

# File lib/grit/lib/grit/git-ruby/file_index.rb, line 34
def initialize(repo_path)
  @index_file = File.join(repo_path, 'file-index')
  if File.file?(@index_file) && (File.size(@index_file) < Grit::GitRuby::FileIndex.max_file_size)
    read_index
  else
    raise IndexFileNotFound
  end
end

Public Instance Methods

commits_for(file) click to toggle source

returns all commits for a file

# File lib/grit/lib/grit/git-ruby/file_index.rb, line 88
def commits_for(file)
  @all_files[file]
end
commits_from(commit_sha) click to toggle source

builds a list of all commits reachable from a single commit

# File lib/grit/lib/grit/git-ruby/file_index.rb, line 56
def commits_from(commit_sha)
  raise UnsupportedRef if commit_sha.is_a? Array

  already = {}
  final = []
  left_to_do = [commit_sha]

  while commit_sha = left_to_do.shift
    next if already[commit_sha]

    final << commit_sha
    already[commit_sha] = true

    commit = @commit_index[commit_sha]
    commit[:parents].each do |sha|
      left_to_do << sha
    end if commit
  end

  sort_commits(final)
end
count(commit_sha) click to toggle source

returns count of all commits reachable from SHA note: originally did this recursively, but ruby gets pissed about that on really big repos where the stack level gets ‘too deep’ (thats what she said)

# File lib/grit/lib/grit/git-ruby/file_index.rb, line 51
def count(commit_sha)
  commits_from(commit_sha).size
end
count_all() click to toggle source

returns count of all commits

# File lib/grit/lib/grit/git-ruby/file_index.rb, line 44
def count_all
  @sha_count
end
last_commits(commit_sha, files_matcher) click to toggle source

returns the shas of the last commits for all the files in [] from commit_sha files_matcher can be a regexp or an array

# File lib/grit/lib/grit/git-ruby/file_index.rb, line 95
def last_commits(commit_sha, files_matcher)
  acceptable = commits_from(commit_sha)

  matches = {}

  if files_matcher.is_a? Regexp
    files = @all_files.keys.select { |file| file =~ files_matcher }
    files_matcher = files
  end

  if files_matcher.is_a? Array
    # find the last commit for each file in the array
    files_matcher.each do |f|
      @all_files[f].each do |try|
        if acceptable.include?(try)
          matches[f] = try
          break
        end
      end if @all_files[f]
    end
  end

  matches
end
sort_commits(sha_array) click to toggle source
# File lib/grit/lib/grit/git-ruby/file_index.rb, line 78
def sort_commits(sha_array)
  sha_array.sort { |a, b| @commit_order[b].to_i <=> @commit_order[a].to_i }
end

Private Instance Methods

read_index() click to toggle source

read and parse the file-index data

# File lib/grit/lib/grit/git-ruby/file_index.rb, line 123
def read_index
  f = File.new(@index_file)
  @sha_count = 0
  @commit_index = {}
  @commit_order = {}
  @all_files = {}
  while line = f.gets
    if /^(\w{40})/.match(line)
      shas = line.scan(/(\w{40})/)
      current_sha = shas.shift.first
      parents = shas.map { |sha| sha.first }
      @commit_index[current_sha] = {:files => [], :parents => parents }
      @commit_order[current_sha] = @sha_count
      @sha_count += 1
    else
      file_name = line.chomp
      tree = ''
      File.dirname(file_name).split('/').each do |part|
        next if part == '.'
        tree += part + '/'
        @all_files[tree] ||= []
        @all_files[tree].unshift(current_sha)
      end
      @all_files[file_name] ||= []
      @all_files[file_name].unshift(current_sha)
      @commit_index[current_sha][:files] << file_name
    end
  end
end