blackwinter-hen 0.1.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/lib/hen.rb ADDED
@@ -0,0 +1,305 @@
1
+ #--
2
+ ###############################################################################
3
+ # #
4
+ # hen -- Just a Rake helper #
5
+ # #
6
+ # Copyright (C) 2007-2008 University of Cologne, #
7
+ # Albertus-Magnus-Platz, #
8
+ # 50932 Cologne, Germany #
9
+ # #
10
+ # Authors: #
11
+ # Jens Wille <jens.wille@uni-koeln.de> #
12
+ # #
13
+ # hen is free software; you can redistribute it and/or modify it under the #
14
+ # terms of the GNU General Public License as published by the Free Software #
15
+ # Foundation; either version 3 of the License, or (at your option) any later #
16
+ # version. #
17
+ # #
18
+ # hen is distributed in the hope that it will be useful, but WITHOUT ANY #
19
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
20
+ # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more #
21
+ # details. #
22
+ # #
23
+ # You should have received a copy of the GNU General Public License along #
24
+ # with hen. If not, see <http://www.gnu.org/licenses/>. #
25
+ # #
26
+ ###############################################################################
27
+ #++
28
+
29
+ require 'yaml'
30
+ require 'forwardable'
31
+
32
+ require 'rubygems'
33
+ require 'rake'
34
+ require 'nuggets/env/user_home'
35
+ require 'nuggets/proc/bind'
36
+
37
+ require 'hen/dsl'
38
+ require 'hen/version'
39
+
40
+ class Hen
41
+
42
+ # The directories which contain the hen files
43
+ HENDIRS = [File.join(File.dirname(__FILE__), 'hens')] +
44
+ (ENV['HENPATH'] || '').split(File::PATH_SEPARATOR)
45
+
46
+ # All hens found, mapped by their name
47
+ HENS = Dir[*HENDIRS.map { |d| "#{d}/*.rake" }].uniq.inject(
48
+ Hash.new { |h, k| h[k] = [] }
49
+ ) { |hash, hen|
50
+ hash[File.basename(hen, '.rake')] << hen; hash
51
+ }
52
+
53
+ # Directories to search for .henrc
54
+ RCDIRS = ['.', ENV.user_home]
55
+
56
+ # A container for all loaded hens
57
+ @hens = {}
58
+
59
+ # The verbosity concerning errors and warnings
60
+ @verbose = true
61
+
62
+ class << self
63
+
64
+ attr_reader :hens, :verbose
65
+
66
+ # call-seq:
67
+ # lay!
68
+ # lay!(:some_hen, :some_other_hen)
69
+ # lay!(:exclude => [:some_hen, :some_other_hen])
70
+ #
71
+ # Loads the hens, causing them to lay their eggs^H^H^Htasks. Either all,
72
+ # if no restrictions are specified, or the given hens, or all but those
73
+ # given in the <tt>:exclude</tt> option.
74
+ def lay!(*args)
75
+ # Extract potential options hash
76
+ options = args.last.is_a?(Hash) ? args.pop : {}
77
+
78
+ @verbose = options[:verbose] if options.has_key?(:verbose)
79
+
80
+ if block_given?
81
+ yield.each { |key, value|
82
+ config[key].update(value)
83
+ }
84
+ end
85
+
86
+ # Handle include/exclude requirements
87
+ excl = options[:exclude]
88
+ args, default = args.empty? ? [excl ? [*excl] : [], true] : [args, false]
89
+
90
+ inclexcl = Hash.new(default)
91
+ args.each { |arg|
92
+ inclexcl[arg.to_s] = !default
93
+ }
94
+
95
+ # Load all available hens (as far as the
96
+ # include/exclude conditions are met)
97
+ load_hens { |hen|
98
+ inclexcl[hen]
99
+ }
100
+
101
+ # Execute each hen definition
102
+ hens.each { |name, hen|
103
+ # Load any dependencies, in case they're not included yet
104
+ begin
105
+ load_hens(*hen.dependencies)
106
+ rescue LoadError => err
107
+ warn "#{name}: Required dependency missing: " <<
108
+ File.basename(err.to_s, '.rake') if verbose
109
+ next
110
+ end
111
+
112
+ hen.lay!
113
+ }
114
+ end
115
+
116
+ # call-seq:
117
+ # add_hen(hen, overwrite = false)
118
+ #
119
+ # Adds +hen+ to the global container. Overwrites
120
+ # an existing hen only if +overwrite+ is true.
121
+ def add_hen(hen, overwrite = false)
122
+ if overwrite
123
+ @hens[hen.name] = hen
124
+ else
125
+ @hens[hen.name] ||= hen
126
+ end
127
+ end
128
+
129
+ # call-seq:
130
+ # Hen[hen] => aHen
131
+ #
132
+ # Get hen by name.
133
+ def [](hen)
134
+ @hens[hen]
135
+ end
136
+
137
+ # call-seq:
138
+ # henrc => aString
139
+ #
140
+ # The path to the user's .henrc
141
+ def henrc(location_only = false)
142
+ @henrc ||= find_henrc(location_only)
143
+ end
144
+
145
+ # call-seq:
146
+ # config => aHash
147
+ # config(key) => aValue
148
+ #
149
+ # The configuration resulting from the user's .henrc. Takes optional
150
+ # +key+ argument as "path" into the config hash, returning the thusly
151
+ # retrieved value.
152
+ #
153
+ # Example:
154
+ # config('a/b/c') #=> @config[:a][:b][:c]
155
+ def config(key = nil)
156
+ @config ||= YAML.load_file(henrc)
157
+ return @config unless key
158
+
159
+ key.split('/').inject(@config) { |value, k|
160
+ value.fetch(k.to_sym)
161
+ }
162
+ rescue IndexError, NoMethodError
163
+ end
164
+
165
+ private
166
+
167
+ # call-seq:
168
+ # find_henrc(location_only = false) => aString
169
+ #
170
+ # Search for a readable .henrc, or, if +location_only+ is true, just return
171
+ # a suitable default location.
172
+ def find_henrc(location_only = false)
173
+ return ENV['HENRC'] || File.join(RCDIRS.last, '.henrc') if location_only
174
+
175
+ if henrc = ENV['HENRC']
176
+ abort "The specified .henrc file could not be found: #{henrc}" \
177
+ unless File.readable?(henrc)
178
+ elsif henrc = RCDIRS.find { |dir|
179
+ h = File.join(dir, '.henrc')
180
+ break h if File.readable?(h)
181
+ }
182
+ else
183
+ abort "No .henrc file could be found! Please " <<
184
+ "create one first by running 'hen config'."
185
+ end
186
+
187
+ henrc
188
+ end
189
+
190
+ # call-seq:
191
+ # load_hens(*hens)
192
+ # load_hens(*hens) { |hen_name| ... }
193
+ #
194
+ # Actually loads the hen files for +hens+, or all available if none are
195
+ # specified. If a block is given, only those hen files are loaded for
196
+ # which the block evaluates to true.
197
+ def load_hens(*hens, &block)
198
+ # By default, include all
199
+ block ||= lambda { |_| true }
200
+
201
+ (hens.empty? ? HENS.keys : hens).each { |hen|
202
+ hen = hen.to_s
203
+ next unless block[hen]
204
+
205
+ HENS[hen].each { |h| load h }
206
+ }
207
+ end
208
+
209
+ end
210
+
211
+ extend Forwardable
212
+
213
+ # Forward to the class
214
+ def_delegators self, :verbose
215
+
216
+ attr_reader :name, :dependencies, :block
217
+
218
+ # call-seq:
219
+ # new(args, overwrite = false) { ... }
220
+ #
221
+ # Creates a new Hen instance of a certain name and optional
222
+ # dependencies; see #resolve_args for details on the +args+
223
+ # argument. Requires a definition block; see #lay! for details.
224
+ #
225
+ # Adds itself to the global hen container via add_hen.
226
+ def initialize(args, overwrite = false, &block)
227
+ @name, @dependencies = resolve_args(args)
228
+
229
+ unless @block = block
230
+ raise LocalJumpError, "#{@name}: no block given" if verbose
231
+ return
232
+ end
233
+
234
+ self.class.add_hen(self, overwrite)
235
+ end
236
+
237
+ # call-seq:
238
+ # hen.lay!
239
+ #
240
+ # Runs the definition block, exposing helper methods from the DSL.
241
+ def lay!
242
+ return if laid?
243
+
244
+ # Call dependencies first
245
+ dependencies.each { |hen|
246
+ self.class[hen].lay!
247
+ }
248
+
249
+ block.bind(DSL).call
250
+ rescue => err
251
+ warn "#{name}: #{err} (#{err.class})" if verbose
252
+ end
253
+
254
+ private
255
+
256
+ # call-seq:
257
+ # resolve_args(args) => [name, dependencies]
258
+ #
259
+ # Splits into hen name and optional dependencies: +args+ may be a single
260
+ # symbol (or string), or a hash with a single key pointing to a list of
261
+ # hens this one depends upon.
262
+ def resolve_args(args)
263
+ name, dependencies = case args
264
+ when Hash
265
+ raise ArgumentError, "Too many hen names: #{args.keys.join(' ')}" \
266
+ if args.size > 1
267
+ raise ArgumentError, 'No hen name given' \
268
+ if args.size < 1
269
+
270
+ [args.keys.first, [*args.values.first]]
271
+ else
272
+ [args, []]
273
+ end
274
+
275
+ [name.to_sym, dependencies.map { |d| d.to_sym }]
276
+ end
277
+
278
+ # call-seq:
279
+ # laid? => true or false
280
+ #
281
+ # Keeps track of whether the block has already been executed.
282
+ def laid?
283
+ return @laid if @laid
284
+
285
+ @laid = true
286
+ false
287
+ end
288
+
289
+ end
290
+
291
+ # call-seq:
292
+ # Hen(args) { ... }
293
+ #
294
+ # Just forwards to Hen.new.
295
+ def Hen(args, &block)
296
+ Hen.new(args, &block)
297
+ end
298
+
299
+ # call-seq:
300
+ # Hen!(args) { ... }
301
+ #
302
+ # Same as above, but overwrites any existing hen with the same name.
303
+ def Hen!(args, &block)
304
+ Hen.new(args, true, &block)
305
+ end
data/lib/hens/gem.rake ADDED
@@ -0,0 +1,129 @@
1
+ Hen :gem => :rdoc do
2
+ # Dependencies:
3
+ # * rdoc -- Uses RDOC_OPTIONS and 'publish_docs' task
4
+
5
+ require 'rake/gempackagetask'
6
+
7
+ gem_options = config[:gem]
8
+ rf_config = config[:rubyforge]
9
+
10
+ if Object.const_defined?(:RDOC_OPTIONS)
11
+ gem_options[:rdoc_options] ||= RDOC_OPTIONS[:options]
12
+ rdoc_files = RDOC_OPTIONS[:rdoc_files]
13
+ end
14
+
15
+ gem_spec = Gem::Specification.new { |spec|
16
+
17
+ ### name
18
+
19
+ gem_options[:name] ||= rf_config[:package]
20
+
21
+ abort 'Gem name missing' unless gem_options[:name]
22
+
23
+ ### version
24
+
25
+ abort 'Gem version missing' unless gem_options[:version]
26
+
27
+ if gem_options.delete(:append_svnversion) && svnversion = `svnversion`[/\d+/]
28
+ gem_options[:version] << '.' << svnversion
29
+ end
30
+
31
+ ### author(s)
32
+
33
+ if author = gem_options.delete(:author)
34
+ gem_options[:authors] ||= [author]
35
+ end
36
+
37
+ ### description
38
+
39
+ gem_options[:description] ||= gem_options[:summary]
40
+
41
+ ### rubyforge project, homepage
42
+
43
+ gem_options[:rubyforge_project] ||= rf_config[:project]
44
+
45
+ if rf_project = gem_options[:rubyforge_project]
46
+ rdoc_dir = rf_config[:rdoc_dir] == :package ?
47
+ rf_config[:package] || gem_options[:name] : RDOC_OPTIONS[:rdoc_dir]
48
+
49
+ gem_options[:homepage] ||= "#{rf_project}.rubyforge.org/#{rdoc_dir}"
50
+ end
51
+
52
+ if gem_options[:homepage] && gem_options[:homepage] !~ %r{://}
53
+ gem_options[:homepage] = 'http://' << gem_options[:homepage]
54
+ end
55
+
56
+ ### extra_rdoc_files, files, executables, bindir
57
+
58
+ gem_options[:files] ||= []
59
+ gem_options[:extra_rdoc_files] ||= rdoc_files - gem_options[:files] if rdoc_files
60
+ gem_options[:files] += gem_options.delete(:extra_files) || []
61
+
62
+ gem_options[:executables] ||= gem_options[:files].grep(/\Abin\//)
63
+
64
+ [:extra_rdoc_files, :files, :executables].each { |files|
65
+ gem_options[files].delete_if { |file| !File.exists?(file) }
66
+ }
67
+
68
+ unless gem_options[:executables].empty?
69
+ gem_options[:bindir] ||= File.dirname(gem_options[:executables].first)
70
+ gem_options[:executables].map! { |executable| File.basename(executable) }
71
+ end
72
+
73
+ ### dependencies
74
+
75
+ (gem_options.delete(:dependencies) || []).each { |dependency|
76
+ spec.add_dependency(*dependency)
77
+ }
78
+
79
+ ### => set options!
80
+
81
+ gem_options.each { |option, value|
82
+ spec.send("#{option}=", value)
83
+ }
84
+ }
85
+
86
+ desc 'Display the gem specification'
87
+ task :gemspec do
88
+ puts gem_spec.to_ruby
89
+ end
90
+
91
+ desc "Update (or create) the project's gemspec file"
92
+ task 'gemspec:update' do
93
+ file = "#{gem_spec.name}.gemspec"
94
+ action = File.exists?(file) ? 'Updated' : 'Created'
95
+
96
+ File.open(file, 'w') { |f| f.puts gem_spec.to_ruby }
97
+
98
+ puts "#{action} #{file}"
99
+ end
100
+
101
+ pkg_task = Rake::GemPackageTask.new(gem_spec) do |pkg|
102
+ pkg.need_tar_gz = true
103
+ pkg.need_zip = true
104
+ end
105
+
106
+ rubyforge do |rf_config, rf_pool|
107
+
108
+ desc 'Package and upload the release to Rubyforge'
109
+ task :release => [:package, :publish_docs] do
110
+ files = Dir[File.join('pkg', "#{pkg_task.package_name}.*")]
111
+ abort 'Nothing to release!' if files.empty?
112
+
113
+ # shorten to (at most) three digits
114
+ version = pkg_task.version.to_s.split(/([.])/)[0..4].join
115
+
116
+ rf = rf_pool.call
117
+
118
+ # TODO: Add release notes and changes.
119
+ #uc = rf.userconfig
120
+ #uc['release_notes'] = description if description
121
+ #uc['release_changes'] = changes if changes
122
+ #uc['preformatted'] = true
123
+
124
+ rf.add_release rf_config[:project], pkg_task.name, version, *files
125
+ end
126
+
127
+ end
128
+
129
+ end
@@ -0,0 +1,79 @@
1
+ Hen :rdoc do
2
+
3
+ require 'rake/rdoctask'
4
+
5
+ rdoc_options = config[:rdoc]
6
+
7
+ if rf_package = config[:rubyforge][:package]
8
+ rdoc_options[:title] ||= "#{rf_package} Application documentation"
9
+ end
10
+
11
+ ### rdoc_dir
12
+
13
+ rdoc_dir = rdoc_options.delete(:rdoc_dir)
14
+
15
+ ### rdoc_files
16
+
17
+ rdoc_files = FileList[rdoc_options.delete(:rdoc_files)].
18
+ sort.uniq.select { |file| File.exists?(file) }
19
+
20
+ ### rdoc_options
21
+
22
+ rdoc_options.delete(:main) unless rdoc_files.include?(rdoc_options[:main])
23
+
24
+ rdoc_options = rdoc_options.map { |option, value|
25
+ option = '--' << option.to_s.tr('_', '-')
26
+ value.is_a?(String) ? [option, value] : value ? option : nil
27
+ }.compact.flatten
28
+
29
+ # Make settings available to other hens
30
+ RDOC_OPTIONS = {
31
+ :rdoc_dir => rdoc_dir,
32
+ :rdoc_files => rdoc_files,
33
+ :options => rdoc_options
34
+ }
35
+
36
+ unless rdoc_files.empty?
37
+ rdoc_task = Rake::RDocTask.new(:doc) { |rdoc|
38
+ rdoc.rdoc_dir = rdoc_dir
39
+ rdoc.rdoc_files = rdoc_files
40
+ rdoc.options = rdoc_options
41
+ }
42
+ else
43
+ task :doc do
44
+ warn 'No files to generate documentation for!'
45
+ end
46
+ end
47
+
48
+ rubyforge do |rf_config|
49
+
50
+ desc 'Publish RDoc to Rubyforge'
51
+ task :publish_docs => :doc do
52
+ rf_project = rf_config[:project]
53
+ abort 'Rubyforge project name missing' unless rf_project
54
+
55
+ rf_user = rf_config[:username]
56
+ abort 'Rubyforge user name missing' unless rf_user
57
+
58
+ rf_host = "#{rf_user}@rubyforge.org"
59
+
60
+ local_dir = rdoc_task.rdoc_dir
61
+ remote_dir = "/var/www/gforge-projects/#{rf_project}"
62
+
63
+ if rdoc_dir = rf_config[:rdoc_dir]
64
+ if rf_package = rf_config[:package]
65
+ rdoc_dir = rf_package if rdoc_dir == :package
66
+ end
67
+
68
+ remote_dir = File.join(remote_dir, rdoc_dir)
69
+ end
70
+
71
+ execute(
72
+ "rsync -av --delete #{local_dir}/ #{rf_host}:#{remote_dir}/",
73
+ "scp -r #{local_dir}/ #{rf_host}:#{remote_dir}/"
74
+ )
75
+ end
76
+
77
+ end
78
+
79
+ end
@@ -0,0 +1,36 @@
1
+ Hen :spec do
2
+
3
+ require 'spec/rake/spectask'
4
+
5
+ spec_options = config[:spec]
6
+
7
+ spec_files = spec_options.delete(:files) || FileList[spec_options.delete(:pattern)]
8
+
9
+ if spec_files && !spec_files.empty?
10
+ if spec_helper = spec_options.delete(:helper) and File.readable?(spec_helper)
11
+ spec_files.delete(spec_helper)
12
+ spec_files.unshift(spec_helper)
13
+ end
14
+
15
+ spec_opts = spec_options.map { |option, value|
16
+ option = '--' << option.to_s.tr('_', '-')
17
+ value.is_a?(String) ? [option, value] : value ? option : nil
18
+ }.compact.flatten
19
+
20
+ spec_task = lambda { |t|
21
+ t.spec_files = spec_files
22
+ t.spec_opts = spec_opts
23
+ }
24
+
25
+ Spec::Rake::SpecTask.new(&spec_task)
26
+
27
+ #desc "Run specs with RCov"
28
+ Spec::Rake::SpecTask.new('spec:rcov') do |t|
29
+ spec_task[t]
30
+
31
+ t.rcov = true
32
+ t.rcov_opts = ['--exclude', spec_files.join(',')]
33
+ end
34
+ end
35
+
36
+ end
@@ -0,0 +1,19 @@
1
+ Hen :test do
2
+
3
+ require 'rake/testtask'
4
+
5
+ test_options = config[:test]
6
+
7
+ test_files = test_options.delete(:files) || FileList[test_options.delete(:pattern)]
8
+
9
+ if test_files && !test_files.empty?
10
+ Rake::TestTask.new { |t|
11
+ t.test_files = test_files
12
+
13
+ test_options.each { |option, value|
14
+ t.send("#{option}=", value)
15
+ }
16
+ }
17
+ end
18
+
19
+ end
metadata ADDED
@@ -0,0 +1,104 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: blackwinter-hen
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.5
5
+ platform: ruby
6
+ authors:
7
+ - Jens Wille
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-01-22 00:00:00 -08:00
13
+ default_executable: hen
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rubyforge
17
+ version_requirement:
18
+ version_requirements: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: "0"
23
+ version:
24
+ - !ruby/object:Gem::Dependency
25
+ name: ruby-nuggets
26
+ version_requirement:
27
+ version_requirements: !ruby/object:Gem::Requirement
28
+ requirements:
29
+ - - ">="
30
+ - !ruby/object:Gem::Version
31
+ version: 0.3.3
32
+ version:
33
+ description: Hoe or Echoe? No, thanks! Just a Rake helper that fits my own personal style.
34
+ email: jens.wille@uni-koeln.de
35
+ executables:
36
+ - hen
37
+ extensions: []
38
+
39
+ extra_rdoc_files:
40
+ - COPYING
41
+ - ChangeLog
42
+ - README
43
+ files:
44
+ - lib/hen.rb
45
+ - lib/hen/cli.rb
46
+ - lib/hen/dsl.rb
47
+ - lib/hen/version.rb
48
+ - bin/hen
49
+ - Rakefile
50
+ - COPYING
51
+ - ChangeLog
52
+ - README
53
+ - lib/hens/rdoc.rake
54
+ - lib/hens/gem.rake
55
+ - lib/hens/test.rake
56
+ - lib/hens/spec.rake
57
+ - example/hens
58
+ - example/hens/sample.rake
59
+ - example/project
60
+ - example/project/Rakefile
61
+ - example/project/COPYING
62
+ - example/project/ChangeLog
63
+ - example/project/lib
64
+ - example/project/lib/__progname__
65
+ - example/project/lib/__progname__/version.rb
66
+ - example/project/lib/__progname__.rb
67
+ - example/project/README
68
+ - example/.henrc
69
+ has_rdoc: true
70
+ homepage: http://prometheus.rubyforge.org/hen
71
+ post_install_message:
72
+ rdoc_options:
73
+ - --inline-source
74
+ - --title
75
+ - hen Application documentation
76
+ - --charset
77
+ - UTF-8
78
+ - --main
79
+ - README
80
+ - --all
81
+ - --line-numbers
82
+ require_paths:
83
+ - lib
84
+ required_ruby_version: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: "0"
89
+ version:
90
+ required_rubygems_version: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ version: "0"
95
+ version:
96
+ requirements: []
97
+
98
+ rubyforge_project: prometheus
99
+ rubygems_version: 1.2.0
100
+ signing_key:
101
+ specification_version: 2
102
+ summary: Hoe or Echoe? No, thanks! Just a Rake helper that fits my own personal style.
103
+ test_files: []
104
+