spud 0.2.3 → 0.2.4

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.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/lib/spud.rb +3 -2
  3. data/lib/spud/block_param_info.rb +80 -0
  4. data/lib/spud/cli/options.rb +35 -0
  5. data/lib/spud/cli/parser.rb +22 -19
  6. data/lib/spud/cli/results.rb +18 -11
  7. data/lib/spud/driver.rb +134 -0
  8. data/lib/spud/error.rb +1 -0
  9. data/lib/spud/help.rb +13 -14
  10. data/lib/spud/lister.rb +27 -22
  11. data/lib/spud/task_arg.rb +15 -12
  12. data/lib/spud/task_args.rb +20 -18
  13. data/lib/spud/task_runners/make/task.rb +66 -0
  14. data/lib/spud/task_runners/package.json/task.rb +70 -0
  15. data/lib/spud/{build_tools/spud → task_runners/spud_task_runner}/dependency.rb +3 -2
  16. data/lib/spud/task_runners/spud_task_runner/file_dsl.rb +56 -0
  17. data/lib/spud/task_runners/spud_task_runner/shell/command.rb +58 -0
  18. data/lib/spud/{build_tools/spud → task_runners/spud_task_runner}/shell/result.rb +9 -4
  19. data/lib/spud/task_runners/spud_task_runner/task.rb +143 -0
  20. data/lib/spud/task_runners/spud_task_runner/task_dsl.rb +82 -0
  21. data/lib/spud/task_runners/task.rb +43 -0
  22. data/lib/spud/task_runners/task_runners.rb +25 -0
  23. data/lib/spud/version.rb +2 -1
  24. data/lib/spud/watch.rb +73 -0
  25. metadata +46 -17
  26. data/lib/spud/build_tools/build_tools.rb +0 -13
  27. data/lib/spud/build_tools/make/task.rb +0 -27
  28. data/lib/spud/build_tools/package.json/task.rb +0 -47
  29. data/lib/spud/build_tools/spud/block_param_info.rb +0 -77
  30. data/lib/spud/build_tools/spud/dsl/file.rb +0 -23
  31. data/lib/spud/build_tools/spud/dsl/task.rb +0 -63
  32. data/lib/spud/build_tools/spud/shell/command.rb +0 -52
  33. data/lib/spud/build_tools/spud/task.rb +0 -177
  34. data/lib/spud/build_tools/task.rb +0 -41
  35. data/lib/spud/options.rb +0 -14
  36. data/lib/spud/runtime.rb +0 -114
@@ -1,13 +0,0 @@
1
- require 'spud/build_tools/spud/task'
2
- require 'spud/build_tools/make/task'
3
- require 'spud/build_tools/package.json/task'
4
-
5
- module Spud
6
- module BuildTools
7
- BUILD_TOOLS = [
8
- Spud::Task,
9
- Make::Task,
10
- PackageJSON::Task,
11
- ]
12
- end
13
- end
@@ -1,27 +0,0 @@
1
- require 'spud/build_tools/task'
2
-
3
- module Spud
4
- module BuildTools
5
- module Make
6
- class Task < BuildTools::Task
7
- def self.mount!
8
- return unless File.exist?('Makefile')
9
-
10
- if `command -v make`.empty?
11
- puts 'Makefile detected, but no installation of `make` exists. Skipping make...'
12
- return
13
- end
14
-
15
- source = File.read('Makefile')
16
- source.scan(/^(\S+):.*/).map(&:first).each do |name|
17
- new(name: name, filename: 'Makefile')
18
- end
19
- end
20
-
21
- def invoke(*)
22
- system('make', name)
23
- end
24
- end
25
- end
26
- end
27
- end
@@ -1,47 +0,0 @@
1
- require 'json'
2
- require 'spud/build_tools/task'
3
-
4
- module Spud
5
- module BuildTools
6
- module PackageJSON
7
- class Task < BuildTools::Task
8
- def self.mount!
9
- return unless File.exist?('package.json')
10
-
11
- opening_commands = %w[npm run]
12
- if File.exist?('package.lock')
13
- if `command -v npm`.empty?
14
- puts 'package.json detected, but no installation of `npm` exists. Skipping npm...'
15
- return
16
- end
17
- elsif File.exist?('yarn.lock')
18
- if `command -v yarn`.empty?
19
- puts 'package.json detected, but no installation of `yarn` exists. Skipping yarn...'
20
- return
21
- else
22
- opening_commands = %w[yarn run]
23
- end
24
- end
25
-
26
- source = File.read('package.json')
27
- json = JSON.parse(source)
28
- scripts = json['scripts']
29
- return unless scripts
30
-
31
- scripts.keys.each do |name|
32
- new(name: name, filename: 'package.json', opening_commands: opening_commands)
33
- end
34
- end
35
-
36
- def initialize(name:, filename:, opening_commands:)
37
- super(name: name, filename: filename)
38
- @opening_commands = opening_commands
39
- end
40
-
41
- def invoke(*)
42
- system(*(@opening_commands + [name]))
43
- end
44
- end
45
- end
46
- end
47
- end
@@ -1,77 +0,0 @@
1
- require 'spud/task_arg'
2
-
3
- module Spud
4
- module BuildTools
5
- module Spud
6
- class BlockParamInfo
7
- # @param filename [String]
8
- # @param block [Proc]
9
- def initialize(filename, &block)
10
- @filename = filename
11
- @block = block
12
- end
13
-
14
- # @return [Array<Spud::TaskArg>]
15
- def task_args
16
- parameters.map do |type, name|
17
- case type
18
- when :req
19
- TaskArg.new(name, 'positional')
20
- when :opt
21
- TaskArg.new(name, 'positional', default: arg_values[name])
22
- when :keyreq
23
- TaskArg.new(name, 'named')
24
- when :key
25
- TaskArg.new(name, 'named', default: arg_values[name])
26
- end
27
- end
28
- end
29
-
30
- # @return [Array]
31
- def dummy_args
32
- [dummy_positional_args, dummy_named_args]
33
- end
34
-
35
- # @return [Array<NilClass>]
36
- def dummy_positional_args
37
- Array.new(parameters.count { |p| p.first == :req })
38
- end
39
-
40
- # @return [Hash{Symbol->NilClass}]
41
- def dummy_named_args
42
- parameters.select { |p| p.first == :keyreq }.map(&:last).each_with_object({}) { |n, h| h[n] = nil }
43
- end
44
-
45
- # @return [String]
46
- def arg_hash_string
47
- "{ #{parameters.map(&:last).map { |n| "#{n}: #{n}" }.join(', ')} }"
48
- end
49
-
50
- # @return [Hash]
51
- def arg_values
52
- @arg_values ||= begin
53
- positional, named = dummy_args
54
- lambda(arg_hash_string).call(*positional, **named)
55
- end
56
- end
57
-
58
- # @return [Array<Array<Symbol>>]
59
- def parameters
60
- @parameters ||= lambda.parameters
61
- end
62
-
63
- # @return [Proc]
64
- def lambda(body = nil)
65
- line = File.read(@filename).split("\n")[@block.source_location.last - 1]
66
-
67
- match = /(do|{)\s*\|(?<params>[^|]+)\|/.match(line)
68
- return -> {} unless match
69
-
70
- param_source = match[:params]
71
- param_source += ', _: nil, __: nil, ___: nil' if body
72
- eval "-> (#{param_source}) { #{body} }"
73
- end
74
- end
75
- end
76
- end
77
- end
@@ -1,23 +0,0 @@
1
- require 'spud/build_tools/spud/task'
2
-
3
- module Spud
4
- module BuildTools
5
- module Spud
6
- module DSL
7
- class File
8
- def require_relative(name)
9
- require("./#{name}")
10
- end
11
-
12
- def task(name, dependencies = {}, &block)
13
- BuildTools::Spud::Task.add_task(name, dependencies, &block)
14
- end
15
-
16
- def method_missing(name, *args, &block)
17
- task(name, *args, &block)
18
- end
19
- end
20
- end
21
- end
22
- end
23
- end
@@ -1,63 +0,0 @@
1
- require 'spud/error'
2
- require 'spud/build_tools/spud/task'
3
- require 'spud/build_tools/spud/shell/command'
4
-
5
- module Spud
6
- module BuildTools
7
- module Spud
8
- module DSL
9
- class Task
10
- def initialize(filename)
11
- @filename = filename
12
- end
13
-
14
- def sh(command)
15
- puts command
16
- Shell::Command.(command)
17
- end
18
-
19
- def shh(command)
20
- Shell::Command.(command)
21
- end
22
-
23
- def shhh(command)
24
- Shell::Command.(command, silent: true)
25
- end
26
-
27
- def sh!(command)
28
- puts command
29
- result = Shell::Command.(command)
30
- raise Error, "sh failed for '#{command}'" unless result.success?
31
- result
32
- end
33
-
34
- def shh!(command)
35
- result = Shell::Command.(command)
36
- raise Error, "sh failed for '#{command}'" unless result.success?
37
- result
38
- end
39
-
40
- def shhh!(command)
41
- result = Shell::Command.(command, silent: true)
42
- raise Error, "sh failed for '#{command}'" unless result.success?
43
- result
44
- end
45
-
46
- def invoke(task, *positional, **named)
47
- Spud::Task.invoke(@filename, task, positional, named)
48
- rescue Error => error
49
- puts "invoke failed for '#{task}': #{error}"
50
- end
51
-
52
- def invoke!(task, *positional, **named)
53
- Spud::Task.invoke(@filename, task, positional, named)
54
- end
55
-
56
- def method_missing(symbol, *positional, **named)
57
- Spud::Task.task_for(@filename, symbol) ? Spud::Task.invoke(@filename, symbol, positional, named) : super
58
- end
59
- end
60
- end
61
- end
62
- end
63
- end
@@ -1,52 +0,0 @@
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
@@ -1,177 +0,0 @@
1
- require 'stringio'
2
- require 'spud/error'
3
- require 'spud/task_args'
4
- require 'spud/build_tools/task'
5
- require 'spud/build_tools/spud/dependency'
6
- require 'spud/build_tools/spud/task'
7
- require 'spud/build_tools/spud/dsl/file'
8
- require 'spud/build_tools/spud/dsl/task'
9
-
10
- module Spud
11
- module BuildTools
12
- module Spud
13
- class Task < BuildTools::Task
14
- # @return [void]
15
- def self.mount!
16
- Dir['**/Spudfile', '**/*.spud'].each do |filename|
17
- @filename = filename
18
- file_dsl.instance_eval(File.read(filename), filename)
19
- end
20
-
21
- @filename = nil
22
- end
23
-
24
- # @return [Spud::DSL::File]
25
- def self.file_dsl
26
- @file_dsl ||= DSL::File.new
27
- end
28
-
29
- # @param task [String]
30
- # @param block [Proc]
31
- # @return [void]
32
- def self.add_task(task, dependencies, &block)
33
- new(
34
- name: qualified_name(@filename, task.to_s),
35
- filename: @filename,
36
- dependencies: dependencies,
37
- &block
38
- )
39
- end
40
-
41
- # @param filename [String]
42
- # @param task [String]
43
- # @param positional [Array]
44
- # @param named [Hash]
45
- def self.invoke(filename, task, positional, named)
46
- task = task.to_s
47
- task_obj = task_for(filename, task)
48
- if task_obj
49
- Runtime.invoke(task_obj.name, positional, named)
50
- else
51
- Runtime.invoke(task, positional, named)
52
- end
53
- end
54
-
55
- # @param filename [String]
56
- # @param task [String]
57
- # @return [BuildTools::Spud::Task]
58
- def self.task_for(filename, task)
59
- Runtime.tasks[qualified_name(filename, task.to_s)]
60
- end
61
-
62
- # @param filename [String]
63
- # @param task [String]
64
- # @return [String]
65
- def self.qualified_name(filename, task)
66
- raise "task '#{task}' somehow created without filename" unless filename
67
-
68
- [qualified_prefix(filename), task.to_s].join('.').gsub(/^\./, '')
69
- end
70
-
71
- # @param filename [String]
72
- # @return [String]
73
- def self.qualified_prefix(filename)
74
- dirname = File.dirname(filename)
75
- dirname = '' if dirname == '.'
76
-
77
- basename = File.basename(filename, '.spud')
78
- basename_array = basename == 'Spudfile' ? [] : [basename]
79
-
80
- (dirname.split('/') + basename_array).join('.')
81
- end
82
-
83
- # @param name [String]
84
- # @param filename [String]
85
- # @param dependencies [Hash]
86
- # @param block [Proc]
87
- def initialize(name:, filename:, dependencies:, &block)
88
- super(name: name, filename: filename)
89
- @dependencies = dependencies.map { |to, from| Dependency.new(to, from) }
90
- @block = block
91
- end
92
-
93
- # @param positional [Array]
94
- # @param named [Hash]
95
- # @return [Object]
96
- def invoke(positional, named)
97
- if up_to_date?
98
- puts "'#{name}' up to date"
99
- return
100
- end
101
-
102
- check_required_args!(positional)
103
-
104
- return task_dsl.instance_exec(*positional, &@block) unless args.any_named?
105
-
106
- task_dsl.instance_exec(*positional, **symbolize_keys(named), &@block)
107
- rescue ArgumentError => error
108
- raise Error, "invocation of '#{name}' with #{error.message}"
109
- end
110
-
111
- # @return [Spud::TaskArgs]
112
- def args
113
- @args ||= ::Spud::TaskArgs.from_block(filename, &@block)
114
- end
115
-
116
- # @return [String]
117
- def details
118
- filename, line_cursor = @block.source_location
119
- line_cursor -= 1
120
-
121
- lines = File.read(filename).split("\n")
122
- builder = StringIO.new
123
-
124
- while lines[line_cursor - 1] && lines[line_cursor - 1].start_with?('#')
125
- line_cursor -= 1
126
- end
127
-
128
- while lines[line_cursor].start_with?('#')
129
- builder.puts lines[line_cursor]
130
- line_cursor += 1
131
- end
132
-
133
- until lines[line_cursor].start_with?('end')
134
- builder.puts lines[line_cursor]
135
- line_cursor += 1
136
- end
137
-
138
- builder.puts lines[line_cursor]
139
- builder.string
140
- end
141
-
142
- private
143
-
144
- # @param positional [Array<String>]
145
- # @return [void]
146
- def check_required_args!(positional)
147
- required_positional = args.required_positional
148
- missing_positional = required_positional.length - positional.length
149
- if missing_positional > 0
150
- arguments = required_positional.length - missing_positional > 1 ? 'arguments' : 'argument'
151
- raise Error, "invocation of '#{name}' missing required #{arguments} #{required_positional.join(', ')}"
152
- end
153
- end
154
-
155
- # @return [Boolean]
156
- def up_to_date?
157
- return false if @dependencies.empty?
158
-
159
- @dependencies.all?(&:up_to_date?)
160
- end
161
-
162
- # @return [Spud::DSL::Task]
163
- def task_dsl
164
- @task_dsl ||= DSL::Task.new(filename)
165
- end
166
-
167
- # @param hash [Hash]
168
- # @return [Hash]
169
- def symbolize_keys(hash)
170
- hash.each_with_object({}) do |(key, value), new_hash|
171
- new_hash[key.is_a?(String) ? key.to_sym : key] = value
172
- end
173
- end
174
- end
175
- end
176
- end
177
- end