updated a bunch of the documentation
[rubygit.git] / lib / git / object.rb
blob7702811d15d48b4f96aab27f35de86e98481f114
1 module Git
2   
3   class GitTagNameDoesNotExist< StandardError 
4   end
5   
6   # represents a git object
7   class Object
8     
9     class AbstractObject
10       attr_accessor :sha, :size, :type, :mode
11     
12       @base = nil
13     
14       def initialize(base, sha)
15         @base = base
16         @sha = sha.to_s
17         @size = @base.lib.object_size(@sha)
18         setup
19       end
20     
21       def contents
22         @base.lib.object_contents(@sha)
23       end
24       
25       def contents_array
26         self.contents.split("\n")
27       end
28       
29       def setup
30         raise NotImplementedError
31       end
32       
33       def to_s
34         @sha
35       end
36       
37       def grep(string, path_limiter = nil, opts = {})
38         default = {:object => @sha, :path_limiter => path_limiter}
39         grep_options = default.merge(opts)
40         @base.lib.grep(string, grep_options)
41       end
42       
43       def diff(objectish)
44         Git::Diff.new(@base, @sha, objectish)
45       end
46       
47       def log(count = 30)
48         Git::Log.new(@base, count).object(@sha)
49       end
50       
51     end
52   
53     
54     class Blob < AbstractObject
55       
56       def initialize(base, sha, mode = nil)
57         super(base, sha)
58         @mode = mode
59       end
60       
61       private
62       
63         def setup
64           @type = 'blob'
65         end
66     end
67   
68     class Tree < AbstractObject
69       
70       @trees = nil
71       @blobs = nil
72       
73       def initialize(base, sha, mode = nil)
74         super(base, sha)
75         @mode = mode
76       end
77       
78       def children
79         blobs.merge(subtrees)
80       end
81       
82       def blobs
83         check_tree
84         @blobs
85       end
86       alias_method :files, :blobs
87       
88       def trees
89         check_tree
90         @trees
91       end
92       alias_method :subtrees, :trees
93       alias_method :subdirectories, :trees
94        
95       private
96       
97         def setup
98           @type = 'tree'
99         end 
101         # actually run the git command
102         def check_tree
103           if !@trees
104             @trees = {}
105             @blobs = {}
106             data = @base.lib.ls_tree(@sha)
107             data['tree'].each { |k, d| @trees[k] = Tree.new(@base, d[:sha], d[:mode]) }
108             data['blob'].each { |k, d| @blobs[k] = Blob.new(@base, d[:sha], d[:mode]) }
109           end
110         end
111       
112     end
113   
114     class Commit < AbstractObject
115       
116       @tree = nil
117       @parents = nil
118       @author = nil
119       @committer = nil
120       @message = nil
121       
122       def message
123         check_commit
124         @message
125       end
126       
127       def gtree
128         check_commit
129         Tree.new(@base, @tree)
130       end
131       
132       def parent
133         parents.first
134       end
135       
136       # array of all parent commits
137       def parents
138         check_commit
139         @parents        
140       end
141       
142       # git author
143       def author     
144         check_commit
145         @author
146       end
147       
148       def author_date
149         author.date
150       end
151       
152       # git author
153       def committer
154         check_commit
155         @committer
156       end
157       
158       def committer_date 
159         committer.date
160       end
161       alias_method :date, :committer_date
163       def diff_parent
164         diff(parent)
165       end
166             
167       private
168       
169         def setup
170           @type = 'commit'
171         end
172   
173         # see if this object has been initialized and do so if not
174         def check_commit
175           if !@tree
176             data = @base.lib.commit_data(@sha)
177             @committer = Git::Author.new(data['committer'])
178             @author = Git::Author.new(data['author'])
179             @tree = Tree.new(@base, data['tree'])
180             @parents = data['parent'].map{ |sha| Commit.new(@base, sha) }
181             @message = data['message'].chomp
182           end
183         end
184       
185     end
186   
187     class Tag < AbstractObject
188       attr_accessor :name
189       
190       def initialize(base, sha, name)
191         super(base, sha)
192         @name = name
193       end
194       
195       private
196         
197         def setup
198           @type = 'tag'
199         end
200         
201     end
202     
203     class << self
204       # if we're calling this, we don't know what type it is yet
205       # so this is our little factory method
206       def new(base, objectish, is_tag = false)
207         if is_tag
208           sha = base.lib.tag_sha(objectish)
209           if sha == ''
210             raise Git::GitTagNameDoesNotExist.new(objectish)
211           end
212           return Tag.new(base, sha, objectish)
213         else
214           sha = base.lib.revparse(objectish)
215           type = base.lib.object_type(sha) 
216         end
217         
218         klass =
219           case type
220           when /blob/:   Blob   
221           when /commit/: Commit
222           when /tree/:   Tree
223           end
224         klass::new(base, sha)
225       end
226     end 
227     
228   end