burke 0.2.2 → 0.3.5

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -25,26 +25,27 @@ Here is a sample Rakefile using Burke.
25
25
  Burke.enable_all
26
26
 
27
27
  # Give Burke some data about the project
28
- Burke.setup do |s|
29
- s.name = 'foo'
30
- s.version = '1.2.3'
31
- s.summary = 'an example Ruby library with extra foo'
28
+ Burke.setup do
29
+ name 'foo'
30
+ version '1.2.3'
31
+ summary 'An example Ruby library with extra foo'
32
32
 
33
- s.docs do |d|
34
- d.markup = 'rdoc'
35
- end
33
+ docs.markup 'rdoc'
34
+
35
+ clean %w[.yardoc]
36
+ clobber %w[pkg doc html coverage]
36
37
 
37
- s.gems do |g|
38
- g.platform 'ruby'
38
+ gems do
39
+ add_platform 'ruby'
39
40
 
40
- g.platform 'x86-linux' do |p|
41
- p.before do |s|
41
+ add_platform 'x86-linux' do
42
+ before_build do |spec|
42
43
  cp 'native/libfoo-x86-linux.so', 'lib/libfoo.so'
43
- s.add_dependency 'ffi'
44
- s.files += ['lib/libfoo.so']
44
+ spec.add_dependency 'ffi'
45
+ spec.files += ['lib/libfoo.so']
45
46
  end
46
47
 
47
- p.after do
48
+ after_build do
48
49
  rm 'lib/libfoo.so'
49
50
  end
50
51
  end
data/Rakefile CHANGED
@@ -1,18 +1,16 @@
1
1
  $LOAD_PATH << File.join(File.dirname(File.expand_path(__FILE__)), 'lib')
2
2
  require 'burke'
3
3
 
4
- Burke.enable_all
5
-
6
- Burke.setup do |s|
7
- s.name = 'burke'
8
- s.summary = 'Helper for creating nice and clean Rake files'
9
- s.author = 'Aiden Nibali'
10
- s.email = 'dismal.denizen@gmail.com'
11
- s.homepage = "http://github.com/dismaldenizen/burke"
4
+ Burke.setup do
5
+ name 'burke'
6
+ summary 'Helper for creating nice, clean Rake files'
7
+ author 'Aiden Nibali'
8
+ email 'dismal.denizen@gmail.com'
9
+ homepage 'http://github.com/dismaldenizen/burke'
12
10
 
13
- s.has_rdoc = true
11
+ clean %w[.yardoc]
12
+ clobber %w[pkg doc html coverage]
14
13
 
15
- s.clean = %w[.yardoc]
16
- s.clobber = %w[pkg doc html]
14
+ rspec.rcov.failure_threshold = 70
17
15
  end
18
16
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.2
1
+ 0.3.5
@@ -0,0 +1,188 @@
1
+ require 'thread'
2
+
3
+ class Proc
4
+ def bind(object)
5
+ block, time = self, Time.now
6
+ (class << object; self end).class_eval do
7
+ method_name = "__bind_#{time.to_i}_#{time.usec}"
8
+ define_method(method_name, &block)
9
+ method = instance_method(method_name)
10
+ remove_method(method_name)
11
+ method
12
+ end.bind(object)
13
+ end
14
+ end
15
+
16
+ class Object
17
+ unless defined? instance_exec # 1.9
18
+ def instance_exec(*arguments, &block)
19
+ block.bind(self)[*arguments]
20
+ end
21
+ end
22
+ end
23
+
24
+ module Burke
25
+ class Holder < Hash
26
+ class CircularReadError < RuntimeError ; end
27
+
28
+ def holder_instance_exec? ; true ; end
29
+
30
+ class << self
31
+ attr_accessor :defaults
32
+
33
+ def inherited clazz
34
+ clazz.instance_eval do
35
+ @fields = []
36
+ @defaults = {}
37
+ end
38
+ end
39
+
40
+ def field name, &block
41
+ name = String(name)
42
+ @fields << name
43
+ @fields.uniq!
44
+ @defaults[name] = block if block_given?
45
+ end
46
+
47
+ def fields *names
48
+ names.each { |name| field name }
49
+ end
50
+
51
+ def field_exists? name
52
+ @fields.include? name
53
+ end
54
+
55
+ def [](hash)
56
+ new.merge hash
57
+ end
58
+ end
59
+
60
+ def initialize *args, &block
61
+ if block_given?
62
+ self.instance_exec self, &block
63
+ else
64
+ super
65
+ end
66
+
67
+ @currently_getting = []
68
+ @currently_getting_mutex = Mutex.new
69
+ end
70
+
71
+ def to_hash
72
+ out = {}
73
+ keys.concat(self.class.defaults.keys).uniq.each do |k|
74
+ out[k] = Holder === self[k] ? self[k].to_hash : self[k]
75
+ end
76
+ out
77
+ end
78
+
79
+ def [](key)
80
+ key = normalize_key key
81
+ assert_field_exists! key
82
+ id = "#{key}-#{Thread.current.object_id}"
83
+ @currently_getting_mutex.synchronize do
84
+ if @currently_getting.include? id
85
+ raise CircularReadError.new "circular read for field '#{key}'"
86
+ end
87
+ @currently_getting << id
88
+ end
89
+ val = if key? key
90
+ super
91
+ elsif self.class.defaults.key? key
92
+ self.instance_eval(&self.class.defaults[key])
93
+ else
94
+ nil
95
+ end
96
+ @currently_getting_mutex.synchronize do
97
+ @currently_getting.delete id
98
+ end
99
+ val
100
+ end
101
+
102
+ def []=(key, value)
103
+ key = normalize_key key
104
+ assert_field_exists! key
105
+ super
106
+ end
107
+
108
+ def merge! other
109
+ other.each do |k, v|
110
+ self[k] ||= v
111
+ end
112
+
113
+ nil
114
+ end
115
+
116
+ def merge other
117
+ holder = self.class.new
118
+
119
+ self.each do |k, v|
120
+ holder[k] = v
121
+ end
122
+
123
+ other.each do |k, v|
124
+ holder[k] ||= v
125
+ end
126
+
127
+ holder
128
+ end
129
+
130
+ def delete key
131
+ super normalize_key(key)
132
+ end
133
+
134
+ def method_missing name, *args, &block
135
+ base, ending = *String(name).match(/(\w*)([!?=]?)/).to_a[1..-1]
136
+ key = normalize_key(base)
137
+ case ending
138
+ when '?'
139
+ if field_exists? key
140
+ !!self[key]
141
+ else
142
+ super
143
+ end
144
+ when '='
145
+ if field_exists? key
146
+ self[key] = *args
147
+ else
148
+ super
149
+ end
150
+ when ''
151
+ if field_exists? key
152
+ if args.empty?
153
+ v = self[key]
154
+ if block_given?
155
+ if v.respond_to? 'holder_instance_exec?' and v.holder_instance_exec?
156
+ v.instance_exec v, &block
157
+ else
158
+ yield v
159
+ end
160
+ end
161
+ v
162
+ else
163
+ self[key] = *args
164
+ end
165
+ else
166
+ super
167
+ end
168
+ else
169
+ super
170
+ end
171
+ end
172
+
173
+ def normalize_key key
174
+ String(key)
175
+ end
176
+
177
+ def field_exists? name
178
+ self.class.field_exists? name
179
+ end
180
+
181
+ def assert_field_exists! name
182
+ unless field_exists? name
183
+ raise NoMethodError, "field '#{name}' is not defined for this Holder."
184
+ end
185
+ end
186
+ end
187
+ end
188
+
@@ -0,0 +1,15 @@
1
+ module Burke
2
+ Settings.field(:clean) { self.clean = [] }
3
+ Settings.field(:clobber) { self.clobber = [] }
4
+
5
+ define_task 'clean' do |s|
6
+ require 'rake/clean'
7
+ CLEAN.include(*s.clean) if s.clean
8
+ end
9
+
10
+ define_task 'clobber' do |s|
11
+ require 'rake/clean'
12
+ CLOBBER.include(*s.clobber) if s.clobber
13
+ end
14
+ end
15
+
@@ -0,0 +1,46 @@
1
+ module Burke
2
+ Settings.field(:docs) { self.docs = DocSettings.new }
3
+
4
+ class DocSettings < Holder
5
+ field 'title' do
6
+ "#{Burke.settings.name} #{Burke.settings.version}"
7
+ end
8
+
9
+ field 'files' do
10
+ fl = FileList.new
11
+ fl.include "lib/**/*.rb"
12
+ fl.include(([readme_file] + extra_files).compact)
13
+ fl.to_a.freeze
14
+ end
15
+
16
+ field 'extra_files' do
17
+ [license_file].compact.freeze
18
+ end
19
+
20
+ field 'readme_file' do
21
+ find_file('readme{.*,}').freeze
22
+ end
23
+
24
+ field 'license_file' do
25
+ find_file('{licen{c,s}e,copying}{.*,}').freeze
26
+ end
27
+
28
+ field 'markup' do
29
+ case File.extname(readme_file).downcase
30
+ when '.rdoc'
31
+ 'rdoc'
32
+ when '.md', '.markdown'
33
+ 'markdown'
34
+ when '.textile'
35
+ 'textile'
36
+ end.freeze
37
+ end
38
+
39
+ private
40
+ def find_file pattern
41
+ files = Dir.glob(pattern, File::FNM_CASEFOLD)
42
+ files.find { |f| File.readable? f and File.file? f }
43
+ end
44
+ end
45
+ end
46
+
@@ -0,0 +1,117 @@
1
+ module Burke
2
+ Settings.field(:gems) { self.gems = GlobalGemSettings.new }
3
+
4
+ define_task 'gems' do |s|
5
+ s.gems.individuals.each do |conf|
6
+ GemTaskManager.add_task conf
7
+ end
8
+
9
+ t = GemTaskManager.task_for_this_platform
10
+ unless t.nil?
11
+ desc "Build gem for this platform"
12
+ task(:gem => t.task_name)
13
+ end
14
+ end
15
+
16
+ define_task 'install' => 'gems' do |s|
17
+ require 'rubygems/installer'
18
+
19
+ t = GemTaskManager.task_for_this_platform
20
+ raise "no gem task for this platform" if t.nil?
21
+
22
+ desc "Install gem for this platform"
23
+ task 'install' => [t.task_name] do
24
+ Gem::Installer.new(File.join(t.package_dir, t.gem_file)).install
25
+ end
26
+ end
27
+
28
+ class GlobalGemSettings < Holder
29
+ field(:package_dir) { 'pkg' }
30
+
31
+ attr_reader :individuals
32
+
33
+ def add_platform plaf, &block
34
+ conf = IndividualGemSettings.new plaf
35
+ @individuals ||= []
36
+ @individuals << conf
37
+ conf.instance_exec conf, &block if block_given?
38
+ conf
39
+ end
40
+ end
41
+
42
+ class IndividualGemSettings < Holder
43
+ attr_reader :platform
44
+
45
+ field(:gemspec) do
46
+ spec = Burke.base_gemspec.dup
47
+ spec.platform = @platform
48
+ spec
49
+ end
50
+ field(:gem_file) { "#{gemspec.full_name}.gem" }
51
+ field(:package_dir) { Burke.settings.gems.package_dir }
52
+
53
+ def initialize plaf
54
+ super
55
+ @platform = Gem::Platform.new plaf
56
+ end
57
+
58
+ def task_name
59
+ "gem:#{platform}"
60
+ end
61
+
62
+ def before_build &block
63
+ @before = block if block_given?
64
+ @before
65
+ end
66
+
67
+ def after_build &block
68
+ @after = block if block_given?
69
+ @after
70
+ end
71
+ end
72
+
73
+ class GemTaskManager
74
+ TASKS = {}
75
+
76
+ def self.add_task conf
77
+ gemspec = conf.gemspec
78
+ name = conf.task_name
79
+ pkg_dir = conf.package_dir
80
+
81
+ unless Rake::Task.tasks.find {|t| t.name == 'gems'}
82
+ desc "Build gems for all targets"
83
+ end
84
+ task(:gems => name)
85
+
86
+ unless Rake::Task.tasks.find {|t| t.name == name}
87
+ desc "Build gem for target '#{gemspec.platform}'"
88
+ end
89
+ task(name) do |t|
90
+ conf.before_build.call gemspec unless conf.before_build.nil?
91
+ builder = Gem::Builder.new(gemspec)
92
+ builder.build
93
+ verbose true do
94
+ mkdir pkg_dir unless File.exists? pkg_dir
95
+ mv conf.gem_file, File.join(pkg_dir, conf.gem_file)
96
+ end
97
+ conf.after_build.call gemspec unless conf.after_build.nil?
98
+ end
99
+
100
+ TASKS[gemspec.platform.to_s] = conf
101
+ end
102
+
103
+ def self.task_for_this_platform
104
+ platform = Gem::Platform.new(RUBY_PLATFORM).to_s
105
+ name = nil
106
+
107
+ if TASKS.key? platform
108
+ name = platform
109
+ elsif TASKS.key? 'ruby'
110
+ name = "ruby"
111
+ end
112
+
113
+ TASKS[name]
114
+ end
115
+ end
116
+ end
117
+
@@ -0,0 +1,12 @@
1
+ module Burke
2
+ define_task 'rdoc' do |s|
3
+ require 'rake/rdoctask'
4
+ d = s.docs
5
+ Rake::RDocTask.new 'rdoc' do |r|
6
+ r.rdoc_files.include d.files
7
+ r.title = d.title
8
+ r.main = d.readme_file if d.readme_file
9
+ end
10
+ end
11
+ end
12
+
@@ -0,0 +1,81 @@
1
+ module Burke
2
+ define_task 'release' do |s|
3
+ begin
4
+ require 'git'
5
+ rescue LoadError
6
+ raise "'git' gem is not available"
7
+ end
8
+ if s.key? 'version'
9
+ raise "version is managed in an unknown way"
10
+ end
11
+ desc 'Release a new version of this project'
12
+ task 'release' do |t|
13
+ g = Git.open '.'
14
+ st = g.status
15
+ unless st.added.empty? and st.changed.empty? and st.deleted.empty?
16
+ puts "Please commit changes with Git before releasing."
17
+ else
18
+ release_type = 0
19
+ until (1..4).include? release_type
20
+ puts "Please select type of release:"
21
+ puts "1. Major"
22
+ puts "2. Minor"
23
+ puts "3. Patch"
24
+ puts "4. Enter version manually"
25
+ print "> "
26
+ release_type = $stdin.gets.to_i
27
+ puts
28
+ end
29
+
30
+ old_version = Gem::Version.new(s.version)
31
+ new_version = nil
32
+
33
+ if release_type == 4
34
+ until new_version
35
+ print "Current version is #{old_version}. "
36
+ puts "Please enter a new version number:"
37
+ print "> "
38
+ new_version = $stdin.gets
39
+ if new_version.strip.empty?
40
+ new_version = nil
41
+ else
42
+ new_version = Gem::Version.new(new_version)
43
+ end
44
+ puts
45
+ end
46
+ else
47
+ segments = old_version.segments
48
+ segments[release_type - 1] += 1
49
+ new_version = Gem::Version.new(segments.join('.'))
50
+ end
51
+
52
+ print "The VERSION file will be changed from containing '#{old_version}' "
53
+ print "to '#{new_version}'. The changes will be commited to the Git "
54
+ print "repository and tagged with 'v#{new_version}'."
55
+ puts
56
+
57
+ continue = nil
58
+ until ['y', 'n', 'yes', 'no'].include? continue
59
+ puts "Continue? [Y]es, [N]o"
60
+ print "> "
61
+ continue = $stdin.gets.strip.downcase
62
+ puts
63
+ end
64
+
65
+ if %w[yes y].include? continue
66
+ open 'VERSION', 'w' do |f|
67
+ f.puts new_version.to_s
68
+ end
69
+
70
+ g.commit_all "version bumped to #{new_version}"
71
+ g.lib.send(:command, 'tag', ['-a', "v#{new_version}", '-m', "version #{new_version}"])
72
+
73
+ puts "Version updated."
74
+ else
75
+ puts "Version not updated."
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
81
+
@@ -0,0 +1,76 @@
1
+ module Burke
2
+ Settings.field(:rspec) { self.rspec = RSpecSettings.new }
3
+
4
+ define_task 'spec' do |s|
5
+ begin
6
+ require 'rspec/core/rake_task'
7
+ rescue LoadError
8
+ raise "'rspec' gem is not available"
9
+ end
10
+
11
+ RSpec::Core::RakeTask.new 'spec' do |t|
12
+ build_spec_task t, s.rspec
13
+ end
14
+ end
15
+
16
+ define_task 'spec:rcov' do |s|
17
+ begin
18
+ require 'rspec/core/rake_task'
19
+ rescue LoadError
20
+ raise "'rspec' gem is not available"
21
+ end
22
+
23
+ desc "Run RSpec code examples and generate full RCov report"
24
+ RSpec::Core::RakeTask.new('spec:rcov') do |t|
25
+ t.rcov = true
26
+ t.rcov_opts = [
27
+ '-Ilib',
28
+ '--exclude', "'spec/,#{s.rakefile_file}'",
29
+ ]
30
+ end
31
+ end
32
+
33
+ define_task 'spec:rcov:verify' do |s|
34
+ begin
35
+ require 'rspec/core/rake_task'
36
+ rescue LoadError
37
+ raise "'rspec' gem is not available"
38
+ end
39
+
40
+ desc "Run RSpec code examples and verify RCov percentage"
41
+ RSpec::Core::RakeTask.new('spec:rcov:verify') do |t|
42
+ t.rcov = true
43
+ t.rcov_opts = [
44
+ '--failure-threshold', s.rspec.rcov.failure_threshold,
45
+ '-Ilib',
46
+ '--exclude', "'spec/,#{s.rakefile_file}'",
47
+ '--no-html'
48
+ ]
49
+ end
50
+ end
51
+
52
+ def self.build_spec_task task, rspec_settings
53
+ t = task
54
+ r = rspec_settings
55
+ t.ruby_opts = r.ruby_opts if r.ruby_opts
56
+ end
57
+
58
+ class RCovSettings < Holder
59
+ field 'failure_threshold'
60
+ end
61
+
62
+ class RSpecSettings < Holder
63
+ field('color') { true }
64
+ field('format') { 'progress' }
65
+
66
+ field 'ruby_opts'
67
+ field('rcov') { self.rcov = RCovSettings.new }
68
+
69
+ private
70
+ def find_file pattern
71
+ files = Dir.glob(pattern, File::FNM_CASEFOLD)
72
+ files.find { |f| File.readable? f and File.file? f }
73
+ end
74
+ end
75
+ end
76
+
@@ -0,0 +1,20 @@
1
+ module Burke
2
+ Settings.field(:test) { self.test = TestSettings.new }
3
+
4
+ define_task 'test' do |s|
5
+ if @settings.test.files.empty?
6
+ raise "project doesn't seem have any test files"
7
+ end
8
+ require 'rake/testtask'
9
+ Rake::TestTask.new do |t|
10
+ t.test_files = s.test.files
11
+ end
12
+ end
13
+
14
+ class TestSettings < Holder
15
+ field 'files' do
16
+ Dir['test/**/{*_{test,tc},{test,tc}_*}.rb'].freeze
17
+ end
18
+ end
19
+ end
20
+
@@ -0,0 +1,20 @@
1
+ module Burke
2
+ define_task 'yard' do |s|
3
+ begin
4
+ require 'yard'
5
+ rescue LoadError
6
+ raise "'yard' gem is not available"
7
+ end
8
+
9
+ opts = []
10
+ d = s.docs
11
+ opts << "--title" << d.title
12
+ opts << "--readme" << d.readme_file if d.readme_file
13
+ opts << "--markup" << d.markup if d.markup
14
+ opts << "--files" << d.extra_files.join(',') unless d.extra_files.empty?
15
+ YARD::Rake::YardocTask.new 'yard' do |t|
16
+ t.options = opts
17
+ end
18
+ end
19
+ end
20
+