toys 0.3.7.1 → 0.3.8

Sign up to get free protection for your applications and to get access to all the features.
data/lib/toys.rb CHANGED
@@ -39,6 +39,11 @@ module Toys
39
39
  # @return [String]
40
40
  #
41
41
  BINARY_PATH = ::ENV["TOYS_BIN_PATH"] || "toys"
42
+
43
+ ##
44
+ # Namespace for standard template classes.
45
+ #
46
+ module Templates; end
42
47
  end
43
48
 
44
49
  require "toys/version"
@@ -108,7 +108,8 @@ module Toys
108
108
  config_file_name: CONFIG_FILE_NAME,
109
109
  index_file_name: INDEX_FILE_NAME,
110
110
  preload_file_name: PRELOAD_FILE_NAME,
111
- middleware_stack: default_middleware_stack
111
+ middleware_stack: default_middleware_stack,
112
+ template_lookup: default_template_lookup
112
113
  )
113
114
  add_standard_paths(cli, directory: directory)
114
115
  cli
@@ -190,5 +191,9 @@ module Toys
190
191
  end
191
192
 
192
193
  # rubocop:enable Metrics/MethodLength
194
+
195
+ def self.default_template_lookup
196
+ Utils::ModuleLookup.new.add_path("toys/templates")
197
+ end
193
198
  end
194
199
  end
@@ -0,0 +1,85 @@
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
+ include :fileutils
65
+
66
+ run 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
+ if ::File.exist?(file)
76
+ rm_rf file
77
+ puts "Cleaned: #{file}"
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,125 @@
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
+ flag :yes, "-y", "--yes", desc: "Do not ask for interactive confirmation"
92
+
93
+ include :exec
94
+ include :fileutils
95
+ include :terminal
96
+
97
+ run do
98
+ configure_exec(exit_on_nonzero_status: true)
99
+ gemspec = ::Gem::Specification.load "#{template.gem_name}.gemspec"
100
+ version = gemspec.version
101
+ gemfile = "#{template.gem_name}-#{version}.gem"
102
+ ::Gem::Package.build gemspec
103
+ mkdir_p "pkg"
104
+ mv gemfile, "pkg"
105
+ if template.push_gem
106
+ if ::File.directory?(".git") && capture("git status -s").strip != ""
107
+ logger.error "Cannot push the gem when there are uncommited changes"
108
+ exit(1)
109
+ end
110
+ exit(1) unless option(:yes) || confirm("Release #{gemfile}?")
111
+ sh "gem push pkg/#{gemfile}"
112
+ if template.tag
113
+ sh "git tag v#{version}"
114
+ if template.push_tag
115
+ template.push_tag = "origin" if template.push_tag == true
116
+ sh "git push #{template.push_tag} v#{version}"
117
+ end
118
+ end
119
+ end
120
+ end
121
+ end
122
+ end
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,125 @@
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 run minitest
34
+ #
35
+ class Minitest
36
+ include Template
37
+
38
+ ##
39
+ # Default tool name
40
+ # @return [String]
41
+ #
42
+ DEFAULT_TOOL_NAME = "test".freeze
43
+
44
+ ##
45
+ # Default set of library paths
46
+ # @return [Array<String>]
47
+ #
48
+ DEFAULT_LIBS = ["lib"].freeze
49
+
50
+ ##
51
+ # Default set of test file globs
52
+ # @return [Array<String>]
53
+ #
54
+ DEFAULT_FILES = ["test/**/test*.rb"].freeze
55
+
56
+ ##
57
+ # Create the template settings for the Minitest template.
58
+ #
59
+ # @param [String] name Name of the tool to create. Defaults to
60
+ # {DEFAULT_TOOL_NAME}.
61
+ # @param [Array<String>] libs An array of library paths to add to the
62
+ # ruby require path. Defaults to {DEFAULT_LIBS}.
63
+ # @param [Array<String>] files An array of globs indicating the test
64
+ # files to load. Defaults to {DEFAULT_FILES}.
65
+ # @param [Boolean] warnings If true, runs tests with Ruby warnings.
66
+ # Defaults to true.
67
+ #
68
+ def initialize(name: DEFAULT_TOOL_NAME,
69
+ libs: DEFAULT_LIBS,
70
+ files: DEFAULT_FILES,
71
+ warnings: true)
72
+ @name = name
73
+ @libs = libs
74
+ @files = files
75
+ @warnings = warnings
76
+ end
77
+
78
+ attr_accessor :name
79
+ attr_accessor :libs
80
+ attr_accessor :files
81
+ attr_accessor :warnings
82
+
83
+ to_expand do |template|
84
+ tool(template.name) do
85
+ desc "Run minitest on the current project."
86
+
87
+ include :exec
88
+
89
+ flag :warnings, "-w", "--[no-]warnings",
90
+ default: template.warnings,
91
+ desc: "Turn on Ruby warnings (defaults to #{template.warnings})"
92
+
93
+ remaining_args :tests, desc: "Paths to the tests to run (defaults to all tests)"
94
+
95
+ run do
96
+ ruby_args = []
97
+ unless template.libs.empty?
98
+ lib_path = template.libs.join(::File::PATH_SEPARATOR)
99
+ ruby_args << "-I#{lib_path}"
100
+ end
101
+ ruby_args << "-w" if self[:warnings]
102
+
103
+ tests = self[:tests]
104
+ if tests.empty?
105
+ Array(template.files).each do |pattern|
106
+ tests.concat(::Dir.glob(pattern))
107
+ end
108
+ tests.uniq!
109
+ end
110
+
111
+ result = ruby(ruby_args, in: :controller) do |controller|
112
+ tests.each do |file|
113
+ controller.in.puts("load '#{file}'")
114
+ end
115
+ end
116
+ if result.error?
117
+ logger.error("Minitest failed!")
118
+ exit(result.exit_code)
119
+ end
120
+ end
121
+ end
122
+ end
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,86 @@
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 run rubocop
34
+ #
35
+ class Rubocop
36
+ include Template
37
+
38
+ ##
39
+ # Default tool name
40
+ # @return [String]
41
+ #
42
+ DEFAULT_TOOL_NAME = "rubocop".freeze
43
+
44
+ ##
45
+ # Create the template settings for the Rubocop template.
46
+ #
47
+ # @param [String] name Name of the tool to create. Defaults to
48
+ # {DEFAULT_TOOL_NAME}.
49
+ # @param [Boolean] fail_on_error If true, exits with a nonzero code if
50
+ # Rubocop fails. Defaults to true.
51
+ # @param [Array<String>] options Additional options passed to the Rubocop
52
+ # CLI.
53
+ #
54
+ def initialize(name: DEFAULT_TOOL_NAME,
55
+ fail_on_error: true,
56
+ options: [])
57
+ @name = name
58
+ @fail_on_error = fail_on_error
59
+ @options = options
60
+ end
61
+
62
+ attr_accessor :name
63
+ attr_accessor :fail_on_error
64
+ attr_accessor :options
65
+
66
+ to_expand do |template|
67
+ tool(template.name) do
68
+ desc "Run rubocop on the current project."
69
+
70
+ include :exec
71
+
72
+ run do
73
+ require "rubocop"
74
+ cli = ::RuboCop::CLI.new
75
+ logger.info "Running RuboCop..."
76
+ result = cli.run(template.options)
77
+ if result.nonzero?
78
+ logger.error "RuboCop failed!"
79
+ exit(1) if template.fail_on_error
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end