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
    
        data/lib/grit/ruby1.9.rb
    ADDED
    
    
    
        data/lib/grit/status.rb
    ADDED
    
    | @@ -0,0 +1,153 @@ | |
| 1 | 
            +
            module Grit
         | 
| 2 | 
            +
             | 
| 3 | 
            +
              class Status
         | 
| 4 | 
            +
                include Enumerable
         | 
| 5 | 
            +
             | 
| 6 | 
            +
                attr_reader :files
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                @base = nil
         | 
| 9 | 
            +
                @files = nil
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                def initialize(base)
         | 
| 12 | 
            +
                  @base = base
         | 
| 13 | 
            +
                  construct_status
         | 
| 14 | 
            +
                end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                def changed
         | 
| 17 | 
            +
                  @files.select { |k, f| f.type == 'M' }
         | 
| 18 | 
            +
                end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                def added
         | 
| 21 | 
            +
                  @files.select { |k, f| f.type == 'A' }
         | 
| 22 | 
            +
                end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                def deleted
         | 
| 25 | 
            +
                  @files.select { |k, f| f.type == 'D' }
         | 
| 26 | 
            +
                end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                def untracked
         | 
| 29 | 
            +
                  @files.select { |k, f| f.untracked }
         | 
| 30 | 
            +
                end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                def pretty
         | 
| 33 | 
            +
                  out = ''
         | 
| 34 | 
            +
                  self.each do |file|
         | 
| 35 | 
            +
                    out << file.path
         | 
| 36 | 
            +
                    out << "\n\tsha(r) " + file.sha_repo.to_s + ' ' + file.mode_repo.to_s
         | 
| 37 | 
            +
                    out << "\n\tsha(i) " + file.sha_index.to_s + ' ' + file.mode_index.to_s
         | 
| 38 | 
            +
                    out << "\n\ttype   " + file.type.to_s
         | 
| 39 | 
            +
                    out << "\n\tstage  " + file.stage.to_s
         | 
| 40 | 
            +
                    out << "\n\tuntrac " + file.untracked.to_s
         | 
| 41 | 
            +
                    out << "\n"
         | 
| 42 | 
            +
                  end
         | 
| 43 | 
            +
                  out << "\n"
         | 
| 44 | 
            +
                  out
         | 
| 45 | 
            +
                end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                # enumerable method
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                def [](file)
         | 
| 50 | 
            +
                  @files[file]
         | 
| 51 | 
            +
                end
         | 
| 52 | 
            +
             | 
| 53 | 
            +
                def each
         | 
| 54 | 
            +
                  @files.each do |k, file|
         | 
| 55 | 
            +
                    yield file
         | 
| 56 | 
            +
                  end
         | 
| 57 | 
            +
                end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                class StatusFile
         | 
| 60 | 
            +
                  attr_accessor :path, :type, :stage, :untracked
         | 
| 61 | 
            +
                  attr_accessor :mode_index, :mode_repo
         | 
| 62 | 
            +
                  attr_accessor :sha_index, :sha_repo
         | 
| 63 | 
            +
             | 
| 64 | 
            +
                  @base = nil
         | 
| 65 | 
            +
             | 
| 66 | 
            +
                  def initialize(base, hash)
         | 
| 67 | 
            +
                    @base = base
         | 
| 68 | 
            +
                    @path = hash[:path]
         | 
| 69 | 
            +
                    @type = hash[:type]
         | 
| 70 | 
            +
                    @stage = hash[:stage]
         | 
| 71 | 
            +
                    @mode_index = hash[:mode_index]
         | 
| 72 | 
            +
                    @mode_repo = hash[:mode_repo]
         | 
| 73 | 
            +
                    @sha_index = hash[:sha_index]
         | 
| 74 | 
            +
                    @sha_repo = hash[:sha_repo]
         | 
| 75 | 
            +
                    @untracked = hash[:untracked]
         | 
| 76 | 
            +
                  end
         | 
| 77 | 
            +
             | 
| 78 | 
            +
                  def blob(type = :index)
         | 
| 79 | 
            +
                    if type == :repo
         | 
| 80 | 
            +
                      @base.object(@sha_repo)
         | 
| 81 | 
            +
                    else
         | 
| 82 | 
            +
                      @base.object(@sha_index) rescue @base.object(@sha_repo)
         | 
| 83 | 
            +
                    end
         | 
| 84 | 
            +
                  end
         | 
| 85 | 
            +
             | 
| 86 | 
            +
                end
         | 
| 87 | 
            +
             | 
| 88 | 
            +
                private
         | 
| 89 | 
            +
             | 
| 90 | 
            +
                  def construct_status
         | 
| 91 | 
            +
                    @files = ls_files
         | 
| 92 | 
            +
             | 
| 93 | 
            +
                    Dir.chdir(@base.working_dir) do
         | 
| 94 | 
            +
                      # find untracked in working dir
         | 
| 95 | 
            +
                      Dir.glob('**/*') do |file|
         | 
| 96 | 
            +
                        if !@files[file]
         | 
| 97 | 
            +
                          @files[file] = {:path => file, :untracked => true} if !File.directory?(file)
         | 
| 98 | 
            +
                        end
         | 
| 99 | 
            +
                      end
         | 
| 100 | 
            +
             | 
| 101 | 
            +
                      # find modified in tree
         | 
| 102 | 
            +
                     diff_files.each do |path, data|
         | 
| 103 | 
            +
                        @files[path] ? @files[path].merge!(data) : @files[path] = data
         | 
| 104 | 
            +
                      end
         | 
| 105 | 
            +
             | 
| 106 | 
            +
                      # find added but not committed - new files
         | 
| 107 | 
            +
                      diff_index('HEAD').each do |path, data|
         | 
| 108 | 
            +
                        @files[path] ? @files[path].merge!(data) : @files[path] = data
         | 
| 109 | 
            +
                      end
         | 
| 110 | 
            +
             | 
| 111 | 
            +
                      @files.each do |k, file_hash|
         | 
| 112 | 
            +
                        @files[k] = StatusFile.new(@base, file_hash)
         | 
| 113 | 
            +
                      end
         | 
| 114 | 
            +
                    end
         | 
| 115 | 
            +
                  end
         | 
| 116 | 
            +
             | 
| 117 | 
            +
                  # compares the index and the working directory
         | 
| 118 | 
            +
                  def diff_files
         | 
| 119 | 
            +
                    hsh = {}
         | 
| 120 | 
            +
                    @base.git.diff_files.split("\n").each do |line|
         | 
| 121 | 
            +
                      (info, file) = line.split("\t")
         | 
| 122 | 
            +
                      (mode_src, mode_dest, sha_src, sha_dest, type) = info.split
         | 
| 123 | 
            +
                      hsh[file] = {:path => file, :mode_file => mode_src.to_s[1, 7], :mode_index => mode_dest,
         | 
| 124 | 
            +
                                    :sha_file => sha_src, :sha_index => sha_dest, :type => type}
         | 
| 125 | 
            +
                    end
         | 
| 126 | 
            +
                    hsh
         | 
| 127 | 
            +
                  end
         | 
| 128 | 
            +
             | 
| 129 | 
            +
                  # compares the index and the repository
         | 
| 130 | 
            +
                  def diff_index(treeish)
         | 
| 131 | 
            +
                    hsh = {}
         | 
| 132 | 
            +
                    @base.git.diff_index({}, treeish).split("\n").each do |line|
         | 
| 133 | 
            +
                      (info, file) = line.split("\t")
         | 
| 134 | 
            +
                      (mode_src, mode_dest, sha_src, sha_dest, type) = info.split
         | 
| 135 | 
            +
                      hsh[file] = {:path => file, :mode_repo => mode_src.to_s[1, 7], :mode_index => mode_dest,
         | 
| 136 | 
            +
                                    :sha_repo => sha_src, :sha_index => sha_dest, :type => type}
         | 
| 137 | 
            +
                    end
         | 
| 138 | 
            +
                    hsh
         | 
| 139 | 
            +
                  end
         | 
| 140 | 
            +
             | 
| 141 | 
            +
                  def ls_files
         | 
| 142 | 
            +
                    hsh = {}
         | 
| 143 | 
            +
                    lines = @base.git.ls_files({:stage => true})
         | 
| 144 | 
            +
                    lines.split("\n").each do |line|
         | 
| 145 | 
            +
                      (info, file) = line.split("\t")
         | 
| 146 | 
            +
                      (mode, sha, stage) = info.split
         | 
| 147 | 
            +
                      hsh[file] = {:path => file, :mode_index => mode, :sha_index => sha, :stage => stage}
         | 
| 148 | 
            +
                    end
         | 
| 149 | 
            +
                    hsh
         | 
| 150 | 
            +
                  end
         | 
| 151 | 
            +
              end
         | 
| 152 | 
            +
             | 
| 153 | 
            +
            end
         | 
| @@ -0,0 +1,88 @@ | |
| 1 | 
            +
            module Grit
         | 
| 2 | 
            +
             | 
| 3 | 
            +
              class Submodule
         | 
| 4 | 
            +
                attr_reader :id
         | 
| 5 | 
            +
                attr_reader :mode
         | 
| 6 | 
            +
                attr_reader :name
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                # Create a Submodule containing just the specified attributes
         | 
| 9 | 
            +
                #   +repo+ is the Repo
         | 
| 10 | 
            +
                #   +atts+ is a Hash of instance variable data
         | 
| 11 | 
            +
                #
         | 
| 12 | 
            +
                # Returns Grit::Submodule (unbaked)
         | 
| 13 | 
            +
                def self.create(repo, atts)
         | 
| 14 | 
            +
                  self.allocate.create_initialize(repo, atts)
         | 
| 15 | 
            +
                end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                # Initializer for Submodule.create
         | 
| 18 | 
            +
                #   +repo+ is the Repo
         | 
| 19 | 
            +
                #   +atts+ is a Hash of instance variable data
         | 
| 20 | 
            +
                #
         | 
| 21 | 
            +
                # Returns Grit::Submodule
         | 
| 22 | 
            +
                def create_initialize(repo, atts)
         | 
| 23 | 
            +
                  @repo = repo
         | 
| 24 | 
            +
                  atts.each do |k, v|
         | 
| 25 | 
            +
                    instance_variable_set("@#{k}".to_sym, v)
         | 
| 26 | 
            +
                  end
         | 
| 27 | 
            +
                  self
         | 
| 28 | 
            +
                end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                # The url of this submodule
         | 
| 31 | 
            +
                #   +ref+ is the committish that should be used to look up the url
         | 
| 32 | 
            +
                #
         | 
| 33 | 
            +
                # Returns String
         | 
| 34 | 
            +
                def url(ref)
         | 
| 35 | 
            +
                  config = self.class.config(@repo, ref)
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                  lookup = config.keys.inject({}) do |acc, key|
         | 
| 38 | 
            +
                    id = config[key]['id']
         | 
| 39 | 
            +
                    acc[id] = config[key]['url']
         | 
| 40 | 
            +
                    acc
         | 
| 41 | 
            +
                  end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                  lookup[@id]
         | 
| 44 | 
            +
                end
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                # The configuration information for the given +repo+
         | 
| 47 | 
            +
                #   +repo+ is the Repo
         | 
| 48 | 
            +
                #   +ref+ is the committish (defaults to 'master')
         | 
| 49 | 
            +
                #
         | 
| 50 | 
            +
                # Returns a Hash of { <path:String> => { 'url' => <url:String>, 'id' => <id:String> } }
         | 
| 51 | 
            +
                # Returns {} if no .gitmodules file was found
         | 
| 52 | 
            +
                def self.config(repo, ref = "master")
         | 
| 53 | 
            +
                  commit = repo.commit(ref)
         | 
| 54 | 
            +
                  blob = commit.tree/'.gitmodules'
         | 
| 55 | 
            +
                  return {} unless blob
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                  lines = blob.data.gsub(/\r\n?/, "\n" ).split("\n")
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                  config = {}
         | 
| 60 | 
            +
                  current = nil
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                  lines.each do |line|
         | 
| 63 | 
            +
                    if line =~ /^\[submodule "(.+)"\]$/
         | 
| 64 | 
            +
                      current = $1
         | 
| 65 | 
            +
                      config[current] = {}
         | 
| 66 | 
            +
                      config[current]['id'] = (commit.tree/current).id
         | 
| 67 | 
            +
                    elsif line =~ /^\t(\w+) = (.+)$/
         | 
| 68 | 
            +
                      config[current][$1] = $2
         | 
| 69 | 
            +
                      config[current]['id'] = (commit.tree/$2).id if $1 == 'path'
         | 
| 70 | 
            +
                    else
         | 
| 71 | 
            +
                      # ignore
         | 
| 72 | 
            +
                    end
         | 
| 73 | 
            +
                  end
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                  config
         | 
| 76 | 
            +
                end
         | 
| 77 | 
            +
             | 
| 78 | 
            +
                def basename
         | 
| 79 | 
            +
                  File.basename(name)
         | 
| 80 | 
            +
                end
         | 
| 81 | 
            +
             | 
| 82 | 
            +
                # Pretty object inspection
         | 
| 83 | 
            +
                def inspect
         | 
| 84 | 
            +
                  %Q{#<Grit::Submodule "#{@id}">}
         | 
| 85 | 
            +
                end
         | 
| 86 | 
            +
              end # Submodule
         | 
| 87 | 
            +
             | 
| 88 | 
            +
            end # Grit
         | 
    
        data/lib/grit/tag.rb
    ADDED
    
    | @@ -0,0 +1,102 @@ | |
| 1 | 
            +
            module Grit
         | 
| 2 | 
            +
             | 
| 3 | 
            +
              class Tag < Ref
         | 
| 4 | 
            +
                extend Lazy
         | 
| 5 | 
            +
             | 
| 6 | 
            +
                lazy_reader :message
         | 
| 7 | 
            +
                lazy_reader :tagger
         | 
| 8 | 
            +
                lazy_reader :tag_date
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                def self.find_all(repo, options = {})
         | 
| 11 | 
            +
                  refs = repo.git.refs(options, prefix)
         | 
| 12 | 
            +
                  refs.split("\n").map do |ref|
         | 
| 13 | 
            +
                    name, id = *ref.split(' ')
         | 
| 14 | 
            +
                    sha = repo.git.commit_from_sha(id)
         | 
| 15 | 
            +
                    raise "Unknown object type." if sha == ''
         | 
| 16 | 
            +
                    commit = Commit.create(repo, :id => sha)
         | 
| 17 | 
            +
                    new(name, commit)
         | 
| 18 | 
            +
                  end
         | 
| 19 | 
            +
                end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                # Writes a new tag object from a hash
         | 
| 22 | 
            +
                #  +repo+ is a Grit repo
         | 
| 23 | 
            +
                #  +hash+ is the hash of tag values
         | 
| 24 | 
            +
                #
         | 
| 25 | 
            +
                # Returns a hash with +sha+ and +size+ of the created object
         | 
| 26 | 
            +
                def self.create_tag_object(repo, hash, default_actor = nil)
         | 
| 27 | 
            +
                  tagger = hash[:tagger]
         | 
| 28 | 
            +
                  if !tagger
         | 
| 29 | 
            +
                    tagger = default_actor ? default_actor : Actor.new("none", "none@none")
         | 
| 30 | 
            +
                    tagger_date = Time.now
         | 
| 31 | 
            +
                  else
         | 
| 32 | 
            +
                    tagger_date = tagger[:date] ? Time.parse(tagger[:date]) : Time.now
         | 
| 33 | 
            +
                    tagger = Actor.new(tagger[:name], tagger[:email])
         | 
| 34 | 
            +
                  end
         | 
| 35 | 
            +
                  data = []
         | 
| 36 | 
            +
                  data << "object #{hash[:object]}"
         | 
| 37 | 
            +
                  data << "type #{hash[:type]}"
         | 
| 38 | 
            +
                  data << "tag #{hash[:tag]}"
         | 
| 39 | 
            +
                  data << "tagger #{tagger.output(tagger_date)}"
         | 
| 40 | 
            +
                  data << ""
         | 
| 41 | 
            +
                  data << hash[:message]
         | 
| 42 | 
            +
                  data = data.join("\n")
         | 
| 43 | 
            +
                  sha = repo.git.put_raw_object(data, 'tag')
         | 
| 44 | 
            +
                  { :sha => sha, :size => data.size }
         | 
| 45 | 
            +
                end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                # Parses the results from `cat-file -p`
         | 
| 48 | 
            +
                #
         | 
| 49 | 
            +
                # data - String tag object data.  Example:
         | 
| 50 | 
            +
                #          object 7bcc0ee821cdd133d8a53e8e7173a334fef448aa
         | 
| 51 | 
            +
                #          type commit
         | 
| 52 | 
            +
                #          tag v0.7.0
         | 
| 53 | 
            +
                #          tagger USER <EMAIL> DATE
         | 
| 54 | 
            +
                #          
         | 
| 55 | 
            +
                #          v0.7.0
         | 
| 56 | 
            +
                #
         | 
| 57 | 
            +
                # Returns parsed Hash.  Example: 
         | 
| 58 | 
            +
                #   {:message => "...", :tagger => "bob", :tag_date => ...}
         | 
| 59 | 
            +
                def self.parse_tag_data(data)
         | 
| 60 | 
            +
                  return unless data =~ /^object/
         | 
| 61 | 
            +
                  parsed = {}
         | 
| 62 | 
            +
                  lines  = data.split("\n")
         | 
| 63 | 
            +
                  parsed[:object] = lines.shift.sub(/^object /, '')
         | 
| 64 | 
            +
                  parsed[:type] = lines.shift.sub(/^type /, '')
         | 
| 65 | 
            +
                  parsed[:tag] = lines.shift.sub(/^tag /, '')
         | 
| 66 | 
            +
                  author_line = lines.shift
         | 
| 67 | 
            +
                  parsed[:tagger], parsed[:tag_date] = Commit.actor(author_line)
         | 
| 68 | 
            +
                  if !parsed[:tagger] || !parsed[:tagger].name
         | 
| 69 | 
            +
                    parsed[:tag_date] ||= Time.utc(1970)
         | 
| 70 | 
            +
                    parsed[:tagger]     = Actor.from_string(author_line.sub(/^tagger /, ''))
         | 
| 71 | 
            +
                  end
         | 
| 72 | 
            +
                  lines.shift # blank line
         | 
| 73 | 
            +
                  parsed[:message] = []
         | 
| 74 | 
            +
                  while lines.first && lines.first !~ /-----BEGIN PGP SIGNATURE-----/
         | 
| 75 | 
            +
                    parsed[:message] << lines.shift
         | 
| 76 | 
            +
                  end
         | 
| 77 | 
            +
                  parsed[:message] = parsed[:message] * "\n"
         | 
| 78 | 
            +
                  parsed[:pgp] = []
         | 
| 79 | 
            +
                  while lines.first
         | 
| 80 | 
            +
                    parsed[:pgp] << lines.shift
         | 
| 81 | 
            +
                  end
         | 
| 82 | 
            +
                  parsed[:pgp] = parsed[:pgp] * "\n"
         | 
| 83 | 
            +
                  parsed
         | 
| 84 | 
            +
                end
         | 
| 85 | 
            +
             | 
| 86 | 
            +
                def lazy_source
         | 
| 87 | 
            +
                  data         = commit.repo.git.cat_ref({:p => true}, name)
         | 
| 88 | 
            +
                  @message     = commit.short_message
         | 
| 89 | 
            +
                  @tagger      = commit.author
         | 
| 90 | 
            +
                  @tag_date    = commit.authored_date
         | 
| 91 | 
            +
                  return self if data.empty?
         | 
| 92 | 
            +
             | 
| 93 | 
            +
                  if parsed = self.class.parse_tag_data(data)
         | 
| 94 | 
            +
                    @message  = parsed[:message]
         | 
| 95 | 
            +
                    @tagger   = parsed[:tagger]
         | 
| 96 | 
            +
                    @tag_date = parsed[:tag_date]
         | 
| 97 | 
            +
                  end
         | 
| 98 | 
            +
                  self
         | 
| 99 | 
            +
                end
         | 
| 100 | 
            +
              end
         | 
| 101 | 
            +
             | 
| 102 | 
            +
            end
         | 
    
        data/lib/grit/tree.rb
    ADDED
    
    | @@ -0,0 +1,125 @@ | |
| 1 | 
            +
            module Grit
         | 
| 2 | 
            +
             | 
| 3 | 
            +
              class Tree
         | 
| 4 | 
            +
                extend Lazy
         | 
| 5 | 
            +
             | 
| 6 | 
            +
                lazy_reader :contents
         | 
| 7 | 
            +
                attr_reader :id
         | 
| 8 | 
            +
                attr_reader :mode
         | 
| 9 | 
            +
                attr_reader :name
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                # Construct the contents of the tree
         | 
| 12 | 
            +
                #   +repo+ is the Repo
         | 
| 13 | 
            +
                #   +treeish+ is the reference
         | 
| 14 | 
            +
                #   +paths+ is an optional Array of directory paths to restrict the tree
         | 
| 15 | 
            +
                #
         | 
| 16 | 
            +
                # Returns Grit::Tree (baked)
         | 
| 17 | 
            +
                def self.construct(repo, treeish, paths = [])
         | 
| 18 | 
            +
                  output = repo.git.ls_tree({}, treeish, *paths)
         | 
| 19 | 
            +
                  self.allocate.construct_initialize(repo, treeish, output)
         | 
| 20 | 
            +
                end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                def construct_initialize(repo, id, text)
         | 
| 23 | 
            +
                  @repo = repo
         | 
| 24 | 
            +
                  @id = id
         | 
| 25 | 
            +
                  @contents = []
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                  text.split("\n").each do |line|
         | 
| 28 | 
            +
                    @contents << content_from_string(repo, line)
         | 
| 29 | 
            +
                  end
         | 
| 30 | 
            +
                  @contents.compact!
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                  self
         | 
| 33 | 
            +
                end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                def lazy_source
         | 
| 36 | 
            +
                  Tree.construct(@repo, @id, [])
         | 
| 37 | 
            +
                end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                # Create an unbaked Tree containing just the specified attributes
         | 
| 40 | 
            +
                #   +repo+ is the Repo
         | 
| 41 | 
            +
                #   +atts+ is a Hash of instance variable data
         | 
| 42 | 
            +
                #
         | 
| 43 | 
            +
                # Returns Grit::Tree (unbaked)
         | 
| 44 | 
            +
                def self.create(repo, atts)
         | 
| 45 | 
            +
                  self.allocate.create_initialize(repo, atts)
         | 
| 46 | 
            +
                end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                # Initializer for Tree.create
         | 
| 49 | 
            +
                #   +repo+ is the Repo
         | 
| 50 | 
            +
                #   +atts+ is a Hash of instance variable data
         | 
| 51 | 
            +
                #
         | 
| 52 | 
            +
                # Returns Grit::Tree (unbaked)
         | 
| 53 | 
            +
                def create_initialize(repo, atts)
         | 
| 54 | 
            +
                  @repo = repo
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                  atts.each do |k, v|
         | 
| 57 | 
            +
                    instance_variable_set("@#{k}", v)
         | 
| 58 | 
            +
                  end
         | 
| 59 | 
            +
                  self
         | 
| 60 | 
            +
                end
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                # Parse a content item and create the appropriate object
         | 
| 63 | 
            +
                #   +repo+ is the Repo
         | 
| 64 | 
            +
                #   +text+ is the single line containing the items data in `git ls-tree` format
         | 
| 65 | 
            +
                #
         | 
| 66 | 
            +
                # Returns Grit::Blob or Grit::Tree
         | 
| 67 | 
            +
                def content_from_string(repo, text)
         | 
| 68 | 
            +
                  mode, type, id, name = text.split(/ |\t/, 4)
         | 
| 69 | 
            +
                  case type
         | 
| 70 | 
            +
                    when "tree"
         | 
| 71 | 
            +
                      Tree.create(repo, :id => id, :mode => mode, :name => name)
         | 
| 72 | 
            +
                    when "blob"
         | 
| 73 | 
            +
                      Blob.create(repo, :id => id, :mode => mode, :name => name)
         | 
| 74 | 
            +
                    when "link"
         | 
| 75 | 
            +
                      Blob.create(repo, :id => id, :mode => mode, :name => name)
         | 
| 76 | 
            +
                    when "commit"
         | 
| 77 | 
            +
                      Submodule.create(repo, :id => id, :mode => mode, :name => name)
         | 
| 78 | 
            +
                    else
         | 
| 79 | 
            +
                      raise Grit::InvalidObjectType, type
         | 
| 80 | 
            +
                  end
         | 
| 81 | 
            +
                end
         | 
| 82 | 
            +
             | 
| 83 | 
            +
                # Find the named object in this tree's contents
         | 
| 84 | 
            +
                #
         | 
| 85 | 
            +
                # Examples
         | 
| 86 | 
            +
                #   Repo.new('/path/to/grit').tree/'lib'
         | 
| 87 | 
            +
                #   # => #<Grit::Tree "6cc23ee138be09ff8c28b07162720018b244e95e">
         | 
| 88 | 
            +
                #   Repo.new('/path/to/grit').tree/'README.txt'
         | 
| 89 | 
            +
                #   # => #<Grit::Blob "8b1e02c0fb554eed2ce2ef737a68bb369d7527df">
         | 
| 90 | 
            +
                #
         | 
| 91 | 
            +
                # Returns Grit::Blob or Grit::Tree or nil if not found
         | 
| 92 | 
            +
                def /(file)
         | 
| 93 | 
            +
                  if file =~ /\//
         | 
| 94 | 
            +
                    file.split("/").inject(self) { |acc, x| acc/x } rescue nil
         | 
| 95 | 
            +
                  else
         | 
| 96 | 
            +
                    self.contents.find { |c| c.name == file }
         | 
| 97 | 
            +
                  end
         | 
| 98 | 
            +
                end
         | 
| 99 | 
            +
             | 
| 100 | 
            +
                def basename
         | 
| 101 | 
            +
                  File.basename(name)
         | 
| 102 | 
            +
                end
         | 
| 103 | 
            +
             | 
| 104 | 
            +
                # Pretty object inspection
         | 
| 105 | 
            +
                def inspect
         | 
| 106 | 
            +
                  %Q{#<Grit::Tree "#{@id}">}
         | 
| 107 | 
            +
                end
         | 
| 108 | 
            +
             | 
| 109 | 
            +
                # Find only Tree objects from contents
         | 
| 110 | 
            +
                def trees
         | 
| 111 | 
            +
                  contents.select {|v| v.kind_of? Tree}
         | 
| 112 | 
            +
                end
         | 
| 113 | 
            +
             | 
| 114 | 
            +
                # Find only Blob objects from contents
         | 
| 115 | 
            +
                def blobs
         | 
| 116 | 
            +
                  contents.select {|v| v.kind_of? Blob}
         | 
| 117 | 
            +
                end
         | 
| 118 | 
            +
             | 
| 119 | 
            +
                # Compares trees by name
         | 
| 120 | 
            +
                def <=>(other)
         | 
| 121 | 
            +
                  name <=> other.name
         | 
| 122 | 
            +
                end
         | 
| 123 | 
            +
              end # Tree
         | 
| 124 | 
            +
             | 
| 125 | 
            +
            end # Grit
         |