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,44 @@ | |
| 1 | 
            +
            #
         | 
| 2 | 
            +
            # converted from the gitrb project
         | 
| 3 | 
            +
            #
         | 
| 4 | 
            +
            # authors:
         | 
| 5 | 
            +
            #    Matthias Lederhofer <matled@gmx.net>
         | 
| 6 | 
            +
            #    Simon 'corecode' Schubert <corecode@fs.ei.tum.de>
         | 
| 7 | 
            +
            #
         | 
| 8 | 
            +
            # provides native ruby access to git objects and pack files
         | 
| 9 | 
            +
            #
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            require 'digest/sha1'
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            module Grit
         | 
| 14 | 
            +
              module GitRuby
         | 
| 15 | 
            +
                module Internal
         | 
| 16 | 
            +
                  OBJ_NONE = 0
         | 
| 17 | 
            +
                  OBJ_COMMIT = 1
         | 
| 18 | 
            +
                  OBJ_TREE = 2
         | 
| 19 | 
            +
                  OBJ_BLOB = 3
         | 
| 20 | 
            +
                  OBJ_TAG = 4
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                  OBJ_TYPES = [nil, :commit, :tree, :blob, :tag].freeze
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                  class RawObject
         | 
| 25 | 
            +
                    attr_accessor :type, :content
         | 
| 26 | 
            +
                    def initialize(type, content)
         | 
| 27 | 
            +
                      @type = type
         | 
| 28 | 
            +
                      @content = content
         | 
| 29 | 
            +
                    end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                    def sha1
         | 
| 32 | 
            +
                      Digest::SHA1.digest("%s %d\0" % [@type, @content.length] + @content)
         | 
| 33 | 
            +
                    end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                    def to_hash
         | 
| 36 | 
            +
                      {
         | 
| 37 | 
            +
                        :type => @type,
         | 
| 38 | 
            +
                        :content => @content
         | 
| 39 | 
            +
                      }
         | 
| 40 | 
            +
                    end
         | 
| 41 | 
            +
                  end
         | 
| 42 | 
            +
                end
         | 
| 43 | 
            +
              end
         | 
| 44 | 
            +
            end
         | 
| @@ -0,0 +1,775 @@ | |
| 1 | 
            +
            #
         | 
| 2 | 
            +
            # converted from the gitrb project
         | 
| 3 | 
            +
            #
         | 
| 4 | 
            +
            # authors:
         | 
| 5 | 
            +
            #    Matthias Lederhofer <matled@gmx.net>
         | 
| 6 | 
            +
            #    Simon 'corecode' Schubert <corecode@fs.ei.tum.de>
         | 
| 7 | 
            +
            #    Scott Chacon <schacon@gmail.com>
         | 
| 8 | 
            +
            #
         | 
| 9 | 
            +
            # provides native ruby access to git objects and pack files
         | 
| 10 | 
            +
            #
         | 
| 11 | 
            +
            require 'grit/git-ruby/internal/raw_object'
         | 
| 12 | 
            +
            require 'grit/git-ruby/internal/pack'
         | 
| 13 | 
            +
            require 'grit/git-ruby/internal/loose'
         | 
| 14 | 
            +
            require 'grit/git-ruby/git_object'
         | 
| 15 | 
            +
             | 
| 16 | 
            +
            require 'rubygems'
         | 
| 17 | 
            +
            require 'diff/lcs'
         | 
| 18 | 
            +
            require 'diff/lcs/hunk'
         | 
| 19 | 
            +
             | 
| 20 | 
            +
            # have to do this so it doesn't interfere with Grit::Diff
         | 
| 21 | 
            +
            module Difference
         | 
| 22 | 
            +
              include Diff
         | 
| 23 | 
            +
            end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
            module Grit
         | 
| 26 | 
            +
              module GitRuby
         | 
| 27 | 
            +
                class Repository
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                  class NoSuchShaFound < StandardError
         | 
| 30 | 
            +
                  end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                  class NoSuchPath < StandardError
         | 
| 33 | 
            +
                  end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                  attr_accessor :git_dir, :options
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                  def initialize(git_dir, options = {})
         | 
| 38 | 
            +
                    @git_dir = git_dir
         | 
| 39 | 
            +
                    @options = options
         | 
| 40 | 
            +
                    @packs = []
         | 
| 41 | 
            +
                  end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                  # returns the loose objects object lazily
         | 
| 44 | 
            +
                  def loose
         | 
| 45 | 
            +
                    @loose ||= initloose
         | 
| 46 | 
            +
                  end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                  # returns the array of pack list objects
         | 
| 49 | 
            +
                  def packs
         | 
| 50 | 
            +
                    @packs ||= initpacks
         | 
| 51 | 
            +
                  end
         | 
| 52 | 
            +
             | 
| 53 | 
            +
             | 
| 54 | 
            +
                  # prints out the type, shas and content of all of the pack files
         | 
| 55 | 
            +
                  def show
         | 
| 56 | 
            +
                    packs.each do |p|
         | 
| 57 | 
            +
                      puts p.name
         | 
| 58 | 
            +
                      puts
         | 
| 59 | 
            +
                      p.each_sha1 do |s|
         | 
| 60 | 
            +
                        puts "**#{p[s].type}**"
         | 
| 61 | 
            +
                        if p[s].type.to_s == 'commit'
         | 
| 62 | 
            +
                          puts s.unpack('H*')
         | 
| 63 | 
            +
                          puts p[s].content
         | 
| 64 | 
            +
                        end
         | 
| 65 | 
            +
                      end
         | 
| 66 | 
            +
                      puts
         | 
| 67 | 
            +
                    end
         | 
| 68 | 
            +
                  end
         | 
| 69 | 
            +
             | 
| 70 | 
            +
             | 
| 71 | 
            +
                  # returns a raw object given a SHA1
         | 
| 72 | 
            +
                  def get_raw_object_by_sha1(sha1o)
         | 
| 73 | 
            +
                    raise NoSuchShaFound if sha1o.nil? || sha1o.empty? || !sha1o.is_a?(String)
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                    sha1 = [sha1o.chomp].pack("H*")
         | 
| 76 | 
            +
                    # try packs
         | 
| 77 | 
            +
                    packs.each do |pack|
         | 
| 78 | 
            +
                      o = pack[sha1]
         | 
| 79 | 
            +
                      return pack[sha1] if o
         | 
| 80 | 
            +
                    end
         | 
| 81 | 
            +
             | 
| 82 | 
            +
                    # try loose storage
         | 
| 83 | 
            +
                    loose.each do |lsobj|
         | 
| 84 | 
            +
                      o = lsobj[sha1]
         | 
| 85 | 
            +
                      return o if o
         | 
| 86 | 
            +
                    end
         | 
| 87 | 
            +
             | 
| 88 | 
            +
                    # try packs again, maybe the object got packed in the meantime
         | 
| 89 | 
            +
                    initpacks
         | 
| 90 | 
            +
                    packs.each do |pack|
         | 
| 91 | 
            +
                      o = pack[sha1]
         | 
| 92 | 
            +
                      return o if o
         | 
| 93 | 
            +
                    end
         | 
| 94 | 
            +
             | 
| 95 | 
            +
            #        puts "*#{sha1o}*"
         | 
| 96 | 
            +
                    raise NoSuchShaFound
         | 
| 97 | 
            +
                  end
         | 
| 98 | 
            +
             | 
| 99 | 
            +
                  def cached(key, object, do_cache = true)
         | 
| 100 | 
            +
                    object
         | 
| 101 | 
            +
                  end
         | 
| 102 | 
            +
             | 
| 103 | 
            +
                  # returns GitRuby object of any type given a SHA1
         | 
| 104 | 
            +
                  def get_object_by_sha1(sha1)
         | 
| 105 | 
            +
                    r = get_raw_object_by_sha1(sha1)
         | 
| 106 | 
            +
                    return nil if !r
         | 
| 107 | 
            +
                    GitObject.from_raw(r)
         | 
| 108 | 
            +
                  end
         | 
| 109 | 
            +
             | 
| 110 | 
            +
                  # writes a raw object into the git repo
         | 
| 111 | 
            +
                  def put_raw_object(content, type)
         | 
| 112 | 
            +
                    loose.first.put_raw_object(content, type)
         | 
| 113 | 
            +
                  end
         | 
| 114 | 
            +
             | 
| 115 | 
            +
                  # returns true or false if that sha exists in the db
         | 
| 116 | 
            +
                  def object_exists?(sha1)
         | 
| 117 | 
            +
                    sha_hex = [sha1].pack("H*")
         | 
| 118 | 
            +
                    return true if in_packs?(sha_hex)
         | 
| 119 | 
            +
                    return true if in_loose?(sha_hex)
         | 
| 120 | 
            +
                    initpacks
         | 
| 121 | 
            +
                    return true if in_packs?(sha_hex) #maybe the object got packed in the meantime
         | 
| 122 | 
            +
                    false
         | 
| 123 | 
            +
                  end
         | 
| 124 | 
            +
             | 
| 125 | 
            +
                  # returns true if the hex-packed sha is in the packfiles
         | 
| 126 | 
            +
                  def in_packs?(sha_hex)
         | 
| 127 | 
            +
                    # try packs
         | 
| 128 | 
            +
                    packs.each do |pack|
         | 
| 129 | 
            +
                      return true if pack[sha_hex]
         | 
| 130 | 
            +
                    end
         | 
| 131 | 
            +
                    false
         | 
| 132 | 
            +
                  end
         | 
| 133 | 
            +
             | 
| 134 | 
            +
                  # returns true if the hex-packed sha is in the loose objects
         | 
| 135 | 
            +
                  def in_loose?(sha_hex)
         | 
| 136 | 
            +
                    loose.each do |lsobj|
         | 
| 137 | 
            +
                      return true if lsobj[sha_hex]
         | 
| 138 | 
            +
                    end
         | 
| 139 | 
            +
                    false
         | 
| 140 | 
            +
                  end
         | 
| 141 | 
            +
             | 
| 142 | 
            +
             | 
| 143 | 
            +
                  # returns the file type (as a symbol) of this sha
         | 
| 144 | 
            +
                  def cat_file_type(sha)
         | 
| 145 | 
            +
                    get_raw_object_by_sha1(sha).type
         | 
| 146 | 
            +
                  end
         | 
| 147 | 
            +
             | 
| 148 | 
            +
                  # returns the file size (as an int) of this sha
         | 
| 149 | 
            +
                  def cat_file_size(sha)
         | 
| 150 | 
            +
                    get_raw_object_by_sha1(sha).content.size
         | 
| 151 | 
            +
                  end
         | 
| 152 | 
            +
             | 
| 153 | 
            +
                  # returns the raw file contents of this sha
         | 
| 154 | 
            +
                  def cat_file(sha)
         | 
| 155 | 
            +
                    get_object_by_sha1(sha).raw_content
         | 
| 156 | 
            +
                  end
         | 
| 157 | 
            +
             | 
| 158 | 
            +
                  # returns a 2-d hash of the tree
         | 
| 159 | 
            +
                  # ['blob']['FILENAME'] = {:mode => '100644', :sha => SHA}
         | 
| 160 | 
            +
                  # ['tree']['DIRNAME'] = {:mode => '040000', :sha => SHA}
         | 
| 161 | 
            +
                  def list_tree(sha)
         | 
| 162 | 
            +
                    data = {'blob' => {}, 'tree' => {}, 'link' => {}, 'commit' => {}}
         | 
| 163 | 
            +
                    get_object_by_sha1(sha).entry.each do |e|
         | 
| 164 | 
            +
                      data[e.format_type][e.name] = {:mode => e.format_mode, :sha => e.sha1}
         | 
| 165 | 
            +
                    end
         | 
| 166 | 
            +
                    data
         | 
| 167 | 
            +
                  end
         | 
| 168 | 
            +
             | 
| 169 | 
            +
                  # returns the raw (cat-file) output for a tree
         | 
| 170 | 
            +
                  # if given a commit sha, it will print the tree of that commit
         | 
| 171 | 
            +
                  # if given a path limiter array, it will limit the output to those
         | 
| 172 | 
            +
                  # if asked for recrusive trees, will traverse trees
         | 
| 173 | 
            +
                  def ls_tree(sha, paths = [], recursive = false)
         | 
| 174 | 
            +
                    if paths.size > 0
         | 
| 175 | 
            +
                      # pathing
         | 
| 176 | 
            +
                      part = []
         | 
| 177 | 
            +
                      paths.each do |path|
         | 
| 178 | 
            +
                        part += ls_tree_path(sha, path)
         | 
| 179 | 
            +
                      end
         | 
| 180 | 
            +
                      return part.join("\n")
         | 
| 181 | 
            +
                    else
         | 
| 182 | 
            +
                      get_raw_tree(sha, recursive)
         | 
| 183 | 
            +
                    end
         | 
| 184 | 
            +
                  end
         | 
| 185 | 
            +
             | 
| 186 | 
            +
                  def get_raw_tree(sha, recursive = false)
         | 
| 187 | 
            +
                    o = get_raw_object_by_sha1(sha)
         | 
| 188 | 
            +
                    if o.type == :commit
         | 
| 189 | 
            +
                      tree = get_object_by_sha1(sha).tree
         | 
| 190 | 
            +
                    elsif o.type == :tag
         | 
| 191 | 
            +
                      commit_sha = get_object_by_sha1(sha).object
         | 
| 192 | 
            +
                      tree = get_object_by_sha1(commit_sha).tree
         | 
| 193 | 
            +
                    elsif o.type == :tree
         | 
| 194 | 
            +
                      tree = sha
         | 
| 195 | 
            +
                    else
         | 
| 196 | 
            +
                      return nil
         | 
| 197 | 
            +
                    end
         | 
| 198 | 
            +
             | 
| 199 | 
            +
                    recursive ? get_raw_trees(tree) : cat_file(tree)
         | 
| 200 | 
            +
                  end
         | 
| 201 | 
            +
             | 
| 202 | 
            +
                  # Grabs tree contents recursively,
         | 
| 203 | 
            +
                  #   e.g. `git ls-tree -r sha`
         | 
| 204 | 
            +
                  def get_raw_trees(sha, path = '')
         | 
| 205 | 
            +
                    out = ''
         | 
| 206 | 
            +
                    cat_file(sha).split("\n").each do |line|
         | 
| 207 | 
            +
                      mode, type, sha, name = line.split(/\s/)
         | 
| 208 | 
            +
             | 
| 209 | 
            +
                      if type == 'tree'
         | 
| 210 | 
            +
                        full_name = path.empty? ? name : "#{path}/#{name}"
         | 
| 211 | 
            +
                        out << get_raw_trees(sha, full_name)
         | 
| 212 | 
            +
                      elsif path.empty?
         | 
| 213 | 
            +
                        out << line + "\n"
         | 
| 214 | 
            +
                      else
         | 
| 215 | 
            +
                        out << line.gsub(name, "#{path}/#{name}") + "\n"
         | 
| 216 | 
            +
                      end
         | 
| 217 | 
            +
                    end
         | 
| 218 | 
            +
             | 
| 219 | 
            +
                    out
         | 
| 220 | 
            +
                  end
         | 
| 221 | 
            +
             | 
| 222 | 
            +
                  # return array of tree entries
         | 
| 223 | 
            +
                  ## TODO : refactor this to remove the fugly
         | 
| 224 | 
            +
                  def ls_tree_path(sha, path, append = nil)
         | 
| 225 | 
            +
                    tree = get_raw_tree(sha)
         | 
| 226 | 
            +
                    if path =~ /\//
         | 
| 227 | 
            +
                      paths = path.split('/')
         | 
| 228 | 
            +
                      last = path[path.size - 1, 1]
         | 
| 229 | 
            +
                      if (last == '/') && (paths.size == 1)
         | 
| 230 | 
            +
                        append = append ? File.join(append, paths.first) : paths.first
         | 
| 231 | 
            +
                        dir_name = tree.split("\n").select { |p| p.split("\t")[1] == paths.first }.first
         | 
| 232 | 
            +
                        raise NoSuchPath if !dir_name
         | 
| 233 | 
            +
                        next_sha = dir_name.split(' ')[2]
         | 
| 234 | 
            +
                        tree = get_raw_tree(next_sha)
         | 
| 235 | 
            +
                        tree = tree.split("\n")
         | 
| 236 | 
            +
                        if append
         | 
| 237 | 
            +
                          mod_tree = []
         | 
| 238 | 
            +
                          tree.each do |ent|
         | 
| 239 | 
            +
                            (info, fpath) = ent.split("\t")
         | 
| 240 | 
            +
                            mod_tree << [info, File.join(append, fpath)].join("\t")
         | 
| 241 | 
            +
                          end
         | 
| 242 | 
            +
                          mod_tree
         | 
| 243 | 
            +
                        else
         | 
| 244 | 
            +
                          tree
         | 
| 245 | 
            +
                        end
         | 
| 246 | 
            +
                      else
         | 
| 247 | 
            +
                        raise NoSuchPath if tree.nil?
         | 
| 248 | 
            +
                        next_path = paths.shift
         | 
| 249 | 
            +
                        dir_name = tree.split("\n").select { |p| p.split("\t")[1] == next_path }.first
         | 
| 250 | 
            +
                        raise NoSuchPath if !dir_name
         | 
| 251 | 
            +
                        next_sha = dir_name.split(' ')[2]
         | 
| 252 | 
            +
                        next_path = append ? File.join(append, next_path) : next_path
         | 
| 253 | 
            +
                        if (last == '/')
         | 
| 254 | 
            +
                          ls_tree_path(next_sha, paths.join("/") + '/', next_path)
         | 
| 255 | 
            +
                        else
         | 
| 256 | 
            +
                          ls_tree_path(next_sha, paths.join("/"), next_path)
         | 
| 257 | 
            +
                        end
         | 
| 258 | 
            +
                      end
         | 
| 259 | 
            +
                    else
         | 
| 260 | 
            +
                      raise NoSuchPath if tree.nil?
         | 
| 261 | 
            +
                      tree = tree.split("\n")
         | 
| 262 | 
            +
                      tree = tree.select { |p| p.split("\t")[1] == path }
         | 
| 263 | 
            +
                      if append
         | 
| 264 | 
            +
                        mod_tree = []
         | 
| 265 | 
            +
                        tree.each do |ent|
         | 
| 266 | 
            +
                          (info, fpath) = ent.split("\t")
         | 
| 267 | 
            +
                          mod_tree << [info, File.join(append, fpath)].join("\t")
         | 
| 268 | 
            +
                        end
         | 
| 269 | 
            +
                        mod_tree
         | 
| 270 | 
            +
                      else
         | 
| 271 | 
            +
                        tree
         | 
| 272 | 
            +
                      end
         | 
| 273 | 
            +
                    end
         | 
| 274 | 
            +
                  end
         | 
| 275 | 
            +
             | 
| 276 | 
            +
                  # returns an array of GitRuby Commit objects
         | 
| 277 | 
            +
                  # [ [sha, raw_output], [sha, raw_output], [sha, raw_output] ... ]
         | 
| 278 | 
            +
                  #
         | 
| 279 | 
            +
                  # takes the following options:
         | 
| 280 | 
            +
                  #  :since - Time object specifying that you don't want commits BEFORE this
         | 
| 281 | 
            +
                  #  :until - Time object specifying that you don't want commit AFTER this
         | 
| 282 | 
            +
                  #  :first_parent - tells log to only walk first parent
         | 
| 283 | 
            +
                  #  :path_limiter - string or array of strings to limit path
         | 
| 284 | 
            +
                  #  :max_count - number to limit the output
         | 
| 285 | 
            +
                  def log(sha, options = {})
         | 
| 286 | 
            +
                    @already_searched = {}
         | 
| 287 | 
            +
                    walk_log(sha, options)
         | 
| 288 | 
            +
                  end
         | 
| 289 | 
            +
             | 
| 290 | 
            +
                  def truncate_arr(arr, sha)
         | 
| 291 | 
            +
                    new_arr = []
         | 
| 292 | 
            +
                    arr.each do |a|
         | 
| 293 | 
            +
                      if a[0] == sha
         | 
| 294 | 
            +
                        return new_arr
         | 
| 295 | 
            +
                      end
         | 
| 296 | 
            +
                      new_arr << a
         | 
| 297 | 
            +
                    end
         | 
| 298 | 
            +
                    return new_arr
         | 
| 299 | 
            +
                  end
         | 
| 300 | 
            +
             | 
| 301 | 
            +
                  def rev_list(sha, options)
         | 
| 302 | 
            +
                    if sha.is_a? Array
         | 
| 303 | 
            +
                      (end_sha, sha) = sha
         | 
| 304 | 
            +
                    end
         | 
| 305 | 
            +
             | 
| 306 | 
            +
                    log = log(sha, options)
         | 
| 307 | 
            +
                    log = log.sort { |a, b| a[2] <=> b[2] }.reverse
         | 
| 308 | 
            +
             | 
| 309 | 
            +
                    if end_sha
         | 
| 310 | 
            +
                      log = truncate_arr(log, end_sha)
         | 
| 311 | 
            +
                    end
         | 
| 312 | 
            +
             | 
| 313 | 
            +
                    # shorten the list if it's longer than max_count (had to get everything in branches)
         | 
| 314 | 
            +
                    if options[:max_count]
         | 
| 315 | 
            +
                      if (opt_len = options[:max_count].to_i) < log.size
         | 
| 316 | 
            +
                        log = log[0, opt_len]
         | 
| 317 | 
            +
                      end
         | 
| 318 | 
            +
                    end
         | 
| 319 | 
            +
             | 
| 320 | 
            +
                    if options[:pretty] == 'raw'
         | 
| 321 | 
            +
                      log.map {|k, v| v }.join('')
         | 
| 322 | 
            +
                    else
         | 
| 323 | 
            +
                      log.map {|k, v| k }.join("\n")
         | 
| 324 | 
            +
                    end
         | 
| 325 | 
            +
                  end
         | 
| 326 | 
            +
             | 
| 327 | 
            +
                  # called by log() to recursively walk the tree
         | 
| 328 | 
            +
                  def walk_log(sha, opts, total_size = 0)
         | 
| 329 | 
            +
                    return [] if @already_searched[sha] # to prevent rechecking branches
         | 
| 330 | 
            +
                    @already_searched[sha] = true
         | 
| 331 | 
            +
             | 
| 332 | 
            +
                    array = []
         | 
| 333 | 
            +
                    if (sha)
         | 
| 334 | 
            +
                      o = get_raw_object_by_sha1(sha)
         | 
| 335 | 
            +
                      if o.type == :tag
         | 
| 336 | 
            +
                        commit_sha = get_object_by_sha1(sha).object
         | 
| 337 | 
            +
                        c = get_object_by_sha1(commit_sha)
         | 
| 338 | 
            +
                      else
         | 
| 339 | 
            +
                        c = GitObject.from_raw(o)
         | 
| 340 | 
            +
                      end
         | 
| 341 | 
            +
             | 
| 342 | 
            +
                      return [] if c.type != :commit
         | 
| 343 | 
            +
             | 
| 344 | 
            +
                      add_sha = true
         | 
| 345 | 
            +
             | 
| 346 | 
            +
                      if opts[:since] && opts[:since].is_a?(Time) && (opts[:since] > c.committer.date)
         | 
| 347 | 
            +
                        add_sha = false
         | 
| 348 | 
            +
                      end
         | 
| 349 | 
            +
                      if opts[:until] && opts[:until].is_a?(Time) && (opts[:until] < c.committer.date)
         | 
| 350 | 
            +
                        add_sha = false
         | 
| 351 | 
            +
                      end
         | 
| 352 | 
            +
             | 
| 353 | 
            +
                      # follow all parents unless '--first-parent' is specified #
         | 
| 354 | 
            +
                      subarray = []
         | 
| 355 | 
            +
             | 
| 356 | 
            +
                      if !c.parent.first && opts[:path_limiter]  # check for the last commit
         | 
| 357 | 
            +
                        add_sha = false
         | 
| 358 | 
            +
                      end
         | 
| 359 | 
            +
             | 
| 360 | 
            +
                      if (!opts[:max_count] || ((array.size + total_size) < opts[:max_count]))
         | 
| 361 | 
            +
             | 
| 362 | 
            +
                        if !opts[:path_limiter]
         | 
| 363 | 
            +
                          output = c.raw_log(sha)
         | 
| 364 | 
            +
                          array << [sha, output, c.committer.date]
         | 
| 365 | 
            +
                        end
         | 
| 366 | 
            +
             | 
| 367 | 
            +
                        if (opts[:max_count] && (array.size + total_size) >= opts[:max_count])
         | 
| 368 | 
            +
                          return array
         | 
| 369 | 
            +
                        end
         | 
| 370 | 
            +
             | 
| 371 | 
            +
                        c.parent.each do |psha|
         | 
| 372 | 
            +
                          if psha && !files_changed?(c.tree, get_object_by_sha1(psha).tree,
         | 
| 373 | 
            +
                                                    opts[:path_limiter])
         | 
| 374 | 
            +
                            add_sha = false
         | 
| 375 | 
            +
                          end
         | 
| 376 | 
            +
                          subarray += walk_log(psha, opts, (array.size + total_size))
         | 
| 377 | 
            +
                          next if opts[:first_parent]
         | 
| 378 | 
            +
                        end
         | 
| 379 | 
            +
             | 
| 380 | 
            +
                        if opts[:path_limiter] && add_sha
         | 
| 381 | 
            +
                          output = c.raw_log(sha)
         | 
| 382 | 
            +
                          array << [sha, output, c.committer.date]
         | 
| 383 | 
            +
                        end
         | 
| 384 | 
            +
             | 
| 385 | 
            +
                        if add_sha
         | 
| 386 | 
            +
                          array += subarray
         | 
| 387 | 
            +
                        end
         | 
| 388 | 
            +
                      end
         | 
| 389 | 
            +
             | 
| 390 | 
            +
                    end
         | 
| 391 | 
            +
             | 
| 392 | 
            +
                    array
         | 
| 393 | 
            +
                  end
         | 
| 394 | 
            +
             | 
| 395 | 
            +
                  def diff(commit1, commit2, options = {})
         | 
| 396 | 
            +
                    patch = ''
         | 
| 397 | 
            +
             | 
| 398 | 
            +
                    commit_obj1 = get_object_by_sha1(commit1)
         | 
| 399 | 
            +
                    tree1 = commit_obj1.tree
         | 
| 400 | 
            +
                    if commit2
         | 
| 401 | 
            +
                      tree2 = get_object_by_sha1(commit2).tree
         | 
| 402 | 
            +
                    else
         | 
| 403 | 
            +
                      tree2 = get_object_by_sha1(commit_obj1.parent.first).tree
         | 
| 404 | 
            +
                    end
         | 
| 405 | 
            +
             | 
| 406 | 
            +
                    qdiff = quick_diff(tree1, tree2)
         | 
| 407 | 
            +
             | 
| 408 | 
            +
                    qdiff.sort.each do |diff_arr|
         | 
| 409 | 
            +
                      path, status, treeSHA1, treeSHA2 = *diff_arr
         | 
| 410 | 
            +
                      format, lines, output = :unified, 3, ''
         | 
| 411 | 
            +
                      file_length_difference = 0
         | 
| 412 | 
            +
             | 
| 413 | 
            +
                      fileA = treeSHA1 ? cat_file(treeSHA1) : ''
         | 
| 414 | 
            +
                      fileB = treeSHA2 ? cat_file(treeSHA2) : ''
         | 
| 415 | 
            +
             | 
| 416 | 
            +
                      sha1 = treeSHA1 || '0000000000000000000000000000000000000000'
         | 
| 417 | 
            +
                      sha2 = treeSHA2 || '0000000000000000000000000000000000000000'
         | 
| 418 | 
            +
             | 
| 419 | 
            +
                      data_old = fileA.split(/\n/).map! { |e| e.chomp }
         | 
| 420 | 
            +
                      data_new = fileB.split(/\n/).map! { |e| e.chomp }
         | 
| 421 | 
            +
             | 
| 422 | 
            +
                      diffs = Difference::LCS.diff(data_old, data_new)
         | 
| 423 | 
            +
                      next if diffs.empty?
         | 
| 424 | 
            +
             | 
| 425 | 
            +
                      a_path = "a/#{path.gsub('./', '')}"
         | 
| 426 | 
            +
                      b_path = "b/#{path.gsub('./', '')}"
         | 
| 427 | 
            +
             | 
| 428 | 
            +
                      header = "diff --git #{a_path} #{b_path}"
         | 
| 429 | 
            +
                      if options[:full_index]
         | 
| 430 | 
            +
                        header << "\n" + 'index ' + sha1 + '..' + sha2
         | 
| 431 | 
            +
                        header << ' 100644' if treeSHA2 # hard coding this because i don't think we use it
         | 
| 432 | 
            +
                      else
         | 
| 433 | 
            +
                        header << "\n" + 'index ' + sha1[0,7] + '..' + sha2[0,7]
         | 
| 434 | 
            +
                        header << ' 100644' if treeSHA2 # hard coding this because i don't think we use it
         | 
| 435 | 
            +
                      end
         | 
| 436 | 
            +
                      header << "\n--- " + (treeSHA1 ? a_path : '/dev/null')
         | 
| 437 | 
            +
                      header << "\n+++ " + (treeSHA2 ? b_path : '/dev/null')
         | 
| 438 | 
            +
                      header += "\n"
         | 
| 439 | 
            +
             | 
| 440 | 
            +
                      oldhunk = hunk = nil
         | 
| 441 | 
            +
             | 
| 442 | 
            +
                      diffs.each do |piece|
         | 
| 443 | 
            +
                        begin
         | 
| 444 | 
            +
                          hunk = Difference::LCS::Hunk.new(data_old, data_new, piece, lines, file_length_difference)
         | 
| 445 | 
            +
                          file_length_difference = hunk.file_length_difference
         | 
| 446 | 
            +
             | 
| 447 | 
            +
                          next unless oldhunk
         | 
| 448 | 
            +
             | 
| 449 | 
            +
                          if lines > 0 && hunk.overlaps?(oldhunk)
         | 
| 450 | 
            +
                            hunk.unshift(oldhunk)
         | 
| 451 | 
            +
                          else
         | 
| 452 | 
            +
                            output << oldhunk.diff(format)
         | 
| 453 | 
            +
                          end
         | 
| 454 | 
            +
                        ensure
         | 
| 455 | 
            +
                          oldhunk = hunk
         | 
| 456 | 
            +
                          output << "\n"
         | 
| 457 | 
            +
                        end
         | 
| 458 | 
            +
                      end
         | 
| 459 | 
            +
             | 
| 460 | 
            +
                      output << oldhunk.diff(format)
         | 
| 461 | 
            +
                      output << "\n"
         | 
| 462 | 
            +
             | 
| 463 | 
            +
                      patch << header + output.lstrip
         | 
| 464 | 
            +
                    end
         | 
| 465 | 
            +
                    patch
         | 
| 466 | 
            +
                  rescue
         | 
| 467 | 
            +
                    '' # one of the trees was bad or lcs isn't there - no diff
         | 
| 468 | 
            +
                  end
         | 
| 469 | 
            +
             | 
| 470 | 
            +
                  # takes 2 tree shas and recursively walks them to find out what
         | 
| 471 | 
            +
                  # files or directories have been modified in them and returns an
         | 
| 472 | 
            +
                  # array of changes
         | 
| 473 | 
            +
                  # [ [full_path, 'added', tree1_hash, nil],
         | 
| 474 | 
            +
                  #   [full_path, 'removed', nil, tree2_hash],
         | 
| 475 | 
            +
                  #   [full_path, 'modified', tree1_hash, tree2_hash]
         | 
| 476 | 
            +
                  #  ]
         | 
| 477 | 
            +
                  def quick_diff(tree1, tree2, path = '.', recurse = true)
         | 
| 478 | 
            +
                    # handle empty trees
         | 
| 479 | 
            +
                    changed = []
         | 
| 480 | 
            +
                    return changed if tree1 == tree2
         | 
| 481 | 
            +
             | 
| 482 | 
            +
                    t1 = list_tree(tree1) if tree1
         | 
| 483 | 
            +
                    t2 = list_tree(tree2) if tree2
         | 
| 484 | 
            +
             | 
| 485 | 
            +
                    # finding files that are different
         | 
| 486 | 
            +
                    t1['blob'].each do |file, hsh|
         | 
| 487 | 
            +
                      t2_file = t2['blob'][file] rescue nil
         | 
| 488 | 
            +
                      full = File.join(path, file)
         | 
| 489 | 
            +
                      if !t2_file
         | 
| 490 | 
            +
                        changed << [full, 'added', hsh[:sha], nil]      # not in parent
         | 
| 491 | 
            +
                      elsif (hsh[:sha] != t2_file[:sha])
         | 
| 492 | 
            +
                        changed << [full, 'modified', hsh[:sha], t2_file[:sha]]   # file changed
         | 
| 493 | 
            +
                      end
         | 
| 494 | 
            +
                    end if t1
         | 
| 495 | 
            +
                    t2['blob'].each do |file, hsh|
         | 
| 496 | 
            +
                      if !t1 || !t1['blob'][file]
         | 
| 497 | 
            +
                        changed << [File.join(path, file), 'removed', nil, hsh[:sha]]
         | 
| 498 | 
            +
                      end
         | 
| 499 | 
            +
                    end if t2
         | 
| 500 | 
            +
             | 
| 501 | 
            +
                    t1['tree'].each do |dir, hsh|
         | 
| 502 | 
            +
                      t2_tree = t2['tree'][dir] rescue nil
         | 
| 503 | 
            +
                      full = File.join(path, dir)
         | 
| 504 | 
            +
                      if !t2_tree
         | 
| 505 | 
            +
                        if recurse
         | 
| 506 | 
            +
                          changed += quick_diff(hsh[:sha], nil, full, true)
         | 
| 507 | 
            +
                        else
         | 
| 508 | 
            +
                          changed << [full, 'added', hsh[:sha], nil]      # not in parent
         | 
| 509 | 
            +
                        end
         | 
| 510 | 
            +
                      elsif (hsh[:sha] != t2_tree[:sha])
         | 
| 511 | 
            +
                        if recurse
         | 
| 512 | 
            +
                          changed += quick_diff(hsh[:sha], t2_tree[:sha], full, true)
         | 
| 513 | 
            +
                        else
         | 
| 514 | 
            +
                          changed << [full, 'modified', hsh[:sha], t2_tree[:sha]]   # file changed
         | 
| 515 | 
            +
                        end
         | 
| 516 | 
            +
                      end
         | 
| 517 | 
            +
                    end if t1
         | 
| 518 | 
            +
                    t2['tree'].each do |dir, hsh|
         | 
| 519 | 
            +
                      t1_tree = t1['tree'][dir] rescue nil
         | 
| 520 | 
            +
                      full = File.join(path, dir)
         | 
| 521 | 
            +
                      if !t1_tree
         | 
| 522 | 
            +
                        if recurse
         | 
| 523 | 
            +
                          changed += quick_diff(nil, hsh[:sha], full, true)
         | 
| 524 | 
            +
                        else
         | 
| 525 | 
            +
                          changed << [full, 'removed', nil, hsh[:sha]]
         | 
| 526 | 
            +
                        end
         | 
| 527 | 
            +
                      end
         | 
| 528 | 
            +
                    end if t2
         | 
| 529 | 
            +
             | 
| 530 | 
            +
                    changed
         | 
| 531 | 
            +
                  end
         | 
| 532 | 
            +
             | 
| 533 | 
            +
                  # returns true if the files in path_limiter were changed, or no path limiter
         | 
| 534 | 
            +
                  # used by the log() function when passed with a path_limiter
         | 
| 535 | 
            +
                  def files_changed?(tree_sha1, tree_sha2, path_limiter = nil)
         | 
| 536 | 
            +
                    if path_limiter
         | 
| 537 | 
            +
                      mod = quick_diff(tree_sha1, tree_sha2)
         | 
| 538 | 
            +
                      files = mod.map { |c| c.first }
         | 
| 539 | 
            +
                      path_limiter.to_a.each do |filepath|
         | 
| 540 | 
            +
                        if files.include?(filepath)
         | 
| 541 | 
            +
                          return true
         | 
| 542 | 
            +
                        end
         | 
| 543 | 
            +
                      end
         | 
| 544 | 
            +
                      return false
         | 
| 545 | 
            +
                    end
         | 
| 546 | 
            +
                    true
         | 
| 547 | 
            +
                  end
         | 
| 548 | 
            +
             | 
| 549 | 
            +
                  def get_subtree(commit_sha, path)
         | 
| 550 | 
            +
                    tree_sha = get_object_by_sha1(commit_sha).tree
         | 
| 551 | 
            +
             | 
| 552 | 
            +
                    if path && !(path == '' || path == '.' || path == './')
         | 
| 553 | 
            +
                      paths = path.split('/')
         | 
| 554 | 
            +
                      paths.each do |pathname|
         | 
| 555 | 
            +
                        tree = get_object_by_sha1(tree_sha)
         | 
| 556 | 
            +
                        if entry = tree.entry.select { |e| e.name == pathname }.first
         | 
| 557 | 
            +
                          tree_sha = entry.sha1 rescue nil
         | 
| 558 | 
            +
                        else
         | 
| 559 | 
            +
                          return false
         | 
| 560 | 
            +
                        end
         | 
| 561 | 
            +
                      end
         | 
| 562 | 
            +
                    end
         | 
| 563 | 
            +
             | 
| 564 | 
            +
                    tree_sha
         | 
| 565 | 
            +
                  end
         | 
| 566 | 
            +
             | 
| 567 | 
            +
                  def blame_tree(commit_sha, path)
         | 
| 568 | 
            +
                    # find subtree
         | 
| 569 | 
            +
                    tree_sha = get_subtree(commit_sha, path)
         | 
| 570 | 
            +
                    return {} if !tree_sha
         | 
| 571 | 
            +
             | 
| 572 | 
            +
                    looking_for = []
         | 
| 573 | 
            +
                    get_object_by_sha1(tree_sha).entry.each do |e|
         | 
| 574 | 
            +
                      looking_for << File.join('.', e.name)
         | 
| 575 | 
            +
                    end
         | 
| 576 | 
            +
             | 
| 577 | 
            +
                    @already_searched = {}
         | 
| 578 | 
            +
                    commits = look_for_commits(commit_sha, path, looking_for)
         | 
| 579 | 
            +
             | 
| 580 | 
            +
                    # cleaning up array
         | 
| 581 | 
            +
                    arr = {}
         | 
| 582 | 
            +
                    commits.each do |commit_array|
         | 
| 583 | 
            +
                      key = commit_array[0].gsub('./', '')
         | 
| 584 | 
            +
                      arr[key] = commit_array[1]
         | 
| 585 | 
            +
                    end
         | 
| 586 | 
            +
                    arr
         | 
| 587 | 
            +
                  end
         | 
| 588 | 
            +
             | 
| 589 | 
            +
                  def look_for_commits(commit_sha, path, looking_for, options = {})
         | 
| 590 | 
            +
                    return [] if @already_searched[commit_sha] # to prevent rechecking branches
         | 
| 591 | 
            +
             | 
| 592 | 
            +
                    @already_searched[commit_sha] = true
         | 
| 593 | 
            +
             | 
| 594 | 
            +
                    commit = get_object_by_sha1(commit_sha)
         | 
| 595 | 
            +
                    tree_sha = get_subtree(commit_sha, path)
         | 
| 596 | 
            +
             | 
| 597 | 
            +
                    found_data = []
         | 
| 598 | 
            +
             | 
| 599 | 
            +
                    # at the beginning of the branch
         | 
| 600 | 
            +
                    if commit.parent.size == 0
         | 
| 601 | 
            +
                      looking_for.each do |search|
         | 
| 602 | 
            +
                        # prevents the rare case of multiple branch starting points with
         | 
| 603 | 
            +
                        # files that have never changed
         | 
| 604 | 
            +
                        if found_data.assoc(search)
         | 
| 605 | 
            +
                          found_data << [search, commit_sha]
         | 
| 606 | 
            +
                        end
         | 
| 607 | 
            +
                      end
         | 
| 608 | 
            +
                      return found_data
         | 
| 609 | 
            +
                    end
         | 
| 610 | 
            +
             | 
| 611 | 
            +
                    # go through the parents recursively, looking for somewhere this has been changed
         | 
| 612 | 
            +
                    commit.parent.each do |pc|
         | 
| 613 | 
            +
                      diff = quick_diff(tree_sha, get_subtree(pc, path), '.', false)
         | 
| 614 | 
            +
             | 
| 615 | 
            +
                      # remove anything found
         | 
| 616 | 
            +
                      looking_for.each do |search|
         | 
| 617 | 
            +
                        if match = diff.assoc(search)
         | 
| 618 | 
            +
                          found_data << [search, commit_sha, match]
         | 
| 619 | 
            +
                          looking_for.delete(search)
         | 
| 620 | 
            +
                        end
         | 
| 621 | 
            +
                      end
         | 
| 622 | 
            +
             | 
| 623 | 
            +
                      if looking_for.size <= 0  # we're done
         | 
| 624 | 
            +
                        return found_data
         | 
| 625 | 
            +
                      end
         | 
| 626 | 
            +
             | 
| 627 | 
            +
                      found_data += look_for_commits(pc, path, looking_for)  # recurse into parent
         | 
| 628 | 
            +
                      return found_data if options[:first_parent]
         | 
| 629 | 
            +
                    end
         | 
| 630 | 
            +
             | 
| 631 | 
            +
                    ## TODO : find most recent commit with change in any parent
         | 
| 632 | 
            +
                    found_data
         | 
| 633 | 
            +
                  end
         | 
| 634 | 
            +
             | 
| 635 | 
            +
                  # initialize a git repository
         | 
| 636 | 
            +
                  def self.init(dir, bare = true)
         | 
| 637 | 
            +
             | 
| 638 | 
            +
                    FileUtils.mkdir_p(dir) if !File.exists?(dir)
         | 
| 639 | 
            +
             | 
| 640 | 
            +
                    FileUtils.cd(dir) do
         | 
| 641 | 
            +
                      if(File.exists?('objects'))
         | 
| 642 | 
            +
                        return false # already initialized
         | 
| 643 | 
            +
                      else
         | 
| 644 | 
            +
                        # initialize directory
         | 
| 645 | 
            +
                        create_initial_config(bare)
         | 
| 646 | 
            +
                        FileUtils.mkdir_p('refs/heads')
         | 
| 647 | 
            +
                        FileUtils.mkdir_p('refs/tags')
         | 
| 648 | 
            +
                        FileUtils.mkdir_p('objects/info')
         | 
| 649 | 
            +
                        FileUtils.mkdir_p('objects/pack')
         | 
| 650 | 
            +
                        FileUtils.mkdir_p('branches')
         | 
| 651 | 
            +
                        add_file('description', 'Unnamed repository; edit this file to name it for gitweb.')
         | 
| 652 | 
            +
                        add_file('HEAD', "ref: refs/heads/master\n")
         | 
| 653 | 
            +
                        FileUtils.mkdir_p('hooks')
         | 
| 654 | 
            +
                        FileUtils.cd('hooks') do
         | 
| 655 | 
            +
                          add_file('applypatch-msg', '# add shell script and make executable to enable')
         | 
| 656 | 
            +
                          add_file('post-commit', '# add shell script and make executable to enable')
         | 
| 657 | 
            +
                          add_file('post-receive', '# add shell script and make executable to enable')
         | 
| 658 | 
            +
                          add_file('post-update', '# add shell script and make executable to enable')
         | 
| 659 | 
            +
                          add_file('pre-applypatch', '# add shell script and make executable to enable')
         | 
| 660 | 
            +
                          add_file('pre-commit', '# add shell script and make executable to enable')
         | 
| 661 | 
            +
                          add_file('pre-rebase', '# add shell script and make executable to enable')
         | 
| 662 | 
            +
                          add_file('update', '# add shell script and make executable to enable')
         | 
| 663 | 
            +
                        end
         | 
| 664 | 
            +
                        FileUtils.mkdir_p('info')
         | 
| 665 | 
            +
                        add_file('info/exclude', "# *.[oa]\n# *~")
         | 
| 666 | 
            +
                      end
         | 
| 667 | 
            +
                    end
         | 
| 668 | 
            +
                  end
         | 
| 669 | 
            +
             | 
| 670 | 
            +
                  def self.create_initial_config(bare = false)
         | 
| 671 | 
            +
                    bare ? bare_status = 'true' : bare_status = 'false'
         | 
| 672 | 
            +
                    config = "[core]\n\trepositoryformatversion = 0\n\tfilemode = true\n\tbare = #{bare_status}\n\tlogallrefupdates = true"
         | 
| 673 | 
            +
                    add_file('config', config)
         | 
| 674 | 
            +
                  end
         | 
| 675 | 
            +
             | 
| 676 | 
            +
                  def self.add_file(name, contents)
         | 
| 677 | 
            +
                    File.open(name, 'w') do |f|
         | 
| 678 | 
            +
                      f.write contents
         | 
| 679 | 
            +
                    end
         | 
| 680 | 
            +
                  end
         | 
| 681 | 
            +
             | 
| 682 | 
            +
                  def close
         | 
| 683 | 
            +
                    @packs.each do |pack|
         | 
| 684 | 
            +
                      pack.close
         | 
| 685 | 
            +
                    end if @packs
         | 
| 686 | 
            +
                  end
         | 
| 687 | 
            +
             | 
| 688 | 
            +
                  protected
         | 
| 689 | 
            +
             | 
| 690 | 
            +
                    def git_path(path)
         | 
| 691 | 
            +
                      return "#@git_dir/#{path}"
         | 
| 692 | 
            +
                    end
         | 
| 693 | 
            +
             | 
| 694 | 
            +
                  private
         | 
| 695 | 
            +
             | 
| 696 | 
            +
                    def initloose
         | 
| 697 | 
            +
                      @loaded = []
         | 
| 698 | 
            +
                      @loose = []
         | 
| 699 | 
            +
                      load_loose(git_path('objects'))
         | 
| 700 | 
            +
                      load_alternate_loose(git_path('objects'))
         | 
| 701 | 
            +
                      @loose
         | 
| 702 | 
            +
                    end
         | 
| 703 | 
            +
             | 
| 704 | 
            +
                    def each_alternate_path(path)
         | 
| 705 | 
            +
                      alt = File.join(path, 'info/alternates')
         | 
| 706 | 
            +
                      return if !File.exists?(alt)
         | 
| 707 | 
            +
             | 
| 708 | 
            +
                      File.readlines(alt).each do |line|
         | 
| 709 | 
            +
                        path = line.chomp
         | 
| 710 | 
            +
                        if path[0, 2] == '..'
         | 
| 711 | 
            +
                          yield File.expand_path(File.join(@git_dir, 'objects', path))
         | 
| 712 | 
            +
             | 
| 713 | 
            +
                          # XXX this is here for backward compatibility with grit < 2.3.0
         | 
| 714 | 
            +
                          # relative alternate objects paths are expanded relative to the
         | 
| 715 | 
            +
                          # objects directory, not the git repository directory.
         | 
| 716 | 
            +
                          yield File.expand_path(File.join(@git_dir, path))
         | 
| 717 | 
            +
                        else
         | 
| 718 | 
            +
                          yield path
         | 
| 719 | 
            +
                        end
         | 
| 720 | 
            +
                      end
         | 
| 721 | 
            +
                    end
         | 
| 722 | 
            +
             | 
| 723 | 
            +
                    def load_alternate_loose(pathname)
         | 
| 724 | 
            +
                      # load alternate loose, too
         | 
| 725 | 
            +
                      each_alternate_path pathname do |path|
         | 
| 726 | 
            +
                        next if @loaded.include?(path)
         | 
| 727 | 
            +
                        next if !File.exist?(path)
         | 
| 728 | 
            +
                        load_loose(path)
         | 
| 729 | 
            +
                        load_alternate_loose(path)
         | 
| 730 | 
            +
                      end
         | 
| 731 | 
            +
                    end
         | 
| 732 | 
            +
             | 
| 733 | 
            +
                    def load_loose(path)
         | 
| 734 | 
            +
                      @loaded << path
         | 
| 735 | 
            +
                      return if !File.exists?(path)
         | 
| 736 | 
            +
                      @loose << Grit::GitRuby::Internal::LooseStorage.new(path)
         | 
| 737 | 
            +
                    end
         | 
| 738 | 
            +
             | 
| 739 | 
            +
                    def initpacks
         | 
| 740 | 
            +
                      close
         | 
| 741 | 
            +
                      @loaded_packs = []
         | 
| 742 | 
            +
                      @packs = []
         | 
| 743 | 
            +
                      load_packs(git_path("objects/pack"))
         | 
| 744 | 
            +
                      load_alternate_packs(git_path('objects'))
         | 
| 745 | 
            +
                      @packs
         | 
| 746 | 
            +
                    end
         | 
| 747 | 
            +
             | 
| 748 | 
            +
                    def load_alternate_packs(pathname)
         | 
| 749 | 
            +
                      each_alternate_path pathname do |path|
         | 
| 750 | 
            +
                        full_pack = File.join(path, 'pack')
         | 
| 751 | 
            +
                        next if @loaded_packs.include?(full_pack)
         | 
| 752 | 
            +
                        load_packs(full_pack)
         | 
| 753 | 
            +
                        load_alternate_packs(path)
         | 
| 754 | 
            +
                      end
         | 
| 755 | 
            +
                    end
         | 
| 756 | 
            +
             | 
| 757 | 
            +
                    def load_packs(path)
         | 
| 758 | 
            +
                      @loaded_packs << path
         | 
| 759 | 
            +
                      return if !File.exists?(path)
         | 
| 760 | 
            +
                       Dir.open(path) do |dir|
         | 
| 761 | 
            +
                        dir.each do |entry|
         | 
| 762 | 
            +
                          next if !(entry =~ /\.pack$/i)
         | 
| 763 | 
            +
                          pack = Grit::GitRuby::Internal::PackStorage.new(File.join(path,entry))
         | 
| 764 | 
            +
                          if @options[:map_packfile]
         | 
| 765 | 
            +
                            pack.cache_objects
         | 
| 766 | 
            +
                          end
         | 
| 767 | 
            +
                          @packs << pack
         | 
| 768 | 
            +
                        end
         | 
| 769 | 
            +
                      end
         | 
| 770 | 
            +
                    end
         | 
| 771 | 
            +
             | 
| 772 | 
            +
                end
         | 
| 773 | 
            +
             | 
| 774 | 
            +
              end
         | 
| 775 | 
            +
            end
         |