vagrant-devcommands 0.8.0 → 0.9.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 +4 -4
- data/CHANGELOG.md +13 -0
- data/README.md +36 -8
- data/lib/vagrant/devcommands.rb +1 -0
- data/lib/vagrant/devcommands/command.rb +19 -2
- data/lib/vagrant/devcommands/help_printer/chain.rb +1 -1
- data/lib/vagrant/devcommands/help_printer/command.rb +1 -1
- data/lib/vagrant/devcommands/internal_command/version.rb +1 -1
- data/lib/vagrant/devcommands/messages.rb +5 -0
- data/lib/vagrant/devcommands/model/command.rb +10 -5
- data/lib/vagrant/devcommands/runner/chain.rb +17 -3
- data/lib/vagrant/devcommands/runner/command.rb +10 -10
- data/lib/vagrant/devcommands/util.rb +14 -0
- data/lib/vagrant/devcommands/util/jaro_winkler.rb +126 -0
- data/lib/vagrant/devcommands/version.rb +1 -1
- data/locales/en.yml +5 -2
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1cdd09f90d6b080675f4b15e4fb9ec4ce3101cf2
|
4
|
+
data.tar.gz: 9968d30256b15ce9247ad33c39e1e1c39a3b6daf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: aa62d03f315aab6378feb9f9ffff8d7c3f3f22930c2b7ab177ab7afea46e34761a7cab7a5c08c4ce249cff2d6e51e288fb6a1d274663ff21b529c5d242bed272
|
7
|
+
data.tar.gz: 6581d21c82f57b249c645844f4e64a5cebe36c4e5171a2992e1a9a9ba914fb4ae710b3d5ae7bfcbe56deb021e5f273910071acfdf655eedf3219d99b85419533
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,18 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## v0.9.0 (2017-05-20)
|
4
|
+
|
5
|
+
- Enhancements
|
6
|
+
- Every command in a chain can specify the machine to be used
|
7
|
+
- If an unknown command is requested a possible alternative
|
8
|
+
is suggested based on the calculated
|
9
|
+
[Jaro-Winkler distance](https://en.wikipedia.org/wiki/Jaro%E2%80%93Winkler_distance)
|
10
|
+
|
11
|
+
- Deprecations
|
12
|
+
- The configuration parameter `:box` has been renamed to `:machine` to
|
13
|
+
match the vagrant naming. Support for the old configuration will be
|
14
|
+
dropped in a future version
|
15
|
+
|
3
16
|
## v0.8.0 (2017-04-19)
|
4
17
|
|
5
18
|
- Enhancements
|
data/README.md
CHANGED
@@ -15,11 +15,11 @@ vagrant run
|
|
15
15
|
|
16
16
|
```shell
|
17
17
|
# single-vm environment
|
18
|
-
# or multi-vm environment with :
|
18
|
+
# or multi-vm environment with :machine option
|
19
19
|
vagrant run your_command
|
20
20
|
|
21
21
|
# multi-vm environment
|
22
|
-
vagrant run
|
22
|
+
vagrant run your_machine your_command
|
23
23
|
```
|
24
24
|
|
25
25
|
This runs commands or alternatively a command chain with the passed name.
|
@@ -32,8 +32,8 @@ Add to a `Commandfile` besides your `Vagrantfile`:
|
|
32
32
|
command 'basic', 'hostname'
|
33
33
|
|
34
34
|
command 'with_options',
|
35
|
-
|
36
|
-
desc: 'executes "hostname" on the
|
35
|
+
machine: :my_machine,
|
36
|
+
desc: 'executes "hostname" on the machine "my_machine"',
|
37
37
|
script: 'hostname',
|
38
38
|
usage: 'vagrant run %{command}',
|
39
39
|
help: <<-eoh
|
@@ -216,9 +216,37 @@ vagrant run chainecho --first="initial" --second="initial"
|
|
216
216
|
vagrant run chainecho --first="param" --second="param"
|
217
217
|
```
|
218
218
|
|
219
|
-
By default every command will be executed using the
|
220
|
-
itself or the only one available. You can, however, run the complete
|
221
|
-
against a specific
|
219
|
+
By default every command will be executed using the machine defined by the
|
220
|
+
command itself or the only one available. You can, however, run the complete
|
221
|
+
chain against a specific machine using `vagrant run your_machine your_chain`.
|
222
|
+
|
223
|
+
#### Chain Definitions with Specific Machines
|
224
|
+
|
225
|
+
If required you can modify the machine a box is run on:
|
226
|
+
|
227
|
+
```ruby
|
228
|
+
command 'chainhost',
|
229
|
+
script: 'hostname'
|
230
|
+
|
231
|
+
chain 'customized_chain_machine',
|
232
|
+
commands: [
|
233
|
+
{ command: 'chainhost' },
|
234
|
+
{ command: 'chainecho', machine: 'secondary' },
|
235
|
+
{ command: 'chainecho', machine: 'tertiary' }
|
236
|
+
]
|
237
|
+
|
238
|
+
Running the chain will execute the following commands:
|
239
|
+
|
240
|
+
```shell
|
241
|
+
> vagrant run customized_chain_machine
|
242
|
+
|
243
|
+
vagrant run chainhost
|
244
|
+
vagrant run secondary chainhost
|
245
|
+
vagrant run tertiary chainhost
|
246
|
+
```
|
247
|
+
|
248
|
+
This configuration can itself be modified by passing a machine name to run
|
249
|
+
all chain commands on using using `vagrant run your_machine your_chain`.
|
222
250
|
|
223
251
|
### Abort Parsing inside Commandfile
|
224
252
|
|
@@ -250,7 +278,7 @@ evaluating a local one.
|
|
250
278
|
### SSH
|
251
279
|
|
252
280
|
If you are using this plugin on a Windows host system, please make sure your
|
253
|
-
regular `vagrant ssh [
|
281
|
+
regular `vagrant ssh [machine]` succeeds. In some cases you may need to add the
|
254
282
|
`ssh.exe` (i.e. from a git installation) manually to your `%PATH%`.
|
255
283
|
|
256
284
|
### Command Definition
|
data/lib/vagrant/devcommands.rb
CHANGED
@@ -4,6 +4,7 @@ module VagrantPlugins
|
|
4
4
|
class Command < Vagrant.plugin(2, :command)
|
5
5
|
NAMESPACE_RUNNER = VagrantPlugins::DevCommands::Runner
|
6
6
|
MESSAGES = VagrantPlugins::DevCommands::Messages
|
7
|
+
UTIL = VagrantPlugins::DevCommands::Util
|
7
8
|
|
8
9
|
def self.synopsis
|
9
10
|
synopsis = VagrantPlugins::DevCommands::SYNOPSIS
|
@@ -20,6 +21,8 @@ module VagrantPlugins
|
|
20
21
|
def execute
|
21
22
|
return 127 unless read_commandfile
|
22
23
|
|
24
|
+
deprecated_box_config?
|
25
|
+
|
23
26
|
command = Util.argv_command(@argv, @env)
|
24
27
|
|
25
28
|
return 127 unless non_empty?(command)
|
@@ -40,13 +43,27 @@ module VagrantPlugins
|
|
40
43
|
def available?(command)
|
41
44
|
unless @registry.available?(command)
|
42
45
|
display_error("Invalid command \"#{command}\"!")
|
46
|
+
did_you_mean(command)
|
43
47
|
run_internal('help', ['--commands'])
|
44
48
|
end
|
45
49
|
|
46
50
|
@registry.available?(command)
|
47
51
|
end
|
48
52
|
|
49
|
-
def
|
53
|
+
def deprecated_box_config?
|
54
|
+
return unless @registry.commands.values.any?(&:deprecated_box_config)
|
55
|
+
|
56
|
+
MESSAGES.deprecated_box_config(&@env.ui.method(:warn))
|
57
|
+
end
|
58
|
+
|
59
|
+
def did_you_mean(command)
|
60
|
+
alternative, score = Util.did_you_mean(command, @registry)
|
61
|
+
|
62
|
+
display_error("Did you mean #{alternative}?", true) if 0.8 < score
|
63
|
+
end
|
64
|
+
|
65
|
+
def display_error(msg, pre_ln = false, post_ln = false)
|
66
|
+
@env.ui.error '' if pre_ln
|
50
67
|
@env.ui.error msg
|
51
68
|
@env.ui.error '' if post_ln
|
52
69
|
end
|
@@ -81,7 +98,7 @@ module VagrantPlugins
|
|
81
98
|
|
82
99
|
runner.run(runnable)
|
83
100
|
rescue RuntimeError => e
|
84
|
-
display_error(e.message, true)
|
101
|
+
display_error(e.message, false, true)
|
85
102
|
run_internal('help', [command])
|
86
103
|
|
87
104
|
nil
|
@@ -10,6 +10,11 @@ module VagrantPlugins
|
|
10
10
|
out.call I18n.t("#{I18N_KEY}.chain_no_help")
|
11
11
|
end
|
12
12
|
|
13
|
+
def self.deprecated_box_config(&out)
|
14
|
+
out.call I18n.t("#{I18N_KEY}.deprecated_box_config")
|
15
|
+
out.call ''
|
16
|
+
end
|
17
|
+
|
13
18
|
def self.command_no_help(&out)
|
14
19
|
out.call I18n.t("#{I18N_KEY}.command_no_help")
|
15
20
|
end
|
@@ -11,11 +11,13 @@ module VagrantPlugins
|
|
11
11
|
attr_reader :parameters
|
12
12
|
attr_reader :script
|
13
13
|
|
14
|
-
attr_reader :
|
14
|
+
attr_reader :machine
|
15
15
|
attr_reader :desc
|
16
16
|
attr_reader :help
|
17
17
|
attr_reader :usage
|
18
18
|
|
19
|
+
attr_reader :deprecated_box_config
|
20
|
+
|
19
21
|
def initialize(spec)
|
20
22
|
@name = spec[:name]
|
21
23
|
|
@@ -23,10 +25,12 @@ module VagrantPlugins
|
|
23
25
|
@parameters = spec[:parameters]
|
24
26
|
@script = spec[:script]
|
25
27
|
|
26
|
-
@
|
27
|
-
@desc
|
28
|
-
@help
|
29
|
-
@usage
|
28
|
+
@machine = spec[:machine] || spec[:box]
|
29
|
+
@desc = spec[:desc]
|
30
|
+
@help = spec[:help]
|
31
|
+
@usage = spec[:usage]
|
32
|
+
|
33
|
+
@deprecated_box_config = spec.key?(:box)
|
30
34
|
end
|
31
35
|
|
32
36
|
def run_script(argv)
|
@@ -87,6 +91,7 @@ module VagrantPlugins
|
|
87
91
|
|
88
92
|
wrap_option_values(escape_option_values(options))
|
89
93
|
end
|
94
|
+
# rubocop:enable Metrics/MethodLength
|
90
95
|
|
91
96
|
def wrap_option_values(options)
|
92
97
|
(@parameters || {}).each do |key, conf|
|
@@ -3,6 +3,8 @@ module VagrantPlugins
|
|
3
3
|
module Runner
|
4
4
|
# Chain runner
|
5
5
|
class Chain
|
6
|
+
UTIL = VagrantPlugins::DevCommands::Util
|
7
|
+
|
6
8
|
def initialize(plugin, argv, env, registry)
|
7
9
|
@plugin = plugin
|
8
10
|
@argv = argv
|
@@ -29,10 +31,22 @@ module VagrantPlugins
|
|
29
31
|
private
|
30
32
|
|
31
33
|
def argv_for(command_def)
|
32
|
-
|
33
|
-
|
34
|
+
argv = patch_machine(@argv.dup, command_def)
|
35
|
+
|
36
|
+
return argv unless command_def.key?(:argv)
|
37
|
+
return argv unless command_def[:argv].is_a?(Array)
|
38
|
+
|
39
|
+
argv + command_def[:argv]
|
40
|
+
end
|
41
|
+
|
42
|
+
def patch_machine(argv, command_def)
|
43
|
+
return argv unless command_def.key?(:machine)
|
34
44
|
|
35
|
-
|
45
|
+
if UTIL.machine_name?(argv[0].to_s, @env.machine_index)
|
46
|
+
argv
|
47
|
+
else
|
48
|
+
[command_def[:machine].to_s] + argv
|
49
|
+
end
|
36
50
|
end
|
37
51
|
|
38
52
|
def runnable_for(command_def)
|
@@ -13,13 +13,13 @@ module VagrantPlugins
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def run(command)
|
16
|
-
argv
|
17
|
-
|
18
|
-
script
|
16
|
+
argv = run_argv
|
17
|
+
machine = run_machine(command)
|
18
|
+
script = run_script(command, argv)
|
19
19
|
|
20
20
|
return 2 unless script
|
21
21
|
|
22
|
-
@plugin.proxy_with_target_vms(
|
22
|
+
@plugin.proxy_with_target_vms(machine, single_target: true) do |vm|
|
23
23
|
env = vm.action(:ssh_run,
|
24
24
|
ssh_opts: { extra_args: ['-q'] },
|
25
25
|
ssh_run_command: script)
|
@@ -38,13 +38,13 @@ module VagrantPlugins
|
|
38
38
|
argv
|
39
39
|
end
|
40
40
|
|
41
|
-
def
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
41
|
+
def run_machine(cmd)
|
42
|
+
machine = nil
|
43
|
+
machine = cmd.machine.to_s if cmd.machine
|
44
|
+
machine = @argv[0] if UTIL.machine_name?(@argv[0].to_s,
|
45
|
+
@env.machine_index)
|
46
46
|
|
47
|
-
|
47
|
+
machine
|
48
48
|
end
|
49
49
|
|
50
50
|
def run_script(command, argv)
|
@@ -2,6 +2,8 @@ module VagrantPlugins
|
|
2
2
|
module DevCommands
|
3
3
|
# Utility module
|
4
4
|
class Util
|
5
|
+
JARO_WINKLER = VagrantPlugins::DevCommands::Util::JaroWinkler
|
6
|
+
|
5
7
|
def self.argv_command(argv, env)
|
6
8
|
return nil if argv.empty?
|
7
9
|
|
@@ -29,6 +31,18 @@ module VagrantPlugins
|
|
29
31
|
end
|
30
32
|
end
|
31
33
|
|
34
|
+
def self.did_you_mean(command, registry)
|
35
|
+
alternatives = registry.commands.keys + registry.chains.keys
|
36
|
+
distances = {}
|
37
|
+
|
38
|
+
alternatives.each do |alternative|
|
39
|
+
calculator = JARO_WINKLER.new(command, alternative)
|
40
|
+
distances[alternative] = calculator.distance
|
41
|
+
end
|
42
|
+
|
43
|
+
distances.max_by { |_k, v| v }
|
44
|
+
end
|
45
|
+
|
32
46
|
def self.machine_name?(name, machine_index)
|
33
47
|
machine_index.any? { |machine| name == machine.name }
|
34
48
|
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
module VagrantPlugins
|
2
|
+
module DevCommands
|
3
|
+
class Util
|
4
|
+
# Jaro Winkler string distance
|
5
|
+
#
|
6
|
+
# Adapted from:
|
7
|
+
# https://github.com/bbatsov/rubocop/blob/ec3123fc3454b080e1100e35480c6466d1240fff/lib/rubocop/string_util.rb
|
8
|
+
class JaroWinkler
|
9
|
+
BOOST_THRESHOLD = 0.7
|
10
|
+
MAX_COMMON_PREFIX_LENGTH = 4
|
11
|
+
SCALING_FACTOR = 0.1
|
12
|
+
|
13
|
+
def initialize(left, right)
|
14
|
+
@left = left.to_s
|
15
|
+
@right = right.to_s
|
16
|
+
|
17
|
+
if @left.size < @right.size
|
18
|
+
@shorter = @left
|
19
|
+
@longer = @right
|
20
|
+
else
|
21
|
+
@shorter = @right
|
22
|
+
@longer = @left
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def distance
|
27
|
+
jaro_distance = compute_distance
|
28
|
+
|
29
|
+
if jaro_distance >= BOOST_THRESHOLD
|
30
|
+
jaro_distance += (
|
31
|
+
limited_common_prefix_length.to_f *
|
32
|
+
SCALING_FACTOR.to_f *
|
33
|
+
(1.0 - jaro_distance)
|
34
|
+
)
|
35
|
+
end
|
36
|
+
|
37
|
+
jaro_distance
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def common_prefix_length
|
43
|
+
@shorter.size.times do |index|
|
44
|
+
return index unless @shorter[index] == @longer[index]
|
45
|
+
end
|
46
|
+
|
47
|
+
@shorter.size
|
48
|
+
end
|
49
|
+
|
50
|
+
def compute_distance
|
51
|
+
common_chars_a, common_chars_b = find_common_characters
|
52
|
+
matched_count = common_chars_a.size
|
53
|
+
|
54
|
+
return 0.0 if matched_count.zero?
|
55
|
+
|
56
|
+
transposition_count = count_transpositions(common_chars_a,
|
57
|
+
common_chars_b)
|
58
|
+
|
59
|
+
compute_non_zero_distance(matched_count.to_f, transposition_count)
|
60
|
+
end
|
61
|
+
|
62
|
+
def compute_non_zero_distance(matched_count, transposition_count)
|
63
|
+
sum = (matched_count / @shorter.size.to_f) +
|
64
|
+
(matched_count / @longer.size.to_f) +
|
65
|
+
((matched_count - transposition_count / 2) / matched_count)
|
66
|
+
|
67
|
+
sum / 3.0
|
68
|
+
end
|
69
|
+
|
70
|
+
def count_transpositions(common_chars_a, common_chars_b)
|
71
|
+
common_chars_a.size.times.count do |index|
|
72
|
+
common_chars_a[index] != common_chars_b[index]
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# rubocop:disable Metrics/MethodLength
|
77
|
+
def find_common_characters
|
78
|
+
common_chars_of_shorter = Array.new(@shorter.size)
|
79
|
+
common_chars_of_longer = Array.new(@longer.size)
|
80
|
+
|
81
|
+
@shorter.each_char.with_index do |shorter_char, shorter_index|
|
82
|
+
matching_index_range(shorter_index).each do |longer_index|
|
83
|
+
longer_char = @longer.chars[longer_index]
|
84
|
+
|
85
|
+
next unless shorter_char == longer_char
|
86
|
+
|
87
|
+
common_chars_of_shorter[shorter_index] = shorter_char
|
88
|
+
common_chars_of_longer[longer_index] = longer_char
|
89
|
+
|
90
|
+
# Mark the matching character as already used
|
91
|
+
@longer.chars[longer_index] = nil
|
92
|
+
|
93
|
+
break
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
[common_chars_of_shorter, common_chars_of_longer].map(&:compact)
|
98
|
+
end
|
99
|
+
# rubocop:enable Metrics/MethodLength
|
100
|
+
|
101
|
+
def limited_common_prefix_length
|
102
|
+
length = common_prefix_length
|
103
|
+
|
104
|
+
if length > MAX_COMMON_PREFIX_LENGTH
|
105
|
+
MAX_COMMON_PREFIX_LENGTH
|
106
|
+
else
|
107
|
+
length
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def matching_index_range(origin)
|
112
|
+
min = origin - matching_window
|
113
|
+
min = 0 if min < 0
|
114
|
+
|
115
|
+
max = origin + matching_window
|
116
|
+
|
117
|
+
min..max
|
118
|
+
end
|
119
|
+
|
120
|
+
def matching_window
|
121
|
+
@matching_window ||= (@longer.size / 2).to_i - 1
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
data/locales/en.yml
CHANGED
@@ -7,7 +7,6 @@ en:
|
|
7
7
|
Display the help of the command given as the first argument if defined.
|
8
8
|
Just like this help for the help command!
|
9
9
|
usage: "Usage: %{what}"
|
10
|
-
|
11
10
|
version:
|
12
11
|
desc: "get currently installed plugin version"
|
13
12
|
help: "Displays the currently installed version of the plugin you are using right now."
|
@@ -15,6 +14,10 @@ en:
|
|
15
14
|
message:
|
16
15
|
chain_no_help: "No detailed help for this chain available."
|
17
16
|
command_no_help: "No detailed help for this command available."
|
17
|
+
deprecated_box_config: |-
|
18
|
+
At least one of your commands is configured with the deprecated
|
19
|
+
option ':box'. This option has been renamed to ':machine' and will
|
20
|
+
stop working in a future version. Please update your Commandfile.
|
18
21
|
missing_commandfile: "Missing Commandfile"
|
19
22
|
no_commands: "No commands defined!"
|
20
23
|
plugin_readme: |-
|
@@ -24,7 +27,7 @@ en:
|
|
24
27
|
A copy of this file should be locally available at:
|
25
28
|
>>> %{readme}
|
26
29
|
plugin_usage: |-
|
27
|
-
Usage: vagrant run [
|
30
|
+
Usage: vagrant run [machine] <command>
|
28
31
|
Help: vagrant run help <command>
|
29
32
|
|
30
33
|
registry:
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vagrant-devcommands
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Marc Neudert
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-05-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: coveralls
|
@@ -95,6 +95,7 @@ files:
|
|
95
95
|
- lib/vagrant/devcommands/runner/internal_command.rb
|
96
96
|
- lib/vagrant/devcommands/synopsis.rb
|
97
97
|
- lib/vagrant/devcommands/util.rb
|
98
|
+
- lib/vagrant/devcommands/util/jaro_winkler.rb
|
98
99
|
- lib/vagrant/devcommands/version.rb
|
99
100
|
- locales/en.yml
|
100
101
|
homepage: https://github.com/mneudert/vagrant-devcommands
|