got log and cat-file moved to pure ruby
authorscott Chacon <schacon@agadorsparticus.(none)>
Fri, 23 Nov 2007 19:16:46 +0000 (23 11:16 -0800)
committerscott Chacon <schacon@agadorsparticus.(none)>
Fri, 23 Nov 2007 19:16:46 +0000 (23 11:16 -0800)
camping/gitweb.rb
lib/git/lib.rb
lib/git/raw/repository.rb [new file with mode: 0644]
tests/units/test_raw_internals.rb

index 092649d..8dc40ba 100644 (file)
@@ -13,6 +13,7 @@ require 'lib/git'
 # todo
 #   - diff/patch between any two objects
 #     - expand patch to entire file
+#   - set title properly
 #   - grep / search function
 #   - prettify : http://projects.wh.techno-weenie.net/changesets/3030
 #   - add user model (add/remove repos)
@@ -90,10 +91,7 @@ module GitWeb::Controllers
   class View < R '/view/(\d+)'
     def get repo_id
       @repo = Repository.find repo_id
-      logger = Logger.new('/tmp/git.log')
-      logger.level = Logger::INFO
-      
-      @git = Git.bare(@repo.path, :log => logger)      
+      @git = Git.bare(@repo.path)     
       render :view
     end
   end
@@ -109,7 +107,10 @@ module GitWeb::Controllers
   class Commit < R '/commit/(\d+)/(\w+)'
     def get repo_id, sha
       @repo = Repository.find repo_id
-      @git = Git.bare(@repo.path)      
+      logger = Logger.new('/tmp/git.log')
+      logger.level = Logger::INFO
+      
+      @git = Git.bare(@repo.path, :log => logger)   
       @commit = @git.gcommit(sha)
       render :commit
     end
@@ -212,7 +213,7 @@ module GitWeb::Views
       body :onload => "sh_highlightDocument();" do
         before = Time.now().usec
         self << yield
-        self << ((Time.now().usec - before).to_f / 60).to_s + ' sec'
+        self << '<br/>' + ((Time.now().usec - before).to_f / 60).to_s + ' sec'
       end
     end
   end
index eb06875..9c6a041 100644 (file)
@@ -13,6 +13,7 @@ module Git
     @path = nil
     
     @logger = nil
+    @raw_repo = nil
     
     def initialize(base = nil, logger = nil)
       if base.is_a?(Git::Base)
@@ -75,6 +76,15 @@ module Git
     end
     
     def full_log_commits(opts = {})
+      if !(opts[:since] || opts[:between] || opts[:path_limiter])
+        # can do this in pure ruby
+        sha = revparse(opts[:object] || branch_current || 'master')
+        count = opts[:count] || 30
+        
+        repo = Git::Raw::Repository.new(@git_dir)
+        return process_commit_data(repo.log(sha, count))
+      end
+      
       arr_opts = ['--pretty=raw']
       arr_opts << "-#{opts[:count]}" if opts[:count]
       arr_opts << "--since=\"#{opts[:since]}\"" if opts[:since].is_a? String
@@ -92,10 +102,13 @@ module Git
       end
             
       head = File.join(@git_dir, 'refs', 'heads', string)
-      return File.read(head) if File.file?(head)
+      return File.read(head).chomp if File.file?(head)
 
       head = File.join(@git_dir, 'refs', 'remotes', string)
-      return File.read(head) if File.file?(head)
+      return File.read(head).chomp if File.file?(head)
+      
+      head = File.join(@git_dir, 'refs', 'tags', string)
+      return File.read(head).chomp if File.file?(head)
       
       command('rev-parse', string)
     end
@@ -111,17 +124,22 @@ module Git
     def object_size(sha)
       command('cat-file', ['-s', sha]).to_i
     end
+
+    def get_raw_repo
+      @raw_repo ||= Git::Raw::Repository.new(@git_dir)
+    end
     
     # returns useful array of raw commit object data
     def commit_data(sha)
       sha = sha.to_s
-      cdata = command_lines('cat-file', ['commit', sha])
+      cdata = get_raw_repo.cat_file(revparse(sha))
+      #cdata = command_lines('cat-file', ['commit', sha])
       process_commit_data(cdata, sha)
     end
     
     def process_commit_data(data, sha = nil)
       in_message = false
-      
+            
       if sha
         hsh = {'sha' => sha, 'message' => '', 'parent' => []}
       else
@@ -129,6 +147,7 @@ module Git
       end
     
       data.each do |line|
+        line = line.chomp
         if in_message && line != ''
           hsh['message'] += line + "\n"
         end
diff --git a/lib/git/raw/repository.rb b/lib/git/raw/repository.rb
new file mode 100644 (file)
index 0000000..4a1c897
--- /dev/null
@@ -0,0 +1,109 @@
+require 'git/raw/internal/object'
+require 'git/raw/internal/pack'
+require 'git/raw/internal/loose'
+require 'git/raw/object'
+
+module Git
+  module Raw
+    
+    class Repository
+      def initialize(git_dir)
+        @git_dir = git_dir
+        @loose = Raw::Internal::LooseStorage.new(git_path("objects"))
+        @packs = []
+        initpacks
+      end
+
+      def show
+        @packs.each do |p|
+          puts p.name
+          puts
+          p.each_sha1 do |s|
+            puts "**#{p[s].type}**"
+            if p[s].type.to_s == 'commit'
+              puts s.unpack('H*')
+              puts p[s].content
+            end
+          end
+          puts
+        end
+      end
+      
+      def cat_file(sha)
+        get_raw_object_by_sha1(sha).content rescue nil
+      end
+      
+      def log(sha, count = 30)
+        output = ''
+        i = 0
+
+        while sha && (i < count) do
+          o = get_raw_object_by_sha1(sha)
+          c = Git::Raw::Object.from_raw(o)
+          
+          output += "commit #{sha}\n"
+          output += o.content + "\n"
+
+          sha = c.parent.first
+          i += 1
+        end
+        
+        output
+      end
+      
+      def get_object_by_sha1(sha1)
+        r = get_raw_object_by_sha1(sha1)
+        return nil if !r
+        Object.from_raw(r, self)
+      end
+
+      def get_raw_object_by_sha1(sha1)
+        sha1 = [sha1].pack("H*")
+
+        # try packs
+        @packs.each do |pack|
+          o = pack[sha1]
+          return o if o
+        end
+
+        # try loose storage
+        o = @loose[sha1]
+        return o if o
+
+        # try packs again, maybe the object got packed in the meantime
+        initpacks
+        @packs.each do |pack|
+          o = pack[sha1]
+          return o if o
+        end
+
+        nil
+      end
+
+      protected
+      
+        def git_path(path)
+          return "#@git_dir/#{path}"
+        end
+
+      private 
+      
+        def initpacks
+          @packs.each do |pack|
+            pack.close
+          end
+          @packs = []
+          Dir.open(git_path("objects/pack/")) do |dir|
+            dir.each do |entry|
+              if entry =~ /\.pack$/i
+                @packs << Git::Raw::Internal::PackStorage.new(git_path("objects/pack/" \
+                                                                  + entry))
+              end
+            end
+          end
+        end
+      
+    end
+    
+  end
+end
index 4299a2b..1437845 100644 (file)
@@ -1,5 +1,5 @@
 #!/usr/bin/env ruby
-
+require 'logger'
 require File.dirname(__FILE__) + '/../test_helper'
 
 class TestRawInternals < Test::Unit::TestCase
@@ -10,26 +10,31 @@ class TestRawInternals < Test::Unit::TestCase
   
   def test_raw_log
     g = Git.bare(@wbare)
-    #g.repack
+    t_log(g)
+  end
+  
+  def test_packed_log
+    g = Git.bare(@wbare)
+    g.repack
+    t_log(g)
+  end
+  
+  def test_commit_object
+    g = Git.bare(@wbare, :log => Logger.new(STDOUT))
     
-    c = g.object("HEAD")
-    puts sha = c.sha
+    c = g.gcommit("v2.5")
+    assert_equal('test', c.message)
+  end
+  
+  def t_log(g)
+    c = g.object("v2.5")
+    sha = c.sha
     
     repo = Git::Raw::Repository.new(@wbare)
-    while sha do
-      o = repo.get_raw_object_by_sha1(sha)
-      c = Git::Raw::Object.from_raw(o)
-    
-      sha = c.parent.first
-      puts sha
-    end
-    
-    g.log(60).each do |c|
-      puts c.sha
-    end
-  
-    puts c.inspect
+    raw_out = repo.log(sha)
     
+    assert_equal('commit 546bec6f8872efa41d5d97a369f669165ecda0de', raw_out.split("\n").first)
+    assert_equal('546bec6f8872efa41d5d97a369f669165ecda0de', c.log(30).first.sha)
   end
-
+  
 end
\ No newline at end of file