summaryrefslogtreecommitdiffstats
path: root/lib/git/raw/repository.rb
blob: bd5e971d0aaa3577e932b2b99bb9e8213242185a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#
# converted from the gitrb project
#
# authors: 
#    Matthias Lederhofer <matled@gmx.net>
#    Simon 'corecode' Schubert <corecode@fs.ei.tum.de>
#
# provides native ruby access to git objects and pack files
#

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 object(sha)
        o = get_raw_object_by_sha1(sha)
        c = Git::Raw::Object.from_raw(o)
      end
            
      def cat_file(sha)
        object(sha).raw_content
      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