kamaze-project 1.0.0
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.
- checksums.yaml +7 -0
- data/.yardopts +18 -0
- data/bin/plop +5 -0
- data/lib/kamaze-project.rb +39 -0
- data/lib/kamaze/project.rb +155 -0
- data/lib/kamaze/project/boot/core_ext.rb +16 -0
- data/lib/kamaze/project/boot/listen.rb +38 -0
- data/lib/kamaze/project/concern.rb +13 -0
- data/lib/kamaze/project/concern/cli.rb +53 -0
- data/lib/kamaze/project/concern/cli/with_exit_on_failure.rb +36 -0
- data/lib/kamaze/project/concern/env.rb +63 -0
- data/lib/kamaze/project/concern/helper.rb +20 -0
- data/lib/kamaze/project/concern/mode.rb +19 -0
- data/lib/kamaze/project/concern/observable.rb +132 -0
- data/lib/kamaze/project/concern/sh.rb +91 -0
- data/lib/kamaze/project/concern/tasks.rb +55 -0
- data/lib/kamaze/project/concern/tools.rb +27 -0
- data/lib/kamaze/project/config.rb +58 -0
- data/lib/kamaze/project/core_ext/object.rb +27 -0
- data/lib/kamaze/project/core_ext/pp.rb +28 -0
- data/lib/kamaze/project/debug.rb +136 -0
- data/lib/kamaze/project/dsl.rb +16 -0
- data/lib/kamaze/project/dsl/definition.rb +43 -0
- data/lib/kamaze/project/dsl/setup.rb +11 -0
- data/lib/kamaze/project/helper.rb +63 -0
- data/lib/kamaze/project/helper/inflector.rb +44 -0
- data/lib/kamaze/project/helper/project.rb +34 -0
- data/lib/kamaze/project/helper/project/config.rb +25 -0
- data/lib/kamaze/project/observable.rb +20 -0
- data/lib/kamaze/project/observer.rb +37 -0
- data/lib/kamaze/project/resources/Vagrantfile +128 -0
- data/lib/kamaze/project/resources/config/tools.yml +15 -0
- data/lib/kamaze/project/struct.rb +34 -0
- data/lib/kamaze/project/tasks/cs.rb +23 -0
- data/lib/kamaze/project/tasks/cs/control.rb +17 -0
- data/lib/kamaze/project/tasks/cs/correct.rb +17 -0
- data/lib/kamaze/project/tasks/cs/pre_commit.rb +66 -0
- data/lib/kamaze/project/tasks/doc.rb +21 -0
- data/lib/kamaze/project/tasks/doc/watch.rb +41 -0
- data/lib/kamaze/project/tasks/gem.rb +14 -0
- data/lib/kamaze/project/tasks/gem/build.rb +34 -0
- data/lib/kamaze/project/tasks/gem/compile.rb +30 -0
- data/lib/kamaze/project/tasks/gem/gemspec.rb +20 -0
- data/lib/kamaze/project/tasks/gem/install.rb +32 -0
- data/lib/kamaze/project/tasks/gem/push.rb +27 -0
- data/lib/kamaze/project/tasks/misc/gitignore.rb +29 -0
- data/lib/kamaze/project/tasks/shell.rb +17 -0
- data/lib/kamaze/project/tasks/sources.rb +6 -0
- data/lib/kamaze/project/tasks/sources/license.rb +35 -0
- data/lib/kamaze/project/tasks/test.rb +16 -0
- data/lib/kamaze/project/tasks/vagrant.rb +71 -0
- data/lib/kamaze/project/tasks/version/edit.rb +16 -0
- data/lib/kamaze/project/tools.rb +18 -0
- data/lib/kamaze/project/tools/base_tool.rb +55 -0
- data/lib/kamaze/project/tools/console.rb +48 -0
- data/lib/kamaze/project/tools/console/output.rb +120 -0
- data/lib/kamaze/project/tools/console/output/buffer.rb +48 -0
- data/lib/kamaze/project/tools/gemspec.rb +33 -0
- data/lib/kamaze/project/tools/gemspec/builder.rb +99 -0
- data/lib/kamaze/project/tools/gemspec/concern.rb +13 -0
- data/lib/kamaze/project/tools/gemspec/concern/reading.rb +49 -0
- data/lib/kamaze/project/tools/gemspec/packager.rb +67 -0
- data/lib/kamaze/project/tools/gemspec/packer.rb +89 -0
- data/lib/kamaze/project/tools/gemspec/packer/command.rb +143 -0
- data/lib/kamaze/project/tools/gemspec/reader.rb +70 -0
- data/lib/kamaze/project/tools/gemspec/reader/decorator.rb +78 -0
- data/lib/kamaze/project/tools/gemspec/writer.rb +127 -0
- data/lib/kamaze/project/tools/gemspec/writer/dep_gen.rb +61 -0
- data/lib/kamaze/project/tools/gemspec/writer/dependency.rb +104 -0
- data/lib/kamaze/project/tools/git.rb +95 -0
- data/lib/kamaze/project/tools/git/hooks.rb +66 -0
- data/lib/kamaze/project/tools/git/hooks/base_hook.rb +33 -0
- data/lib/kamaze/project/tools/git/hooks/pre_commit.rb +81 -0
- data/lib/kamaze/project/tools/git/status.rb +101 -0
- data/lib/kamaze/project/tools/git/status/decorator.rb +39 -0
- data/lib/kamaze/project/tools/git/status/file.rb +180 -0
- data/lib/kamaze/project/tools/git/status/files_array.rb +39 -0
- data/lib/kamaze/project/tools/git/status/index.rb +77 -0
- data/lib/kamaze/project/tools/git/status/worktree.rb +19 -0
- data/lib/kamaze/project/tools/git/util.rb +35 -0
- data/lib/kamaze/project/tools/licenser.rb +197 -0
- data/lib/kamaze/project/tools/packager.rb +86 -0
- data/lib/kamaze/project/tools/packager/filesystem.rb +178 -0
- data/lib/kamaze/project/tools/packager/filesystem/operator.rb +83 -0
- data/lib/kamaze/project/tools/packager/filesystem/operator/utils.rb +77 -0
- data/lib/kamaze/project/tools/process_locker.rb +106 -0
- data/lib/kamaze/project/tools/rspec.rb +115 -0
- data/lib/kamaze/project/tools/rubocop.rb +128 -0
- data/lib/kamaze/project/tools/rubocop/arguments.rb +19 -0
- data/lib/kamaze/project/tools/rubocop/config.rb +43 -0
- data/lib/kamaze/project/tools/shell.rb +85 -0
- data/lib/kamaze/project/tools/vagrant.rb +182 -0
- data/lib/kamaze/project/tools/vagrant/composer.rb +88 -0
- data/lib/kamaze/project/tools/vagrant/composer/file.rb +79 -0
- data/lib/kamaze/project/tools/vagrant/remote.rb +79 -0
- data/lib/kamaze/project/tools/vagrant/shell.rb +102 -0
- data/lib/kamaze/project/tools/vagrant/writer.rb +81 -0
- data/lib/kamaze/project/tools/yardoc.rb +75 -0
- data/lib/kamaze/project/tools/yardoc/file.rb +55 -0
- data/lib/kamaze/project/tools/yardoc/watchable.rb +70 -0
- data/lib/kamaze/project/tools/yardoc/watcher.rb +106 -0
- data/lib/kamaze/project/tools_provider.rb +161 -0
- data/lib/kamaze/project/tools_provider/resolver.rb +42 -0
- data/lib/kamaze/project/version.rb +104 -0
- data/lib/kamaze/project/version.yml +17 -0
- metadata +321 -0
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Copyright (C) 2017-2018 Dimitri Arrigoni <dimitri@arrigoni.me>
|
|
4
|
+
# License GPLv3+: GNU GPL version 3 or later
|
|
5
|
+
# <http://www.gnu.org/licenses/gpl.html>.
|
|
6
|
+
# This is free software: you are free to change and redistribute it.
|
|
7
|
+
# There is NO WARRANTY, to the extent permitted by law.
|
|
8
|
+
|
|
9
|
+
require_relative '../packager'
|
|
10
|
+
require_relative 'filesystem/operator'
|
|
11
|
+
require 'pathname'
|
|
12
|
+
|
|
13
|
+
# Filesystem description used during packaging
|
|
14
|
+
#
|
|
15
|
+
# Filesystem has an Operator, which is intended to manipulate
|
|
16
|
+
# described files and directories.
|
|
17
|
+
# Package has a name, see ``package_name``,
|
|
18
|
+
# package name SHOULD be constitued with two (_path_) parts.
|
|
19
|
+
# Package dirs are labeled, as a default, only ``:src`` is provided.
|
|
20
|
+
# Labels are used to constitute the complete directory path
|
|
21
|
+
# (relative to ``pwd``).
|
|
22
|
+
class Kamaze::Project::Tools::Packager::Filesystem
|
|
23
|
+
# Package dir (root directory)
|
|
24
|
+
#
|
|
25
|
+
# Relative to current pwd
|
|
26
|
+
#
|
|
27
|
+
# @type [String]
|
|
28
|
+
attr_writer :package_basedir
|
|
29
|
+
|
|
30
|
+
# Working directory
|
|
31
|
+
#
|
|
32
|
+
# @type [String]
|
|
33
|
+
attr_writer :working_dir
|
|
34
|
+
|
|
35
|
+
# @type [Array<String|Pathname>]
|
|
36
|
+
attr_writer :source_files
|
|
37
|
+
|
|
38
|
+
# Name given to the package
|
|
39
|
+
#
|
|
40
|
+
# @type [String]
|
|
41
|
+
attr_accessor :package_name
|
|
42
|
+
|
|
43
|
+
# Labels for packaging stages
|
|
44
|
+
#
|
|
45
|
+
# @type [Array<Symbol>]
|
|
46
|
+
attr_writer :package_labels
|
|
47
|
+
|
|
48
|
+
# Labels for purgeables dirs (during prepare)
|
|
49
|
+
#
|
|
50
|
+
# @type [Array<Symbol>]
|
|
51
|
+
attr_writer :purgeables
|
|
52
|
+
|
|
53
|
+
# @type [Boolean]
|
|
54
|
+
attr_writer :verbose
|
|
55
|
+
|
|
56
|
+
def initialize
|
|
57
|
+
@package_basedir = 'build'
|
|
58
|
+
@package_name = 'sample/package'
|
|
59
|
+
|
|
60
|
+
@working_dir = Dir.pwd
|
|
61
|
+
@package_labels = [:src]
|
|
62
|
+
|
|
63
|
+
@verbose = true
|
|
64
|
+
@operator = self.operator
|
|
65
|
+
|
|
66
|
+
yield self if block_given?
|
|
67
|
+
|
|
68
|
+
@source_files ||= []
|
|
69
|
+
@purgeables ||= []
|
|
70
|
+
|
|
71
|
+
mute_attributes!(mutable_attributes)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Get packaging dir (root directory)
|
|
75
|
+
#
|
|
76
|
+
# @return [Pathname]
|
|
77
|
+
def package_basedir
|
|
78
|
+
::Pathname.new(@package_basedir)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Get package dir identified by its name
|
|
82
|
+
#
|
|
83
|
+
# @return [Pathname]
|
|
84
|
+
def package_dir
|
|
85
|
+
package_basedir.join(package_name)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# Get (named) paths (as: src, tmp and bin)
|
|
89
|
+
#
|
|
90
|
+
# @return [Hash]
|
|
91
|
+
def package_dirs
|
|
92
|
+
@package_labels.map do |k|
|
|
93
|
+
[k, package_dir.join(k.to_s)]
|
|
94
|
+
end.to_h
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# Get purgeable (named) paths
|
|
98
|
+
#
|
|
99
|
+
# @return [Hash]
|
|
100
|
+
def purgeable_dirs
|
|
101
|
+
@purgeables.map do |k|
|
|
102
|
+
[k, package_dirs[k]] if package_dirs[k]
|
|
103
|
+
end.to_h
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# Get (original) working dir
|
|
107
|
+
#
|
|
108
|
+
# @return [Pathname]
|
|
109
|
+
def working_dir
|
|
110
|
+
::Pathname.new(@working_dir)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
alias pwd working_dir
|
|
114
|
+
|
|
115
|
+
# Get source files
|
|
116
|
+
#
|
|
117
|
+
# @return [Array<Pathname>]
|
|
118
|
+
def source_files
|
|
119
|
+
@source_files.sort.map { |path| ::Pathname.new(path) }
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def method_missing(method, *args, &block)
|
|
123
|
+
if respond_to_missing?(method)
|
|
124
|
+
operator.public_send(method, *args, &block)
|
|
125
|
+
else
|
|
126
|
+
super
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def respond_to_missing?(method, include_private = false)
|
|
131
|
+
return true if operator.respond_to?(method, include_private)
|
|
132
|
+
|
|
133
|
+
super(method, include_private)
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def mutable_attributes
|
|
137
|
+
[
|
|
138
|
+
:verbose,
|
|
139
|
+
:purgeables,
|
|
140
|
+
:working_dir,
|
|
141
|
+
:source_files,
|
|
142
|
+
:package_basedir,
|
|
143
|
+
:package_name,
|
|
144
|
+
:package_labels
|
|
145
|
+
].sort
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def mutable_attribute?(attr)
|
|
149
|
+
attr = attr.to_s.gsub(/=$?/, '').to_sym
|
|
150
|
+
|
|
151
|
+
mutable_attributes.include?(attr)
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
protected
|
|
155
|
+
|
|
156
|
+
# @return [Boolean]
|
|
157
|
+
attr_reader :verbose
|
|
158
|
+
|
|
159
|
+
# Get operator
|
|
160
|
+
#
|
|
161
|
+
# @return [Kamaze::Project::Tools::Packager::Filesystem::Operator]
|
|
162
|
+
def operator
|
|
163
|
+
const_class = self.class.const_get(:Operator)
|
|
164
|
+
|
|
165
|
+
const_class.new(self, verbose: verbose)
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
# Pass some attributes to protected
|
|
169
|
+
#
|
|
170
|
+
# @return [self]
|
|
171
|
+
def mute_attributes!(attributes)
|
|
172
|
+
attributes.each do |m|
|
|
173
|
+
self.singleton_class.class_eval { protected "#{m}=" }
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
self
|
|
177
|
+
end
|
|
178
|
+
end
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Copyright (C) 2017-2018 Dimitri Arrigoni <dimitri@arrigoni.me>
|
|
4
|
+
# License GPLv3+: GNU GPL version 3 or later
|
|
5
|
+
# <http://www.gnu.org/licenses/gpl.html>.
|
|
6
|
+
# This is free software: you are free to change and redistribute it.
|
|
7
|
+
# There is NO WARRANTY, to the extent permitted by law.
|
|
8
|
+
|
|
9
|
+
require 'pathname'
|
|
10
|
+
require_relative '../filesystem'
|
|
11
|
+
require_relative 'operator/utils'
|
|
12
|
+
|
|
13
|
+
# Filesystem operator (manipulator)
|
|
14
|
+
#
|
|
15
|
+
# This class is intended to manipulate a ``Filesystem``.
|
|
16
|
+
class Kamaze::Project::Tools::Packager::Filesystem::Operator
|
|
17
|
+
include Utils
|
|
18
|
+
|
|
19
|
+
# @return [Kamaze::Project::Tools::Packager::Filesystem]
|
|
20
|
+
attr_reader :fs
|
|
21
|
+
|
|
22
|
+
# @param [Kamaze::Project::Tools::Packager::Filesystem] filesystem
|
|
23
|
+
# @param [Hash] options
|
|
24
|
+
# @see fs
|
|
25
|
+
def initialize(filesystem, options = {})
|
|
26
|
+
@fs = filesystem
|
|
27
|
+
@options = { verbose: true }.merge(options.to_h)
|
|
28
|
+
|
|
29
|
+
# Pass included methods to protected
|
|
30
|
+
utils_methods.each do |m|
|
|
31
|
+
if self.public_methods.include?(m)
|
|
32
|
+
self.singleton_class.class_eval { protected m }
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Prepare package
|
|
38
|
+
#
|
|
39
|
+
# @return [self]
|
|
40
|
+
def prepare
|
|
41
|
+
fs.package_dirs.each_value { |dir| mkdir_p(dir, options) }
|
|
42
|
+
|
|
43
|
+
self.purge_purgeables.prepare_srcdir
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Purge purgeables elements
|
|
47
|
+
#
|
|
48
|
+
# @return [self]
|
|
49
|
+
def purge_purgeables
|
|
50
|
+
fs.purgeable_dirs.each_value { |dir| purge(dir, options) }
|
|
51
|
+
|
|
52
|
+
self
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Prepare ``src`` dir
|
|
56
|
+
#
|
|
57
|
+
# Source files are refreshed (deleted and copied again)
|
|
58
|
+
#
|
|
59
|
+
# @return [self]
|
|
60
|
+
def prepare_srcdir
|
|
61
|
+
src_dir = ::Pathname.new(fs.package_dirs.fetch(:src))
|
|
62
|
+
|
|
63
|
+
purge(src_dir, options)
|
|
64
|
+
skel_dirs(src_dir, fs.source_files, options)
|
|
65
|
+
|
|
66
|
+
fs.source_files.map do |path|
|
|
67
|
+
origin = path.realpath # resolves symlinks
|
|
68
|
+
|
|
69
|
+
cp(origin, src_dir.join(path), options.merge(preserve: true))
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
self
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def verbose?
|
|
76
|
+
options[:verbose] == true
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
protected
|
|
80
|
+
|
|
81
|
+
# @return [Hash]
|
|
82
|
+
attr_reader :options
|
|
83
|
+
end
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Copyright (C) 2017-2018 Dimitri Arrigoni <dimitri@arrigoni.me>
|
|
4
|
+
# License GPLv3+: GNU GPL version 3 or later
|
|
5
|
+
# <http://www.gnu.org/licenses/gpl.html>.
|
|
6
|
+
# This is free software: you are free to change and redistribute it.
|
|
7
|
+
# There is NO WARRANTY, to the extent permitted by law.
|
|
8
|
+
|
|
9
|
+
require 'pathname'
|
|
10
|
+
require 'fileutils'
|
|
11
|
+
require 'rake/file_utils'
|
|
12
|
+
|
|
13
|
+
require_relative '../operator'
|
|
14
|
+
|
|
15
|
+
# Utilities related to files/paths manipulations
|
|
16
|
+
module Kamaze::Project::Tools::Packager::Filesystem::Operator::Utils
|
|
17
|
+
include FileUtils
|
|
18
|
+
|
|
19
|
+
protected
|
|
20
|
+
|
|
21
|
+
# Purge a directory
|
|
22
|
+
#
|
|
23
|
+
# @param [Pathname] dir
|
|
24
|
+
# @return [Pathname]
|
|
25
|
+
def purge(dir, options = {})
|
|
26
|
+
options = { verbose: true }.merge(options)
|
|
27
|
+
dir = ::Pathname.new(dir)
|
|
28
|
+
|
|
29
|
+
if dir.exist?
|
|
30
|
+
ls(dir).each do |entry|
|
|
31
|
+
rm_rf(dir.join(entry), options)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
dir
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Make dirs from given basedir using entries (filepaths)
|
|
39
|
+
#
|
|
40
|
+
# @param [String|Pathname] basedir
|
|
41
|
+
# @param [Array<>] entries
|
|
42
|
+
# @param [Hash] options
|
|
43
|
+
# @return [Pathname]
|
|
44
|
+
def skel_dirs(basedir, entries, options = {})
|
|
45
|
+
basedir = ::Pathname.new(basedir)
|
|
46
|
+
|
|
47
|
+
map_dirs(entries).each { |dir| mkdir_p(basedir.join(dir), options) }
|
|
48
|
+
|
|
49
|
+
basedir
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# List entries
|
|
53
|
+
#
|
|
54
|
+
# @param [String] dir
|
|
55
|
+
# @return [Array<Pathname>]
|
|
56
|
+
def ls(dir)
|
|
57
|
+
::Pathname.new(dir).entries
|
|
58
|
+
.map { |path| ::Pathname.new(path) }
|
|
59
|
+
.delete_if { |path| ['.', '..'].include?(path.basename.to_s) }
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Extract directories from given paths
|
|
63
|
+
#
|
|
64
|
+
# @param [Array<String>] paths
|
|
65
|
+
# @return [Array<Pathname>]
|
|
66
|
+
def map_dirs(paths)
|
|
67
|
+
paths.map { |path| ::Pathname.new(path) }
|
|
68
|
+
.map(&:dirname)
|
|
69
|
+
.delete_if { |path| ['.', '..'].include?(path.basename.to_s) }
|
|
70
|
+
.uniq.sort
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# @return [Array<Symbol>]
|
|
74
|
+
def utils_methods
|
|
75
|
+
FileUtils.public_methods - self.public_methods
|
|
76
|
+
end
|
|
77
|
+
end
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Copyright (C) 2017-2018 Dimitri Arrigoni <dimitri@arrigoni.me>
|
|
4
|
+
# License GPLv3+: GNU GPL version 3 or later
|
|
5
|
+
# <http://www.gnu.org/licenses/gpl.html>.
|
|
6
|
+
# This is free software: you are free to change and redistribute it.
|
|
7
|
+
# There is NO WARRANTY, to the extent permitted by law.
|
|
8
|
+
|
|
9
|
+
require_relative '../tools'
|
|
10
|
+
require 'etc'
|
|
11
|
+
require 'fileutils'
|
|
12
|
+
require 'pathname'
|
|
13
|
+
require 'tmpdir'
|
|
14
|
+
require 'process_lock'
|
|
15
|
+
require 'active_support/inflector'
|
|
16
|
+
|
|
17
|
+
module Kamaze::Project::Tools
|
|
18
|
+
class ProcessLocker < BaseTool
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Process Locker
|
|
23
|
+
#
|
|
24
|
+
# @see https://github.com/ianheggie/process_lock
|
|
25
|
+
class Kamaze::Project::Tools::ProcessLocker < Kamaze::Project::Tools::BaseTool
|
|
26
|
+
# Manage lock on given block
|
|
27
|
+
#
|
|
28
|
+
# @return [Object]
|
|
29
|
+
def lock(lockname)
|
|
30
|
+
mklock(lockname).acquire { yield }
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Manage lock on given block
|
|
34
|
+
#
|
|
35
|
+
# @raise [Errno::EALREADY]
|
|
36
|
+
# @raise [ProcessLock::AlreadyLocked]
|
|
37
|
+
# @return [Object]
|
|
38
|
+
def lock!(lockname)
|
|
39
|
+
mklock(lockname).acquire! { yield }
|
|
40
|
+
rescue ProcessLock::AlreadyLocked
|
|
41
|
+
raise Errno::EALREADY if mklock(lockname).alive?
|
|
42
|
+
raise
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# @return [Pathname]
|
|
46
|
+
def tmpdir
|
|
47
|
+
tmp = Pathname.new(Dir.tmpdir)
|
|
48
|
+
uid = Etc.getpwnam(Etc.getlogin).uid
|
|
49
|
+
dir = [inflector.underscore(self.class.name).tr('/', '-'), uid].join('.')
|
|
50
|
+
|
|
51
|
+
tmp.join(dir)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
class << self
|
|
55
|
+
def method_missing(method, *args, &block)
|
|
56
|
+
if respond_to_missing?(method)
|
|
57
|
+
self.new.public_send(method, *args, &block)
|
|
58
|
+
else
|
|
59
|
+
super
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def respond_to_missing?(method, include_private = false)
|
|
64
|
+
return true if self.new.respond_to?(method, include_private)
|
|
65
|
+
|
|
66
|
+
super(method, include_private)
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
protected
|
|
71
|
+
|
|
72
|
+
# @param [String] lockname
|
|
73
|
+
# @return [ProcessLock]
|
|
74
|
+
def mklock(lockname)
|
|
75
|
+
lockfile = mktemp(lockname)
|
|
76
|
+
|
|
77
|
+
ProcessLock.new(lockfile)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Create a temporary file
|
|
81
|
+
#
|
|
82
|
+
# @param [String] lockname
|
|
83
|
+
# @return [Pathname]
|
|
84
|
+
def mktemp(lockname)
|
|
85
|
+
lockname = Pathname.new(lockname.to_s).basename('.*')
|
|
86
|
+
|
|
87
|
+
mktmpdir.join(lockname)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# Create ``tmpdir``
|
|
91
|
+
#
|
|
92
|
+
# @param [Hash] options
|
|
93
|
+
# @return [Pathname]
|
|
94
|
+
def mktmpdir(options = {})
|
|
95
|
+
tmpdir = self.tmpdir
|
|
96
|
+
options[:mode] ||= 0o700
|
|
97
|
+
|
|
98
|
+
FileUtils.mkdir_p(tmpdir, options)
|
|
99
|
+
|
|
100
|
+
tmpdir
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def inflector
|
|
104
|
+
ActiveSupport::Inflector
|
|
105
|
+
end
|
|
106
|
+
end
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Copyright (C) 2017-2018 Dimitri Arrigoni <dimitri@arrigoni.me>
|
|
4
|
+
# License GPLv3+: GNU GPL version 3 or later
|
|
5
|
+
# <http://www.gnu.org/licenses/gpl.html>.
|
|
6
|
+
# This is free software: you are free to change and redistribute it.
|
|
7
|
+
# There is NO WARRANTY, to the extent permitted by law.
|
|
8
|
+
|
|
9
|
+
require_relative '../tools'
|
|
10
|
+
require_relative '../concern/cli/with_exit_on_failure'
|
|
11
|
+
|
|
12
|
+
# Provide wrapper based on top of ``RSpec::Core::Runner``
|
|
13
|
+
#
|
|
14
|
+
# Sample of use:
|
|
15
|
+
#
|
|
16
|
+
# ```ruby
|
|
17
|
+
# tools.fetch(:rspec).tap do |rspec|
|
|
18
|
+
# rspec.tags = args[:tags].to_s.split(',').map(&:strip)
|
|
19
|
+
# end.run
|
|
20
|
+
# ```
|
|
21
|
+
#
|
|
22
|
+
# @see https://www.relishapp.com/rspec/rspec-core/docs/command-line/rake-task
|
|
23
|
+
# @see https://github.com/rspec/rspec-core/blob/master/lib/rspec/core/runner.rb
|
|
24
|
+
# @see https://relishapp.com/rspec/rspec-core/v/2-4/docs/command-line/tag-option
|
|
25
|
+
class Kamaze::Project::Tools::Rspec < Kamaze::Project::Tools::BaseTool
|
|
26
|
+
include Kamaze::Project::Concern::Cli::WithExitOnFailure
|
|
27
|
+
|
|
28
|
+
# Default arguments used by ``RSpec::Core::Runner``
|
|
29
|
+
#
|
|
30
|
+
# @type [Array|Arguments]
|
|
31
|
+
# @return [Arguments]
|
|
32
|
+
attr_accessor :defaults
|
|
33
|
+
|
|
34
|
+
attr_accessor :stdout
|
|
35
|
+
|
|
36
|
+
attr_accessor :stderr
|
|
37
|
+
|
|
38
|
+
# @return [Array<String>]
|
|
39
|
+
attr_accessor :tags
|
|
40
|
+
|
|
41
|
+
def mutable_attributes
|
|
42
|
+
[:defaults, :stdout, :stderr]
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# @raise [SystemExit]
|
|
46
|
+
# @return [self]
|
|
47
|
+
def run
|
|
48
|
+
with_exit_on_failure do
|
|
49
|
+
options = arguments.concat(options_arguments).map(&:to_s)
|
|
50
|
+
|
|
51
|
+
self.retcode = core.run(options, stderr, stdout).to_i
|
|
52
|
+
reset
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
self
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Arguments used by ``CLI`` (during execution/``run``)
|
|
59
|
+
#
|
|
60
|
+
# @return [Arguments]
|
|
61
|
+
def arguments
|
|
62
|
+
@arguments = @defaults if @arguments.to_a.size.zero?
|
|
63
|
+
|
|
64
|
+
tags.to_a.each do |tag|
|
|
65
|
+
next if @arguments.slice_before('--tag').to_a.include?(['--tag', tag])
|
|
66
|
+
|
|
67
|
+
@arguments += ['--tag', tag]
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
{
|
|
71
|
+
true => @arguments,
|
|
72
|
+
false => @arguments.clone.concat(options_arguments).map(&:to_s).freeze
|
|
73
|
+
}.fetch(caller_locations(1..1).first.path == __FILE__)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
protected
|
|
77
|
+
|
|
78
|
+
# Reset arguments + retcode
|
|
79
|
+
#
|
|
80
|
+
# @return [self]
|
|
81
|
+
def reset
|
|
82
|
+
@arguments = nil
|
|
83
|
+
self.retcode = nil if retcode.to_i.zero?
|
|
84
|
+
|
|
85
|
+
self
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def setup
|
|
89
|
+
reset
|
|
90
|
+
|
|
91
|
+
@tags = []
|
|
92
|
+
@stdout ||= $stdout
|
|
93
|
+
@stderr ||= $stderr
|
|
94
|
+
@defaults ||= []
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# @return [RSpec::Core::Runner]
|
|
98
|
+
def core
|
|
99
|
+
require 'rspec/core'
|
|
100
|
+
|
|
101
|
+
RSpec::Core::Runner
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# @return [Array<String>]
|
|
105
|
+
def options_arguments
|
|
106
|
+
options_files = Pathname.new(Dir.pwd).join('.rspec')
|
|
107
|
+
defaults = []
|
|
108
|
+
|
|
109
|
+
if options_files.file? and options_files.readable?
|
|
110
|
+
defaults += ['-O', '.rspec']
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
defaults
|
|
114
|
+
end
|
|
115
|
+
end
|