spud 0.1.18 → 0.1.19
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 +4 -4
- data/lib/spud.rb +2 -182
- data/lib/spud/build_tools/build_tools.rb +13 -0
- data/lib/spud/build_tools/make/task.rb +27 -0
- data/lib/spud/build_tools/package.json/task.rb +47 -0
- data/lib/spud/build_tools/spud/block_param_info.rb +77 -0
- data/lib/spud/build_tools/spud/dsl/file.rb +23 -0
- data/lib/spud/build_tools/spud/dsl/task.rb +63 -0
- data/lib/spud/build_tools/spud/shell/command.rb +52 -0
- data/lib/spud/build_tools/spud/shell/result.rb +26 -0
- data/lib/spud/build_tools/spud/task.rb +125 -0
- data/lib/spud/build_tools/task.rb +33 -0
- data/lib/spud/cli/parser.rb +101 -0
- data/lib/spud/cli/results.rb +25 -0
- data/lib/{error.rb → spud/error.rb} +1 -0
- data/lib/spud/help.rb +23 -0
- data/lib/spud/lister.rb +86 -0
- data/lib/spud/options.rb +14 -0
- data/lib/spud/runtime.rb +104 -0
- data/lib/spud/task_arg.rb +51 -0
- data/lib/spud/task_args.rb +49 -0
- data/lib/spud/version.rb +3 -0
- metadata +48 -28
- data/lib/args.rb +0 -73
- data/lib/build_tools/build_rule.rb +0 -21
- data/lib/build_tools/build_tool.rb +0 -19
- data/lib/build_tools/build_tools.rb +0 -13
- data/lib/build_tools/make/make.rb +0 -33
- data/lib/build_tools/package.json/package.json.rb +0 -33
- data/lib/build_tools/spud/file_context.rb +0 -33
- data/lib/build_tools/spud/rule.rb +0 -124
- data/lib/build_tools/spud/rule_context.rb +0 -62
- data/lib/build_tools/spud/shell_error.rb +0 -7
- data/lib/build_tools/spud/spud.rb +0 -27
- data/lib/shell.rb +0 -38
- data/lib/version.rb +0 -3
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'stringio'
|
2
|
+
require 'open3'
|
3
|
+
require 'spud/build_tools/spud/shell/result'
|
4
|
+
|
5
|
+
module Spud
|
6
|
+
module BuildTools
|
7
|
+
module Spud
|
8
|
+
module Shell
|
9
|
+
class Command
|
10
|
+
attr_reader :result
|
11
|
+
|
12
|
+
# @param command [String]
|
13
|
+
# @param silent [Boolean]
|
14
|
+
# @param handle [IO]
|
15
|
+
def self.call(command, silent: false, handle: STDOUT)
|
16
|
+
cmd = new(command, silent: silent, handle: handle)
|
17
|
+
cmd.issue!
|
18
|
+
cmd.result
|
19
|
+
end
|
20
|
+
|
21
|
+
# @param command [String]
|
22
|
+
# @param silent [Boolean]
|
23
|
+
# @param handle [IO]
|
24
|
+
def initialize(command, silent: false, handle: STDOUT)
|
25
|
+
@command = command
|
26
|
+
@silent = silent
|
27
|
+
@handle = handle
|
28
|
+
|
29
|
+
@result = nil
|
30
|
+
end
|
31
|
+
|
32
|
+
# @return [void]
|
33
|
+
def issue!
|
34
|
+
capturer = StringIO.new
|
35
|
+
|
36
|
+
Open3.popen2e(@command) do |_stdin, stdout, thread|
|
37
|
+
loop do
|
38
|
+
line = stdout.gets
|
39
|
+
break unless line
|
40
|
+
|
41
|
+
@handle.write line unless @silent
|
42
|
+
capturer.puts line
|
43
|
+
end
|
44
|
+
|
45
|
+
@result = Result.new(capturer.string, thread.value)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Spud
|
2
|
+
module BuildTools
|
3
|
+
module Spud
|
4
|
+
module Shell
|
5
|
+
class Result < String
|
6
|
+
attr_reader :status
|
7
|
+
|
8
|
+
# @param output [String]
|
9
|
+
# @param status [Process::Status]
|
10
|
+
def initialize(output, status)
|
11
|
+
super(output)
|
12
|
+
@status = status
|
13
|
+
end
|
14
|
+
|
15
|
+
def method_missing(symbol, *args)
|
16
|
+
status.respond_to?(symbol) ? status.send(symbol, *args) : super
|
17
|
+
end
|
18
|
+
|
19
|
+
def respond_to_missing?(symbol, *)
|
20
|
+
status.respond_to?(symbol) || super
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
require 'spud/error'
|
2
|
+
require 'spud/task_args'
|
3
|
+
require 'spud/build_tools/task'
|
4
|
+
require 'spud/build_tools/spud/task'
|
5
|
+
require 'spud/build_tools/spud/dsl/file'
|
6
|
+
require 'spud/build_tools/spud/dsl/task'
|
7
|
+
|
8
|
+
module Spud
|
9
|
+
module BuildTools
|
10
|
+
module Spud
|
11
|
+
class Task < BuildTools::Task
|
12
|
+
# @return [void]
|
13
|
+
def self.mount!
|
14
|
+
Dir['**/Spudfile', '**/*.spud'].each do |filename|
|
15
|
+
@filename = filename
|
16
|
+
file_dsl.instance_eval(File.read(filename), filename)
|
17
|
+
end
|
18
|
+
|
19
|
+
@filename = nil
|
20
|
+
end
|
21
|
+
|
22
|
+
# @return [Spud::DSL::File]
|
23
|
+
def self.file_dsl
|
24
|
+
@file_dsl ||= DSL::File.new
|
25
|
+
end
|
26
|
+
|
27
|
+
# @param task [String]
|
28
|
+
# @param block [Proc]
|
29
|
+
# @return [void]
|
30
|
+
def self.add_task(task, &block)
|
31
|
+
raise "task '#{task}' somehow created without filename" unless @filename
|
32
|
+
|
33
|
+
qualified_name = [qualified_prefix(@filename), task.to_s].join('.').gsub(/^\./, '')
|
34
|
+
new(name: qualified_name, filename: @filename, &block)
|
35
|
+
end
|
36
|
+
|
37
|
+
# @param filename [String]
|
38
|
+
# @param task [String]
|
39
|
+
# @param positional [Array]
|
40
|
+
# @param named [Hash]
|
41
|
+
def self.invoke(filename, task, positional, named)
|
42
|
+
task = task.to_s
|
43
|
+
task_obj = task_for(filename, task)
|
44
|
+
if task_obj
|
45
|
+
Runtime.invoke(task_obj.name, positional, named)
|
46
|
+
else
|
47
|
+
Runtime.invoke(task, positional, named)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# @param filename [String]
|
52
|
+
# @param task [String]
|
53
|
+
def self.task_for(filename, task)
|
54
|
+
task = task.to_s
|
55
|
+
if task.include?('.')
|
56
|
+
Runtime.tasks[task]
|
57
|
+
else
|
58
|
+
Runtime.tasks[[qualified_prefix(filename), task.to_s].join('.').gsub(/^\./, '')]
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# @param filename [String]
|
63
|
+
# @return [String]
|
64
|
+
def self.qualified_prefix(filename)
|
65
|
+
dirname = File.dirname(filename)
|
66
|
+
dirname = '' if dirname == '.'
|
67
|
+
|
68
|
+
basename = File.basename(filename, '.spud')
|
69
|
+
basename_array = basename == 'Spudfile' ? [] : [basename]
|
70
|
+
|
71
|
+
(dirname.split('/') + basename_array).join('.')
|
72
|
+
end
|
73
|
+
|
74
|
+
def initialize(name:, filename:, &block)
|
75
|
+
super
|
76
|
+
@block = block
|
77
|
+
end
|
78
|
+
|
79
|
+
# @param positional [Array]
|
80
|
+
# @param named [Hash]
|
81
|
+
# @return [Object]
|
82
|
+
def invoke(positional, named)
|
83
|
+
check_required!(positional)
|
84
|
+
|
85
|
+
return task_dsl.instance_exec(*positional, &@block) unless args.any_named?
|
86
|
+
|
87
|
+
task_dsl.instance_exec(*positional, **symbolize_keys(named), &@block)
|
88
|
+
rescue ArgumentError => error
|
89
|
+
raise Error, "invocation of '#{name}' with #{error.message}"
|
90
|
+
end
|
91
|
+
|
92
|
+
# @return [Spud::TaskArgs]
|
93
|
+
def args
|
94
|
+
@args ||= ::Spud::TaskArgs.from_block(filename, &@block)
|
95
|
+
end
|
96
|
+
|
97
|
+
private
|
98
|
+
|
99
|
+
# @param positional [Array<String>]
|
100
|
+
# @return [void]
|
101
|
+
def check_required!(positional)
|
102
|
+
required_positional = args.required_positional
|
103
|
+
missing_positional = required_positional.length - positional.length
|
104
|
+
if missing_positional > 0
|
105
|
+
arguments = required_positional.length - missing_positional > 1 ? 'arguments' : 'argument'
|
106
|
+
raise Error, "invocation of '#{name}' missing required #{arguments} #{required_positional.join(', ')}"
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
# @return [Spud::DSL::Task]
|
111
|
+
def task_dsl
|
112
|
+
@task_dsl ||= DSL::Task.new(filename)
|
113
|
+
end
|
114
|
+
|
115
|
+
# @param hash [Hash]
|
116
|
+
# @return [Hash]
|
117
|
+
def symbolize_keys(hash)
|
118
|
+
hash.each_with_object({}) do |(key, value), new_hash|
|
119
|
+
new_hash[key.is_a?(String) ? key.to_sym : key] = value
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Spud
|
2
|
+
module BuildTools
|
3
|
+
class Task
|
4
|
+
# @return [String]
|
5
|
+
attr_reader :name
|
6
|
+
# @return [String]
|
7
|
+
attr_reader :filename
|
8
|
+
# @return [Spud::TaskArgs]
|
9
|
+
attr_reader :args
|
10
|
+
|
11
|
+
# @return [void]
|
12
|
+
def self.mount!
|
13
|
+
raise NotImplementedError
|
14
|
+
end
|
15
|
+
|
16
|
+
# @param name [String]
|
17
|
+
# @param filename [String]
|
18
|
+
def initialize(name:, filename:)
|
19
|
+
@name = name
|
20
|
+
@filename = filename
|
21
|
+
|
22
|
+
Runtime.tasks[name.to_s] = self
|
23
|
+
end
|
24
|
+
|
25
|
+
# @param positional [Array]
|
26
|
+
# @param named [Hash]
|
27
|
+
# @return [Object]
|
28
|
+
def invoke(positional = [], named = {})
|
29
|
+
raise NotImplementedError
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
require 'spud/cli/results'
|
2
|
+
|
3
|
+
module Spud
|
4
|
+
module CLI
|
5
|
+
class Parser
|
6
|
+
# @return [Spud::CLI::Results]
|
7
|
+
attr_reader :results
|
8
|
+
|
9
|
+
# @return [void]
|
10
|
+
def self.parse!
|
11
|
+
parse(ARGV)
|
12
|
+
end
|
13
|
+
|
14
|
+
# @param args [Array<String>]
|
15
|
+
# @return [Spud::CLI::Results]
|
16
|
+
def self.parse(args)
|
17
|
+
new(args).parse!
|
18
|
+
end
|
19
|
+
|
20
|
+
# @param args [Array<String>]
|
21
|
+
def initialize(args)
|
22
|
+
@args = args.dup
|
23
|
+
@results = Results.new
|
24
|
+
end
|
25
|
+
|
26
|
+
# @return [void]
|
27
|
+
def parse!
|
28
|
+
parse_arg! until done?
|
29
|
+
results
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
# @return [void]
|
35
|
+
def parse_arg!
|
36
|
+
if before_task_name?
|
37
|
+
flag? ? handle_option! : set_task_name!
|
38
|
+
else
|
39
|
+
if flag?
|
40
|
+
results.named[lstrip_hyphens(take!)] = take!
|
41
|
+
else
|
42
|
+
results.positional << take!
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# @return [void]
|
48
|
+
def handle_option!
|
49
|
+
flag = take!
|
50
|
+
case flag
|
51
|
+
when '-h', '--help' then options.help = true
|
52
|
+
when '-f', '--files' then options.files = true
|
53
|
+
when '-w', '--watch' then options.watches << take!
|
54
|
+
when '--debug' then options.debug = true
|
55
|
+
else raise Error, "invalid option: '#{flag}'"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# @return [Spud::Options]
|
60
|
+
def options
|
61
|
+
results.options
|
62
|
+
end
|
63
|
+
|
64
|
+
# @param flag [String]
|
65
|
+
# @return [String]
|
66
|
+
def lstrip_hyphens(flag)
|
67
|
+
flag.gsub(/^-+/, '')
|
68
|
+
end
|
69
|
+
|
70
|
+
# @return [Boolean]
|
71
|
+
def before_task_name?
|
72
|
+
!results.task
|
73
|
+
end
|
74
|
+
|
75
|
+
# @return [void]
|
76
|
+
def set_task_name!
|
77
|
+
results.task = take!
|
78
|
+
end
|
79
|
+
|
80
|
+
# @return [String]
|
81
|
+
def take!
|
82
|
+
@args.shift
|
83
|
+
end
|
84
|
+
|
85
|
+
# @return [String]
|
86
|
+
def arg
|
87
|
+
@args.first
|
88
|
+
end
|
89
|
+
|
90
|
+
# @return [Boolean]
|
91
|
+
def flag?
|
92
|
+
arg.start_with?('-')
|
93
|
+
end
|
94
|
+
|
95
|
+
# @return [Boolean]
|
96
|
+
def done?
|
97
|
+
@args.empty?
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'spud/options'
|
2
|
+
|
3
|
+
module Spud
|
4
|
+
module CLI
|
5
|
+
class Results
|
6
|
+
# @return [String]
|
7
|
+
attr_accessor :task
|
8
|
+
|
9
|
+
# @return [Spud::Options]
|
10
|
+
def options
|
11
|
+
@options ||= Options.new
|
12
|
+
end
|
13
|
+
|
14
|
+
# @return [Array<String>]
|
15
|
+
def positional
|
16
|
+
@positional ||= []
|
17
|
+
end
|
18
|
+
|
19
|
+
# @return [Hash{String->String}]
|
20
|
+
def named
|
21
|
+
@named ||= {}
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/spud/help.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'stringio'
|
2
|
+
require 'spud/version'
|
3
|
+
|
4
|
+
module Spud
|
5
|
+
module Help
|
6
|
+
# @return [void]
|
7
|
+
def self.print!
|
8
|
+
help = StringIO.new
|
9
|
+
|
10
|
+
help.puts "spud #{VERSION}"
|
11
|
+
help.puts
|
12
|
+
help.puts 'usage:'
|
13
|
+
help.puts ' spud [options] <task> [args]'
|
14
|
+
help.puts
|
15
|
+
help.puts 'options:'
|
16
|
+
help.puts ' -h, --help show this help dialog'
|
17
|
+
help.puts ' -f, --files list parsed files'
|
18
|
+
help.puts ' --debug run in debug mode'
|
19
|
+
|
20
|
+
puts help.string
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/spud/lister.rb
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'stringio'
|
2
|
+
|
3
|
+
module Spud
|
4
|
+
class Lister
|
5
|
+
# @param tasks [Array<BuildTools::Task>]
|
6
|
+
def initialize(tasks)
|
7
|
+
@tasks = tasks
|
8
|
+
end
|
9
|
+
|
10
|
+
# @return [void]
|
11
|
+
def list!
|
12
|
+
builder = StringIO.new
|
13
|
+
|
14
|
+
@tasks.each do |task|
|
15
|
+
builder.write task.name.ljust(max_task_length)
|
16
|
+
|
17
|
+
if show_positional_args?
|
18
|
+
builder.write ' '
|
19
|
+
builder.write task.args.positional.join(' ').ljust(max_positional_string_length)
|
20
|
+
end
|
21
|
+
|
22
|
+
if show_named_args?
|
23
|
+
builder.write ' '
|
24
|
+
builder.write task.args.named.join(' ').ljust(max_named_string_length)
|
25
|
+
end
|
26
|
+
|
27
|
+
if show_filenames?
|
28
|
+
builder.write ' '
|
29
|
+
builder.write task.filename
|
30
|
+
end
|
31
|
+
|
32
|
+
builder.write "\n"
|
33
|
+
end
|
34
|
+
|
35
|
+
puts builder.string
|
36
|
+
end
|
37
|
+
|
38
|
+
# @return [void]
|
39
|
+
def list_filenames!
|
40
|
+
puts filenames.join("\n")
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
# @return [Integer]
|
46
|
+
def max_task_length
|
47
|
+
@max_task_length ||= @tasks.map { |task| task.name.length }.max
|
48
|
+
end
|
49
|
+
|
50
|
+
# @return [Integer]
|
51
|
+
def max_positional_string_length
|
52
|
+
@max_positional_string_length ||= @tasks
|
53
|
+
.map { |task| task.args.positional.join(' ') }
|
54
|
+
.map(&:length)
|
55
|
+
.max
|
56
|
+
end
|
57
|
+
|
58
|
+
# @return [Boolean]
|
59
|
+
def show_positional_args?
|
60
|
+
@show_positional_args ||= @tasks.any? { |task| task.args.any_positional? }
|
61
|
+
end
|
62
|
+
|
63
|
+
# @return [Integer]
|
64
|
+
def max_named_string_length
|
65
|
+
@max_named_string_length ||= @tasks
|
66
|
+
.map { |task| task.args.named.join(' ') }
|
67
|
+
.map(&:length)
|
68
|
+
.max
|
69
|
+
end
|
70
|
+
|
71
|
+
# @return [Boolean]
|
72
|
+
def show_named_args?
|
73
|
+
@show_named_args ||= @tasks.any? { |task| task.args.any_named? }
|
74
|
+
end
|
75
|
+
|
76
|
+
# @return [Array<String>]
|
77
|
+
def filenames
|
78
|
+
@filenames ||= @tasks.map(&:filename).uniq
|
79
|
+
end
|
80
|
+
|
81
|
+
# @return [Boolean]
|
82
|
+
def show_filenames?
|
83
|
+
filenames.length > 1
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|