cucumber_fm-core 0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. data/LICENCE +20 -0
  2. data/lib/cucumber_f_m/aggregator.rb +65 -0
  3. data/lib/cucumber_f_m/comment_module/comment.rb +7 -0
  4. data/lib/cucumber_f_m/config.rb +37 -0
  5. data/lib/cucumber_f_m/cvs/git.rb +7 -0
  6. data/lib/cucumber_f_m/feature.rb +141 -0
  7. data/lib/cucumber_f_m/feature_element/background.rb +10 -0
  8. data/lib/cucumber_f_m/feature_element/comment.rb +13 -0
  9. data/lib/cucumber_f_m/feature_element/component/comments.rb +21 -0
  10. data/lib/cucumber_f_m/feature_element/component/information/component.rb +16 -0
  11. data/lib/cucumber_f_m/feature_element/component/tags.rb +108 -0
  12. data/lib/cucumber_f_m/feature_element/component/title.rb +26 -0
  13. data/lib/cucumber_f_m/feature_element/component/total_estimation.rb +42 -0
  14. data/lib/cucumber_f_m/feature_element/example.rb +7 -0
  15. data/lib/cucumber_f_m/feature_element/info.rb +13 -0
  16. data/lib/cucumber_f_m/feature_element/narrative.rb +7 -0
  17. data/lib/cucumber_f_m/feature_element/scenario.rb +15 -0
  18. data/lib/cucumber_f_m/feature_element/scenario_outline.rb +23 -0
  19. data/lib/cucumber_f_m/feature_element/step.rb +7 -0
  20. data/lib/cucumber_f_m/statistic.rb +31 -0
  21. data/lib/cucumber_f_m/tag_filter.rb +85 -0
  22. data/lib/cucumber_feature_manager.rb +164 -0
  23. data/lib/grit/lib/grit.rb +75 -0
  24. data/lib/grit/lib/grit/actor.rb +36 -0
  25. data/lib/grit/lib/grit/blame.rb +61 -0
  26. data/lib/grit/lib/grit/blob.rb +126 -0
  27. data/lib/grit/lib/grit/commit.rb +247 -0
  28. data/lib/grit/lib/grit/commit_stats.rb +128 -0
  29. data/lib/grit/lib/grit/config.rb +44 -0
  30. data/lib/grit/lib/grit/diff.rb +70 -0
  31. data/lib/grit/lib/grit/errors.rb +7 -0
  32. data/lib/grit/lib/grit/git-ruby.rb +267 -0
  33. data/lib/grit/lib/grit/git-ruby/commit_db.rb +52 -0
  34. data/lib/grit/lib/grit/git-ruby/file_index.rb +193 -0
  35. data/lib/grit/lib/grit/git-ruby/git_object.rb +350 -0
  36. data/lib/grit/lib/grit/git-ruby/internal/file_window.rb +58 -0
  37. data/lib/grit/lib/grit/git-ruby/internal/loose.rb +137 -0
  38. data/lib/grit/lib/grit/git-ruby/internal/pack.rb +384 -0
  39. data/lib/grit/lib/grit/git-ruby/internal/raw_object.rb +37 -0
  40. data/lib/grit/lib/grit/git-ruby/object.rb +325 -0
  41. data/lib/grit/lib/grit/git-ruby/repository.rb +767 -0
  42. data/lib/grit/lib/grit/git.rb +323 -0
  43. data/lib/grit/lib/grit/index.rb +122 -0
  44. data/lib/grit/lib/grit/lazy.rb +33 -0
  45. data/lib/grit/lib/grit/merge.rb +45 -0
  46. data/lib/grit/lib/grit/ref.rb +74 -0
  47. data/lib/grit/lib/grit/repo.rb +482 -0
  48. data/lib/grit/lib/grit/ruby1.9.rb +7 -0
  49. data/lib/grit/lib/grit/status.rb +151 -0
  50. data/lib/grit/lib/grit/submodule.rb +88 -0
  51. data/lib/grit/lib/grit/tag.rb +16 -0
  52. data/lib/grit/lib/grit/tree.rb +123 -0
  53. data/lib/grit/lib/open3_detach.rb +46 -0
  54. data/spec/cucumber_f_m/aggregator_spec.rb +210 -0
  55. data/spec/cucumber_f_m/comment_module/comment_spec.rb +4 -0
  56. data/spec/cucumber_f_m/config_spec.rb +27 -0
  57. data/spec/cucumber_f_m/cvs/git_spec.rb +40 -0
  58. data/spec/cucumber_f_m/feature_all_tags_to_scenario_spec.rb +7 -0
  59. data/spec/cucumber_f_m/feature_file_manipulation_spec.rb +29 -0
  60. data/spec/cucumber_f_m/feature_module/background_spec.rb +30 -0
  61. data/spec/cucumber_f_m/feature_module/comment_spec.rb +23 -0
  62. data/spec/cucumber_f_m/feature_module/example_spec.rb +5 -0
  63. data/spec/cucumber_f_m/feature_module/info_spec.rb +30 -0
  64. data/spec/cucumber_f_m/feature_module/narrative_spec.rb +7 -0
  65. data/spec/cucumber_f_m/feature_module/scenario_outline_spec.rb +39 -0
  66. data/spec/cucumber_f_m/feature_module/scenario_spec.rb +33 -0
  67. data/spec/cucumber_f_m/feature_module/step_spec.rb +7 -0
  68. data/spec/cucumber_f_m/feature_module/tag_spec.rb +96 -0
  69. data/spec/cucumber_f_m/feature_spec.rb +229 -0
  70. data/spec/cucumber_f_m/tag_filter_spec.rb +191 -0
  71. data/spec/cucumber_feature_manager_spec.rb +59 -0
  72. data/spec/data/feature_manager/some_ruby_file.rb +0 -0
  73. data/spec/spec_helper.rb +1 -0
  74. metadata +141 -0
@@ -0,0 +1,58 @@
1
+ #
2
+ # converted from the gitrb project
3
+ #
4
+ # authors:
5
+ # Matthias Lederhofer <matled@gmx.net>
6
+ # Simon 'corecode' Schubert <corecode@fs.ei.tum.de>
7
+ # Scott Chacon <schacon@gmail.com>
8
+ #
9
+ # provides native ruby access to git objects and pack files
10
+ #
11
+
12
+ module Grit
13
+ module GitRuby
14
+ module Internal
15
+ class FileWindow
16
+ def initialize(file, version = 1)
17
+ @file = file
18
+ @offset = nil
19
+ if version == 2
20
+ @global_offset = 8
21
+ else
22
+ @global_offset = 0
23
+ end
24
+ end
25
+
26
+ def unmap
27
+ @file = nil
28
+ end
29
+
30
+ def [](*idx)
31
+ idx = idx[0] if idx.length == 1
32
+ case idx
33
+ when Range
34
+ offset = idx.first
35
+ len = idx.last - idx.first + idx.exclude_end? ? 0 : 1
36
+ when Fixnum
37
+ offset = idx
38
+ len = nil
39
+ when Array
40
+ offset, len = idx
41
+ else
42
+ raise RuntimeError, "invalid index param: #{idx.class}"
43
+ end
44
+ if @offset != offset
45
+ @file.seek(offset + @global_offset)
46
+ end
47
+ @offset = offset + len ? len : 1
48
+ if not len
49
+ @file.read(1).getord(0)
50
+ else
51
+ @file.read(len)
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+
@@ -0,0 +1,137 @@
1
+ #
2
+ # converted from the gitrb project
3
+ #
4
+ # authors:
5
+ # Matthias Lederhofer <matled@gmx.net>
6
+ # Simon 'corecode' Schubert <corecode@fs.ei.tum.de>
7
+ # Scott Chacon <schacon@gmail.com>
8
+ #
9
+ # provides native ruby access to git objects and pack files
10
+ #
11
+
12
+ require 'zlib'
13
+ require 'digest/sha1'
14
+ require 'grit/git-ruby/internal/raw_object'
15
+
16
+ module Grit
17
+ module GitRuby
18
+ module Internal
19
+ class LooseObjectError < StandardError
20
+ end
21
+
22
+ class LooseStorage
23
+ def initialize(directory)
24
+ @directory = directory
25
+ end
26
+
27
+ def [](sha1)
28
+ sha1 = sha1.unpack("H*")[0]
29
+ begin
30
+ return nil unless sha1[0...2] && sha1[2..39]
31
+ path = @directory + '/' + sha1[0...2] + '/' + sha1[2..39]
32
+ get_raw_object(File.read(path))
33
+ rescue Errno::ENOENT
34
+ nil
35
+ end
36
+ end
37
+
38
+ def get_raw_object(buf)
39
+ if buf.length < 2
40
+ raise LooseObjectError, "object file too small"
41
+ end
42
+
43
+ if legacy_loose_object?(buf)
44
+ content = Zlib::Inflate.inflate(buf)
45
+ header, content = content.split(/\0/, 2)
46
+ if !header || !content
47
+ raise LooseObjectError, "invalid object header"
48
+ end
49
+ type, size = header.split(/ /, 2)
50
+ if !%w(blob tree commit tag).include?(type) || size !~ /^\d+$/
51
+ raise LooseObjectError, "invalid object header"
52
+ end
53
+ type = type.to_sym
54
+ size = size.to_i
55
+ else
56
+ type, size, used = unpack_object_header_gently(buf)
57
+ content = Zlib::Inflate.inflate(buf[used..-1])
58
+ end
59
+ raise LooseObjectError, "size mismatch" if content.length != size
60
+ return RawObject.new(type, content)
61
+ end
62
+
63
+ # currently, I'm using the legacy format because it's easier to do
64
+ # this function takes content and a type and writes out the loose object and returns a sha
65
+ def put_raw_object(content, type)
66
+ size = content.length.to_s
67
+ LooseStorage.verify_header(type, size)
68
+
69
+ header = "#{type} #{size}\0"
70
+ store = header + content
71
+
72
+ sha1 = Digest::SHA1.hexdigest(store)
73
+ path = @directory+'/'+sha1[0...2]+'/'+sha1[2..40]
74
+
75
+ if !File.exists?(path)
76
+ content = Zlib::Deflate.deflate(store)
77
+
78
+ FileUtils.mkdir_p(@directory+'/'+sha1[0...2])
79
+ File.open(path, 'wb') do |f|
80
+ f.write content
81
+ end
82
+ end
83
+ return sha1
84
+ end
85
+
86
+ # simply figure out the sha
87
+ def self.calculate_sha(content, type)
88
+ size = content.length.to_s
89
+ verify_header(type, size)
90
+ header = "#{type} #{size}\0"
91
+ store = header + content
92
+
93
+ Digest::SHA1.hexdigest(store)
94
+ end
95
+
96
+ def self.verify_header(type, size)
97
+ if !%w(blob tree commit tag).include?(type) || size !~ /^\d+$/
98
+ raise LooseObjectError, "invalid object header"
99
+ end
100
+ end
101
+
102
+ # private
103
+ def unpack_object_header_gently(buf)
104
+ used = 0
105
+ c = buf.getord(used)
106
+ used += 1
107
+
108
+ type = (c >> 4) & 7;
109
+ size = c & 15;
110
+ shift = 4;
111
+ while c & 0x80 != 0
112
+ if buf.length <= used
113
+ raise LooseObjectError, "object file too short"
114
+ end
115
+ c = buf.getord(used)
116
+ used += 1
117
+
118
+ size += (c & 0x7f) << shift
119
+ shift += 7
120
+ end
121
+ type = OBJ_TYPES[type]
122
+ if ![:blob, :tree, :commit, :tag].include?(type)
123
+ raise LooseObjectError, "invalid loose object type"
124
+ end
125
+ return [type, size, used]
126
+ end
127
+ private :unpack_object_header_gently
128
+
129
+ def legacy_loose_object?(buf)
130
+ word = (buf.getord(0) << 8) + buf.getord(1)
131
+ buf.getord(0) == 0x78 && word % 31 == 0
132
+ end
133
+ private :legacy_loose_object?
134
+ end
135
+ end
136
+ end
137
+ end
@@ -0,0 +1,384 @@
1
+ #
2
+ # converted from the gitrb project
3
+ #
4
+ # authors:
5
+ # Matthias Lederhofer <matled@gmx.net>
6
+ # Simon 'corecode' Schubert <corecode@fs.ei.tum.de>
7
+ # Scott Chacon <schacon@gmail.com>
8
+ #
9
+ # provides native ruby access to git objects and pack files
10
+ #
11
+
12
+ require 'zlib'
13
+ require 'grit/git-ruby/internal/raw_object'
14
+ require 'grit/git-ruby/internal/file_window'
15
+
16
+ PACK_SIGNATURE = "PACK"
17
+ PACK_IDX_SIGNATURE = "\377tOc"
18
+
19
+ module Grit
20
+ module GitRuby
21
+ module Internal
22
+ class PackFormatError < StandardError
23
+ end
24
+
25
+ class PackStorage
26
+ OBJ_OFS_DELTA = 6
27
+ OBJ_REF_DELTA = 7
28
+
29
+ FanOutCount = 256
30
+ SHA1Size = 20
31
+ IdxOffsetSize = 4
32
+ OffsetSize = 4
33
+ CrcSize = 4
34
+ OffsetStart = FanOutCount * IdxOffsetSize
35
+ SHA1Start = OffsetStart + OffsetSize
36
+ EntrySize = OffsetSize + SHA1Size
37
+ EntrySizeV2 = SHA1Size + CrcSize + OffsetSize
38
+
39
+ def initialize(file)
40
+ if file =~ /\.idx$/
41
+ file = file[0...-3] + 'pack'
42
+ end
43
+ @name = file
44
+ @cache = {}
45
+ init_pack
46
+ end
47
+
48
+ def with_idx(index_file = nil)
49
+ if !index_file
50
+ index_file = @name
51
+ idxfile = File.open(@name[0...-4]+'idx', 'rb')
52
+ else
53
+ idxfile = File.open(index_file, 'rb')
54
+ end
55
+
56
+ # read header
57
+ sig = idxfile.read(4)
58
+ ver = idxfile.read(4).unpack("N")[0]
59
+
60
+ if sig == PACK_IDX_SIGNATURE
61
+ if(ver != 2)
62
+ raise PackFormatError, "pack #@name has unknown pack file version #{ver}"
63
+ end
64
+ @version = 2
65
+ else
66
+ @version = 1
67
+ end
68
+
69
+ idx = FileWindow.new(idxfile, @version)
70
+ yield idx
71
+ idx.unmap
72
+ ensure
73
+ idxfile.close
74
+ end
75
+
76
+ def with_packfile
77
+ packfile = File.open(@name, 'rb')
78
+ yield packfile
79
+ ensure
80
+ packfile.close
81
+ end
82
+
83
+ def cache_objects
84
+ @cache = {}
85
+ with_packfile do |packfile|
86
+ each_entry do |sha, offset|
87
+ data, type = unpack_object(packfile, offset, {:caching => true})
88
+ if data
89
+ @cache[sha] = RawObject.new(OBJ_TYPES[type], data)
90
+ end
91
+ end
92
+ end
93
+ end
94
+
95
+ def name
96
+ @name
97
+ end
98
+
99
+ def close
100
+ # shouldnt be anything open now
101
+ end
102
+
103
+ # given an index file, list out the shas that it's packfile contains
104
+ def get_shas
105
+ shas = []
106
+ each_sha1 { |sha| shas << sha.unpack("H*")[0] }
107
+ shas
108
+ end
109
+
110
+ def [](sha1)
111
+ if obj = @cache[sha1]
112
+ return obj
113
+ end
114
+
115
+ offset = find_object(sha1)
116
+ return nil if !offset
117
+ @cache[sha1] = obj = parse_object(offset)
118
+ return obj
119
+ end
120
+
121
+ def init_pack
122
+ with_idx do |idx|
123
+ @offsets = [0]
124
+ FanOutCount.times do |i|
125
+ pos = idx[i * IdxOffsetSize,IdxOffsetSize].unpack('N')[0]
126
+ if pos < @offsets[i]
127
+ raise PackFormatError, "pack #@name has discontinuous index #{i}"
128
+ end
129
+ @offsets << pos
130
+ end
131
+ @size = @offsets[-1]
132
+ end
133
+ end
134
+
135
+ def each_entry
136
+ with_idx do |idx|
137
+ if @version == 2
138
+ data = read_data_v2(idx)
139
+ data.each do |sha1, crc, offset|
140
+ yield sha1, offset
141
+ end
142
+ else
143
+ pos = OffsetStart
144
+ @size.times do
145
+ offset = idx[pos,OffsetSize].unpack('N')[0]
146
+ sha1 = idx[pos+OffsetSize,SHA1Size]
147
+ pos += EntrySize
148
+ yield sha1, offset
149
+ end
150
+ end
151
+ end
152
+ end
153
+
154
+ def read_data_v2(idx)
155
+ data = []
156
+ pos = OffsetStart
157
+ @size.times do |i|
158
+ data[i] = [idx[pos,SHA1Size], 0, 0]
159
+ pos += SHA1Size
160
+ end
161
+ @size.times do |i|
162
+ crc = idx[pos,CrcSize]
163
+ data[i][1] = crc
164
+ pos += CrcSize
165
+ end
166
+ @size.times do |i|
167
+ offset = idx[pos,OffsetSize].unpack('N')[0]
168
+ data[i][2] = offset
169
+ pos += OffsetSize
170
+ end
171
+ data
172
+ end
173
+ private :read_data_v2
174
+
175
+ def each_sha1
176
+ with_idx do |idx|
177
+ if @version == 2
178
+ data = read_data_v2(idx)
179
+ data.each do |sha1, crc, offset|
180
+ yield sha1
181
+ end
182
+ else
183
+ pos = SHA1Start
184
+ @size.times do
185
+ sha1 = idx[pos,SHA1Size]
186
+ pos += EntrySize
187
+ yield sha1
188
+ end
189
+ end
190
+ end
191
+ end
192
+
193
+ def find_object_in_index(idx, sha1)
194
+ slot = sha1.getord(0)
195
+ return nil if !slot
196
+ first, last = @offsets[slot,2]
197
+ while first < last
198
+ mid = (first + last) / 2
199
+ if @version == 2
200
+ midsha1 = idx[OffsetStart + (mid * SHA1Size), SHA1Size]
201
+ cmp = midsha1 <=> sha1
202
+
203
+ if cmp < 0
204
+ first = mid + 1
205
+ elsif cmp > 0
206
+ last = mid
207
+ else
208
+ pos = OffsetStart + (@size * (SHA1Size + CrcSize)) + (mid * OffsetSize)
209
+ offset = idx[pos, OffsetSize].unpack('N')[0]
210
+ return offset
211
+ end
212
+ else
213
+ midsha1 = idx[SHA1Start + mid * EntrySize,SHA1Size]
214
+ cmp = midsha1 <=> sha1
215
+
216
+ if cmp < 0
217
+ first = mid + 1
218
+ elsif cmp > 0
219
+ last = mid
220
+ else
221
+ pos = OffsetStart + mid * EntrySize
222
+ offset = idx[pos,OffsetSize].unpack('N')[0]
223
+ return offset
224
+ end
225
+ end
226
+ end
227
+ nil
228
+ end
229
+
230
+ def find_object(sha1)
231
+ obj = nil
232
+ with_idx do |idx|
233
+ obj = find_object_in_index(idx, sha1)
234
+ end
235
+ obj
236
+ end
237
+ private :find_object
238
+
239
+ def parse_object(offset)
240
+ obj = nil
241
+ with_packfile do |packfile|
242
+ data, type = unpack_object(packfile, offset)
243
+ obj = RawObject.new(OBJ_TYPES[type], data)
244
+ end
245
+ obj
246
+ end
247
+ protected :parse_object
248
+
249
+ def unpack_object(packfile, offset, options = {})
250
+ obj_offset = offset
251
+ packfile.seek(offset)
252
+
253
+ c = packfile.read(1).getord(0)
254
+ size = c & 0xf
255
+ type = (c >> 4) & 7
256
+ shift = 4
257
+ offset += 1
258
+ while c & 0x80 != 0
259
+ c = packfile.read(1).getord(0)
260
+ size |= ((c & 0x7f) << shift)
261
+ shift += 7
262
+ offset += 1
263
+ end
264
+
265
+ return [false, false] if !(type == OBJ_COMMIT || type == OBJ_TREE) && options[:caching]
266
+
267
+ case type
268
+ when OBJ_OFS_DELTA, OBJ_REF_DELTA
269
+ data, type = unpack_deltified(packfile, type, offset, obj_offset, size, options)
270
+ #puts type
271
+ when OBJ_COMMIT, OBJ_TREE, OBJ_BLOB, OBJ_TAG
272
+ data = unpack_compressed(offset, size)
273
+ else
274
+ raise PackFormatError, "invalid type #{type}"
275
+ end
276
+ [data, type]
277
+ end
278
+ private :unpack_object
279
+
280
+ def unpack_deltified(packfile, type, offset, obj_offset, size, options = {})
281
+ packfile.seek(offset)
282
+ data = packfile.read(SHA1Size)
283
+
284
+ if type == OBJ_OFS_DELTA
285
+ i = 0
286
+ c = data.getord(i)
287
+ base_offset = c & 0x7f
288
+ while c & 0x80 != 0
289
+ c = data.getord(i += 1)
290
+ base_offset += 1
291
+ base_offset <<= 7
292
+ base_offset |= c & 0x7f
293
+ end
294
+ base_offset = obj_offset - base_offset
295
+ offset += i + 1
296
+ else
297
+ base_offset = find_object(data)
298
+ offset += SHA1Size
299
+ end
300
+
301
+ base, type = unpack_object(packfile, base_offset)
302
+
303
+ return [false, false] if !(type == OBJ_COMMIT || type == OBJ_TREE) && options[:caching]
304
+
305
+ delta = unpack_compressed(offset, size)
306
+ [patch_delta(base, delta), type]
307
+ end
308
+ private :unpack_deltified
309
+
310
+ def unpack_compressed(offset, destsize)
311
+ outdata = ""
312
+ with_packfile do |packfile|
313
+ packfile.seek(offset)
314
+ zstr = Zlib::Inflate.new
315
+ while outdata.size < destsize
316
+ indata = packfile.read(4096)
317
+ if indata.size == 0
318
+ raise PackFormatError, 'error reading pack data'
319
+ end
320
+ outdata += zstr.inflate(indata)
321
+ end
322
+ if outdata.size > destsize
323
+ raise PackFormatError, 'error reading pack data'
324
+ end
325
+ zstr.close
326
+ end
327
+ outdata
328
+ end
329
+ private :unpack_compressed
330
+
331
+ def patch_delta(base, delta)
332
+ src_size, pos = patch_delta_header_size(delta, 0)
333
+ if src_size != base.size
334
+ raise PackFormatError, 'invalid delta data'
335
+ end
336
+
337
+ dest_size, pos = patch_delta_header_size(delta, pos)
338
+ dest = ""
339
+ while pos < delta.size
340
+ c = delta.getord(pos)
341
+ pos += 1
342
+ if c & 0x80 != 0
343
+ pos -= 1
344
+ cp_off = cp_size = 0
345
+ cp_off = delta.getord(pos += 1) if c & 0x01 != 0
346
+ cp_off |= delta.getord(pos += 1) << 8 if c & 0x02 != 0
347
+ cp_off |= delta.getord(pos += 1) << 16 if c & 0x04 != 0
348
+ cp_off |= delta.getord(pos += 1) << 24 if c & 0x08 != 0
349
+ cp_size = delta.getord(pos += 1) if c & 0x10 != 0
350
+ cp_size |= delta.getord(pos += 1) << 8 if c & 0x20 != 0
351
+ cp_size |= delta.getord(pos += 1) << 16 if c & 0x40 != 0
352
+ cp_size = 0x10000 if cp_size == 0
353
+ pos += 1
354
+ dest += base[cp_off,cp_size]
355
+ elsif c != 0
356
+ dest += delta[pos,c]
357
+ pos += c
358
+ else
359
+ raise PackFormatError, 'invalid delta data'
360
+ end
361
+ end
362
+ dest
363
+ end
364
+ private :patch_delta
365
+
366
+ def patch_delta_header_size(delta, pos)
367
+ size = 0
368
+ shift = 0
369
+ begin
370
+ c = delta.getord(pos)
371
+ if c == nil
372
+ raise PackFormatError, 'invalid delta header'
373
+ end
374
+ pos += 1
375
+ size |= (c & 0x7f) << shift
376
+ shift += 7
377
+ end while c & 0x80 != 0
378
+ [size, pos]
379
+ end
380
+ private :patch_delta_header_size
381
+ end
382
+ end
383
+ end
384
+ end