<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>lib/grit/git-ruby/git_object.rb</filename>
    </added>
    <added>
      <filename>test/dot_git/packed-refs</filename>
    </added>
    <added>
      <filename>test/dot_git/refs/heads/nonpack</filename>
    </added>
    <added>
      <filename>test/test_raw.rb</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -2,3 +2,4 @@ coverage
 pkg/*.tgz
 doc
 test/specifics.rb
+test.rb</diff>
      <filename>.gitignore</filename>
    </modified>
    <modified>
      <diff>@@ -36,7 +36,7 @@ module Grit
     end
     
     def id_abbrev
-      @id_abbrev ||= @repo.git.rev_parse({:short =&gt; true}, self.id).chomp
+      @id_abbrev ||= @repo.git.rev_parse({}, self.id).chomp[0, 7]
     end
     
     # Create an unbaked Commit containing just the specified attributes
@@ -84,7 +84,7 @@ module Grit
     # Returns Grit::Commit[] (baked)
     def self.find_all(repo, ref, options = {})
       allowed_options = [:max_count, :skip, :since]
-      
+          
       default_options = {:pretty =&gt; &quot;raw&quot;}
       actual_options = default_options.merge(options)
       
@@ -93,8 +93,10 @@ module Grit
       else
         output = repo.git.rev_list(actual_options.merge(:all =&gt; true))
       end
-      
+            
       self.list_from_string(repo, output)
+    rescue Grit::GitRuby::Repository::NoSuchShaFound
+      []
     end
     
     # Parse out commit information into an array of baked Commit objects
@@ -102,6 +104,10 @@ module Grit
     #   +text+ is the text output from the git command (raw format)
     #
     # Returns Grit::Commit[] (baked)
+    #
+    # really should re-write this to be more accepting of non-standard commit messages
+    # - it broke when 'encoding' was introduced - not sure what else might show up
+    #
     def self.list_from_string(repo, text)
       lines = text.split(&quot;\n&quot;)
       
@@ -117,6 +123,9 @@ module Grit
         author, authored_date = self.actor(lines.shift)
         committer, committed_date = self.actor(lines.shift)
         
+        # not doing anything with this yet, but it's sometimes there
+        encoding = lines.shift.split.last if lines.first =~ /^encoding/
+        
         lines.shift
         
         message_lines = []</diff>
      <filename>lib/grit/commit.rb</filename>
    </modified>
    <modified>
      <diff>@@ -16,7 +16,7 @@ module Grit
       elsif options[:s]
         file_size(ref)
       elsif options[:p]
-        ruby_git.cat_file(ref)
+        try_run { ruby_git.cat_file(ref) }
       end
     end
     
@@ -28,7 +28,7 @@ module Grit
 
     # git diff --full-index 'ec037431382e83c3e95d4f2b3d145afbac8ea55d' 'f1ec1aea10986159456846b8a05615b87828d6c6'
     def diff(options, sha1, sha2)
-      ruby_git.diff(sha1, sha2, options)
+      try_run { ruby_git.diff(sha1, sha2, options) }
     end
     
     def rev_list(options, ref = 'master')
@@ -44,7 +44,12 @@ module Grit
           return method_missing('rev-list', options, ref) 
         end
       else
-        return ruby_git.rev_list(rev_parse({}, ref), options)      
+        aref = rev_parse({}, ref)
+        if aref.is_a? Array
+          return method_missing('rev-list', options, ref) 
+        else
+          return try_run { ruby_git.rev_list(aref, options) }
+        end
       end
     end
     
@@ -67,19 +72,29 @@ module Grit
       head = File.join(@git_dir, 'refs', 'tags', string)
       return File.read(head).chomp if File.file?(head)
       
-      ## !! check packed-refs file, too !! 
+      ## check packed-refs file, too 
+      packref = File.join(@git_dir, 'packed-refs')
+      if File.file?(packref)
+        File.readlines(packref).each do |line|
+          if m = /^(\w{40}) (.*?)$/.match(line)
+            next if !Regexp.new(string + '$').match(m[2])
+            return m[1].chomp
+          end
+        end
+      end
+      
       ## !! more - partials and such !!
       
       # revert to calling git - grr
-      return method_missing('rev-parse', {}, string)
+      return method_missing('rev-parse', {}, string).chomp
     end
     
     def file_size(ref)
-      ruby_git.cat_file_size(ref).to_s
+      try_run { ruby_git.cat_file_size(ref).to_s }
     end
     
     def file_type(ref)
-      ruby_git.cat_file_type(ref)
+      try_run { ruby_git.cat_file_type(ref).to_s }
     end
     
     def blame_tree(commit, path = nil)
@@ -101,6 +116,26 @@ module Grit
     
     private
     
+      def try_run
+        ret = ''
+        Timeout.timeout(self.class.git_timeout) do
+          ret = yield
+        end
+        @bytes_read += ret.size
+
+        #if @bytes_read &gt; 5242880 # 5.megabytes
+        #  bytes = @bytes_read
+        #  @bytes_read = 0
+        #  raise Grit::Git::GitTimeout.new(command, bytes) 
+        #end
+
+        ret
+      rescue Timeout::Error =&gt; e
+        bytes = @bytes_read
+        @bytes_read = 0
+        raise Grit::Git::GitTimeout.new(command, bytes)
+      end
+    
       def looking_for(commit, path = nil)
         tree_sha = ruby_git.get_subtree(rev_parse({}, commit), path)
 </diff>
      <filename>lib/grit/git-ruby.rb</filename>
    </modified>
    <modified>
      <diff>@@ -14,11 +14,13 @@
 module Grit
   module GitRuby
 
-  # class for author/committer/tagger lines
   class FileIndex
     
     class IndexFileNotFound &lt; StandardError
     end
+
+    class UnsupportedRef &lt; StandardError
+    end
     
     attr_reader :files
     
@@ -45,6 +47,8 @@ module Grit
     end
     
     def commits_from(commit_sha)
+      raise UnsupportedRef if commit_sha.is_a? Array
+      
       already = {}
       final = []
       left_to_do = [commit_sha]
@@ -61,7 +65,11 @@ module Grit
         end if commit
       end
 
-      final
+      sort_commits(final)
+    end
+    
+    def sort_commits(sha_array)
+      sha_array.sort { |a, b| @commit_order[b] &lt;=&gt; @commit_order[a] }
     end
     
     # returns files changed at commit sha
@@ -109,6 +117,7 @@ module Grit
         f = File.new(@index_file)
         @sha_count = 0
         @commit_index = {}
+        @commit_order = {}
         @all_files = {}
         while line = f.gets
           if /^(\w{40})/.match(line)
@@ -116,6 +125,7 @@ module Grit
             current_sha = shas.shift.first
             parents = shas.map { |sha| sha.first }
             @commit_index[current_sha] = {:files =&gt; [], :parents =&gt; parents }
+            @commit_order[current_sha] = @sha_count
             @sha_count += 1
           else
             file_name = line.chomp</diff>
      <filename>lib/grit/git-ruby/file_index.rb</filename>
    </modified>
    <modified>
      <diff>@@ -11,7 +11,7 @@
 require 'grit/git-ruby/internal/raw_object'
 require 'grit/git-ruby/internal/pack'
 require 'grit/git-ruby/internal/loose'
-require 'grit/git-ruby/object'
+require 'grit/git-ruby/git_object'
 
 require 'rubygems'
 require 'diff/lcs'
@@ -28,6 +28,9 @@ module Grit
       
       class NoSuchShaFound &lt; StandardError
       end
+
+      class NoSuchPath &lt; StandardError
+      end
       
       attr_accessor :git_dir, :options
       
@@ -96,7 +99,7 @@ module Grit
       def get_object_by_sha1(sha1)
         r = get_raw_object_by_sha1(sha1)
         return nil if !r
-        Object.from_raw(r)
+        GitObject.from_raw(r)
       end
       
       # writes a raw object into the git repo
@@ -149,7 +152,7 @@ module Grit
       # ['blob']['FILENAME'] = {:mode =&gt; '100644', :sha =&gt; SHA}
       # ['tree']['DIRNAME'] = {:mode =&gt; '040000', :sha =&gt; SHA}
       def list_tree(sha)        
-        data = {'blob' =&gt; {}, 'tree' =&gt; {}}
+        data = {'blob' =&gt; {}, 'tree' =&gt; {}, 'link' =&gt; {}, 'commit' =&gt; {}}
         get_object_by_sha1(sha).entry.each do |e|
           data[e.format_type][e.name] = {:mode =&gt; e.format_mode, :sha =&gt; e.sha1}
         end 
@@ -176,6 +179,9 @@ module Grit
         o = get_raw_object_by_sha1(sha)
         if o.type == :commit
           tree = cat_file(get_object_by_sha1(sha).tree)
+        elsif o.type == :tag
+          commit_sha = get_object_by_sha1(sha).object
+          tree = cat_file(get_object_by_sha1(commit_sha).tree)
         else
           tree = cat_file(sha)
         end
@@ -192,6 +198,7 @@ module Grit
           if (last == '/') &amp;&amp; (paths.size == 1)
             append = append ? File.join(append, paths.first) : paths.first
             dir_name = tree.split(&quot;\n&quot;).select { |p| p.split(&quot;\t&quot;)[1] == paths.first }.first
+            raise NoSuchPath if !dir_name
             next_sha = dir_name.split(' ')[2]
             tree = get_raw_tree(next_sha)
             tree = tree.split(&quot;\n&quot;)
@@ -208,6 +215,7 @@ module Grit
           else
             next_path = paths.shift
             dir_name = tree.split(&quot;\n&quot;).select { |p| p.split(&quot;\t&quot;)[1] == next_path }.first
+            raise NoSuchPath if !dir_name
             next_sha = dir_name.split(' ')[2]
             next_path = append ? File.join(append, next_path) : next_path
             if (last == '/')
@@ -264,7 +272,7 @@ module Grit
         
         log = log(sha, options)
         log = log.sort { |a, b| a[2] &lt;=&gt; b[2] }.reverse
-        
+                
         if end_sha
           log = truncate_arr(log, end_sha)
         end
@@ -282,9 +290,14 @@ module Grit
         @already_searched[sha] = true
         
         array = []          
-        if (sha)
+        if (sha)          
           o = get_raw_object_by_sha1(sha)
-          c = Object.from_raw(o)
+          if o.type == :tag
+            commit_sha = get_object_by_sha1(sha).object
+            c = get_object_by_sha1(commit_sha)
+          else
+            c = GitObject.from_raw(o)
+          end
 
           add_sha = true
           
@@ -347,7 +360,9 @@ module Grit
         else
           tree2 = get_object_by_sha1(commit_obj1.parent.first).tree
         end
+        
         qdiff = quick_diff(tree1, tree2)
+        
         qdiff.sort.each do |diff_arr|
           format, lines, output = :unified, 3, ''
           file_length_difference = 0
@@ -362,7 +377,7 @@ module Grit
           data_new = fileB.split(/\n/).map! { |e| e.chomp }
           
           diffs = Difference::LCS.diff(data_old, data_new)    
-          return if diffs.empty?
+          return '' if diffs.empty?
 
           header = 'diff --git a/' + diff_arr[0].gsub('./', '') + ' b/' + diff_arr[0].gsub('./', '')
           if options[:full_index]
@@ -402,6 +417,8 @@ module Grit
           patch &lt;&lt; header + output.lstrip      
         end
         patch
+      rescue
+        '' # one of the trees was bad or lcs isn't there - no diff 
       end
       
       # takes 2 tree shas and recursively walks them to find out what
@@ -418,7 +435,7 @@ module Grit
          
          t1 = list_tree(tree1) if tree1
          t2 = list_tree(tree2) if tree2
-
+        
          # finding files that are different
          t1['blob'].each do |file, hsh|
            t2_file = t2['blob'][file] rescue nil
@@ -430,9 +447,9 @@ module Grit
            end
          end if t1
          t2['blob'].each do |file, hsh|
-           if !t1['blob'][file]
+           if !t1 || !t1['blob'][file]
              changed &lt;&lt; [File.join(path, file), 'removed', nil, hsh[:sha]]
-           end if t1
+           end
          end if t2
 
          t1['tree'].each do |dir, hsh|
@@ -453,7 +470,7 @@ module Grit
            end
          end if t1
          t2['tree'].each do |dir, hsh|
-           t1_tree = t2['tree'][dir] rescue nil
+           t1_tree = t1['tree'][dir] rescue nil
            full = File.join(path, dir)
            if !t1_tree
              if recurse
@@ -585,23 +602,35 @@ module Grit
       
         def initpacks
           close
-          
           @packs = []
-          if f = File.exists?(git_path(&quot;objects/pack&quot;))
-            Dir.open(git_path(&quot;objects/pack/&quot;)) do |dir|
-              dir.each do |entry|
-                if entry =~ /\.pack$/i
-                  pack = Grit::GitRuby::Internal::PackStorage.new(git_path(&quot;objects/pack/&quot; + entry))
-                  if @options[:map_packfile]
-                    pack.cache_objects
-                  end
-                  @packs &lt;&lt; pack
-                end
-              end
+          
+          load_packs(git_path(&quot;objects/pack&quot;))
+
+          # load alternate packs, too
+          alt = git_path('objects/info/alternates')
+          if File.exists?(alt)
+            File.readlines(alt).each do |line|
+              full_pack = File.join(line.chomp, 'pack')
+              load_packs(full_pack)
             end
           end
+          
           @packs
         end
+        
+        def load_packs(path)
+          return if !File.exists?(path)
+           Dir.open(path) do |dir|
+            dir.each do |entry|
+              next if !(entry =~ /\.pack$/i)
+              pack = Grit::GitRuby::Internal::PackStorage.new(File.join(path,entry))
+              if @options[:map_packfile]
+                pack.cache_objects
+              end
+              @packs &lt;&lt; pack
+            end
+          end
+        end
       
     end
     </diff>
      <filename>lib/grit/git-ruby/repository.rb</filename>
    </modified>
    <modified>
      <diff>@@ -54,13 +54,6 @@ module Grit
       
       call = &quot;#{Git.git_binary} --git-dir='#{self.git_dir}' #{cmd.to_s.gsub(/_/, '-')} #{(opt_args + ext_args).join(' ')}&quot;
       puts call if Grit.debug
-      
-      puts
-      puts '**'
-      puts call
-      puts '**'
-      puts
-      
       response = timeout ? sh(call) : wild_sh(call)
       puts response if Grit.debug
       response</diff>
      <filename>lib/grit/git.rb</filename>
    </modified>
    <modified>
      <diff>@@ -11,8 +11,19 @@ module Grit
       # Returns Grit::Ref[] (baked)
       def find_all(repo, options = {})      
         refs = []
-        
-        Dir.chdir(repo.git.git_dir) do
+
+        Dir.chdir(repo.path) do
+          if File.file?('packed-refs')
+            File.readlines('packed-refs').each do |line|
+              if m = /^(\w{40}) (.*?)$/.match(line)
+                next if !Regexp.new('^' + prefix).match(m[2])
+                name = m[2].sub(&quot;#{prefix}/&quot;, '')
+                commit = Commit.create(repo, :id =&gt; m[1])
+                refs &lt;&lt; self.new(name, commit)
+              end
+            end
+          end
+          
           files = Dir.glob(prefix + '/**/*')
           files.each do |ref|
             next if !File.file?(ref)
@@ -22,7 +33,7 @@ module Grit
             refs &lt;&lt; self.new(name, commit)
           end
         end
-        
+                
         refs
       end
 </diff>
      <filename>lib/grit/ref.rb</filename>
    </modified>
    <modified>
      <diff>@@ -309,7 +309,6 @@ module Grit
 
     # run archive directly to a file
     def archive_to_file(treeish = 'master', prefix = nil, filename = 'archive.tar.gz')
-      Grit.debug = true
       options = {}
       options[:prefix] = prefix if prefix
       self.git.archive(options, treeish, &quot;| gzip &gt; #{filename}&quot;)</diff>
      <filename>lib/grit/repo.rb</filename>
    </modified>
    <modified>
      <diff>@@ -69,6 +69,8 @@ module Grit
           Tree.create(repo, :id =&gt; id, :mode =&gt; mode, :name =&gt; name)
         when &quot;blob&quot;
           Blob.create(repo, :id =&gt; id, :mode =&gt; mode, :name =&gt; name)
+        when &quot;link&quot;
+          Blob.create(repo, :id =&gt; id, :mode =&gt; mode, :name =&gt; name)
         when &quot;commit&quot;
           nil
         else</diff>
      <filename>lib/grit/tree.rb</filename>
    </modified>
    <modified>
      <diff>@@ -2,7 +2,7 @@ require File.dirname(__FILE__) + '/helper'
 
 class TestCommit &lt; Test::Unit::TestCase
   def setup
-    @r = Repo.new(GRIT_REPO)
+    @r = Repo.new(File.join(File.dirname(__FILE__), *%w[dot_git]), :is_bare =&gt; true)
   end
   
   # __bake__
@@ -19,7 +19,6 @@ class TestCommit &lt; Test::Unit::TestCase
   # short_name
   
   def test_id_abbrev
-    Git.any_instance.expects(:rev_parse).returns(fixture('rev_parse'))
     assert_equal '80f136f', @r.commit('80f136f500dfdb8c3e8abf4ae716f875f0a1b57f').id_abbrev
   end
   </diff>
      <filename>test/test_commit.rb</filename>
    </modified>
    <modified>
      <diff>@@ -10,7 +10,7 @@ class TestDiff &lt; Test::Unit::TestCase
   def test_list_from_string_new_mode
     output = fixture('diff_new_mode')
     
-    diffs = Diff.list_from_string(@r, output)
+    diffs = Grit::Diff.list_from_string(@r, output)
     assert_equal 2, diffs.size
     assert_equal 10, diffs.first.diff.split(&quot;\n&quot;).size
     assert_equal nil, diffs.last.diff</diff>
      <filename>test/test_diff.rb</filename>
    </modified>
    <modified>
      <diff>@@ -18,4 +18,14 @@ class TestHead &lt; Test::Unit::TestCase
     head = @r.heads[1]
     assert_equal %Q{#&lt;Grit::Head &quot;test/chacon&quot;&gt;}, head.inspect
   end
+
+  def test_head_count
+    assert_equal 4, @r.heads.size
+  end
+
+
+  def test_nonpack
+    assert @r.heads.map { |h| h.name }.include?('nonpack')
+  end
+
 end</diff>
      <filename>test/test_head.rb</filename>
    </modified>
    <modified>
      <diff>@@ -42,12 +42,11 @@ class TestRepo &lt; Test::Unit::TestCase
   end
 
   def test_heads_should_populate_head_data
-    Git.any_instance.expects(:for_each_ref).returns(fixture('for_each_ref'))
-
+    @r = Repo.new(File.join(File.dirname(__FILE__), *%w[dot_git]), :is_bare =&gt; true)
     head = @r.heads.first
-
+    
     assert_equal 'master', head.name
-    assert_equal '634396b2f541a9f2d58b00be1a07f0c358b999b3', head.commit.id
+    assert_equal 'ca8a30f5a7f0f163bbe3b6f0abf18a6c83b0687a', head.commit.id
   end
 
   # branches
@@ -182,13 +181,13 @@ class TestRepo &lt; Test::Unit::TestCase
   # archive
 
   def test_archive_tar
-    @r.archive_tar
+    #@r.archive_tar  -- no assertion being done here
   end
 
   # archive_tar_gz
 
   def test_archive_tar_gz
-    @r.archive_tar_gz
+    #@r.archive_tar_gz -- again, no assertion
   end
 
   # enable_daemon_serve</diff>
      <filename>test/test_repo.rb</filename>
    </modified>
    <modified>
      <diff>@@ -110,7 +110,7 @@ class TestRubyGit &lt; Test::Unit::TestCase
   def test_rev_list_range
     range = '30e367cef2203eba2b341dc9050993b06fd1e108..3fa4e130fa18c92e3030d4accb5d3e0cadd40157'
     out = @git.rev_list({}, range)
-    assert_equal out, fixture('rev_list_range').chomp
+    assert_equal fixture('rev_list_range'), out
   end
 
   def test_ls_tree_paths_multi</diff>
      <filename>test/test_rubygit.rb</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>a92a84f8cafa92ad576b2c9622bf48163b6afea4</id>
    </parent>
  </parents>
  <author>
    <name>Scott Chacon</name>
    <email>schacon@gmail.com</email>
  </author>
  <url>http://github.com/bmizerany/grit/commit/c7f1990597b63aeded4f81ebd3fb29e0aded5606</url>
  <id>c7f1990597b63aeded4f81ebd3fb29e0aded5606</id>
  <committed-date>2008-07-08T20:32:35-07:00</committed-date>
  <authored-date>2008-07-08T20:32:35-07:00</authored-date>
  <message>pulled in changes from github</message>
  <tree>e8177906af2487234fc54f3517aa06a90521870e</tree>
  <committer>
    <name>Scott Chacon</name>
    <email>schacon@gmail.com</email>
  </committer>
</commit>
