burke 0.2.2 → 0.3.5

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/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
+