toys-core 0.3.2

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.
@@ -0,0 +1,99 @@
1
+ # Copyright 2018 Daniel Azuma
2
+ #
3
+ # All rights reserved.
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without
6
+ # modification, are permitted provided that the following conditions are met:
7
+ #
8
+ # * Redistributions of source code must retain the above copyright notice,
9
+ # this list of conditions and the following disclaimer.
10
+ # * Redistributions in binary form must reproduce the above copyright notice,
11
+ # this list of conditions and the following disclaimer in the documentation
12
+ # and/or other materials provided with the distribution.
13
+ # * Neither the name of the copyright holder, nor the names of any other
14
+ # contributors to this software, may be used to endorse or promote products
15
+ # derived from this software without specific prior written permission.
16
+ #
17
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
+ # POSSIBILITY OF SUCH DAMAGE.
28
+ ;
29
+
30
+ require "toys/middleware/base"
31
+
32
+ module Toys
33
+ module Middleware
34
+ ##
35
+ # A middleware that displays a version string for certain tools if the
36
+ # `--version` switch is given. You can specify which tools respond to
37
+ # this switch, and the string that will be displayed.
38
+ #
39
+ class ShowVersion < Base
40
+ ##
41
+ # Default version switches
42
+ # @return [Array<String>]
43
+ #
44
+ DEFAULT_VERSION_SWITCHES = ["--version"].freeze
45
+
46
+ ##
47
+ # Return a simple version displayer that returns the given string for
48
+ # the root tool.
49
+ #
50
+ # @return [Proc]
51
+ #
52
+ def self.root_version_displayer(version)
53
+ proc { |tool| tool.root? ? version : false }
54
+ end
55
+
56
+ ##
57
+ # Create a ShowVersion middleware
58
+ #
59
+ # @param [Proc] version_displayer A proc that takes a tool and returns
60
+ # either the version string that should be displayed, or a falsy
61
+ # value to indicate the tool should not have a `--version` switch.
62
+ # Defaults to a "null" displayer that returns false for all tools.
63
+ # @param [Array<String>] version_switches A list of switches that should
64
+ # trigger displaying the version. Default is
65
+ # {DEFAULT_VERSION_SWITCHES}.
66
+ #
67
+ def initialize(version_displayer: nil,
68
+ version_switches: DEFAULT_VERSION_SWITCHES)
69
+ @version_displayer = version_displayer || proc { |_| false }
70
+ @version_switches = version_switches
71
+ end
72
+
73
+ ##
74
+ # Adds the version switch if requested.
75
+ #
76
+ def config(tool)
77
+ version = @version_displayer.call(tool)
78
+ if version
79
+ tool.add_switch(:_show_version, *@version_switches,
80
+ doc: "Show version",
81
+ handler: ->(_val, _prev) { version },
82
+ only_unique: true)
83
+ end
84
+ yield
85
+ end
86
+
87
+ ##
88
+ # This middleware displays the version.
89
+ #
90
+ def execute(context)
91
+ if context[:_show_version]
92
+ puts context[:_show_version]
93
+ else
94
+ yield
95
+ end
96
+ end
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,123 @@
1
+ # Copyright 2018 Daniel Azuma
2
+ #
3
+ # All rights reserved.
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without
6
+ # modification, are permitted provided that the following conditions are met:
7
+ #
8
+ # * Redistributions of source code must retain the above copyright notice,
9
+ # this list of conditions and the following disclaimer.
10
+ # * Redistributions in binary form must reproduce the above copyright notice,
11
+ # this list of conditions and the following disclaimer in the documentation
12
+ # and/or other materials provided with the distribution.
13
+ # * Neither the name of the copyright holder, nor the names of any other
14
+ # contributors to this software, may be used to endorse or promote products
15
+ # derived from this software without specific prior written permission.
16
+ #
17
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
+ # POSSIBILITY OF SUCH DAMAGE.
28
+ ;
29
+
30
+ module Toys
31
+ ##
32
+ # A template definition. Template classes should include this module.
33
+ #
34
+ # A template is a configurable set of DSL code that can be run in a toys
35
+ # configuration to automate tool defintion. For example, toys provides a
36
+ # "minitest" template that generates a "test" tool that invokes minitest.
37
+ # Templates will often support configuration; for example the minitest
38
+ # template lets you configure the paths to the test files.
39
+ #
40
+ # ## Usage
41
+ #
42
+ # To create a template, define a class and include this module.
43
+ # The class defines the "configuration" of the template. If your template
44
+ # has options/parameters, you should provide a constructor, and methods
45
+ # appropriate to edit those options. The arguments given to the
46
+ # {Toys::ConfigDSL#expand} method are passed to your constructor, and your
47
+ # template object is passed to any block given to {Toys::ConfigDSL#expand}.
48
+ #
49
+ # Next, in your template class, call the `to_expand` method, which is defined
50
+ # in {Toys::Template::ClassMethods#to_expand}. Pass this a block which
51
+ # defines the implementation of the template. Effectively, the contents of
52
+ # this block are "inserted" into the user's configuration. The template
53
+ # object is passed to the block so you have access to the template options.
54
+ #
55
+ # ## Example
56
+ #
57
+ # This is a simple template that generates a "hello" tool. The tool simply
58
+ # prints a `"Hello, #{name}!"` greeting. The name is set as a template
59
+ # option; it is defined when the template is expanded in a toys
60
+ # configuration.
61
+ #
62
+ # # Define a template by creating a class that includes Toys::Template.
63
+ # class MyHelloTemplate
64
+ # include Toys::Template
65
+ #
66
+ # # A user of the template may pass an optional name as a parameter to
67
+ # # `expand`, or leave it as the default of "world".
68
+ # def initialize(name: "world")
69
+ # @name = name
70
+ # end
71
+ #
72
+ # # The template is passed to the expand block, so a user of the
73
+ # # template may also call this method to set the name.
74
+ # attr_accessor :name
75
+ #
76
+ # # The following block is inserted when the template is expanded.
77
+ # to_expand do |template|
78
+ # desc "Prints a greeting to #{template.name}"
79
+ # tool "templated-greeting" do
80
+ # execute do
81
+ # puts "Hello, #{template.name}!"
82
+ # end
83
+ # end
84
+ # end
85
+ # end
86
+ #
87
+ # Now you can use the template in your `.toys.rb` file like this:
88
+ #
89
+ # expand(MyHelloTemplate, name: "rubyists")
90
+ #
91
+ # or alternately:
92
+ #
93
+ # expand(MyHelloTemplate) do |template|
94
+ # template.name = "rubyists"
95
+ # end
96
+ #
97
+ # And it will create a tool called "templated-greeting".
98
+ #
99
+ module Template
100
+ ## @private
101
+ def self.included(mod)
102
+ mod.extend(ClassMethods)
103
+ end
104
+
105
+ ##
106
+ # Class methods that will be added to a template class.
107
+ #
108
+ module ClassMethods
109
+ ##
110
+ # Provide the block that implements the template.
111
+ #
112
+ def to_expand(&block)
113
+ @expander = block
114
+ end
115
+
116
+ ##
117
+ # You may alternately set the expander block using this accessor.
118
+ # @return [Proc]
119
+ #
120
+ attr_accessor :expander
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,55 @@
1
+ # Copyright 2018 Daniel Azuma
2
+ #
3
+ # All rights reserved.
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without
6
+ # modification, are permitted provided that the following conditions are met:
7
+ #
8
+ # * Redistributions of source code must retain the above copyright notice,
9
+ # this list of conditions and the following disclaimer.
10
+ # * Redistributions in binary form must reproduce the above copyright notice,
11
+ # this list of conditions and the following disclaimer in the documentation
12
+ # and/or other materials provided with the distribution.
13
+ # * Neither the name of the copyright holder, nor the names of any other
14
+ # contributors to this software, may be used to endorse or promote products
15
+ # derived from this software without specific prior written permission.
16
+ #
17
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
+ # POSSIBILITY OF SUCH DAMAGE.
28
+ ;
29
+
30
+ require "toys/utils/module_lookup"
31
+
32
+ module Toys
33
+ ##
34
+ # Namespace for common templates
35
+ #
36
+ module Templates
37
+ ##
38
+ # Return a template class by name.
39
+ #
40
+ # Currently recognized template names are:
41
+ #
42
+ # * `:clean` : Creates a tool that cleans build artifacts.
43
+ # * `:gem_build` : Creates a tool that builds and/or releases gems.
44
+ # * `:minitest` : Creates a tool that runs unit tests.
45
+ # * `:rubocop` : Creates a tool that runs rubocop.
46
+ # * `:yardoc` : Creates a tool that generates YARD documentation.
47
+ #
48
+ # @param [String,Symbol] name Name of the template class to return
49
+ # @return [Class,nil] The class, or `nil` if not found
50
+ #
51
+ def self.lookup(name)
52
+ Utils::ModuleLookup.lookup(:templates, name)
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,82 @@
1
+ # Copyright 2018 Daniel Azuma
2
+ #
3
+ # All rights reserved.
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without
6
+ # modification, are permitted provided that the following conditions are met:
7
+ #
8
+ # * Redistributions of source code must retain the above copyright notice,
9
+ # this list of conditions and the following disclaimer.
10
+ # * Redistributions in binary form must reproduce the above copyright notice,
11
+ # this list of conditions and the following disclaimer in the documentation
12
+ # and/or other materials provided with the distribution.
13
+ # * Neither the name of the copyright holder, nor the names of any other
14
+ # contributors to this software, may be used to endorse or promote products
15
+ # derived from this software without specific prior written permission.
16
+ #
17
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
+ # POSSIBILITY OF SUCH DAMAGE.
28
+ ;
29
+
30
+ module Toys
31
+ module Templates
32
+ ##
33
+ # A template for tools that clean build artifacts
34
+ #
35
+ class Clean
36
+ include Template
37
+
38
+ ##
39
+ # Default tool name
40
+ # @return [String]
41
+ #
42
+ DEFAULT_TOOL_NAME = "clean".freeze
43
+
44
+ ##
45
+ # Create the template settings for the Clean template.
46
+ #
47
+ # @param [String] name Name of the tool to create. Defaults to
48
+ # {DEFAULT_TOOL_NAME}.
49
+ # @param [Array<String>] paths An array of glob patterns indicating what
50
+ # to clean.
51
+ #
52
+ def initialize(name: DEFAULT_TOOL_NAME, paths: [])
53
+ @name = name
54
+ @paths = paths
55
+ end
56
+
57
+ attr_accessor :name
58
+ attr_accessor :paths
59
+
60
+ to_expand do |template|
61
+ tool(template.name) do
62
+ desc "Clean built files and directories."
63
+
64
+ use :file_utils
65
+
66
+ execute do
67
+ files = []
68
+ patterns = Array(template.paths)
69
+ patterns.each do |pattern|
70
+ files.concat(::Dir.glob(pattern))
71
+ end
72
+ files.uniq!
73
+
74
+ files.each do |file|
75
+ rm_rf file
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,121 @@
1
+ # Copyright 2018 Daniel Azuma
2
+ #
3
+ # All rights reserved.
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without
6
+ # modification, are permitted provided that the following conditions are met:
7
+ #
8
+ # * Redistributions of source code must retain the above copyright notice,
9
+ # this list of conditions and the following disclaimer.
10
+ # * Redistributions in binary form must reproduce the above copyright notice,
11
+ # this list of conditions and the following disclaimer in the documentation
12
+ # and/or other materials provided with the distribution.
13
+ # * Neither the name of the copyright holder, nor the names of any other
14
+ # contributors to this software, may be used to endorse or promote products
15
+ # derived from this software without specific prior written permission.
16
+ #
17
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
+ # POSSIBILITY OF SUCH DAMAGE.
28
+ ;
29
+
30
+ require "rubygems/package"
31
+
32
+ module Toys
33
+ module Templates
34
+ ##
35
+ # A template for tools that build and release gems
36
+ #
37
+ class GemBuild
38
+ include Template
39
+
40
+ ##
41
+ # Default tool name
42
+ # @return [String]
43
+ #
44
+ DEFAULT_TOOL_NAME = "build".freeze
45
+
46
+ ##
47
+ # Create the template settings for the GemBuild template.
48
+ #
49
+ # @param [String] name Name of the tool to create. Defaults to
50
+ # {DEFAULT_TOOL_NAME}.
51
+ # @param [String] gem_name Name of the gem to build. If not provided,
52
+ # defaults to the first gemspec file it finds.
53
+ # @param [Boolean] push_gem If true, pushes the built gem to rubygems.
54
+ # @param [Boolean] tag If true, tags the git repo with the gem version.
55
+ # @param [Boolean,String] push_tag If truthy, pushes the new tag to
56
+ # a git remote. You may specify which remote by setting the value to
57
+ # a string. Otherwise, if the value is simply `true`, the "origin"
58
+ # remote is used by default.
59
+ #
60
+ def initialize(name: DEFAULT_TOOL_NAME,
61
+ gem_name: nil,
62
+ push_gem: false,
63
+ tag: false,
64
+ push_tag: false)
65
+ @name = name
66
+ @gem_name = gem_name
67
+ @push_gem = push_gem
68
+ @tag = tag
69
+ @push_tag = push_tag
70
+ end
71
+
72
+ attr_accessor :name
73
+ attr_accessor :gem_name
74
+ attr_accessor :push_gem
75
+ attr_accessor :tag
76
+ attr_accessor :push_tag
77
+
78
+ to_expand do |template|
79
+ unless template.gem_name
80
+ candidates = ::Dir.glob("*.gemspec")
81
+ if candidates.empty?
82
+ raise ToolDefinitionError, "Could not find a gemspec"
83
+ end
84
+ template.gem_name = candidates.first.sub(/\.gemspec$/, "")
85
+ end
86
+ task_type = template.push_gem ? "Release" : "Build"
87
+
88
+ tool(template.name) do
89
+ desc "#{task_type} the gem: #{template.gem_name}"
90
+
91
+ use :file_utils
92
+ use :exec
93
+
94
+ execute do
95
+ configure_exec(exit_on_nonzero_status: true)
96
+ gemspec = ::Gem::Specification.load "#{template.gem_name}.gemspec"
97
+ version = gemspec.version
98
+ gemfile = "#{template.gem_name}-#{version}.gem"
99
+ ::Gem::Package.build gemspec
100
+ mkdir_p "pkg"
101
+ mv gemfile, "pkg"
102
+ if template.push_gem
103
+ if ::File.directory?(".git") && capture("git status -s").strip != ""
104
+ logger.error "Cannot push the gem when there are uncommited changes"
105
+ exit(1)
106
+ end
107
+ sh "gem push pkg/#{gemfile}"
108
+ if template.tag
109
+ sh "git tag v#{version}"
110
+ if template.push_tag
111
+ template.push_tag = "origin" if template.push_tag == true
112
+ sh "git push #{template.push_tag} v#{version}"
113
+ end
114
+ end
115
+ end
116
+ end
117
+ end
118
+ end
119
+ end
120
+ end
121
+ end