gemma 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,150 @@
1
+ = gemma
2
+
3
+ http://github.com/jdleesmiller/gemma
4
+
5
+ == DESCRIPTION
6
+
7
+ If you are using .gemspecs as intended
8
+ (http://yehudakatz.com/2010/04/02/using-gemspecs-as-intended/), gemma generates
9
+ common rake tasks with default settings extracted from your .gemspec file.
10
+
11
+ == SYNOPSIS
12
+
13
+ To create a gem called +mygem+, first create <tt>mygem.gemspec</tt> as
14
+ described in http://yehudakatz.com/2010/04/02/using-gemspecs-as-intended/.
15
+
16
+ For more information about the gemspec, see the Gem::Specification Reference
17
+ (http://docs.rubygems.org/read/chapter/20).
18
+
19
+ Then put the following at the top of your <tt>Rakefile.rb</tt>:
20
+ begin
21
+ require 'rubygems'
22
+ require 'gemma'
23
+
24
+ Gemma::RakeTasks.with_gemspec_file 'mygem.gemspec'
25
+ rescue LoadError
26
+ # Gemma is not installed; print an (optional) message:
27
+ puts "Install gemma (sudo gem install gemma) for standard rake tasks."
28
+ end
29
+
30
+ This gives you a list of standard rake tasks with settings based on your
31
+ gemspec, in addition to any that you define yourself. (Note that the yard task
32
+ only appears if you have the yard gem installed.)
33
+
34
+ rake clean # Remove any temporary products.
35
+ rake clobber # Remove any generated file.
36
+ rake clobber_rcov # Remove rcov products for rcov
37
+ rake clobber_rdoc # Remove rdoc products
38
+ rake rcov # Analyze code coverage with tests
39
+ rake rdoc # Build the rdoc HTML Files
40
+ rake rerdoc # Force a rebuild of the RDOC files
41
+ rake test # Run tests
42
+ rake yard # Generate YARD Documentation
43
+
44
+ You can customize the generated tasks by passing a block to
45
+ +with_gemspec_file+:
46
+
47
+ Gemma::RakeTasks.with_gemspec_file 'mygem.gemspec' do |g|
48
+ g.rdoc.title = 'My Gem Is Great'
49
+ end
50
+
51
+ See the gemma API docs for more information.
52
+
53
+ == REQUIREMENTS
54
+
55
+ You must have ruby, rubygems and rake installed. Tasks are also included for
56
+ rcov (http://eigenclass.org/hiki.rb?rcov) and yard (http://yardoc.org/).
57
+
58
+ Gemma has been tested on:
59
+ * x86-linux (Ubuntu 10.04) with Ruby 1.8.7p249
60
+ * x86-linux (rvm) with Ruby 1.9.2p0 (2010-08-18 revision 29034)
61
+ * x86_64-linux (CentOS) with Ruby 1.8.7p72
62
+ * with yard 0.5.8 and 0.6.1
63
+ * with rcov 0.9.6 and 0.9.9
64
+ Gemma has not yet been tested on Windows.
65
+
66
+ == INSTALL
67
+
68
+ You should be able to install with
69
+
70
+ gem install gemma
71
+
72
+ Alternatively, you can get the source with
73
+
74
+ git clone git://github.com/jdleesmiller/gemma.git
75
+
76
+ and run
77
+
78
+ gem build gemma.gemspec
79
+ gem install gemma-<version>.gem
80
+
81
+ == RELATED PROJECTS
82
+
83
+ There are many projects that make gem development easier.
84
+ Hoe and Jeweler are the most popular; they generate the gemspec and tasks using
85
+ a configuration specified in the Rakefile, which is the opposite to what gemma
86
+ does. Mr Bones is a gem template generator that appears to be similar to Hoe
87
+ and Jeweler, but I haven't used it myself.
88
+
89
+ * http://seattlerb.rubyforge.org/hoe/
90
+ * http://github.com/technicalpickles/jeweler
91
+ * http://codeforpeople.rubyforge.org/bones/
92
+
93
+ gemesis provides tasks for building, releasing and installing gems based on the
94
+ gemspec, but (at the time of writing) it doesn't provide tasks for tests and
95
+ documentation, etc.
96
+
97
+ * http://github.com/markryall/gemesis/tree/master/lib/gemesis
98
+
99
+ rake-compiler provides support for compiling native extensions from a
100
+ gemspec, and it looks like it should work fairly well with gemma.
101
+
102
+ * http://github.com/luislavena/rake-compiler
103
+
104
+ Other helpful articles:
105
+
106
+ * http://rubygems.rubyforge.org/rubygems-update/Gem/Version.html
107
+ * http://jeffkreeftmeijer.com/2010/why-arent-you-using-git-flow/
108
+
109
+ == TODO
110
+
111
+ * make it easier to add custom tasks and / or new task generators, as in
112
+ # DOES NOT WORK YET
113
+ Gemma::RakeTasks.with_gemspec_file 'mygem.gemspec' do |g|
114
+ g.yard_dev = Gemma::RakeTasks::YardTasks.new(g.gemspec, :yard_dev)
115
+ g.yard_dev.output = 'dev_docs'
116
+ g.yard_dev.options.push('--protected', '--private')
117
+ end
118
+ * more tasks (e.g. to publish docs)
119
+ * generate gem skeletons
120
+ * tasks for version control? (see http://github.com/nvie/gitflow)
121
+ * contributions welcome!
122
+
123
+ == HISTORY
124
+
125
+ <em>0.0.1</em>
126
+ * first release
127
+
128
+ == LICENSE
129
+
130
+ Copyright (c) 2010 John Lees-Miller
131
+
132
+ Permission is hereby granted, free of charge, to any person obtaining
133
+ a copy of this software and associated documentation files (the
134
+ 'Software'), to deal in the Software without restriction, including
135
+ without limitation the rights to use, copy, modify, merge, publish,
136
+ distribute, sublicense, and/or sell copies of the Software, and to
137
+ permit persons to whom the Software is furnished to do so, subject to
138
+ the following conditions:
139
+
140
+ The above copyright notice and this permission notice shall be
141
+ included in all copies or substantial portions of the Software.
142
+
143
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
144
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
145
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
146
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
147
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
148
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
149
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
150
+
@@ -0,0 +1,21 @@
1
+ require 'gemma/version'
2
+ require 'gemma/options'
3
+ require 'gemma/rake_tasks'
4
+
5
+ # Load default Rakefile plugins:
6
+ require 'gemma/rake_tasks/plugin'
7
+ require 'gemma/rake_tasks/gem_tasks'
8
+ require 'gemma/rake_tasks/rcov_tasks'
9
+ require 'gemma/rake_tasks/rdoc_tasks'
10
+ require 'gemma/rake_tasks/yard_tasks'
11
+ require 'gemma/rake_tasks/test_unit_tasks'
12
+
13
+ #require 'gemma/utility'
14
+
15
+ # Load default Rakefile plugins:
16
+ #require 'gemma/rakefile/rdoc'
17
+ #require 'gemma/rakefile/yard'
18
+ #require 'gemma/rakefile/test_unit'
19
+ #require 'gemma/rakefile/rcov'
20
+ #require 'gemma/rakefile/gem'
21
+
@@ -0,0 +1,97 @@
1
+ module Gemma
2
+ module Options
3
+ #
4
+ # @attr [String, nil] argument
5
+ # @attr [Array<String>] remaining_options
6
+ #
7
+ ExtractResult = Struct.new(:argument, :remaining_options)
8
+
9
+ #
10
+ # Extract the last option with one of the given `names` from `input`.
11
+ #
12
+ # Long form options of the form `--foo`, `--foo bar` and `--foo=bar` are
13
+ # supported (where `--foo` is the option name and `bar` is the argument in
14
+ # the last two forms).
15
+ #
16
+ # Short form options of the form `-f`, `-fbar` and `-f bar` are supported
17
+ # (where `-f` is the option name and `bar` is the argument in the last two
18
+ # forms). However concatenated short forms are not supported; that is, the
19
+ # option `-fg` is interpreted as `-f g` (option `f` with argument `g`)
20
+ # rather than `-f -g` (options `f` and `g` with no arguments).
21
+ #
22
+ # Abbreviated long form options (e.g. `--ex` for `--example`) are not
23
+ # supported, because this method doesn't know the full set of acceptable
24
+ # options, so it can't resolve ambiguities.
25
+ #
26
+ # If an option appears more than once, the argument for the last one is
27
+ # returned, and the previous matching options and arguments are deleted
28
+ # (i.e. not returned in {ExtractResult#remaining_options}).
29
+ #
30
+ # Matching options that appear after a `--` terminator are not extracted;
31
+ # they remain in the {ExtractResult#remaining_options} list.
32
+ #
33
+ # @example
34
+ # Gemma::Options.extract(%w(-a), %w(-a foo bar.txt))
35
+ # #=> #<struct Gemma::Options::ExtractResult argument="foo",
36
+ # # remaining_options=["bar.txt"]>
37
+ #
38
+ # @param [Array<String>] names one or more names for the option to extract
39
+ # (`['--file','-f']`, for example)
40
+ #
41
+ # @param [Array<String>] options to extract from; you should ensure that
42
+ # there isn't leading/trailing whitespace (strip), because this method
43
+ # doesn't detect it
44
+ #
45
+ # @return [ExtractResult] contains the argument for the given option and the
46
+ # rest of the options
47
+ #
48
+ def self.extract names, options
49
+ options = options.dup
50
+ result = nil
51
+ done = []
52
+
53
+ until options.empty?
54
+ x = options.shift
55
+ if x == '--' then
56
+ # Stop at the '--' terminator.
57
+ done << x
58
+ break
59
+ elsif x =~ /^(--[^=]+)/ then
60
+ if names.member?($1) then
61
+ # Found a long style option; look for its argument (if any).
62
+ if x =~ /=(.*)$/ then
63
+ result = $1
64
+ elsif !options.empty? && options.first !~ /^-./
65
+ result = options.shift
66
+ else
67
+ result = ''
68
+ end
69
+ else
70
+ done << x
71
+ end
72
+ elsif x =~ /^(-(.))(.*)/ then
73
+ # Found a short style option; this may actually represent several
74
+ # options; look for matching short options.
75
+ name, letter, rest = $1, $2, $3
76
+ if names.member?(name)
77
+ if rest.length > 0
78
+ result = rest
79
+ elsif !options.empty? && options.first !~ /^-./
80
+ result = options.shift
81
+ else
82
+ result = ''
83
+ end
84
+ else
85
+ done << x
86
+ end
87
+ else
88
+ # Not an option; just let it pass through.
89
+ done << x
90
+ end
91
+ end
92
+
93
+ ExtractResult.new(result, done + options)
94
+ end
95
+ end
96
+ end
97
+
@@ -0,0 +1,120 @@
1
+ require 'rake/clean'
2
+
3
+ module Gemma
4
+ #
5
+ # Generate standard gem development tasks; the tasks are configured using
6
+ # the settings in the given gemspec file.
7
+ #
8
+ # @example To create the default tasks based on your _mygem_.gemspec file:
9
+ # # At the top of Rakefile.rb.
10
+ # require 'rubygems'
11
+ # require 'gemma'
12
+ #
13
+ # Gemma::RakeTasks.with_gemspec_file 'mygem.gemspec'
14
+ #
15
+ # # ... other tasks ...
16
+ #
17
+ class RakeTasks
18
+
19
+ # Alias for new.
20
+ class <<self
21
+ alias :with_gemspec_file :new
22
+ end
23
+
24
+ #
25
+ # Constructor for internal use; you should usually use the
26
+ # `with_gemspec_file` alias (see examples in {RakeTasks}).
27
+ #
28
+ # @param [String, Gem::Specification] gemspec either the name of a gemspec
29
+ # file or a gemspec object; the latter is intended mainly for testing
30
+ #
31
+ # @yield [tasks] used to customize the tasks to be created
32
+ #
33
+ # @yieldparam [Gemma::RakeTasks] tasks self
34
+ #
35
+ # @private
36
+ #
37
+ def initialize gemspec, &block
38
+ # Load gemspec.
39
+ if gemspec.is_a?(String)
40
+ @gemspec_file_name = gemspec
41
+ @gemspec = Gem::Specification::load(gemspec_file_name)
42
+ elsif gemspec.is_a?(Gem::Specification)
43
+ @gemspec_file_name = nil
44
+ @gemspec = gemspec
45
+ else
46
+ raise ArgumentError
47
+ end
48
+
49
+ @plugins = {}
50
+ create_default_plugins
51
+
52
+ # Let the user add more plugins and alter settings.
53
+ block.call(self) if block_given?
54
+
55
+ @plugins.values.each do |plugin|
56
+ plugin.create_rake_tasks
57
+ end
58
+ end
59
+
60
+ #
61
+ # File from which the {#gemspec} was loaded.
62
+ #
63
+ # @return [String] not nil if a gemspec file name was passed to the
64
+ # constructor; otherwise, nil
65
+ #
66
+ attr_reader :gemspec_file_name
67
+
68
+ #
69
+ # The specification used to configure the rake tasks.
70
+ #
71
+ # @return [Gem::Specification] not nil; you should not modify this object
72
+ # (make the changes in the gemspec file instead).
73
+ #
74
+ attr_reader :gemspec
75
+
76
+ #
77
+ # @return [Hash<Symbol, Plugin>]
78
+ #
79
+ attr_reader :plugins
80
+
81
+ #
82
+ # @return [RcovTasks]
83
+ #
84
+ def rcov; @plugins[:rcov] end
85
+
86
+ #
87
+ # @return [RDocTasks]
88
+ #
89
+ def rdoc; @plugins[:rdoc] end
90
+
91
+ #
92
+ # @return [TestUnitTasks]
93
+ #
94
+ def test; @plugins[:test] end
95
+
96
+ #
97
+ # @return [YardTasks]
98
+ #
99
+ def yard; @plugins[:yard] end
100
+
101
+ #
102
+ # @return [GemTasks]
103
+ #
104
+ #def gem; @plugins[:gem] end
105
+
106
+ protected
107
+
108
+ def create_default_plugins
109
+ @plugins[:rcov] = Gemma::RakeTasks::RcovTasks.new(gemspec)
110
+ @plugins[:rdoc] = Gemma::RakeTasks::RDocTasks.new(gemspec)
111
+ @plugins[:test] = Gemma::RakeTasks::TestUnitTasks.new(gemspec)
112
+ @plugins[:yard] = Gemma::RakeTasks::YardTasks.new(gemspec)
113
+
114
+ # not that helpful yet
115
+ # @plugins[:gem] = Gemma::RakeTasks::GemTasks.new(gemspec,
116
+ # gemspec_file_name)
117
+ end
118
+
119
+ end
120
+ end
@@ -0,0 +1,74 @@
1
+ module Gemma
2
+ class RakeTasks
3
+ #
4
+ # Create tasks to build and release (push) gems.
5
+ #
6
+ # TODO not done yet
7
+ #
8
+ class GemTasks < Plugin
9
+ #
10
+ # @param [Gem::Specification] gemspec
11
+ # @param [String, nil] gemspec_file_name
12
+ #
13
+ def initialize gemspec, gemspec_file_name
14
+ super(gemspec)
15
+
16
+ @gemspec_file_name = gemspec_file_name
17
+
18
+ # Defaults.
19
+ @output = 'pkg'
20
+ end
21
+
22
+ #
23
+ # Name of the gemspec file to be built; if this is nil, no gem tasks are
24
+ # generated.
25
+ #
26
+ # @return [String, nil]
27
+ #
28
+ attr_accessor :gemspec_file_name
29
+
30
+ #
31
+ # Name of directory in which gem files are placed; defaults to pkg.
32
+ #
33
+ # @return [String]
34
+ #
35
+ attr_accessor :output
36
+
37
+ #
38
+ # Full path to gem file.
39
+ #
40
+ # @return [String]
41
+ #
42
+ def gem_file
43
+ File.join(output, gemspec.file_name)
44
+ end
45
+
46
+ #
47
+ # Internal method; see {Plugin#create_rake_tasks}.
48
+ #
49
+ # @return [nil]
50
+ #
51
+ # @private
52
+ #
53
+ def create_rake_tasks
54
+ if gemspec_file_name
55
+ directory output
56
+
57
+ desc "gem build"
58
+ task :build => output do
59
+ sh "gem build #{gemspec_file_name}"
60
+ mv gemspec.file_name, gem_file
61
+ end
62
+ CLOBBER.include(gem_file)
63
+
64
+ desc "gem release"
65
+ task :release => :build do
66
+ sh "gem push #{gem_file}"
67
+ end
68
+ end
69
+
70
+ nil
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,36 @@
1
+ module Gemma
2
+ class RakeTasks
3
+ #
4
+ # Plugins generate rake tasks based on the content of the gemspec.
5
+ #
6
+ # The intention is that the plugin processes the gemspec and sets
7
+ # (intelligent) default values when it is created. The {RakeTasks} object
8
+ # then calls {#create_rake_tasks} on every plugin that it knows about, after
9
+ # it has run its configuration block. The configuration block gives the
10
+ # caller a chance to customize the inputs to all of the plugins before they
11
+ # are generated.
12
+ #
13
+ class Plugin
14
+ def initialize gemspec
15
+ @gemspec = gemspec
16
+ end
17
+
18
+ #
19
+ # @return [Gem::Specification]
20
+ #
21
+ attr_reader :gemspec
22
+
23
+ #
24
+ # Internal method called by {RakeTasks} after the configuration block
25
+ # has executed; overriden by plugins to create rake tasks.
26
+ #
27
+ # @return [nil]
28
+ #
29
+ # @abstract
30
+ #
31
+ def create_rake_tasks
32
+ raise NotImplementedError
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,78 @@
1
+ module Gemma
2
+ class RakeTasks
3
+ #
4
+ # Create tasks to run test coverage using the built-in `rcov` tool. By
5
+ # default, the `test_files` given in the gemspec are used to measure
6
+ # coverage.
7
+ #
8
+ # This plugin is based on the `Rcov::RcovTask` that comes bundled with rcov.
9
+ # If you need an option that isn't exposed by the plugin, you can modify the
10
+ # `RcovTask` object directly in a block passed to {#with_rcov_task}.
11
+ #
12
+ class RcovTasks < Plugin
13
+ #
14
+ # @param [Gem::Specification] gemspec
15
+ #
16
+ def initialize gemspec
17
+ super(gemspec)
18
+
19
+ # Defaults.
20
+ @task_name = :rcov
21
+ @output = 'rcov'
22
+ @with_rcov_task = nil
23
+ end
24
+
25
+ #
26
+ # Name of rake task; defaults to rcov.
27
+ #
28
+ # @return [Symbol]
29
+ #
30
+ attr_accessor :task_name
31
+
32
+ #
33
+ # Output directory for the XHTML report; defaults to rcov.
34
+ #
35
+ # @return [String]
36
+ #
37
+ attr_accessor :output
38
+
39
+ #
40
+ # Customize the rcov task.
41
+ #
42
+ # @yield [rcov] called after the defaults are set but before the rcov task
43
+ # is generated
44
+ #
45
+ # @yieldparam [Rcov::RcovTask] rcov
46
+ #
47
+ # @return [nil]
48
+ #
49
+ def with_rcov_task &block
50
+ @with_rcov_task = block
51
+ nil
52
+ end
53
+
54
+ #
55
+ # Internal method; see {Plugin#create_rake_tasks}.
56
+ #
57
+ # @return [nil]
58
+ #
59
+ # @private
60
+ #
61
+ def create_rake_tasks
62
+ begin
63
+ require 'rcov/rcovtask'
64
+ Rcov::RcovTask.new(self.task_name) do |rcov|
65
+ rcov.libs = gemspec.require_paths
66
+ rcov.test_files = gemspec.test_files
67
+ rcov.warning = true
68
+ rcov.rcov_opts << "-x ^/"
69
+ rcov.output_dir = self.output
70
+ @with_rcov_task.call(rcov) if @with_rcov_task
71
+ end
72
+ rescue LoadError
73
+ # Assume rcov is not installed.
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,159 @@
1
+ module Gemma
2
+ class RakeTasks
3
+ #
4
+ # Create tasks for generating `rdoc` API documentation with settings from
5
+ # the gemspec.
6
+ #
7
+ # The default settings are based on the `files`, `rdoc_options` and
8
+ # `extra_rdoc_files` data in the gemspec. By default, test cases (which
9
+ # might be included in `files`) are not documented.
10
+ #
11
+ # If an rdoc gem is installed, it will be used; otherwise, the built-in
12
+ # rdoc will be used.
13
+ #
14
+ # This plugin is based on the `Rake::RDocTask` that comes bundled with rake.
15
+ # If you need an option that isn't exposed by the plugin, you can modify the
16
+ # `RDocTask` object directly in a block passed to {#with_rdoc_task}.
17
+ #
18
+ class RDocTasks < Plugin
19
+ #
20
+ # @param [Gem::Specification] gemspec
21
+ #
22
+ def initialize gemspec
23
+ super(gemspec)
24
+
25
+ # Defaults.
26
+ @use_gem_if_available = true
27
+ @task_name = :rdoc
28
+ @with_rdoc_task = nil
29
+
30
+ # I'm not sure whether it's a good idea to pass -o in the gemspec, but
31
+ # for now we'll handle it, because it's needed in the Rakefile.
32
+ @options = gemspec.rdoc_options
33
+ @output, @options = Options.extract(%w(-o --output --op), @options).to_a
34
+ @output ||= 'rdoc'
35
+
36
+ # Extract --main, --title and --template so RDocTask can have them.
37
+ @main, @options = Options.extract(%w(-m --main), @options).to_a
38
+ @title, @options = Options.extract(%w(-t --title), @options).to_a
39
+ @template, @options = Options.extract(%w(-T --template), @options).to_a
40
+
41
+ # Don't include the test files by default.
42
+ @files = gemspec.files - gemspec.test_files
43
+ end
44
+
45
+ #
46
+ # Name of rake task used to generate these docs; defaults to rdoc.
47
+ #
48
+ # @return [Symbol]
49
+ #
50
+ attr_accessor :task_name
51
+
52
+ #
53
+ # Name of output directory (the rdoc option --output); extracted from
54
+ # gemspec; defaults to rdoc.
55
+ #
56
+ # @return [String]
57
+ #
58
+ attr_accessor :output
59
+
60
+ #
61
+ # Name of file to display in index.html (the rdoc option --main);
62
+ # extracted from gemspec; defaults to nil (none).
63
+ #
64
+ # @return [String, nil]
65
+ #
66
+ attr_accessor :main
67
+
68
+ #
69
+ # Title for HTML output (the rdoc option --title); extracted from gemspec;
70
+ # defaults to nil (unspecified).
71
+ #
72
+ # @return [String, nil]
73
+ #
74
+ attr_accessor :title
75
+
76
+ #
77
+ # Name of template used to generate html output (the rdoc option
78
+ # --template); extracted from gemspec; defaults to nil (unspecified).
79
+ #
80
+ # @return [String, nil]
81
+ #
82
+ attr_accessor :template
83
+
84
+ #
85
+ # If an rdoc gem is installed, use it instead of the rdoc from the
86
+ # standard library (default true).
87
+ #
88
+ # While rdoc is part of the ruby standard library, newer versions are
89
+ # available as gems.
90
+ #
91
+ # @return [Boolean]
92
+ #
93
+ attr_accessor :use_gem_if_available
94
+
95
+ #
96
+ # Files to be processed by rdoc; extracted from gemspec; test files are
97
+ # not included by default.
98
+ #
99
+ # @return [Array<String>]
100
+ #
101
+ attr_accessor :files
102
+
103
+ #
104
+ # Options to be passed to rdoc; extracted from gemspec; note that
105
+ # the {#output}, {#main}, {#title} and {#template} options and the
106
+ # {#files} list are handled separately.
107
+ #
108
+ # @return [Array<String>]
109
+ #
110
+ attr_accessor :options
111
+
112
+ #
113
+ # Customize the rdoc task.
114
+ #
115
+ # @yield [rd] called after the defaults are set but before the rdoc tasks
116
+ # are generated
117
+ #
118
+ # @yieldparam [Rake::RDocTask] rd
119
+ #
120
+ # @return [nil]
121
+ #
122
+ def with_rdoc_task &block
123
+ @with_rdoc_task = block
124
+ nil
125
+ end
126
+
127
+ #
128
+ # Internal method; see {Plugin#create_rake_tasks}.
129
+ #
130
+ # @return [nil]
131
+ #
132
+ # @private
133
+ #
134
+ def create_rake_tasks
135
+ if use_gem_if_available
136
+ begin
137
+ gem('rdoc')
138
+ rescue LoadError
139
+ # ignore -- just use the standard library one
140
+ end
141
+ end
142
+
143
+ require 'rake/rdoctask'
144
+ Rake::RDocTask.new(self.task_name) do |rd|
145
+ rd.rdoc_dir = self.output
146
+ rd.rdoc_files = self.files
147
+ rd.title = self.title
148
+ rd.main = self.main
149
+ rd.template = self.template
150
+ rd.options = self.options
151
+ rd.inline_source = false # doesn't seem to work on 1.8.7
152
+ @with_rdoc_task.call(rd) if @with_rdoc_task
153
+ end
154
+
155
+ nil
156
+ end
157
+ end
158
+ end
159
+ end
@@ -0,0 +1,64 @@
1
+ module Gemma
2
+ class RakeTasks
3
+ #
4
+ # Create tasks to run Test::Unit tests using the built-in (standard library)
5
+ # `test/unit`. By default, the `test_files` given in the gemspec are tested.
6
+ #
7
+ # This plugin is based on the `Rake::TestTask` that comes bundled with rake.
8
+ # If you need an option that isn't exposed by the plugin, you can modify the
9
+ # `TestTask` object directly in a block passed to {#with_test_task}.
10
+ #
11
+ class TestUnitTasks < Plugin
12
+ #
13
+ # @param [Gem::Specification] gemspec
14
+ #
15
+ def initialize gemspec
16
+ super(gemspec)
17
+
18
+ # Defaults.
19
+ @task_name = :test
20
+ @with_test_task = nil
21
+ end
22
+
23
+ #
24
+ # Name of rake task used to generate these docs; defaults to test.
25
+ #
26
+ # @return [Symbol]
27
+ #
28
+ attr_accessor :task_name
29
+
30
+ #
31
+ # Customize the test task.
32
+ #
33
+ # @yield [tt] called after the defaults are set but before the test task
34
+ # is generated
35
+ #
36
+ # @yieldparam [Rake::TestTask] tt
37
+ #
38
+ # @return [nil]
39
+ #
40
+ def with_test_task &block
41
+ @with_test_task = block
42
+ nil
43
+ end
44
+
45
+ #
46
+ # Internal method; see {Plugin#create_rake_tasks}.
47
+ #
48
+ # @return [nil]
49
+ #
50
+ # @private
51
+ #
52
+ def create_rake_tasks
53
+ require 'rake/testtask'
54
+ Rake::TestTask.new(self.task_name) do |tt|
55
+ tt.libs = gemspec.require_paths
56
+ tt.test_files = gemspec.test_files
57
+ tt.warning = true
58
+ @with_test_task.call(tt) if @with_test_task
59
+ end
60
+ nil
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,165 @@
1
+ module Gemma
2
+ class RakeTasks
3
+ #
4
+ # Create tasks to generate documentation with yard (yardoc) if it is
5
+ # available.
6
+ #
7
+ # The files to document are extracted from the gemspec's `files` and
8
+ # `extra_rdoc_files` members.
9
+ #
10
+ # Unfortunately, yardoc's command line options are largely incompatible with
11
+ # those for rdoc, but the `--main` and `--title` options from `rdoc_options`
12
+ # are also passed through to yardoc by default. The short forms `-m` and
13
+ # `-t` of these arguments are also passed on as `--main` and `--title` to
14
+ # yardoc (note that `-m` and `-t` mean different things to yardoc than to
15
+ # rdoc!). Note that any files (that is, non-options) in `rdoc_options` are
16
+ # also ignored.
17
+ #
18
+ # If you want to further customize your yardoc output, you can add options
19
+ # in the {Gemma::RakeTasks.with_gemspec_file} configuration block.
20
+ #
21
+ # This plugin is based on the `YARD::Rake::YardocTask` that comes bundled
22
+ # with yard. If you need an option that isn't exposed by the plugin, you
23
+ # can modify the `YardocTask` object directly in a block passed to
24
+ # {#with_yardoc_task}.
25
+ #
26
+ class YardTasks < Plugin
27
+ #
28
+ # @param [Gem::Specification] gemspec
29
+ #
30
+ def initialize gemspec
31
+ super(gemspec)
32
+
33
+ # Defaults.
34
+ @task_name = :yard
35
+ @output = 'yard'
36
+ @with_yardoc_task = nil
37
+
38
+ # Extract supported rdoc options and add to the default yard options.
39
+ # Keep track of main, if it is given, because we have to remove it from
40
+ # the extra files list (otherwise it shows up twice in the output).
41
+ @main = Options.extract(%w(-m --main), gemspec.rdoc_options).argument
42
+ @title = Options.extract(%w(-t --title), gemspec.rdoc_options).argument
43
+
44
+ @options = []
45
+
46
+ # Don't document the test files.
47
+ # Yard splits up the ruby files from the 'extra' files.
48
+ @files = gemspec.files - gemspec.test_files - gemspec.extra_rdoc_files
49
+ @extra_files = gemspec.extra_rdoc_files.dup
50
+ @extra_files.delete(main) if main
51
+ end
52
+
53
+ #
54
+ # Name of rake task used to generate these docs; defaults to yard.
55
+ #
56
+ # @return [Symbol]
57
+ #
58
+ attr_accessor :task_name
59
+
60
+ #
61
+ # Name of output directory (the yard option --output); defaults to yard.
62
+ #
63
+ # @return [String]
64
+ #
65
+ attr_accessor :output
66
+
67
+ #
68
+ # Name of file to display in index.html (the yard option --main);
69
+ # extracted from gemspec; defaults to nil (none).
70
+ #
71
+ # @return [String, nil]
72
+ #
73
+ attr_accessor :main
74
+
75
+ #
76
+ # Title for HTML output (the yard option --title); extracted from gemspec;
77
+ # defaults to nil (unspecified).
78
+ #
79
+ # @return [String, nil]
80
+ #
81
+ attr_accessor :title
82
+
83
+ #
84
+ # Ruby files to be processed by yard; these are extracted from the
85
+ # gemspec; test files are not included by default.
86
+ #
87
+ # @return [Array<String>]
88
+ #
89
+ attr_accessor :files
90
+
91
+ #
92
+ # Extra files (e.g. FAQ, LICENSE) to be processed by yard; these are
93
+ # extracted from the gemspec.
94
+ #
95
+ # @return [Array<String>]
96
+ #
97
+ attr_accessor :extra_files
98
+
99
+ #
100
+ # Options to be passed to yard; note that the {#output} option and the
101
+ # {#files} and {#extra_files} lists are handled separately.
102
+ #
103
+ # @return [Array<String>]
104
+ #
105
+ attr_accessor :options
106
+
107
+ #
108
+ # Customize the yardoc task (e.g. to add blocks to run before or after the
109
+ # docs are generated).
110
+ #
111
+ # @yield [yd] called after the defaults are set but before the yard task
112
+ # is generated
113
+ #
114
+ # @yieldparam [YARD::Rake::YardocTask] yd
115
+ #
116
+ # @return [nil]
117
+ #
118
+ def with_yardoc_task &block
119
+ @with_yardoc_task = block
120
+ nil
121
+ end
122
+
123
+ #
124
+ # Internal method; see {Plugin#create_rake_tasks}.
125
+ #
126
+ # @return [nil]
127
+ #
128
+ # @private
129
+ #
130
+ def create_rake_tasks
131
+ begin
132
+ require 'yard'
133
+ YARD::Rake::YardocTask.new do |yd|
134
+ yd.name = self.task_name
135
+ yd.options = complete_options
136
+ yd.files = self.files
137
+ yd.files.push('-', *self.extra_files) unless self.extra_files.empty?
138
+ @with_yardoc_task.call(yd) if @with_yardoc_task
139
+ end
140
+ CLOBBER.include(self.output)
141
+ CLOBBER.include('.yardoc')
142
+ rescue LoadError
143
+ # Assume yard is not installed.
144
+ end
145
+ nil
146
+ end
147
+
148
+ private
149
+
150
+ #
151
+ # Options to be passed to yardoc; this includes {#options} and the
152
+ # {#main}, {#title} and {#output} options.
153
+ #
154
+ # @return [Array<String>]
155
+ #
156
+ def complete_options
157
+ opts = self.options.dup
158
+ opts.push('--main', self.main) if self.main
159
+ opts.push('--title', self.title) if self.title
160
+ opts.push('--output', self.output)
161
+ opts
162
+ end
163
+ end
164
+ end
165
+ end
@@ -0,0 +1,3 @@
1
+ module Gemma
2
+ VERSION = '0.0.2'
3
+ end
@@ -0,0 +1,137 @@
1
+ require "test/unit"
2
+ require "rubygems"
3
+ require "gemma"
4
+ require "set"
5
+
6
+ class TestGemma < Test::Unit::TestCase
7
+ def test_empty_spec
8
+ s = Gem::Specification.new
9
+ Gemma::RakeTasks.new(s)
10
+ end
11
+
12
+ def test_rdoc
13
+ s = Gem::Specification.new
14
+ s.files = %w(lib/a.rb lib/b.rb)
15
+ s.test_files = %w(test/test_a.rb test/test_a.rb)
16
+ s.rdoc_options = ['--main', 'README.md']
17
+ s.extra_rdoc_files = ['README.md', 'FAQ']
18
+
19
+ Gemma::RakeTasks.new(s) do |g|
20
+ assert_equal %w(lib/a.rb lib/b.rb README.md FAQ).to_set,
21
+ g.rdoc.files.to_set
22
+ assert_equal [], g.rdoc.options
23
+ assert_equal 'README.md', g.rdoc.main
24
+ assert_equal nil, g.rdoc.title
25
+
26
+ g.rdoc.with_rdoc_task do |rd|
27
+ assert_equal rd.rdoc_files, g.rdoc.files
28
+ end
29
+ end
30
+ end
31
+
32
+ def test_yard
33
+ s = Gem::Specification.new
34
+ s.files = %w(lib/a.rb)
35
+ s.test_files = %w(test/test_a.rb)
36
+ s.rdoc_options = ['--main', 'README.rdoc']
37
+ s.extra_rdoc_files = ['README.rdoc']
38
+
39
+ # Just one option.
40
+ # A file should not be passed as an extra file if it's the --main file.
41
+ # Test files should not be documented.
42
+ Gemma::RakeTasks.new(s) do |g|
43
+ assert_equal %w(lib/a.rb), g.yard.files
44
+ assert_equal [], g.yard.extra_files
45
+ assert_equal 'README.rdoc', g.yard.main
46
+ assert_equal [], g.yard.options
47
+ assert_equal 'yard', g.yard.output
48
+ assert_equal :yard, g.yard.task_name
49
+ assert_equal nil, g.yard.title
50
+
51
+ g.yard.with_yardoc_task do |yd|
52
+ assert_equal %w(lib/a.rb), yd.files
53
+ assert_equal 4, yd.options.size
54
+ assert_equal 'README.rdoc',
55
+ Gemma::Options.extract(%w(--main), yd.options).argument
56
+ assert_equal 'yard',
57
+ Gemma::Options.extract(%w(--output), yd.options).argument
58
+ end
59
+ end
60
+
61
+ # Add some extra files (that aren't the --main file).
62
+ s.extra_rdoc_files << 'FAQ'
63
+ Gemma::RakeTasks.new(s) do |g|
64
+ assert_equal %w(lib/a.rb), g.yard.files
65
+ assert_equal %w(FAQ), g.yard.extra_files
66
+ assert_equal 'README.rdoc', g.yard.main
67
+ assert_equal [], g.yard.options
68
+ end
69
+
70
+ # Make sure extra options are ignored.
71
+ s.rdoc_options = ['--main', 'README.rdoc', '--diagram']
72
+ Gemma::RakeTasks.new(s) do |g|
73
+ assert_equal %w(lib/a.rb), g.yard.files
74
+ assert_equal %w(FAQ), g.yard.extra_files
75
+ assert_equal 'README.rdoc', g.yard.main
76
+ assert_equal [], g.yard.options
77
+ end
78
+ s.rdoc_options = ['--diagram', '--main', 'README.rdoc']
79
+ Gemma::RakeTasks.new(s) do |g|
80
+ assert_equal %w(lib/a.rb), g.yard.files
81
+ assert_equal %w(FAQ), g.yard.extra_files
82
+ assert_equal 'README.rdoc', g.yard.main
83
+ assert_equal [], g.yard.options
84
+ end
85
+
86
+ # Some more complicated options.
87
+ # Note that we ignore things that could be files ('bat').
88
+ s.rdoc_options = ['foo bar', '--baz', 'bat', '--title', 'a b c',
89
+ '--diagram', '--main', 'README.rdoc', 'ABCD']
90
+ Gemma::RakeTasks.new(s) do |g|
91
+ assert_equal 'a b c', g.yard.title
92
+ assert_equal [], g.yard.options
93
+
94
+ g.yard.with_yardoc_task do |yd|
95
+ assert_equal %w(lib/a.rb - FAQ), yd.files
96
+ assert_equal 6, yd.options.size
97
+ assert_equal 'README.rdoc',
98
+ Gemma::Options.extract(%w(--main), yd.options).argument
99
+ assert_equal 'yard',
100
+ Gemma::Options.extract(%w(--output), yd.options).argument
101
+ assert_equal 'a b c',
102
+ Gemma::Options.extract(%w(--title), yd.options).argument
103
+ end
104
+ end
105
+ end
106
+
107
+ def test_test_unit
108
+ s = Gem::Specification.new
109
+ s.files = %w(lib/a.rb lib/b.rb)
110
+ s.test_files = %w(test/test_a.rb test/test_b.rb)
111
+ s.require_paths << 'ext'
112
+
113
+ Gemma::RakeTasks.new(s) do |g|
114
+ g.test.with_test_task do |tt|
115
+ assert_equal %w(lib ext).to_set, tt.libs.to_set
116
+ assert_equal %w(test/test_a.rb test/test_b.rb).to_set,
117
+ tt.file_list.to_a.to_set
118
+ end
119
+ end
120
+ end
121
+
122
+ def test_rcov
123
+ s = Gem::Specification.new
124
+ s.files = %w(lib/a.rb lib/b.rb)
125
+ s.test_files = %w(test/test_a.rb test/test_b.rb)
126
+ s.require_paths << 'ext'
127
+
128
+ Gemma::RakeTasks.new(s) do |g|
129
+ g.rcov.with_rcov_task do |rcov|
130
+ assert_equal %w(lib ext).to_set, rcov.libs.to_set
131
+ assert_equal %w(test/test_a.rb test/test_b.rb).to_set,
132
+ rcov.file_list.to_a.to_set
133
+ end
134
+ end
135
+ end
136
+ end
137
+
@@ -0,0 +1,101 @@
1
+ require "test/unit"
2
+ require "rubygems"
3
+ require "gemma"
4
+
5
+ class TestOptions < Test::Unit::TestCase
6
+ include Gemma
7
+
8
+ def test_empty
9
+ # empty input
10
+ assert_equal Options::ExtractResult.new(nil, []),
11
+ Options.extract(%w(--a), [])
12
+ end
13
+
14
+ def test_long_form
15
+ input = %w(--a av --b --c=cv)
16
+
17
+ # option a has an argument
18
+ assert_equal Options::ExtractResult.new('av', %w(--b --c=cv)),
19
+ Options.extract(%w(--a), input)
20
+
21
+ # option b has no argument; result is ''
22
+ assert_equal Options::ExtractResult.new('', %w(--a av --c=cv)),
23
+ Options.extract(%w(--b), input)
24
+
25
+ # option c also has argument
26
+ assert_equal Options::ExtractResult.new('cv', %w(--a av --b)),
27
+ Options.extract(%w(--c), input)
28
+
29
+ # there is no option d; result is nil
30
+ assert_equal Options::ExtractResult.new(nil, input),
31
+ Options.extract(%w(--d), input)
32
+ end
33
+
34
+ def test_terminator
35
+ # just the -- terminator
36
+ assert_equal Options::ExtractResult.new(nil, ['--']),
37
+ Options.extract(%w(--a), ['--'])
38
+
39
+ # should keep content before and after the -- terminator
40
+ assert_equal Options::ExtractResult.new(nil, %w(a -- b)),
41
+ Options.extract(%w(--a), %w(a -- b))
42
+ end
43
+
44
+ def test_terminator_2
45
+ input = %w(foo --a av -- --b bv)
46
+
47
+ # should not be able to find options after the -- terminator
48
+ assert_equal Options::ExtractResult.new('av', %w(foo -- --b bv)),
49
+ Options.extract(%w(--a), input)
50
+ assert_equal Options::ExtractResult.new(nil, input),
51
+ Options.extract(%w(--b), input)
52
+ assert_equal Options::ExtractResult.new('', %w(-- --b)),
53
+ Options.extract(%w(--a), %w(--a -- --b))
54
+ assert_equal Options::ExtractResult.new(nil, %w(--a -- --b)),
55
+ Options.extract(%w(--b), %w(--a -- --b))
56
+ end
57
+
58
+ def test_short_form
59
+ # should be able to find -a but not -b
60
+ input = %w(foo -a av -- -b bv)
61
+ assert_equal Options::ExtractResult.new('av', %w(foo -- -b bv)),
62
+ Options.extract(%w(-a), input)
63
+ assert_equal Options::ExtractResult.new(nil, input),
64
+ Options.extract(%w(-b), input)
65
+
66
+ # the -aav and -b bv forms
67
+ input = %w(-aav -b bv)
68
+ assert_equal Options::ExtractResult.new('av', %w(-b bv)),
69
+ Options.extract(%w(-a), input)
70
+ assert_equal Options::ExtractResult.new('bv', %w(-aav)),
71
+ Options.extract(%w(-b), input)
72
+
73
+ # short form with no argument
74
+ assert_equal Options::ExtractResult.new('', %w(-a av)),
75
+ Options.extract(%w(-b), %w(-a av -b))
76
+
77
+ # missing short form argument
78
+ assert_equal Options::ExtractResult.new(nil, %w(-a av -b foo bar.txt)),
79
+ Options.extract(%w(-c), %w(-a av -b foo bar.txt))
80
+ end
81
+
82
+ def test_multiple_options
83
+ # single -a means we pick up a1
84
+ assert_equal Options::ExtractResult.new('a1', []),
85
+ Options.extract(%w(-a), %w(-a a1))
86
+
87
+ # the second -a means that we pick up a2
88
+ assert_equal Options::ExtractResult.new('a2', []),
89
+ Options.extract(%w(-a), %w(-a a1 -a a2))
90
+ assert_equal Options::ExtractResult.new('a2', %w(hi -bfoo)),
91
+ Options.extract(%w(-a), %w(hi -a a1 -a a2 -bfoo))
92
+
93
+ # mixing long and short forms doesn't affect this
94
+ assert_equal Options::ExtractResult.new('a2', []),
95
+ Options.extract(%w(-a --a), %w(-a a1 --a a2))
96
+
97
+ # a duplicate option after the -- terminator makes no difference
98
+ assert_equal Options::ExtractResult.new('a1', %w(-- -aa2)),
99
+ Options.extract(%w(-a), %w(-a a1 -- -aa2))
100
+ end
101
+ end
metadata ADDED
@@ -0,0 +1,86 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: gemma
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 2
10
+ version: 0.0.2
11
+ platform: ruby
12
+ authors:
13
+ - John Lees-Miller
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-09-20 00:00:00 +01:00
19
+ default_executable:
20
+ dependencies: []
21
+
22
+ description: |
23
+ If you are using .gemspecs as intended
24
+ (http://yehudakatz.com/2010/04/02/using-gemspecs-as-intended/), gemma generates
25
+ common rake tasks with default settings extracted from your .gemspec file.
26
+
27
+ email:
28
+ - jdleesmiller@gmail.com
29
+ executables: []
30
+
31
+ extensions: []
32
+
33
+ extra_rdoc_files:
34
+ - README.rdoc
35
+ files:
36
+ - lib/gemma/rake_tasks/gem_tasks.rb
37
+ - lib/gemma/rake_tasks/rcov_tasks.rb
38
+ - lib/gemma/rake_tasks/yard_tasks.rb
39
+ - lib/gemma/rake_tasks/rdoc_tasks.rb
40
+ - lib/gemma/rake_tasks/test_unit_tasks.rb
41
+ - lib/gemma/rake_tasks/plugin.rb
42
+ - lib/gemma/options.rb
43
+ - lib/gemma/rake_tasks.rb
44
+ - lib/gemma/version.rb
45
+ - lib/gemma.rb
46
+ - README.rdoc
47
+ - test/test_options.rb
48
+ - test/test_gemma.rb
49
+ has_rdoc: true
50
+ homepage: http://github.com/jdleesmiller/gemma
51
+ licenses: []
52
+
53
+ post_install_message:
54
+ rdoc_options:
55
+ - --main
56
+ - README.rdoc
57
+ require_paths:
58
+ - lib
59
+ required_ruby_version: !ruby/object:Gem::Requirement
60
+ none: false
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ hash: 3
65
+ segments:
66
+ - 0
67
+ version: "0"
68
+ required_rubygems_version: !ruby/object:Gem::Requirement
69
+ none: false
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ hash: 3
74
+ segments:
75
+ - 0
76
+ version: "0"
77
+ requirements: []
78
+
79
+ rubyforge_project:
80
+ rubygems_version: 1.3.7
81
+ signing_key:
82
+ specification_version: 3
83
+ summary: Generate helpful rake tasks from your gemspec.
84
+ test_files:
85
+ - test/test_options.rb
86
+ - test/test_gemma.rb