grouik 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/src/bin/grouik +36 -0
- data/src/lib/grouik/cli.rb +172 -0
- data/src/lib/grouik/concerns/helpable.rb +19 -0
- data/src/lib/grouik/concerns.rb +16 -0
- data/src/lib/grouik/formatter.rb +67 -0
- data/src/lib/grouik/helpers/cli.rb +102 -0
- data/src/lib/grouik/helpers/loader.rb +72 -0
- data/src/lib/grouik/helpers/process.rb +82 -0
- data/src/lib/grouik/helpers.rb +50 -0
- data/src/lib/grouik/loadable.rb +51 -0
- data/src/lib/grouik/loader.rb +156 -0
- data/src/lib/grouik/output/message.rb +54 -0
- data/src/lib/grouik/output/messager.rb +86 -0
- data/src/lib/grouik/output.rb +13 -0
- data/src/lib/grouik/process.rb +195 -0
- data/src/lib/grouik/types.rb +46 -0
- data/src/lib/grouik/version_info.yml +16 -0
- data/src/lib/grouik.rb +101 -0
- metadata +216 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 83f25d1bc75415d52ac220b352808fc496eedbf1
|
4
|
+
data.tar.gz: 8315a3d896b9556d0b716a27855c8d2fd87c0ab8
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b775cb7d82ec784f43d903ad6a36a98daa7de4db8ff343a83833cda9baff530c72d2a73639e51dd95dafa864f40e0033d603da89b10566ac60e1a95df7a60b2c
|
7
|
+
data.tar.gz: cc9ceee6b5db5d7c98083ccfe7fb954f61f70a73a4a81d1e706402c9a9caa44ec5df9d3b5d4f292c84e5a821d7e16c6840d8f4a55e789ed5acc9dcb16d6b03fe
|
data/src/bin/grouik
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
# Copyright (C) 2017 Dimitri Arrigoni <dimitri@arrigoni.me>
|
5
|
+
# License GPLv3+: GNU GPL version 3 or later
|
6
|
+
# <http://www.gnu.org/licenses/gpl.html>.
|
7
|
+
# This is free software: you are free to change and redistribute it.
|
8
|
+
# There is NO WARRANTY, to the extent permitted by law.
|
9
|
+
|
10
|
+
require 'pathname'
|
11
|
+
$0 = Pathname.new(__FILE__).basename.to_s
|
12
|
+
|
13
|
+
# run bundled in a development context -------------------------------
|
14
|
+
if Pathname.new(__dir__).join('..', '..', '%s.gemspec' % $PROGRAM_NAME).file?
|
15
|
+
require 'rubygems'
|
16
|
+
require 'bundler'
|
17
|
+
Bundler.setup(:default)
|
18
|
+
end
|
19
|
+
|
20
|
+
# require lib requirements -------------------------------------------
|
21
|
+
[nil, :cli].each do |r|
|
22
|
+
req = r ? "#{$PROGRAM_NAME}/#{r}" : $PROGRAM_NAME
|
23
|
+
begin
|
24
|
+
require Pathname.new(__dir__).join('..', 'lib', '%s' % req)
|
25
|
+
rescue LoadError
|
26
|
+
begin
|
27
|
+
require req
|
28
|
+
rescue LoadError
|
29
|
+
require 'rubygems'
|
30
|
+
require req
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# process command line options and run -------------------------------
|
36
|
+
exit Grouik::Cli.run
|
@@ -0,0 +1,172 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright (C) 2017 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 'optparse'
|
10
|
+
require 'ostruct'
|
11
|
+
require 'pathname'
|
12
|
+
require 'yaml'
|
13
|
+
|
14
|
+
require 'grouik' unless defined?(Grouik)
|
15
|
+
require 'grouik/concerns'
|
16
|
+
|
17
|
+
# Grouik command line interface
|
18
|
+
#
|
19
|
+
# Provides a ready to use program, based on ``Grouik`` library
|
20
|
+
class Grouik::Cli
|
21
|
+
attr_reader :argv
|
22
|
+
attr_reader :options
|
23
|
+
attr_reader :arguments
|
24
|
+
|
25
|
+
include Grouik::Concerns::Helpable
|
26
|
+
|
27
|
+
class << self
|
28
|
+
# Program name
|
29
|
+
#
|
30
|
+
# @return [String]
|
31
|
+
def program_name
|
32
|
+
Pathname.new($PROGRAM_NAME).basename('.rb').to_s
|
33
|
+
end
|
34
|
+
|
35
|
+
# Run
|
36
|
+
#
|
37
|
+
# @param [Array] argv
|
38
|
+
def run(argv = ARGV)
|
39
|
+
self.new(argv).run
|
40
|
+
end
|
41
|
+
|
42
|
+
# default options
|
43
|
+
def defaults
|
44
|
+
{
|
45
|
+
stats: true,
|
46
|
+
paths: ['.'],
|
47
|
+
basedir: '.',
|
48
|
+
output: STDOUT,
|
49
|
+
ignores: [],
|
50
|
+
require: nil,
|
51
|
+
template: nil,
|
52
|
+
}
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# @return [String]
|
57
|
+
def program_name
|
58
|
+
self.class.program_name
|
59
|
+
end
|
60
|
+
|
61
|
+
# Constructor
|
62
|
+
#
|
63
|
+
# @param [Array] argv
|
64
|
+
def initialize(argv = ARGV)
|
65
|
+
@argv = argv.clone
|
66
|
+
@options = self.class.defaults
|
67
|
+
# @options = config unless config.empty?
|
68
|
+
@arguments = []
|
69
|
+
end
|
70
|
+
|
71
|
+
# Provide an ``OptionParser``
|
72
|
+
#
|
73
|
+
# @return [OptionParser]
|
74
|
+
def parser
|
75
|
+
parser = helpers.get(:cli).make_parser(@options)
|
76
|
+
parser.banner = 'Usage: %s [OPTION]... [FILE]...' % program_name
|
77
|
+
|
78
|
+
parser
|
79
|
+
end
|
80
|
+
|
81
|
+
# Parse command line options
|
82
|
+
#
|
83
|
+
# Abort process (error code SHOULD BE ``22``) on invalid option
|
84
|
+
#
|
85
|
+
# @return [self]
|
86
|
+
def parse!
|
87
|
+
argv = self.argv.clone
|
88
|
+
begin
|
89
|
+
parser.parse!(argv)
|
90
|
+
rescue OptionParser::InvalidOption
|
91
|
+
STDERR.puts(parser)
|
92
|
+
exit(Errno::EINVAL::Errno)
|
93
|
+
end
|
94
|
+
@arguments = argv
|
95
|
+
# @options = prepare_options(@options)
|
96
|
+
self
|
97
|
+
end
|
98
|
+
|
99
|
+
# Get processable items (based on command arguments), used during execution
|
100
|
+
#
|
101
|
+
# @return [Array<OpenStruct>]
|
102
|
+
def processables
|
103
|
+
processables = []
|
104
|
+
if arguments.empty?
|
105
|
+
processables[0] = OpenStruct.new(
|
106
|
+
path: Pathname.new(Dir.pwd),
|
107
|
+
options: options,
|
108
|
+
'file?' => false
|
109
|
+
)
|
110
|
+
else
|
111
|
+
arguments.each do |filepath|
|
112
|
+
config = helpers.get(:cli).read_config(filepath)
|
113
|
+
|
114
|
+
processables << OpenStruct.new(
|
115
|
+
path: Pathname.new(filepath).dirname,
|
116
|
+
file: Pathname.new(filepath),
|
117
|
+
options: config,
|
118
|
+
'file?' => true
|
119
|
+
)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
processables.map(&:freeze)
|
124
|
+
end
|
125
|
+
|
126
|
+
# Execute CLI and return exit code
|
127
|
+
#
|
128
|
+
# @return [Fixnum]
|
129
|
+
def run
|
130
|
+
parse!
|
131
|
+
|
132
|
+
if options[:version]
|
133
|
+
STDOUT.puts helpers.get(:cli).version_chapter
|
134
|
+
return 0
|
135
|
+
end
|
136
|
+
|
137
|
+
processables.each do |processable|
|
138
|
+
Dir.chdir(processable.path) do
|
139
|
+
process(processable.options)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
0
|
143
|
+
end
|
144
|
+
|
145
|
+
protected
|
146
|
+
|
147
|
+
# Initiate and run a new ``Process`` from options
|
148
|
+
#
|
149
|
+
# @param [Hash] options
|
150
|
+
# @return [Grouik::Process]
|
151
|
+
def process(options)
|
152
|
+
options = helpers.get(:cli).prepare_options(options)
|
153
|
+
|
154
|
+
process = Grouik.process do |process|
|
155
|
+
process.basedir = options.fetch(:basedir)
|
156
|
+
process.paths = options.fetch(:paths)
|
157
|
+
process.ignores = options[:ignores]
|
158
|
+
process.output = options.fetch(:output)
|
159
|
+
process.template = options[:template]
|
160
|
+
process.bootstrap = options[:require]
|
161
|
+
end
|
162
|
+
|
163
|
+
process.on_success do |process|
|
164
|
+
process.display_status if options[:stats]
|
165
|
+
end.on_failure do |process|
|
166
|
+
process.display_status if options[:stats]
|
167
|
+
exit Errno::ECANCELED::Errno
|
168
|
+
end
|
169
|
+
|
170
|
+
process
|
171
|
+
end
|
172
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright (C) 2017 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
|
+
# Provide ``helpers`` method
|
10
|
+
module Grouik::Concerns::Helpable
|
11
|
+
extend ActiveSupport::Concern
|
12
|
+
|
13
|
+
# Loads helper
|
14
|
+
#
|
15
|
+
# @return [Grouik::Helpers]
|
16
|
+
def helpers
|
17
|
+
Grouik.get(:helpers)
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright (C) 2017 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
|
+
# Concerns in use
|
10
|
+
module Grouik::Concerns
|
11
|
+
require 'active_support/concern'
|
12
|
+
|
13
|
+
[:helpable].each do |concern|
|
14
|
+
require 'grouik/concerns/%s' % concern
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright (C) 2017 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 'tenjin'
|
11
|
+
|
12
|
+
# Formatter used to render loadables
|
13
|
+
class Grouik::Formatter
|
14
|
+
attr_reader :options
|
15
|
+
attr_reader :loadables
|
16
|
+
attr_reader :template
|
17
|
+
|
18
|
+
def initialize(loadables, options = {})
|
19
|
+
@loadables = loadables
|
20
|
+
@options = options
|
21
|
+
@formatted = nil
|
22
|
+
@engine = Tenjin::Engine.new(cache: false)
|
23
|
+
@template = options[:template]
|
24
|
+
end
|
25
|
+
|
26
|
+
# @return [Pathname|nil]
|
27
|
+
def template
|
28
|
+
@template ? Pathname.new(@template).realpath : nil
|
29
|
+
end
|
30
|
+
|
31
|
+
def to_s
|
32
|
+
formatted
|
33
|
+
end
|
34
|
+
|
35
|
+
def format
|
36
|
+
@formatted = @formatted.nil? ? output : @formatted
|
37
|
+
|
38
|
+
return self
|
39
|
+
end
|
40
|
+
|
41
|
+
def formatted
|
42
|
+
format
|
43
|
+
@formatted.clone
|
44
|
+
end
|
45
|
+
|
46
|
+
class << self
|
47
|
+
def format(loadables, options = {})
|
48
|
+
self.new(loadables, options).format
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
protected
|
53
|
+
|
54
|
+
def output
|
55
|
+
items = loadables.to_a.map { |i| "require '#{i}'" }
|
56
|
+
|
57
|
+
return items.join("\n") + "\n" unless template
|
58
|
+
|
59
|
+
context = {
|
60
|
+
requirement: lambda do |indent = nil|
|
61
|
+
items.map { |i| '%s%s' % [indent, i] }.join("\n")
|
62
|
+
end
|
63
|
+
}
|
64
|
+
|
65
|
+
@engine.render(template.to_s, context)
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright (C) 2017 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 'optparse'
|
10
|
+
|
11
|
+
# Cli helper, see ``Grouik::Cli``
|
12
|
+
class Grouik::Helpers::Cli
|
13
|
+
# Provide an ``OptionParser``
|
14
|
+
#
|
15
|
+
# @param [Hash] options
|
16
|
+
# @return [OptionParser]
|
17
|
+
def make_parser(options = {})
|
18
|
+
parser = OptionParser.new
|
19
|
+
|
20
|
+
{
|
21
|
+
basedir: ['--basedir=BASEDIR', 'Basedir [%s]' % options[:basedir]],
|
22
|
+
output: ['-o=OUTPUT', '--output=OUTPUT', 'Output [/dev/stdout]'],
|
23
|
+
require: ['-r=REQUIRE', '--require=REQUIRE',
|
24
|
+
'Required file on startup'],
|
25
|
+
ignores: ['--ignores x,y,z', Array, 'Ignores'],
|
26
|
+
paths: ['--paths x,y,z', Array, 'Paths'],
|
27
|
+
stats: ['--[no-]stats', 'Display some stats'],
|
28
|
+
version: ['--version', 'Display the version and exit']
|
29
|
+
}.each do |k, v|
|
30
|
+
parser.on(*v) { |o| options[k] = o }
|
31
|
+
end
|
32
|
+
|
33
|
+
parser
|
34
|
+
end
|
35
|
+
|
36
|
+
# Prepare options
|
37
|
+
#
|
38
|
+
# Process values in order to easify their use
|
39
|
+
#
|
40
|
+
# @param [Hash] options
|
41
|
+
# @return [Hash]
|
42
|
+
def prepare_options(options)
|
43
|
+
[:require, :output].each do |k|
|
44
|
+
next unless options[k]
|
45
|
+
begin
|
46
|
+
options[k] = Pathname.new(options[k])
|
47
|
+
rescue TypeError
|
48
|
+
next
|
49
|
+
end
|
50
|
+
unless options[k].absolute?
|
51
|
+
options[k] = Pathname.new(Dir.pwd).join(options[k])
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
[:ignores, :paths].each do |k|
|
56
|
+
next unless options[k]
|
57
|
+
options[k] = [options[k]] if options[k].is_a? String
|
58
|
+
|
59
|
+
options[k] = options[k].to_a.map { |s| /#{s}/ } if :ignores == k
|
60
|
+
end
|
61
|
+
|
62
|
+
options
|
63
|
+
end
|
64
|
+
|
65
|
+
# Get the license
|
66
|
+
#
|
67
|
+
# @return [String]
|
68
|
+
def license
|
69
|
+
Grouik.version_info[:license].to_s.gsub(/\n{3}/mi, "\n\n")
|
70
|
+
end
|
71
|
+
|
72
|
+
# Get a displayable version
|
73
|
+
#
|
74
|
+
# Some inspiration taken from ``wget --version``
|
75
|
+
#
|
76
|
+
# @return [String]
|
77
|
+
def version_chapter
|
78
|
+
['%s %s on %s' % [Grouik.name, Grouik::VERSION, host_os],
|
79
|
+
nil,
|
80
|
+
license].join("\n")
|
81
|
+
end
|
82
|
+
|
83
|
+
# @return [String]
|
84
|
+
def host_os
|
85
|
+
RbConfig::CONFIG['host_os']
|
86
|
+
end
|
87
|
+
|
88
|
+
# Read a config file
|
89
|
+
#
|
90
|
+
# @param [String] path
|
91
|
+
# @return [Hash]
|
92
|
+
def read_config(path)
|
93
|
+
file = Pathname.new(path.to_s)
|
94
|
+
config = YAML.safe_load(file.read)
|
95
|
+
|
96
|
+
h = config.each_with_object({}) do |(k, v), n|
|
97
|
+
n[k.intern] = v
|
98
|
+
end
|
99
|
+
|
100
|
+
h
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright (C) 2017 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 'grouik/types'
|
10
|
+
|
11
|
+
# Loader helper, see ``Grouik::Loader``
|
12
|
+
class Grouik::Helpers::Loader
|
13
|
+
# Make loadables
|
14
|
+
#
|
15
|
+
# @@return [Grouik::Types::Loadables]
|
16
|
+
def make_loadables
|
17
|
+
Grouik::Types::Loadables.new
|
18
|
+
end
|
19
|
+
|
20
|
+
# Make ignores
|
21
|
+
#
|
22
|
+
# @param [Array<String|Regexp>] input
|
23
|
+
# @return [Array<Regexp>]
|
24
|
+
def make_ignores(input)
|
25
|
+
input.to_a.map { |s| s.is_a?(Regexp) ? s : /^#{s}$/ }
|
26
|
+
end
|
27
|
+
|
28
|
+
# Register paths
|
29
|
+
#
|
30
|
+
# @param [String] basedir
|
31
|
+
# @param [Array<String|Pathname>] paths
|
32
|
+
def register_paths(basedir, paths)
|
33
|
+
basedir = Pathname.new(basedir)
|
34
|
+
|
35
|
+
paths.reverse.each do |path|
|
36
|
+
$LOAD_PATH.unshift basedir.realpath.join(path).to_s
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# @return [Pathname]
|
41
|
+
def pwd
|
42
|
+
Pathname.new(Dir.pwd)
|
43
|
+
end
|
44
|
+
|
45
|
+
# @param [String] path
|
46
|
+
# @return [Array<Pathname>]
|
47
|
+
def files_in_path(path)
|
48
|
+
loaddir = path.to_s
|
49
|
+
basereg = %r{^#{Regexp.quote(loaddir)}\/}
|
50
|
+
|
51
|
+
Dir.glob(path.join('**/*.rb'))
|
52
|
+
.sort
|
53
|
+
.map { |file| file.gsub(basereg, '') }
|
54
|
+
.map { |file| Pathname.new(file) }
|
55
|
+
end
|
56
|
+
|
57
|
+
# Collect loadables by paths
|
58
|
+
#
|
59
|
+
# @param [Array<String>] paths
|
60
|
+
# @return [Grouik::Types::Loadables]
|
61
|
+
def collect_loadables(paths)
|
62
|
+
loadables = self.make_loadables
|
63
|
+
|
64
|
+
paths.each do |path|
|
65
|
+
self.files_in_path(path).each do |file|
|
66
|
+
loadables = loadables.add_file(file, path.to_s)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
loadables
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright (C) 2017 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
|
+
# Helper providing outputs (mostly useful in a CLI/Rake context)
|
10
|
+
#
|
11
|
+
# Main methods are ``display_errors`` and ``display_status``
|
12
|
+
class Grouik::Helpers::Process
|
13
|
+
# Display loading errors
|
14
|
+
#
|
15
|
+
# @param [Grouik::Process] process
|
16
|
+
# @return [self]
|
17
|
+
def display_errors(process)
|
18
|
+
process.errors.each do |_k, struct|
|
19
|
+
Grouik.message do |m|
|
20
|
+
m.stream = STDERR
|
21
|
+
m.type = 'error'
|
22
|
+
m.content = ('%s:%s: %s' % [
|
23
|
+
struct.source,
|
24
|
+
struct.line,
|
25
|
+
struct.message,
|
26
|
+
])
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Display (on ``STDERR``) loader related statistics
|
32
|
+
#
|
33
|
+
# @param [Grouik::Process] process
|
34
|
+
# @return [self]
|
35
|
+
def display_status(process)
|
36
|
+
message = '%s: %s files; %s iterations; %s errors (%.4f) [%s]'
|
37
|
+
loader = process.loader
|
38
|
+
|
39
|
+
Grouik.message do |m|
|
40
|
+
m.stream = STDERR
|
41
|
+
m.type = 'status_%s' % status(process)
|
42
|
+
m.content = (message %
|
43
|
+
[
|
44
|
+
status(process).to_s.capitalize,
|
45
|
+
loader.loadables.size,
|
46
|
+
loader.attempts,
|
47
|
+
loader.errors.size,
|
48
|
+
loader.stats ? loader.stats.real : 0,
|
49
|
+
format_filepath(process.output)
|
50
|
+
])
|
51
|
+
end
|
52
|
+
self
|
53
|
+
end
|
54
|
+
|
55
|
+
# Denote status from process
|
56
|
+
#
|
57
|
+
# @return [Symbol]
|
58
|
+
def status(process)
|
59
|
+
statuses = { true => :success, false => :failure }
|
60
|
+
|
61
|
+
statuses.fetch(process.success?)
|
62
|
+
end
|
63
|
+
|
64
|
+
protected
|
65
|
+
|
66
|
+
# Format a filepath with a ``require`` format
|
67
|
+
#
|
68
|
+
# @param [Pathname|String|Object] filepath
|
69
|
+
def format_filepath(filepath)
|
70
|
+
filepath = filepath.to_s
|
71
|
+
|
72
|
+
$LOAD_PATH.each do |path|
|
73
|
+
regexp = %r{^#{Regexp.quote(path.to_s)}\/}
|
74
|
+
if regexp.match(filepath)
|
75
|
+
filepath.gsub!(regexp, '').gsub!(/\.rb$/, '')
|
76
|
+
break
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
filepath
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright (C) 2017 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 'active_support/inflector'
|
11
|
+
|
12
|
+
# Helpers (loader)
|
13
|
+
#
|
14
|
+
# Provide easy access to helpers
|
15
|
+
module Grouik::Helpers
|
16
|
+
class << self
|
17
|
+
# Retrieve helper by name
|
18
|
+
#
|
19
|
+
# @param [String|Symbol] target
|
20
|
+
# @return [Object]
|
21
|
+
def get(target)
|
22
|
+
class_name = self.classify(target)
|
23
|
+
|
24
|
+
require load_dir.join(target.to_s) unless const_defined?(class_name)
|
25
|
+
|
26
|
+
inflector.constantize(class_name).new
|
27
|
+
end
|
28
|
+
|
29
|
+
# Directory where helpers stand
|
30
|
+
#
|
31
|
+
# @return [Pathname]
|
32
|
+
def load_dir
|
33
|
+
Pathname.new(__FILE__.gsub(/\.rb$/, ''))
|
34
|
+
end
|
35
|
+
|
36
|
+
protected
|
37
|
+
|
38
|
+
# @return ActiveSupport::Inflector
|
39
|
+
def inflector
|
40
|
+
ActiveSupport::Inflector
|
41
|
+
end
|
42
|
+
|
43
|
+
# Transform string
|
44
|
+
#
|
45
|
+
# return [String]
|
46
|
+
def classify(target)
|
47
|
+
'%s::%s' % [name, inflector.classify(target.to_s.gsub('/', '::'))]
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
|
3
|
+
# Describe a loable item (Ruby file)
|
4
|
+
class Grouik::Loadable
|
5
|
+
attr_reader :base
|
6
|
+
attr_reader :path
|
7
|
+
attr_reader :basedir
|
8
|
+
|
9
|
+
# @param [String] base
|
10
|
+
# @param [String] path
|
11
|
+
# @param [String] basedir
|
12
|
+
def initialize(base, path, basedir = '.')
|
13
|
+
@base = Pathname.new(base)
|
14
|
+
@path = path
|
15
|
+
@basedir = Pathname.new(basedir).realpath
|
16
|
+
end
|
17
|
+
|
18
|
+
# @param [Boolean] format format as loadable from ``$LOAD_PATH``
|
19
|
+
# @return [String]
|
20
|
+
def path(format = false)
|
21
|
+
path = @path.to_s
|
22
|
+
|
23
|
+
{
|
24
|
+
true => path,
|
25
|
+
false => basedir.join(base, path).to_s
|
26
|
+
}[(format and loadable?)].gsub(/\.rb$/, '')
|
27
|
+
end
|
28
|
+
|
29
|
+
# @return [String]
|
30
|
+
def to_s
|
31
|
+
path(true)
|
32
|
+
end
|
33
|
+
|
34
|
+
# @return [Boolean]
|
35
|
+
def load(from = nil)
|
36
|
+
path = from ? Pathname.new(from).join(self.path) : self.path
|
37
|
+
|
38
|
+
return require path
|
39
|
+
end
|
40
|
+
|
41
|
+
def loadable?
|
42
|
+
self.class.paths.include?(basedir.join(base).to_s)
|
43
|
+
end
|
44
|
+
|
45
|
+
class << self
|
46
|
+
# @return [Array<String>]
|
47
|
+
def paths
|
48
|
+
$LOAD_PATH.map(&:to_s)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|