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.
- data/LICENCE +20 -0
- data/lib/cucumber_f_m/aggregator.rb +65 -0
- data/lib/cucumber_f_m/comment_module/comment.rb +7 -0
- data/lib/cucumber_f_m/config.rb +37 -0
- data/lib/cucumber_f_m/cvs/git.rb +7 -0
- data/lib/cucumber_f_m/feature.rb +141 -0
- data/lib/cucumber_f_m/feature_element/background.rb +10 -0
- data/lib/cucumber_f_m/feature_element/comment.rb +13 -0
- data/lib/cucumber_f_m/feature_element/component/comments.rb +21 -0
- data/lib/cucumber_f_m/feature_element/component/information/component.rb +16 -0
- data/lib/cucumber_f_m/feature_element/component/tags.rb +108 -0
- data/lib/cucumber_f_m/feature_element/component/title.rb +26 -0
- data/lib/cucumber_f_m/feature_element/component/total_estimation.rb +42 -0
- data/lib/cucumber_f_m/feature_element/example.rb +7 -0
- data/lib/cucumber_f_m/feature_element/info.rb +13 -0
- data/lib/cucumber_f_m/feature_element/narrative.rb +7 -0
- data/lib/cucumber_f_m/feature_element/scenario.rb +15 -0
- data/lib/cucumber_f_m/feature_element/scenario_outline.rb +23 -0
- data/lib/cucumber_f_m/feature_element/step.rb +7 -0
- data/lib/cucumber_f_m/statistic.rb +31 -0
- data/lib/cucumber_f_m/tag_filter.rb +85 -0
- data/lib/cucumber_feature_manager.rb +164 -0
- data/lib/grit/lib/grit.rb +75 -0
- data/lib/grit/lib/grit/actor.rb +36 -0
- data/lib/grit/lib/grit/blame.rb +61 -0
- data/lib/grit/lib/grit/blob.rb +126 -0
- data/lib/grit/lib/grit/commit.rb +247 -0
- data/lib/grit/lib/grit/commit_stats.rb +128 -0
- data/lib/grit/lib/grit/config.rb +44 -0
- data/lib/grit/lib/grit/diff.rb +70 -0
- data/lib/grit/lib/grit/errors.rb +7 -0
- data/lib/grit/lib/grit/git-ruby.rb +267 -0
- data/lib/grit/lib/grit/git-ruby/commit_db.rb +52 -0
- data/lib/grit/lib/grit/git-ruby/file_index.rb +193 -0
- data/lib/grit/lib/grit/git-ruby/git_object.rb +350 -0
- data/lib/grit/lib/grit/git-ruby/internal/file_window.rb +58 -0
- data/lib/grit/lib/grit/git-ruby/internal/loose.rb +137 -0
- data/lib/grit/lib/grit/git-ruby/internal/pack.rb +384 -0
- data/lib/grit/lib/grit/git-ruby/internal/raw_object.rb +37 -0
- data/lib/grit/lib/grit/git-ruby/object.rb +325 -0
- data/lib/grit/lib/grit/git-ruby/repository.rb +767 -0
- data/lib/grit/lib/grit/git.rb +323 -0
- data/lib/grit/lib/grit/index.rb +122 -0
- data/lib/grit/lib/grit/lazy.rb +33 -0
- data/lib/grit/lib/grit/merge.rb +45 -0
- data/lib/grit/lib/grit/ref.rb +74 -0
- data/lib/grit/lib/grit/repo.rb +482 -0
- data/lib/grit/lib/grit/ruby1.9.rb +7 -0
- data/lib/grit/lib/grit/status.rb +151 -0
- data/lib/grit/lib/grit/submodule.rb +88 -0
- data/lib/grit/lib/grit/tag.rb +16 -0
- data/lib/grit/lib/grit/tree.rb +123 -0
- data/lib/grit/lib/open3_detach.rb +46 -0
- data/spec/cucumber_f_m/aggregator_spec.rb +210 -0
- data/spec/cucumber_f_m/comment_module/comment_spec.rb +4 -0
- data/spec/cucumber_f_m/config_spec.rb +27 -0
- data/spec/cucumber_f_m/cvs/git_spec.rb +40 -0
- data/spec/cucumber_f_m/feature_all_tags_to_scenario_spec.rb +7 -0
- data/spec/cucumber_f_m/feature_file_manipulation_spec.rb +29 -0
- data/spec/cucumber_f_m/feature_module/background_spec.rb +30 -0
- data/spec/cucumber_f_m/feature_module/comment_spec.rb +23 -0
- data/spec/cucumber_f_m/feature_module/example_spec.rb +5 -0
- data/spec/cucumber_f_m/feature_module/info_spec.rb +30 -0
- data/spec/cucumber_f_m/feature_module/narrative_spec.rb +7 -0
- data/spec/cucumber_f_m/feature_module/scenario_outline_spec.rb +39 -0
- data/spec/cucumber_f_m/feature_module/scenario_spec.rb +33 -0
- data/spec/cucumber_f_m/feature_module/step_spec.rb +7 -0
- data/spec/cucumber_f_m/feature_module/tag_spec.rb +96 -0
- data/spec/cucumber_f_m/feature_spec.rb +229 -0
- data/spec/cucumber_f_m/tag_filter_spec.rb +191 -0
- data/spec/cucumber_feature_manager_spec.rb +59 -0
- data/spec/data/feature_manager/some_ruby_file.rb +0 -0
- data/spec/spec_helper.rb +1 -0
- metadata +141 -0
@@ -0,0 +1,323 @@
|
|
1
|
+
require 'tempfile'
|
2
|
+
module Grit
|
3
|
+
|
4
|
+
class Git
|
5
|
+
class GitTimeout < RuntimeError
|
6
|
+
attr_reader :command, :bytes_read
|
7
|
+
|
8
|
+
def initialize(command = nil, bytes_read = nil)
|
9
|
+
@command = command
|
10
|
+
@bytes_read = bytes_read
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
undef_method :clone
|
15
|
+
|
16
|
+
include GitRuby
|
17
|
+
|
18
|
+
def exist?
|
19
|
+
File.exist?(self.git_dir)
|
20
|
+
end
|
21
|
+
|
22
|
+
def put_raw_object(content, type)
|
23
|
+
ruby_git.put_raw_object(content, type)
|
24
|
+
end
|
25
|
+
|
26
|
+
def object_exists?(object_id)
|
27
|
+
ruby_git.object_exists?(object_id)
|
28
|
+
end
|
29
|
+
|
30
|
+
def select_existing_objects(object_ids)
|
31
|
+
object_ids.select do |object_id|
|
32
|
+
object_exists?(object_id)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
class << self
|
37
|
+
attr_accessor :git_binary, :git_timeout, :git_max_size
|
38
|
+
end
|
39
|
+
|
40
|
+
if RUBY_PLATFORM.downcase =~ /mswin(?!ce)|mingw|bccwin/
|
41
|
+
self.git_binary = "git" # using search path
|
42
|
+
else
|
43
|
+
self.git_binary = "/usr/bin/env git"
|
44
|
+
end
|
45
|
+
self.git_timeout = 10
|
46
|
+
self.git_max_size = 5242880 # 5.megabytes
|
47
|
+
|
48
|
+
def self.with_timeout(timeout = 10.seconds)
|
49
|
+
old_timeout = Grit::Git.git_timeout
|
50
|
+
Grit::Git.git_timeout = timeout
|
51
|
+
yield
|
52
|
+
Grit::Git.git_timeout = old_timeout
|
53
|
+
end
|
54
|
+
|
55
|
+
attr_accessor :git_dir, :bytes_read, :work_tree
|
56
|
+
|
57
|
+
def initialize(git_dir)
|
58
|
+
self.git_dir = git_dir
|
59
|
+
self.work_tree = git_dir.gsub(/\/\.git$/,'')
|
60
|
+
self.bytes_read = 0
|
61
|
+
end
|
62
|
+
|
63
|
+
def shell_escape(str)
|
64
|
+
str.to_s.gsub("'", "\\\\'").gsub(";", '\\;')
|
65
|
+
end
|
66
|
+
alias_method :e, :shell_escape
|
67
|
+
|
68
|
+
# Check if a normal file exists on the filesystem
|
69
|
+
# +file+ is the relative path from the Git dir
|
70
|
+
#
|
71
|
+
# Returns Boolean
|
72
|
+
def fs_exist?(file)
|
73
|
+
File.exist?(File.join(self.git_dir, file))
|
74
|
+
end
|
75
|
+
|
76
|
+
# Read a normal file from the filesystem.
|
77
|
+
# +file+ is the relative path from the Git dir
|
78
|
+
#
|
79
|
+
# Returns the String contents of the file
|
80
|
+
def fs_read(file)
|
81
|
+
File.read(File.join(self.git_dir, file))
|
82
|
+
end
|
83
|
+
|
84
|
+
# Write a normal file to the filesystem.
|
85
|
+
# +file+ is the relative path from the Git dir
|
86
|
+
# +contents+ is the String content to be written
|
87
|
+
#
|
88
|
+
# Returns nothing
|
89
|
+
def fs_write(file, contents)
|
90
|
+
path = File.join(self.git_dir, file)
|
91
|
+
FileUtils.mkdir_p(File.dirname(path))
|
92
|
+
File.open(path, 'w') do |f|
|
93
|
+
f.write(contents)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
# Delete a normal file from the filesystem
|
98
|
+
# +file+ is the relative path from the Git dir
|
99
|
+
#
|
100
|
+
# Returns nothing
|
101
|
+
def fs_delete(file)
|
102
|
+
FileUtils.rm_rf(File.join(self.git_dir, file))
|
103
|
+
end
|
104
|
+
|
105
|
+
# Move a normal file
|
106
|
+
# +from+ is the relative path to the current file
|
107
|
+
# +to+ is the relative path to the destination file
|
108
|
+
#
|
109
|
+
# Returns nothing
|
110
|
+
def fs_move(from, to)
|
111
|
+
FileUtils.mv(File.join(self.git_dir, from), File.join(self.git_dir, to))
|
112
|
+
end
|
113
|
+
|
114
|
+
# Make a directory
|
115
|
+
# +dir+ is the relative path to the directory to create
|
116
|
+
#
|
117
|
+
# Returns nothing
|
118
|
+
def fs_mkdir(dir)
|
119
|
+
FileUtils.mkdir_p(File.join(self.git_dir, dir))
|
120
|
+
end
|
121
|
+
|
122
|
+
# Chmod the the file or dir and everything beneath
|
123
|
+
# +file+ is the relative path from the Git dir
|
124
|
+
#
|
125
|
+
# Returns nothing
|
126
|
+
def fs_chmod(mode, file = '/')
|
127
|
+
FileUtils.chmod_R(mode, File.join(self.git_dir, file))
|
128
|
+
end
|
129
|
+
|
130
|
+
def list_remotes
|
131
|
+
remotes = []
|
132
|
+
Dir.chdir(File.join(self.git_dir, 'refs/remotes')) do
|
133
|
+
remotes = Dir.glob('*')
|
134
|
+
end
|
135
|
+
remotes
|
136
|
+
rescue
|
137
|
+
[]
|
138
|
+
end
|
139
|
+
|
140
|
+
def create_tempfile(seed, unlink = false)
|
141
|
+
path = Tempfile.new(seed).path
|
142
|
+
File.unlink(path) if unlink
|
143
|
+
return path
|
144
|
+
end
|
145
|
+
|
146
|
+
def commit_from_sha(id)
|
147
|
+
git_ruby_repo = GitRuby::Repository.new(self.git_dir)
|
148
|
+
object = git_ruby_repo.get_object_by_sha1(id)
|
149
|
+
|
150
|
+
if object.type == :commit
|
151
|
+
id
|
152
|
+
elsif object.type == :tag
|
153
|
+
object.object
|
154
|
+
else
|
155
|
+
''
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
def check_applies(head_sha, applies_sha)
|
160
|
+
git_index = create_tempfile('index', true)
|
161
|
+
(o1, exit1) = raw_git("git read-tree #{head_sha} 2>/dev/null", git_index)
|
162
|
+
(o2, exit2) = raw_git("git diff #{applies_sha}^ #{applies_sha} | git apply --check --cached >/dev/null 2>/dev/null", git_index)
|
163
|
+
return (exit1 + exit2)
|
164
|
+
end
|
165
|
+
|
166
|
+
def get_patch(applies_sha)
|
167
|
+
git_index = create_tempfile('index', true)
|
168
|
+
(patch, exit2) = raw_git("git diff #{applies_sha}^ #{applies_sha}", git_index)
|
169
|
+
patch
|
170
|
+
end
|
171
|
+
|
172
|
+
def apply_patch(head_sha, patch)
|
173
|
+
git_index = create_tempfile('index', true)
|
174
|
+
|
175
|
+
git_patch = create_tempfile('patch')
|
176
|
+
File.open(git_patch, 'w+') { |f| f.print patch }
|
177
|
+
|
178
|
+
raw_git("git read-tree #{head_sha} 2>/dev/null", git_index)
|
179
|
+
(op, exit) = raw_git("git apply --cached < #{git_patch}", git_index)
|
180
|
+
if exit == 0
|
181
|
+
return raw_git("git write-tree", git_index).first.chomp
|
182
|
+
end
|
183
|
+
false
|
184
|
+
end
|
185
|
+
|
186
|
+
# RAW CALLS WITH ENV SETTINGS
|
187
|
+
def raw_git_call(command, index)
|
188
|
+
tmp = ENV['GIT_INDEX_FILE']
|
189
|
+
ENV['GIT_INDEX_FILE'] = index
|
190
|
+
out = `#{command}`
|
191
|
+
after = ENV['GIT_INDEX_FILE'] # someone fucking with us ??
|
192
|
+
ENV['GIT_INDEX_FILE'] = tmp
|
193
|
+
if after != index
|
194
|
+
raise 'environment was changed for the git call'
|
195
|
+
end
|
196
|
+
[out, $?.exitstatus]
|
197
|
+
end
|
198
|
+
|
199
|
+
def raw_git(command, index)
|
200
|
+
output = nil
|
201
|
+
Dir.chdir(self.git_dir) do
|
202
|
+
output = raw_git_call(command, index)
|
203
|
+
end
|
204
|
+
output
|
205
|
+
end
|
206
|
+
# RAW CALLS WITH ENV SETTINGS END
|
207
|
+
|
208
|
+
|
209
|
+
|
210
|
+
# Run the given git command with the specified arguments and return
|
211
|
+
# the result as a String
|
212
|
+
# +cmd+ is the command
|
213
|
+
# +options+ is a hash of Ruby style options
|
214
|
+
# +args+ is the list of arguments (to be joined by spaces)
|
215
|
+
#
|
216
|
+
# Examples
|
217
|
+
# git.rev_list({:max_count => 10, :header => true}, "master")
|
218
|
+
#
|
219
|
+
# Returns String
|
220
|
+
def method_missing(cmd, options = {}, *args)
|
221
|
+
run('', cmd, '', options, args)
|
222
|
+
end
|
223
|
+
|
224
|
+
# Bypass any pure Ruby implementations and go straight to the native Git command
|
225
|
+
#
|
226
|
+
# Returns String
|
227
|
+
def native(cmd, options = {}, *args)
|
228
|
+
method_missing(cmd, options, *args)
|
229
|
+
end
|
230
|
+
|
231
|
+
def run(prefix, cmd, postfix, options, args)
|
232
|
+
timeout = options.delete(:timeout) rescue nil
|
233
|
+
timeout = true if timeout.nil?
|
234
|
+
|
235
|
+
opt_args = transform_options(options)
|
236
|
+
|
237
|
+
if RUBY_PLATFORM.downcase =~ /mswin(?!ce)|mingw|bccwin/
|
238
|
+
ext_args = args.reject { |a| a.empty? }.map { |a| (a == '--' || a[0].chr == '|') ? a : "\"#{e(a)}\"" }
|
239
|
+
call = "#{prefix}#{Git.git_binary} --git-dir=\"#{self.git_dir}\" #{cmd.to_s.gsub(/_/, '-')} #{(opt_args + ext_args).join(' ')}#{e(postfix)}"
|
240
|
+
else
|
241
|
+
ext_args = args.reject { |a| a.empty? }.map { |a| (a == '--' || a[0].chr == '|') ? a : "'#{e(a)}'" }
|
242
|
+
call = "#{prefix}#{Git.git_binary} --git-dir='#{self.git_dir}' #{cmd.to_s.gsub(/_/, '-')} #{(opt_args + ext_args).join(' ')}#{e(postfix)}"
|
243
|
+
end
|
244
|
+
|
245
|
+
Grit.log(call) if Grit.debug
|
246
|
+
response, err = timeout ? sh(call) : wild_sh(call)
|
247
|
+
Grit.log(response) if Grit.debug
|
248
|
+
Grit.log(err) if Grit.debug
|
249
|
+
response
|
250
|
+
end
|
251
|
+
|
252
|
+
def sh(command)
|
253
|
+
ret, err = '', ''
|
254
|
+
Open3.popen3(command) do |_, stdout, stderr|
|
255
|
+
Timeout.timeout(self.class.git_timeout) do
|
256
|
+
while tmp = stdout.read(1024)
|
257
|
+
ret += tmp
|
258
|
+
if (@bytes_read += tmp.size) > self.class.git_max_size
|
259
|
+
bytes = @bytes_read
|
260
|
+
@bytes_read = 0
|
261
|
+
raise GitTimeout.new(command, bytes)
|
262
|
+
end
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
while tmp = stderr.read(1024)
|
267
|
+
err += tmp
|
268
|
+
end
|
269
|
+
end
|
270
|
+
[ret, err]
|
271
|
+
rescue Timeout::Error, Grit::Git::GitTimeout
|
272
|
+
bytes = @bytes_read
|
273
|
+
@bytes_read = 0
|
274
|
+
raise GitTimeout.new(command, bytes)
|
275
|
+
end
|
276
|
+
|
277
|
+
def wild_sh(command)
|
278
|
+
ret, err = '', ''
|
279
|
+
Open3.popen3(command) do |_, stdout, stderr|
|
280
|
+
while tmp = stdout.read(1024)
|
281
|
+
ret += tmp
|
282
|
+
end
|
283
|
+
|
284
|
+
while tmp = stderr.read(1024)
|
285
|
+
err += tmp
|
286
|
+
end
|
287
|
+
end
|
288
|
+
[ret, err]
|
289
|
+
end
|
290
|
+
|
291
|
+
# Transform Ruby style options into git command line options
|
292
|
+
# +options+ is a hash of Ruby style options
|
293
|
+
#
|
294
|
+
# Returns String[]
|
295
|
+
# e.g. ["--max-count=10", "--header"]
|
296
|
+
def transform_options(options)
|
297
|
+
args = []
|
298
|
+
options.keys.each do |opt|
|
299
|
+
if opt.to_s.size == 1
|
300
|
+
if options[opt] == true
|
301
|
+
args << "-#{opt}"
|
302
|
+
elsif options[opt] == false
|
303
|
+
# ignore
|
304
|
+
else
|
305
|
+
val = options.delete(opt)
|
306
|
+
args << "-#{opt.to_s} '#{e(val)}'"
|
307
|
+
end
|
308
|
+
else
|
309
|
+
if options[opt] == true
|
310
|
+
args << "--#{opt.to_s.gsub(/_/, '-')}"
|
311
|
+
elsif options[opt] == false
|
312
|
+
# ignore
|
313
|
+
else
|
314
|
+
val = options.delete(opt)
|
315
|
+
args << "--#{opt.to_s.gsub(/_/, '-')}='#{e(val)}'"
|
316
|
+
end
|
317
|
+
end
|
318
|
+
end
|
319
|
+
args
|
320
|
+
end
|
321
|
+
end # Git
|
322
|
+
|
323
|
+
end # Grit
|
@@ -0,0 +1,122 @@
|
|
1
|
+
module Grit
|
2
|
+
|
3
|
+
class Index
|
4
|
+
attr_accessor :repo, :tree, :current_tree
|
5
|
+
|
6
|
+
def initialize(repo)
|
7
|
+
self.repo = repo
|
8
|
+
self.tree = {}
|
9
|
+
self.current_tree = nil
|
10
|
+
end
|
11
|
+
|
12
|
+
# Add a file to the index
|
13
|
+
# +path+ is the path (including filename)
|
14
|
+
# +data+ is the binary contents of the file
|
15
|
+
#
|
16
|
+
# Returns nothing
|
17
|
+
def add(file_path, data)
|
18
|
+
path = file_path.split('/')
|
19
|
+
filename = path.pop
|
20
|
+
|
21
|
+
current = self.tree
|
22
|
+
|
23
|
+
path.each do |dir|
|
24
|
+
current[dir] ||= {}
|
25
|
+
node = current[dir]
|
26
|
+
current = node
|
27
|
+
end
|
28
|
+
|
29
|
+
current[filename] = data
|
30
|
+
end
|
31
|
+
|
32
|
+
# Sets the current tree
|
33
|
+
# +tree+ the branch/tag/sha... to use - a string
|
34
|
+
#
|
35
|
+
# Returns index (self)
|
36
|
+
def read_tree(tree)
|
37
|
+
self.current_tree = self.repo.tree(tree)
|
38
|
+
end
|
39
|
+
|
40
|
+
# Commit the contents of the index
|
41
|
+
# +message+ is the commit message [nil]
|
42
|
+
# +parents+ is one or more commits to attach this commit to to form a new head [nil]
|
43
|
+
# +actor+ is the details of the user making the commit [nil]
|
44
|
+
# +last_tree+ is a tree to compare with - to avoid making empty commits [nil]
|
45
|
+
# +head+ is the branch to write this head to [master]
|
46
|
+
#
|
47
|
+
# Returns a String of the SHA1 of the commit
|
48
|
+
def commit(message, parents = nil, actor = nil, last_tree = nil, head = 'master')
|
49
|
+
tree_sha1 = write_tree(self.tree, self.current_tree)
|
50
|
+
return false if tree_sha1 == last_tree # don't write identical commits
|
51
|
+
|
52
|
+
contents = []
|
53
|
+
contents << ['tree', tree_sha1].join(' ')
|
54
|
+
parents.each do |p|
|
55
|
+
contents << ['parent', p].join(' ') if p
|
56
|
+
end if parents
|
57
|
+
|
58
|
+
if actor
|
59
|
+
name = actor.name
|
60
|
+
email = actor.email
|
61
|
+
else
|
62
|
+
config = Config.new(self.repo)
|
63
|
+
name = config['user.name']
|
64
|
+
email = config['user.email']
|
65
|
+
end
|
66
|
+
|
67
|
+
author_string = "#{name} <#{email}> #{Time.now.to_i} -0700" # !! TODO : gotta fix this
|
68
|
+
contents << ['author', author_string].join(' ')
|
69
|
+
contents << ['committer', author_string].join(' ')
|
70
|
+
contents << ''
|
71
|
+
contents << message
|
72
|
+
|
73
|
+
commit_sha1 = self.repo.git.put_raw_object(contents.join("\n"), 'commit')
|
74
|
+
|
75
|
+
self.repo.update_ref(head, commit_sha1)
|
76
|
+
end
|
77
|
+
|
78
|
+
# Recursively write a tree to the index
|
79
|
+
# +tree+ is the tree
|
80
|
+
#
|
81
|
+
# Returns the SHA1 String of the tree
|
82
|
+
def write_tree(tree, now_tree = nil)
|
83
|
+
tree_contents = {}
|
84
|
+
|
85
|
+
# fill in original tree
|
86
|
+
now_tree.contents.each do |obj|
|
87
|
+
sha = [obj.id].pack("H*")
|
88
|
+
k = obj.name
|
89
|
+
k += '/' if (obj.class == Grit::Tree)
|
90
|
+
tree_contents[k] = "%s %s\0%s" % [obj.mode.to_s, obj.name, sha]
|
91
|
+
end if now_tree
|
92
|
+
|
93
|
+
# overwrite with new tree contents
|
94
|
+
tree.each do |k, v|
|
95
|
+
case v
|
96
|
+
when String
|
97
|
+
sha = write_blob(v)
|
98
|
+
sha = [sha].pack("H*")
|
99
|
+
str = "%s %s\0%s" % ['100644', k, sha]
|
100
|
+
tree_contents[k] = str
|
101
|
+
when Hash
|
102
|
+
ctree = now_tree/k if now_tree
|
103
|
+
sha = write_tree(v, ctree)
|
104
|
+
sha = [sha].pack("H*")
|
105
|
+
str = "%s %s\0%s" % ['040000', k, sha]
|
106
|
+
tree_contents[k + '/'] = str
|
107
|
+
end
|
108
|
+
end
|
109
|
+
tr = tree_contents.sort.map { |k, v| v }.join('')
|
110
|
+
self.repo.git.put_raw_object(tr, 'tree')
|
111
|
+
end
|
112
|
+
|
113
|
+
# Write the blob to the index
|
114
|
+
# +data+ is the data to write
|
115
|
+
#
|
116
|
+
# Returns the SHA1 String of the blob
|
117
|
+
def write_blob(data)
|
118
|
+
self.repo.git.put_raw_object(data, 'blob')
|
119
|
+
end
|
120
|
+
end # Index
|
121
|
+
|
122
|
+
end # Grit
|
@@ -0,0 +1,33 @@
|
|
1
|
+
##
|
2
|
+
# Allows attributes to be declared as lazy, meaning that they won't be
|
3
|
+
# computed until they are asked for.
|
4
|
+
#
|
5
|
+
# Works by delegating each lazy_reader to a cached lazy_source method.
|
6
|
+
#
|
7
|
+
# class Person
|
8
|
+
# lazy_reader :eyes
|
9
|
+
#
|
10
|
+
# def lazy_source
|
11
|
+
# OpenStruct.new(:eyes => 2)
|
12
|
+
# end
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
# >> Person.new.eyes
|
16
|
+
# => 2
|
17
|
+
#
|
18
|
+
module Lazy
|
19
|
+
def lazy_reader(*args)
|
20
|
+
args.each do |arg|
|
21
|
+
ivar = "@#{arg}"
|
22
|
+
define_method(arg) do
|
23
|
+
if instance_variable_defined?(ivar)
|
24
|
+
val = instance_variable_get(ivar)
|
25
|
+
return val if val
|
26
|
+
end
|
27
|
+
instance_variable_set(ivar, (@lazy_source ||= lazy_source).send(arg))
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
Object.extend Lazy unless Object.ancestors.include? Lazy
|