gitrb 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
data/gitrb.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'gitrb'
3
- s.version = '0.0.5'
3
+ s.version = '0.0.6'
4
4
  s.summary = 'Pure ruby git implementation'
5
5
  s.author = 'Daniel Mendler'
6
6
  s.email = 'mail@daniel-mendler.de'
data/lib/gitrb/commit.rb CHANGED
@@ -47,20 +47,20 @@ module Gitrb
47
47
 
48
48
  def parse(data)
49
49
  headers, @message = data.split("\n\n", 2)
50
- repository.encode(@message)
50
+ repository.set_encoding(@message)
51
51
 
52
52
  headers.split("\n").each do |header|
53
53
  key, value = header.split(' ', 2)
54
54
 
55
55
  case key
56
56
  when 'parent'
57
- @parent << Reference.new(:repository => repository, :id => repository.encode(value))
57
+ @parent << Reference.new(:repository => repository, :id => repository.set_encoding(value))
58
58
  when 'author'
59
- @author = User.parse(repository.encode(value))
59
+ @author = User.parse(repository.set_encoding(value))
60
60
  when 'committer'
61
- @committer = User.parse(repository.encode(value))
61
+ @committer = User.parse(repository.set_encoding(value))
62
62
  when 'tree'
63
- @tree = Reference.new(:repository => repository, :id => repository.encode(value))
63
+ @tree = Reference.new(:repository => repository, :id => repository.set_encoding(value))
64
64
  end
65
65
  end
66
66
 
data/lib/gitrb/pack.rb CHANGED
@@ -159,7 +159,7 @@ module Gitrb
159
159
 
160
160
  def find_object(sha1)
161
161
  with_idx do |idx|
162
- slot = Util.ord(sha1, 0)
162
+ slot = sha1[0].ord
163
163
  return nil if !slot
164
164
  first, last = @offsets[slot,2]
165
165
  while first < last
@@ -200,13 +200,13 @@ module Gitrb
200
200
  obj_offset = offset
201
201
  packfile.seek(offset)
202
202
 
203
- c = Util.ord(packfile.read(1), 0)
203
+ c = packfile.read(1)[0].ord
204
204
  size = c & 0xf
205
205
  type = (c >> 4) & 7
206
206
  shift = 4
207
207
  offset += 1
208
208
  while c & 0x80 != 0
209
- c = Util.ord(packfile.read(1), 0)
209
+ c = packfile.read(1)[0].ord
210
210
  size |= ((c & 0x7f) << shift)
211
211
  shift += 7
212
212
  offset += 1
@@ -229,10 +229,10 @@ module Gitrb
229
229
 
230
230
  if type == OBJ_OFS_DELTA
231
231
  i = 0
232
- c = Util.ord(data, i)
232
+ c = data[i].ord
233
233
  base_offset = c & 0x7f
234
234
  while c & 0x80 != 0
235
- c = Util.ord(data, i += 1)
235
+ c = data[i += 1].ord
236
236
  base_offset += 1
237
237
  base_offset <<= 7
238
238
  base_offset |= c & 0x7f
@@ -279,18 +279,18 @@ module Gitrb
279
279
  dest_size, pos = patch_delta_header_size(delta, pos)
280
280
  dest = ""
281
281
  while pos < delta.size
282
- c = Util.ord(delta, pos)
282
+ c = delta[pos].ord
283
283
  pos += 1
284
284
  if c & 0x80 != 0
285
285
  pos -= 1
286
286
  cp_off = cp_size = 0
287
- cp_off = Util.ord(delta, pos += 1) if c & 0x01 != 0
288
- cp_off |= Util.ord(delta, pos += 1) << 8 if c & 0x02 != 0
289
- cp_off |= Util.ord(delta, pos += 1) << 16 if c & 0x04 != 0
290
- cp_off |= Util.ord(delta, pos += 1) << 24 if c & 0x08 != 0
291
- cp_size = Util.ord(delta, pos += 1) if c & 0x10 != 0
292
- cp_size |= Util.ord(delta, pos += 1) << 8 if c & 0x20 != 0
293
- cp_size |= Util.ord(delta, pos += 1) << 16 if c & 0x40 != 0
287
+ cp_off = delta[pos += 1].ord if c & 0x01 != 0
288
+ cp_off |= delta[pos += 1].ord << 8 if c & 0x02 != 0
289
+ cp_off |= delta[pos += 1].ord << 16 if c & 0x04 != 0
290
+ cp_off |= delta[pos += 1].ord << 24 if c & 0x08 != 0
291
+ cp_size = delta[pos += 1].ord if c & 0x10 != 0
292
+ cp_size |= delta[pos += 1].ord << 8 if c & 0x20 != 0
293
+ cp_size |= delta[pos += 1].ord << 16 if c & 0x40 != 0
294
294
  cp_size = 0x10000 if cp_size == 0
295
295
  pos += 1
296
296
  dest << base[cp_off,cp_size]
@@ -308,7 +308,7 @@ module Gitrb
308
308
  size = 0
309
309
  shift = 0
310
310
  begin
311
- c = Util.ord(delta, pos)
311
+ c = delta[pos].ord
312
312
  if c == nil
313
313
  raise PackFormatError, 'invalid delta header'
314
314
  end
@@ -22,12 +22,24 @@ module Gitrb
22
22
  class Repository
23
23
  attr_reader :path, :index, :root, :branch, :lock_file, :head, :encoding
24
24
 
25
+ SHA_PATTERN = /[A-Fa-f0-9]{5,40}/
26
+ REVISION_PATTERN = /[\w\-\.]+([\^~](\d+)?)*/
27
+
28
+ # Encoding stuff
29
+ DEFAULT_ENCODING = 'utf-8'
30
+
31
+ if RUBY_VERSION > '1.9'
32
+ def set_encoding(s); s.force_encoding(@encoding); end
33
+ else
34
+ def set_encoding(s); s; end
35
+ end
36
+
25
37
  # Initialize a repository.
26
38
  def initialize(options = {})
27
39
  @bare = options[:bare] || false
28
40
  @branch = options[:branch] || 'master'
29
41
  @logger = options[:logger] || Logger.new(nil)
30
- @encoding = options[:encoding] || 'utf-8'
42
+ @encoding = options[:encoding] || DEFAULT_ENCODING
31
43
 
32
44
  @path = options[:path]
33
45
  @path.chomp!('/')
@@ -49,18 +61,6 @@ module Gitrb
49
61
  load
50
62
  end
51
63
 
52
- # Encode string
53
- if RUBY_VERSION > '1.9'
54
- def encode(s)
55
- # We have binary data which has to be encoded
56
- s.force_encoding(@encoding)
57
- end
58
- else
59
- def encode(s)
60
- s
61
- end
62
- end
63
-
64
64
  # Bare repository?
65
65
  def bare?
66
66
  @bare
@@ -89,9 +89,15 @@ module Gitrb
89
89
 
90
90
  # Diff
91
91
  def diff(from, to, path = nil)
92
- from = from.id if Commit === from
93
- to = to.id if Commit === to
94
- Diff.new(from, to, git_diff('--full-index', from, to, '--', path))
92
+ if from && !(Commit === from)
93
+ raise ArgumentError if !(String === from)
94
+ from = Reference.new(:repository => self, :id => from)
95
+ end
96
+ if !(Commit === to)
97
+ raise ArgumentError if !(String === to)
98
+ to = Reference.new(:repository => self, :id => to)
99
+ end
100
+ Diff.new(from, to, git_diff_tree('--root', '-u', '--full-index', from && from.id, to.id, '--', path))
95
101
  end
96
102
 
97
103
  # All changes made inside a transaction are atomic. If some
@@ -155,7 +161,7 @@ module Gitrb
155
161
  end
156
162
  commits
157
163
  rescue => ex
158
- return [] if ex.message =~ /bad default revision 'HEAD'/
164
+ return [] if ex.message =~ /bad default revision 'HEAD'/i
159
165
  raise
160
166
  end
161
167
 
@@ -163,20 +169,29 @@ module Gitrb
163
169
  #
164
170
  # Returns a tree, blob, commit or tag object.
165
171
  def get(id)
166
- return nil if id.nil? || id.length < 5
167
- list = @objects.find(id).to_a
168
- return list.first if list.size == 1
172
+ raise NotFound, "No id given" if id.nil?
173
+ if id =~ SHA_PATTERN
174
+ raise NotFound, "Sha too short" if id.length < 5
175
+ list = @objects.find(id).to_a
176
+ return list.first if list.size == 1
177
+ elsif id =~ REVISION_PATTERN
178
+ list = git_rev_parse(id).split("\n") rescue nil
179
+ raise NotFound, "Revision not found" if !list || list.empty?
180
+ raise NotFound, "Revision is ambiguous" if list.size > 1
181
+ id = list.first
182
+ end
169
183
 
170
184
  @logger.debug "gitrb: Loading #{id}"
171
185
 
172
186
  path = object_path(id)
173
187
  if File.exists?(path) || (glob = Dir.glob(path + '*')).size >= 1
174
188
  if glob
175
- raise NotFound, "Sha not unique" if glob.size > 1
176
- path = glob[0]
189
+ raise NotFound, "Sha is ambiguous" if glob.size > 1
190
+ path = glob.first
191
+ id = path[-41..-40] + path[-38..-1]
177
192
  end
178
193
 
179
- buf = File.open(path, "rb") { |f| f.read }
194
+ buf = File.open(path, 'rb') { |f| f.read }
180
195
 
181
196
  raise NotFound, "Not a loose object: #{id}" if !legacy_loose_object?(buf)
182
197
 
@@ -185,18 +200,22 @@ module Gitrb
185
200
 
186
201
  raise NotFound, "Bad object: #{id}" if content.length != size.to_i
187
202
  else
188
- list = @packs.find(id).to_a
189
- raise NotFound, "Object not found" if list.size != 1
203
+ trie = @packs.find(id)
204
+ raise NotFound, "Object not found" if !trie
205
+
206
+ id += trie.key[-(41 - id.length)...-1]
207
+
208
+ list = trie.to_a
209
+ raise NotFound, "Sha is ambiguous" if list.size > 1
190
210
 
191
211
  pack, offset = list.first
192
212
  content, type = pack.get_object(offset)
193
213
  end
194
214
 
195
- raise NotFound, "Object not found" if !type
196
-
197
215
  @logger.debug "gitrb: Loaded #{id}"
198
216
 
199
- object = Gitrb::Object.factory(type, :repository => self, :id => encode(id), :data => content)
217
+ set_encoding(id)
218
+ object = Gitrb::Object.factory(type, :repository => self, :id => id, :data => content)
200
219
  @objects.insert(id, object)
201
220
  object
202
221
  end
@@ -225,6 +244,7 @@ module Gitrb
225
244
 
226
245
  @logger.debug "gitrb: Stored #{id}"
227
246
 
247
+ set_encoding(id)
228
248
  object.repository = self
229
249
  object.id = id
230
250
  @objects.insert(id, object)
@@ -242,10 +262,11 @@ module Gitrb
242
262
 
243
263
  @logger.debug "gitrb: #{cmd}"
244
264
 
265
+ # Read in binary mode (ascii-8bit) and convert afterwards
245
266
  out = if block_given?
246
- IO.popen(cmd, &block)
247
- else
248
- `#{cmd}`.chomp
267
+ IO.popen(cmd, 'rb', &block)
268
+ else
269
+ set_encoding IO.popen(cmd, 'rb') {|io| io.read }
249
270
  end
250
271
 
251
272
  if $?.exitstatus > 0
@@ -385,7 +406,7 @@ module Gitrb
385
406
  end
386
407
 
387
408
  def legacy_loose_object?(buf)
388
- Util.ord(buf, 0) == 0x78 && ((Util.ord(buf, 0) << 8) + Util.ord(buf, 1)) % 31 == 0
409
+ buf[0].ord == 0x78 && ((buf[0].ord << 8) | buf[1].ord) % 31 == 0
389
410
  end
390
411
 
391
412
  end
data/lib/gitrb/tag.rb CHANGED
@@ -14,6 +14,7 @@ module Gitrb
14
14
 
15
15
  def parse(data)
16
16
  headers, @message = data.split("\n\n", 2)
17
+ repository.set_encoding(@message)
17
18
 
18
19
  headers.split("\n").each do |header|
19
20
  key, value = header.split(' ', 2)
@@ -21,9 +22,9 @@ module Gitrb
21
22
  when 'type'
22
23
  @tagtype = value
23
24
  when 'object'
24
- @object = Reference.new(:repository => repository, :id => repository.encode(value))
25
+ @object = Reference.new(:repository => repository, :id => repository.set_encoding(value))
25
26
  when 'tagger'
26
- @tagger = User.parse(repository.encode(value))
27
+ @tagger = User.parse(repository.set_encoding(value))
27
28
  end
28
29
  end
29
30
 
data/lib/gitrb/tree.rb CHANGED
@@ -24,8 +24,8 @@ module Gitrb
24
24
 
25
25
  # Set new repository (modified flag is reset)
26
26
  def id=(id)
27
- super
28
27
  @modified = false
28
+ super
29
29
  end
30
30
 
31
31
  # Has this tree been modified?
@@ -36,7 +36,7 @@ module Gitrb
36
36
  def dump
37
37
  @children.to_a.sort {|a,b| a.first <=> b.first }.map do |name, child|
38
38
  child.save if !(Reference === child) || child.resolved?
39
- "#{child.mode} #{name}\0#{[child.id].pack("H*")}"
39
+ "#{child.mode} #{name}\0#{repository.set_encoding [child.id].pack("H*")}"
40
40
  end.join
41
41
  end
42
42
 
@@ -137,9 +137,9 @@ module Gitrb
137
137
  @children.clear
138
138
  data = StringIO.new(data)
139
139
  while !data.eof?
140
- mode = repository.encode Util.read_bytes_until(data, ' ')
141
- name = repository.encode Util.read_bytes_until(data, "\0")
142
- id = repository.encode data.read(20).unpack("H*").first
140
+ mode = repository.set_encoding Util.read_bytes_until(data, ' ')
141
+ name = repository.set_encoding Util.read_bytes_until(data, "\0")
142
+ id = repository.set_encoding data.read(20).unpack("H*").first
143
143
  @children[name] = Reference.new(:repository => repository, :id => id, :mode => mode)
144
144
  end
145
145
  end
data/lib/gitrb/util.rb CHANGED
@@ -17,9 +17,5 @@ module Gitrb
17
17
  str
18
18
  end
19
19
  end
20
-
21
- def self.ord(s, i)
22
- s[i].ord
23
- end
24
20
  end
25
21
  end
@@ -17,9 +17,40 @@ describe Gitrb do
17
17
  end
18
18
 
19
19
  it 'should fail to initialize without a valid git repository' do
20
- lambda {
20
+ lambda do
21
21
  Gitrb::Repository.new(:path => '/')
22
- }.should raise_error(ArgumentError)
22
+ end.should raise_error(ArgumentError)
23
+ end
24
+
25
+ it 'should put and get objects by sha' do
26
+ blob1 = repo.put(Gitrb::Blob.new(:data => 'Hello'))
27
+ blob2 = repo.put(Gitrb::Blob.new(:data => 'World'))
28
+
29
+ repo.get(blob1.id).should === blob1
30
+ repo.get(blob1.id[0..4]).should === blob1
31
+ repo.get(blob1.id[0..10]).should === blob1
32
+
33
+ repo.get(blob2.id).should === blob2
34
+ repo.get(blob2.id[0..4]).should === blob2
35
+ repo.get(blob2.id[0..10]).should === blob2
36
+ end
37
+
38
+ it 'should find commits by revision' do
39
+ repo.root['a'] = Gitrb::Blob.new(:data => 'Hello')
40
+ commit1 = repo.commit
41
+
42
+ repo.get('HEAD').should === commit1
43
+ repo.get('master').should === commit1
44
+ lambda { repo.get('HEAD^') }.should raise_error(Gitrb::NotFound)
45
+
46
+ repo.root['a'] = Gitrb::Blob.new(:data => 'World')
47
+ commit2 = repo.commit
48
+
49
+ repo.get('master').should === commit2
50
+ repo.get('HEAD').should === commit2
51
+ repo.get('HEAD^').should === commit1
52
+ repo.get('HEAD~').should === commit1
53
+ lambda { repo.get('HEAD^^') }.should raise_error(Gitrb::NotFound)
23
54
  end
24
55
 
25
56
  it 'should find modified entries' do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gitrb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Mendler
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-12-20 00:00:00 +01:00
12
+ date: 2009-12-22 00:00:00 +01:00
13
13
  default_executable:
14
14
  dependencies: []
15
15