spud 0.2.3 → 0.2.4

Sign up to get free protection for your applications and to get access to all the features.
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