spud 0.1.16 → 0.2.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 70f9d7ff9fce7b159e20ad827c5de7edbaa7eded1cb6be6b31359857558a9c24
4
- data.tar.gz: c536674d162d71fa1d348f79d365c6b11e4059049d1f9ffc73a4d7b6450c5859
3
+ metadata.gz: 12c0947e9a6ed28a7e5be6d84476232612e567b239beff99648ada975921dc51
4
+ data.tar.gz: 12dc859d0cfd9307bc4fcd6ed5858e75af83179ad59c1a17ac21d83955e04ba5
5
5
  SHA512:
6
- metadata.gz: 31eadcc43318c65a7be3e88e8e477b0064c0b8b8e7763cf197f29a4ba96323095f0b7ed99770a15ece2a10c568e6caa9a90d1078cc8c165c76d4b5678884ee27
7
- data.tar.gz: 9453fe0ceb937c7ed989fb357db0665be4dde3ddf89d809adb969a74064c337ca752beb23fe6a4b17463261dde4415c13d1dca660f390001ba01fadeefed4418
6
+ metadata.gz: 06f7ddbab9f8369e52fd3ecf467a2afcb12536b59ab50c97f2aa731ebac12af6f0b4bac9c0034309451073331472fa04aeeb6d11e8541e27fd5387f7028ee453
7
+ data.tar.gz: 227eeefc6c59f2bd6a9f02470070c5424fa3b53e4f872613da31026bf342909d432b8d5e2a49ded2b28372b435ab96d92c616a810dc2d9dd4fb5484702670d5f
@@ -1,187 +1,7 @@
1
- require 'stringio'
2
- require_relative 'args'
3
- require_relative 'version'
4
- require_relative 'shell'
5
- require_relative 'build_tools/build_tools'
6
- require_relative 'build_tools/spud/shell_error'
1
+ require_relative 'spud/runtime'
7
2
 
8
3
  module Spud
9
4
  def self.run!
10
- Spud.new.run!
11
- end
12
-
13
- class Spud
14
- attr_accessor :watch_process
15
-
16
- def run!
17
- puts options if debug?
18
- puts watches_present: watches_present? if debug?
19
- puts wait: wait? if debug?
20
-
21
- if help?
22
- print_help!
23
- return
24
- end
25
-
26
- if version?
27
- puts VERSION
28
- return
29
- end
30
-
31
- unless rule_present?
32
- print_rules!
33
- return
34
- end
35
-
36
- if watches_present?
37
- watch(options[:watches], rule_name, *args[:positional], **args[:keyword])
38
- return
39
- end
40
-
41
- invoke(rule_name, *args[:positional], **args[:keyword])
42
- rescue BuildTools::SpudBuild::ShellError => e
43
- raise e if debug?
44
-
45
- rescue => e
46
- raise e if debug?
47
- puts e.message
48
- end
49
-
50
- def invoke(name, *args, **kwargs)
51
- rule = rules[name.to_s]
52
- raise Error, "no rule found for '#{name}'" unless rule
53
- rule.invoke(*args, **kwargs)
54
- end
55
-
56
- def watch(globs, name, *args, **kwargs)
57
- rule = rules[name.to_s]
58
- raise Error, "no rule found for '#{name}'" unless rule
59
-
60
- thread = nil
61
- timestamps = {}
62
- loop do
63
- begin
64
- filenames = Dir.glob(*globs)
65
- filenames.each do |filename|
66
- new_timestamp = File.mtime(filename)
67
- old_timestamp = timestamps[filename]
68
-
69
- if !old_timestamp || new_timestamp > old_timestamp
70
- timestamps[filename] = new_timestamp
71
-
72
- watch_process.kill! if watch_process
73
- thread.kill if thread
74
-
75
- thread = Thread.new { invoke(name, *args, **kwargs) }
76
- break
77
- end
78
- end
79
-
80
- sleep 0.1
81
- rescue Interrupt
82
- thread.kill if thread
83
- watch_process.kill! if watch_process
84
- break
85
- end
86
- end
87
- end
88
-
89
- def wait?
90
- @wait ||= !watches_present?
91
- end
92
-
93
- private
94
-
95
- # Rules
96
- def rules
97
- @rules ||= build_tools.reduce({}) { |rules, tool| rules.merge(tool.rules) }
98
- end
99
-
100
- def build_tools
101
- @build_tools ||= BuildTools::BUILD_TOOLS
102
- .reverse
103
- .map { |tool| tool.new(self) }
104
- .each(&:mount!)
105
- end
106
-
107
- def print_rules!
108
- longest_name = 0
109
- longest_filename = 0
110
- longest_positional = 0
111
- longest_keyword = 0
112
- table = []
113
- rules.each do |name, rule|
114
- longest_name = name.length if name.length > longest_name
115
-
116
- positional = rule.positional_params.map(&method(:wrap_param)).join(' ')
117
- longest_positional = positional.length if positional.length > longest_positional
118
-
119
- keyword = rule.keyword_params.map(&method(:prefix_param)).join(' ')
120
- longest_keyword = keyword.length if keyword.length > longest_keyword
121
-
122
- longest_filename = rule.filename.length if rule.filename.length > longest_filename
123
-
124
- table << [name, positional, keyword, rule.filename]
125
- end
126
-
127
- table.each do |(name, positional, keyword, filename)|
128
- fields = [name.ljust(longest_name)]
129
- fields << positional.ljust(longest_positional) unless longest_positional == 0
130
- fields << keyword.ljust(longest_keyword) unless longest_keyword == 0
131
- fields << filename.ljust(longest_filename)
132
-
133
- puts fields.join(' ')
134
- end
135
- end
136
-
137
- def wrap_param(name)
138
- "<#{name}>"
139
- end
140
-
141
- def prefix_param(name)
142
- name.length == 1 ? "-#{name}" : "--#{name}"
143
- end
144
-
145
- # Help
146
- def print_help!
147
- help = StringIO.new
148
-
149
- help.puts "spud #{VERSION}"
150
- help.puts
151
- help.puts 'usage:'
152
- help.puts ' spud [options] <rule> [args]'
153
- help.puts
154
- help.puts 'options:'
155
- help.puts ' -h, --help show this help dialog dialog'
156
- help.puts ' -v, --version show spud version'
157
- help.puts ' -w, --watch <files> watch files for changes'
158
- help.puts ' --debug run in debug mode'
159
-
160
- puts help.string
161
- end
162
-
163
- # Options
164
- def watches_present?
165
- @watches_present ||= !options[:watches].empty?
166
- end
167
-
168
- %i[help version debug].each { |option| define_method("#{option}?") { options[option] } }
169
-
170
- # Args
171
- def rule_present?
172
- rule_name
173
- end
174
-
175
- def options
176
- @options ||= args[:options]
177
- end
178
-
179
- def rule_name
180
- @rule_name ||= args[:rule]
181
- end
182
-
183
- def args
184
- @args ||= Args.parse_args!
185
- end
5
+ Runtime.run!
186
6
  end
187
7
  end
@@ -0,0 +1,13 @@
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
@@ -0,0 +1,27 @@
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
@@ -0,0 +1,47 @@
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
@@ -0,0 +1,77 @@
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
@@ -0,0 +1,23 @@
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, *, &block)
13
+ BuildTools::Spud::Task.add_task(name, &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
@@ -0,0 +1,63 @@
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