jugyo-grit 2.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/API.txt +101 -0
- data/History.txt +153 -0
- data/LICENSE +22 -0
- data/PURE_TODO +35 -0
- data/README.md +242 -0
- data/Rakefile +153 -0
- data/benchmarks.rb +129 -0
- data/benchmarks.txt +21 -0
- data/examples/ex_add_commit.rb +13 -0
- data/examples/ex_index.rb +21 -0
- data/jugyo-grit.gemspec +74 -0
- data/lib/grit.rb +75 -0
- data/lib/grit/actor.rb +52 -0
- data/lib/grit/blame.rb +66 -0
- data/lib/grit/blob.rb +126 -0
- data/lib/grit/commit.rb +308 -0
- data/lib/grit/commit_stats.rb +128 -0
- data/lib/grit/config.rb +44 -0
- data/lib/grit/diff.rb +79 -0
- data/lib/grit/errors.rb +10 -0
- data/lib/grit/git-ruby.rb +259 -0
- data/lib/grit/git-ruby/commit_db.rb +52 -0
- data/lib/grit/git-ruby/git_object.rb +353 -0
- data/lib/grit/git-ruby/internal/file_window.rb +58 -0
- data/lib/grit/git-ruby/internal/loose.rb +137 -0
- data/lib/grit/git-ruby/internal/pack.rb +391 -0
- data/lib/grit/git-ruby/internal/raw_object.rb +44 -0
- data/lib/grit/git-ruby/repository.rb +775 -0
- data/lib/grit/git.rb +501 -0
- data/lib/grit/index.rb +222 -0
- data/lib/grit/lazy.rb +35 -0
- data/lib/grit/merge.rb +45 -0
- data/lib/grit/ref.rb +78 -0
- data/lib/grit/repo.rb +709 -0
- data/lib/grit/ruby1.9.rb +7 -0
- data/lib/grit/status.rb +153 -0
- data/lib/grit/submodule.rb +88 -0
- data/lib/grit/tag.rb +102 -0
- data/lib/grit/tree.rb +125 -0
- metadata +134 -0
| @@ -0,0 +1,128 @@ | |
| 1 | 
            +
            module Grit
         | 
| 2 | 
            +
             | 
| 3 | 
            +
              class CommitStats
         | 
| 4 | 
            +
             | 
| 5 | 
            +
                attr_reader :id, :files, :additions, :deletions, :total
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                # Instantiate a new CommitStats
         | 
| 8 | 
            +
                #   +id+ is the id of the commit
         | 
| 9 | 
            +
                #   +files+ is an array of :
         | 
| 10 | 
            +
                #     [ [filename, adds, deletes, total],
         | 
| 11 | 
            +
                #       [filename, adds, deletes, total],
         | 
| 12 | 
            +
                #       [filename, adds, deletes, total] ]
         | 
| 13 | 
            +
                #
         | 
| 14 | 
            +
                # Returns Grit::CommitStats (baked)
         | 
| 15 | 
            +
                def initialize(repo, id, files)
         | 
| 16 | 
            +
                  @repo = repo
         | 
| 17 | 
            +
                  @id = id
         | 
| 18 | 
            +
                  @files = files
         | 
| 19 | 
            +
                  @additions  = files.inject(0) { |total, a| total += a[1] }
         | 
| 20 | 
            +
                  @deletions  = files.inject(0) { |total, a| total += a[2] }
         | 
| 21 | 
            +
                  @total  = files.inject(0) { |total, a| total += a[3] }
         | 
| 22 | 
            +
                end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                # Find all commit stats matching the given criteria.
         | 
| 25 | 
            +
                #   +repo+ is the Repo
         | 
| 26 | 
            +
                #   +ref+ is the ref from which to begin (SHA1 or name) or nil for --all
         | 
| 27 | 
            +
                #   +options+ is a Hash of optional arguments to git
         | 
| 28 | 
            +
                #     :max_count is the maximum number of commits to fetch
         | 
| 29 | 
            +
                #     :skip is the number of commits to skip
         | 
| 30 | 
            +
                #
         | 
| 31 | 
            +
                # Returns assoc array [sha, Grit::Commit[] (baked)]
         | 
| 32 | 
            +
                def self.find_all(repo, ref, options = {})
         | 
| 33 | 
            +
                  allowed_options = [:max_count, :skip, :since]
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                  default_options = {:numstat => true}
         | 
| 36 | 
            +
                  actual_options = default_options.merge(options)
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                  if ref
         | 
| 39 | 
            +
                    output = repo.git.log(actual_options, ref)
         | 
| 40 | 
            +
                  else
         | 
| 41 | 
            +
                    output = repo.git.log(actual_options.merge(:all => true))
         | 
| 42 | 
            +
                  end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                  self.list_from_string(repo, output)
         | 
| 45 | 
            +
                end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                # Parse out commit information into an array of baked Commit objects
         | 
| 48 | 
            +
                #   +repo+ is the Repo
         | 
| 49 | 
            +
                #   +text+ is the text output from the git command (raw format)
         | 
| 50 | 
            +
                #
         | 
| 51 | 
            +
                # Returns assoc array [sha, Grit::Commit[] (baked)]
         | 
| 52 | 
            +
                def self.list_from_string(repo, text)
         | 
| 53 | 
            +
                  lines = text.split("\n")
         | 
| 54 | 
            +
             | 
| 55 | 
            +
                  commits = []
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                  while !lines.empty?
         | 
| 58 | 
            +
                    id = lines.shift.split.last
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                    lines.shift
         | 
| 61 | 
            +
                    lines.shift
         | 
| 62 | 
            +
                    lines.shift
         | 
| 63 | 
            +
             | 
| 64 | 
            +
                    message_lines = []
         | 
| 65 | 
            +
                    message_lines << lines.shift[4..-1] while lines.first =~ /^ {4}/ || lines.first == ''
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                    lines.shift while lines.first && lines.first.empty?
         | 
| 68 | 
            +
             | 
| 69 | 
            +
                    files = []
         | 
| 70 | 
            +
                    while lines.first =~ /^([-\d]+)\s+([-\d]+)\s+(.+)/
         | 
| 71 | 
            +
                      (additions, deletions, filename) = lines.shift.split
         | 
| 72 | 
            +
                      additions = additions.to_i
         | 
| 73 | 
            +
                      deletions = deletions.to_i
         | 
| 74 | 
            +
                      total = additions + deletions
         | 
| 75 | 
            +
                      files << [filename, additions, deletions, total]
         | 
| 76 | 
            +
                    end
         | 
| 77 | 
            +
             | 
| 78 | 
            +
                    lines.shift while lines.first && lines.first.empty?
         | 
| 79 | 
            +
             | 
| 80 | 
            +
                    commits << [id, CommitStats.new(repo, id, files)]
         | 
| 81 | 
            +
                  end
         | 
| 82 | 
            +
             | 
| 83 | 
            +
                  commits
         | 
| 84 | 
            +
                end
         | 
| 85 | 
            +
             | 
| 86 | 
            +
                # Pretty object inspection
         | 
| 87 | 
            +
                def inspect
         | 
| 88 | 
            +
                  %Q{#<Grit::CommitStats "#{@id}">}
         | 
| 89 | 
            +
                end
         | 
| 90 | 
            +
             | 
| 91 | 
            +
                # Convert to an easy-to-traverse structure
         | 
| 92 | 
            +
                def to_diffstat
         | 
| 93 | 
            +
                  files.map do |metadata|
         | 
| 94 | 
            +
                    DiffStat.new(*metadata)
         | 
| 95 | 
            +
                  end
         | 
| 96 | 
            +
                end
         | 
| 97 | 
            +
             | 
| 98 | 
            +
                # private
         | 
| 99 | 
            +
             | 
| 100 | 
            +
                def to_hash
         | 
| 101 | 
            +
                  {
         | 
| 102 | 
            +
                    'id'        => id,
         | 
| 103 | 
            +
                    'files'     => files,
         | 
| 104 | 
            +
                    'additions' => additions,
         | 
| 105 | 
            +
                    'deletions' => deletions,
         | 
| 106 | 
            +
                    'total'     => total
         | 
| 107 | 
            +
                  }
         | 
| 108 | 
            +
                end
         | 
| 109 | 
            +
             | 
| 110 | 
            +
              end # CommitStats
         | 
| 111 | 
            +
             | 
| 112 | 
            +
              class DiffStat
         | 
| 113 | 
            +
                attr_reader :filename, :additions, :deletions
         | 
| 114 | 
            +
             | 
| 115 | 
            +
                def initialize(filename, additions, deletions, total=nil)
         | 
| 116 | 
            +
                  @filename, @additions, @deletions = filename, additions, deletions
         | 
| 117 | 
            +
                end
         | 
| 118 | 
            +
             | 
| 119 | 
            +
                def net
         | 
| 120 | 
            +
                  additions - deletions
         | 
| 121 | 
            +
                end
         | 
| 122 | 
            +
             | 
| 123 | 
            +
                def inspect
         | 
| 124 | 
            +
                  "#{filename}: +#{additions} -#{deletions}"
         | 
| 125 | 
            +
                end
         | 
| 126 | 
            +
              end
         | 
| 127 | 
            +
             | 
| 128 | 
            +
            end # Grit
         | 
    
        data/lib/grit/config.rb
    ADDED
    
    | @@ -0,0 +1,44 @@ | |
| 1 | 
            +
            module Grit
         | 
| 2 | 
            +
             | 
| 3 | 
            +
              class Config
         | 
| 4 | 
            +
                def initialize(repo)
         | 
| 5 | 
            +
                  @repo = repo
         | 
| 6 | 
            +
                end
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                def []=(key, value)
         | 
| 9 | 
            +
                  @repo.git.config({}, key, value)
         | 
| 10 | 
            +
                  @data = nil
         | 
| 11 | 
            +
                end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                def [](key)
         | 
| 14 | 
            +
                  data[key]
         | 
| 15 | 
            +
                end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                def fetch(key, default = nil)
         | 
| 18 | 
            +
                  data[key] || default || raise(IndexError.new("key not found"))
         | 
| 19 | 
            +
                end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                def keys
         | 
| 22 | 
            +
                  data.keys
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                protected
         | 
| 26 | 
            +
                  def data
         | 
| 27 | 
            +
                    @data ||= load_config
         | 
| 28 | 
            +
                  end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                  def load_config
         | 
| 31 | 
            +
                    hash = {}
         | 
| 32 | 
            +
                    config_lines.map do |line|
         | 
| 33 | 
            +
                      key, value = line.split(/=/, 2)
         | 
| 34 | 
            +
                      hash[key] = value
         | 
| 35 | 
            +
                    end
         | 
| 36 | 
            +
                    hash
         | 
| 37 | 
            +
                  end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                  def config_lines
         | 
| 40 | 
            +
                    @repo.git.config(:list => true).split(/\n/)
         | 
| 41 | 
            +
                  end
         | 
| 42 | 
            +
              end # Config
         | 
| 43 | 
            +
             | 
| 44 | 
            +
            end # Grit
         | 
    
        data/lib/grit/diff.rb
    ADDED
    
    | @@ -0,0 +1,79 @@ | |
| 1 | 
            +
            module Grit
         | 
| 2 | 
            +
             | 
| 3 | 
            +
              class Diff
         | 
| 4 | 
            +
                attr_reader :a_path, :b_path
         | 
| 5 | 
            +
                attr_reader :a_blob, :b_blob
         | 
| 6 | 
            +
                attr_reader :a_mode, :b_mode
         | 
| 7 | 
            +
                attr_reader :new_file, :deleted_file, :renamed_file
         | 
| 8 | 
            +
                attr_reader :similarity_index
         | 
| 9 | 
            +
                attr_accessor :diff
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                def initialize(repo, a_path, b_path, a_blob, b_blob, a_mode, b_mode, new_file, deleted_file, diff, renamed_file = false, similarity_index = 0)
         | 
| 12 | 
            +
                  @repo   = repo
         | 
| 13 | 
            +
                  @a_path = a_path
         | 
| 14 | 
            +
                  @b_path = b_path
         | 
| 15 | 
            +
                  @a_blob = a_blob =~ /^0{40}$/ ? nil : Blob.create(repo, :id => a_blob)
         | 
| 16 | 
            +
                  @b_blob = b_blob =~ /^0{40}$/ ? nil : Blob.create(repo, :id => b_blob)
         | 
| 17 | 
            +
                  @a_mode = a_mode
         | 
| 18 | 
            +
                  @b_mode = b_mode
         | 
| 19 | 
            +
                  @new_file         = new_file     || @a_blob.nil?
         | 
| 20 | 
            +
                  @deleted_file     = deleted_file || @b_blob.nil?
         | 
| 21 | 
            +
                  @renamed_file     = renamed_file
         | 
| 22 | 
            +
                  @similarity_index = similarity_index.to_i
         | 
| 23 | 
            +
                  @diff             = diff
         | 
| 24 | 
            +
                end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                def self.list_from_string(repo, text)
         | 
| 27 | 
            +
                  lines = text.split("\n")
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                  diffs = []
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                  while !lines.empty?
         | 
| 32 | 
            +
                    m, a_path, b_path = *lines.shift.match(%r{^diff --git a/(.+?) b/(.+)$})
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                    if lines.first =~ /^old mode/
         | 
| 35 | 
            +
                      m, a_mode = *lines.shift.match(/^old mode (\d+)/)
         | 
| 36 | 
            +
                      m, b_mode = *lines.shift.match(/^new mode (\d+)/)
         | 
| 37 | 
            +
                    end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                    if lines.empty? || lines.first =~ /^diff --git/
         | 
| 40 | 
            +
                      diffs << Diff.new(repo, a_path, b_path, nil, nil, a_mode, b_mode, false, false, nil)
         | 
| 41 | 
            +
                      next
         | 
| 42 | 
            +
                    end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                    sim_index    = 0
         | 
| 45 | 
            +
                    new_file     = false
         | 
| 46 | 
            +
                    deleted_file = false
         | 
| 47 | 
            +
                    renamed_file = false
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                    if lines.first =~ /^new file/
         | 
| 50 | 
            +
                      m, b_mode = lines.shift.match(/^new file mode (.+)$/)
         | 
| 51 | 
            +
                      a_mode    = nil
         | 
| 52 | 
            +
                      new_file  = true
         | 
| 53 | 
            +
                    elsif lines.first =~ /^deleted file/
         | 
| 54 | 
            +
                      m, a_mode    = lines.shift.match(/^deleted file mode (.+)$/)
         | 
| 55 | 
            +
                      b_mode       = nil
         | 
| 56 | 
            +
                      deleted_file = true
         | 
| 57 | 
            +
                    elsif lines.first =~ /^similarity index (\d+)\%/
         | 
| 58 | 
            +
                      sim_index    = $1.to_i
         | 
| 59 | 
            +
                      renamed_file = true
         | 
| 60 | 
            +
                      2.times { lines.shift } # shift away the 2 `rename from/to ...` lines
         | 
| 61 | 
            +
                    end
         | 
| 62 | 
            +
             | 
| 63 | 
            +
                    m, a_blob, b_blob, b_mode = *lines.shift.match(%r{^index ([0-9A-Fa-f]+)\.\.([0-9A-Fa-f]+) ?(.+)?$})
         | 
| 64 | 
            +
                    b_mode.strip! if b_mode
         | 
| 65 | 
            +
             | 
| 66 | 
            +
                    diff_lines = []
         | 
| 67 | 
            +
                    while lines.first && lines.first !~ /^diff/
         | 
| 68 | 
            +
                      diff_lines << lines.shift
         | 
| 69 | 
            +
                    end
         | 
| 70 | 
            +
                    diff = diff_lines.join("\n")
         | 
| 71 | 
            +
             | 
| 72 | 
            +
                    diffs << Diff.new(repo, a_path, b_path, a_blob, b_blob, a_mode, b_mode, new_file, deleted_file, diff, renamed_file, sim_index)
         | 
| 73 | 
            +
                  end
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                  diffs
         | 
| 76 | 
            +
                end
         | 
| 77 | 
            +
              end # Diff
         | 
| 78 | 
            +
             | 
| 79 | 
            +
            end # Grit
         | 
    
        data/lib/grit/errors.rb
    ADDED
    
    
| @@ -0,0 +1,259 @@ | |
| 1 | 
            +
            require 'grit/git-ruby/repository'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Grit
         | 
| 4 | 
            +
             | 
| 5 | 
            +
              # the functions in this module intercept the calls to git binary
         | 
| 6 | 
            +
              # made buy the grit objects and attempts to run them in pure ruby
         | 
| 7 | 
            +
              # if it will be faster, or if the git binary is not available (!!TODO!!)
         | 
| 8 | 
            +
              module GitRuby
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                attr_accessor :ruby_git_repo, :git_file_index
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                def init(options, *args)
         | 
| 13 | 
            +
                  if options.size == 0
         | 
| 14 | 
            +
                    Grit::GitRuby::Repository.init(@git_dir)
         | 
| 15 | 
            +
                  else
         | 
| 16 | 
            +
                    method_missing('init', options, *args)
         | 
| 17 | 
            +
                  end
         | 
| 18 | 
            +
                end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                def cat_file(options, sha)
         | 
| 21 | 
            +
                  if options[:t]
         | 
| 22 | 
            +
                    file_type(sha)
         | 
| 23 | 
            +
                  elsif options[:s]
         | 
| 24 | 
            +
                    file_size(sha)
         | 
| 25 | 
            +
                  elsif options[:p]
         | 
| 26 | 
            +
                    try_run { ruby_git.cat_file(sha) }
         | 
| 27 | 
            +
                  end
         | 
| 28 | 
            +
                rescue Grit::GitRuby::Repository::NoSuchShaFound
         | 
| 29 | 
            +
                  ''
         | 
| 30 | 
            +
                end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                def cat_ref(options, ref)
         | 
| 33 | 
            +
                  sha = rev_parse({}, ref)
         | 
| 34 | 
            +
                  cat_file(options, sha)
         | 
| 35 | 
            +
                end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                # lib/grit/tree.rb:16:      output = repo.git.ls_tree({}, treeish, *paths)
         | 
| 38 | 
            +
                def ls_tree(options, treeish, *paths)
         | 
| 39 | 
            +
                  sha = rev_parse({}, treeish)
         | 
| 40 | 
            +
                  ruby_git.ls_tree(sha, paths.flatten, options.delete(:r))
         | 
| 41 | 
            +
                rescue Grit::GitRuby::Repository::NoSuchShaFound
         | 
| 42 | 
            +
                  ''
         | 
| 43 | 
            +
                end
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                # git diff --full-index 'ec037431382e83c3e95d4f2b3d145afbac8ea55d' 'f1ec1aea10986159456846b8a05615b87828d6c6'
         | 
| 46 | 
            +
                def diff(options, sha1, sha2 = nil)
         | 
| 47 | 
            +
                  try_run { ruby_git.diff(sha1, sha2, options) }
         | 
| 48 | 
            +
                end
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                def rev_list(options, *refs)
         | 
| 51 | 
            +
                  refs = ['master'] if refs.empty?
         | 
| 52 | 
            +
                  options.delete(:skip) if options[:skip].to_i == 0
         | 
| 53 | 
            +
                  allowed_options = [:max_count, :since, :until, :pretty]  # this is all I can do right now
         | 
| 54 | 
            +
                  if ((options.keys - allowed_options).size > 0) || refs.size > 1
         | 
| 55 | 
            +
                    method_missing('rev-list', options, *refs)
         | 
| 56 | 
            +
                  elsif (options.size == 0)
         | 
| 57 | 
            +
                    # pure rev-list
         | 
| 58 | 
            +
                    ref = refs.first
         | 
| 59 | 
            +
                    begin
         | 
| 60 | 
            +
                      file_index.commits_from(rev_parse({}, ref)).join("\n") + "\n"
         | 
| 61 | 
            +
                    rescue
         | 
| 62 | 
            +
                      method_missing('rev-list', options, *refs)
         | 
| 63 | 
            +
                    end
         | 
| 64 | 
            +
                  else
         | 
| 65 | 
            +
                    ref = refs.first
         | 
| 66 | 
            +
                    aref = rev_parse({:verify => true}, ref)
         | 
| 67 | 
            +
                    if aref.is_a? Array
         | 
| 68 | 
            +
                      method_missing('rev-list', options, *refs)
         | 
| 69 | 
            +
                    else
         | 
| 70 | 
            +
                      try_run { ruby_git.rev_list(aref, options) }
         | 
| 71 | 
            +
                    end
         | 
| 72 | 
            +
                  end
         | 
| 73 | 
            +
                end
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                def rev_parse(options, string)
         | 
| 76 | 
            +
                  raise RuntimeError, "invalid string: #{string.inspect}" unless string.is_a?(String)
         | 
| 77 | 
            +
             | 
| 78 | 
            +
                  if string =~ /\.\./
         | 
| 79 | 
            +
                    (sha1, sha2) = string.split('..')
         | 
| 80 | 
            +
                    return [rev_parse({}, sha1), rev_parse({}, sha2)]
         | 
| 81 | 
            +
                  end
         | 
| 82 | 
            +
             | 
| 83 | 
            +
                  if /^[0-9a-f]{40}$/.match(string)  # passing in a sha - just no-op it
         | 
| 84 | 
            +
                    return string.chomp
         | 
| 85 | 
            +
                  end
         | 
| 86 | 
            +
             | 
| 87 | 
            +
                  head = File.join(@git_dir, 'refs', 'heads', string)
         | 
| 88 | 
            +
                  return File.read(head).chomp if File.file?(head)
         | 
| 89 | 
            +
             | 
| 90 | 
            +
                  head = File.join(@git_dir, 'refs', 'remotes', string)
         | 
| 91 | 
            +
                  return File.read(head).chomp if File.file?(head)
         | 
| 92 | 
            +
             | 
| 93 | 
            +
                  head = File.join(@git_dir, 'refs', 'tags', string)
         | 
| 94 | 
            +
                  return File.read(head).chomp if File.file?(head)
         | 
| 95 | 
            +
             | 
| 96 | 
            +
                  ## check packed-refs file, too
         | 
| 97 | 
            +
                  packref = File.join(@git_dir, 'packed-refs')
         | 
| 98 | 
            +
                  if File.file?(packref)
         | 
| 99 | 
            +
                    File.readlines(packref).each do |line|
         | 
| 100 | 
            +
                      if m = /^(\w{40}) refs\/.+?\/(.*?)$/.match(line)
         | 
| 101 | 
            +
                        next if !Regexp.new(Regexp.escape(string) + '$').match(m[3])
         | 
| 102 | 
            +
                        return m[1].chomp
         | 
| 103 | 
            +
                      end
         | 
| 104 | 
            +
                    end
         | 
| 105 | 
            +
                  end
         | 
| 106 | 
            +
             | 
| 107 | 
            +
                  ## !! more - partials and such !!
         | 
| 108 | 
            +
             | 
| 109 | 
            +
                  # revert to calling git - grr
         | 
| 110 | 
            +
                  return method_missing('rev-parse', options, string).chomp
         | 
| 111 | 
            +
                end
         | 
| 112 | 
            +
             | 
| 113 | 
            +
                def refs(options, prefix)
         | 
| 114 | 
            +
                  refs = []
         | 
| 115 | 
            +
                  already = {}
         | 
| 116 | 
            +
                  Dir.chdir(@git_dir) do
         | 
| 117 | 
            +
                    files = Dir.glob(prefix + '/**/*')
         | 
| 118 | 
            +
                    files.each do |ref|
         | 
| 119 | 
            +
                      next if !File.file?(ref)
         | 
| 120 | 
            +
                      id = File.read(ref).chomp
         | 
| 121 | 
            +
                      name = ref.sub("#{prefix}/", '')
         | 
| 122 | 
            +
                      if !already[name]
         | 
| 123 | 
            +
                        refs << "#{name} #{id}"
         | 
| 124 | 
            +
                        already[name] = true
         | 
| 125 | 
            +
                      end
         | 
| 126 | 
            +
                    end
         | 
| 127 | 
            +
             | 
| 128 | 
            +
                    if File.file?('packed-refs')
         | 
| 129 | 
            +
                      File.readlines('packed-refs').each do |line|
         | 
| 130 | 
            +
                        if m = /^(\w{40}) (.*?)$/.match(line)
         | 
| 131 | 
            +
                          next if !Regexp.new('^' + prefix).match(m[2])
         | 
| 132 | 
            +
                          name = m[2].sub("#{prefix}/", '')
         | 
| 133 | 
            +
                          if !already[name]
         | 
| 134 | 
            +
                            refs << "#{name} #{m[1]}"
         | 
| 135 | 
            +
                            already[name] = true
         | 
| 136 | 
            +
                          end
         | 
| 137 | 
            +
                        end
         | 
| 138 | 
            +
                      end
         | 
| 139 | 
            +
                    end
         | 
| 140 | 
            +
                  end
         | 
| 141 | 
            +
             | 
| 142 | 
            +
                  refs.join("\n")
         | 
| 143 | 
            +
                end
         | 
| 144 | 
            +
             | 
| 145 | 
            +
                def tags(options, prefix)
         | 
| 146 | 
            +
                  refs = []
         | 
| 147 | 
            +
                  already = {}
         | 
| 148 | 
            +
             | 
| 149 | 
            +
                  Dir.chdir(repo.path) do
         | 
| 150 | 
            +
                    files = Dir.glob(prefix + '/**/*')
         | 
| 151 | 
            +
             | 
| 152 | 
            +
                    files.each do |ref|
         | 
| 153 | 
            +
                      next if !File.file?(ref)
         | 
| 154 | 
            +
             | 
| 155 | 
            +
                      id = File.read(ref).chomp
         | 
| 156 | 
            +
                      name = ref.sub("#{prefix}/", '')
         | 
| 157 | 
            +
             | 
| 158 | 
            +
                      if !already[name]
         | 
| 159 | 
            +
                        refs << "#{name} #{id}"
         | 
| 160 | 
            +
                        already[name] = true
         | 
| 161 | 
            +
                      end
         | 
| 162 | 
            +
                    end
         | 
| 163 | 
            +
             | 
| 164 | 
            +
                    if File.file?('packed-refs')
         | 
| 165 | 
            +
                      lines = File.readlines('packed-refs')
         | 
| 166 | 
            +
                      lines.each_with_index do |line, i|
         | 
| 167 | 
            +
                        if m = /^(\w{40}) (.*?)$/.match(line)
         | 
| 168 | 
            +
                          next if !Regexp.new('^' + prefix).match(m[2])
         | 
| 169 | 
            +
                          name = m[2].sub("#{prefix}/", '')
         | 
| 170 | 
            +
             | 
| 171 | 
            +
                          # Annotated tags in packed-refs include a reference
         | 
| 172 | 
            +
                          # to the commit object on the following line.
         | 
| 173 | 
            +
                          next_line = lines[i + 1]
         | 
| 174 | 
            +
             | 
| 175 | 
            +
                          id =
         | 
| 176 | 
            +
                          if next_line && next_line[0] == ?^
         | 
| 177 | 
            +
                            next_line[1..-1].chomp
         | 
| 178 | 
            +
                          else
         | 
| 179 | 
            +
                            m[1]
         | 
| 180 | 
            +
                          end
         | 
| 181 | 
            +
             | 
| 182 | 
            +
                          if !already[name]
         | 
| 183 | 
            +
                            refs << "#{name} #{id}"
         | 
| 184 | 
            +
                            already[name] = true
         | 
| 185 | 
            +
                          end
         | 
| 186 | 
            +
                        end
         | 
| 187 | 
            +
                      end
         | 
| 188 | 
            +
                    end
         | 
| 189 | 
            +
                  end
         | 
| 190 | 
            +
             | 
| 191 | 
            +
                  refs.join("\n")
         | 
| 192 | 
            +
                end
         | 
| 193 | 
            +
             | 
| 194 | 
            +
                def file_size(ref)
         | 
| 195 | 
            +
                  try_run { ruby_git.cat_file_size(ref).to_s }
         | 
| 196 | 
            +
                end
         | 
| 197 | 
            +
             | 
| 198 | 
            +
                def file_type(ref)
         | 
| 199 | 
            +
                  try_run { ruby_git.cat_file_type(ref).to_s }
         | 
| 200 | 
            +
                end
         | 
| 201 | 
            +
             | 
| 202 | 
            +
                def ruby_git
         | 
| 203 | 
            +
                  @ruby_git_repo ||= Repository.new(@git_dir)
         | 
| 204 | 
            +
                end
         | 
| 205 | 
            +
             | 
| 206 | 
            +
                private
         | 
| 207 | 
            +
             | 
| 208 | 
            +
                  def try_run
         | 
| 209 | 
            +
                    ret = ''
         | 
| 210 | 
            +
                    Timeout.timeout(self.class.git_timeout) do
         | 
| 211 | 
            +
                      ret = yield
         | 
| 212 | 
            +
                    end
         | 
| 213 | 
            +
                    @bytes_read += ret.size
         | 
| 214 | 
            +
             | 
| 215 | 
            +
                    #if @bytes_read > 5242880 # 5.megabytes
         | 
| 216 | 
            +
                    #  bytes = @bytes_read
         | 
| 217 | 
            +
                    #  @bytes_read = 0
         | 
| 218 | 
            +
                    #  raise Grit::Git::GitTimeout.new(command, bytes)
         | 
| 219 | 
            +
                    #end
         | 
| 220 | 
            +
             | 
| 221 | 
            +
                    ret
         | 
| 222 | 
            +
                  rescue Timeout::Error => e
         | 
| 223 | 
            +
                    bytes = @bytes_read
         | 
| 224 | 
            +
                    @bytes_read = 0
         | 
| 225 | 
            +
                    raise Grit::Git::GitTimeout.new(command, bytes)
         | 
| 226 | 
            +
                  end
         | 
| 227 | 
            +
             | 
| 228 | 
            +
                  def looking_for(commit, path = nil)
         | 
| 229 | 
            +
                    tree_sha = ruby_git.get_subtree(rev_parse({}, commit), path)
         | 
| 230 | 
            +
             | 
| 231 | 
            +
                    looking_for = []
         | 
| 232 | 
            +
                    ruby_git.get_object_by_sha1(tree_sha).entry.each do |e|
         | 
| 233 | 
            +
                      if path && !(path == '' || path == '.' || path == './')
         | 
| 234 | 
            +
                        file = File.join(path, e.name)
         | 
| 235 | 
            +
                      else
         | 
| 236 | 
            +
                        file = e.name
         | 
| 237 | 
            +
                      end
         | 
| 238 | 
            +
                      file += '/' if e.type == :directory
         | 
| 239 | 
            +
                      looking_for << file
         | 
| 240 | 
            +
                    end
         | 
| 241 | 
            +
                    looking_for
         | 
| 242 | 
            +
                  end
         | 
| 243 | 
            +
             | 
| 244 | 
            +
                  def clean_paths(commit_array)
         | 
| 245 | 
            +
                    new_commits = {}
         | 
| 246 | 
            +
                    commit_array.each do |file, sha|
         | 
| 247 | 
            +
                      file = file.chop if file[file.size - 1 , 1] == '/'
         | 
| 248 | 
            +
                      new_commits[file] = sha
         | 
| 249 | 
            +
                    end
         | 
| 250 | 
            +
                    new_commits
         | 
| 251 | 
            +
                  end
         | 
| 252 | 
            +
             | 
| 253 | 
            +
                # TODO
         | 
| 254 | 
            +
                # git grep -n 'foo' 'master'
         | 
| 255 | 
            +
                # git log --pretty='raw' --max-count='1' 'master' -- 'LICENSE'
         | 
| 256 | 
            +
                # git log --pretty='raw' --max-count='1' 'master' -- 'test'
         | 
| 257 | 
            +
             | 
| 258 | 
            +
              end
         | 
| 259 | 
            +
            end
         |