tty-command 0.8.0 → 0.10.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 +5 -5
- data/CHANGELOG.md +41 -1
- data/LICENSE.txt +1 -1
- data/README.md +83 -60
- data/lib/tty-command.rb +1 -3
- data/lib/tty/command.rb +17 -17
- data/lib/tty/command/child_process.rb +9 -10
- data/lib/tty/command/cmd.rb +24 -15
- data/lib/tty/command/dry_runner.rb +3 -4
- data/lib/tty/command/exit_error.rb +1 -2
- data/lib/tty/command/printers/abstract.rb +8 -10
- data/lib/tty/command/printers/null.rb +1 -4
- data/lib/tty/command/printers/pretty.rb +23 -22
- data/lib/tty/command/printers/progress.rb +3 -8
- data/lib/tty/command/printers/quiet.rb +3 -7
- data/lib/tty/command/process_runner.rb +57 -50
- data/lib/tty/command/result.rb +4 -3
- data/lib/tty/command/truncator.rb +4 -5
- data/lib/tty/command/version.rb +2 -2
- metadata +24 -64
- data/.gitignore +0 -9
- data/.rspec +0 -4
- data/.travis.yml +0 -29
- data/CODE_OF_CONDUCT.md +0 -49
- data/Gemfile +0 -14
- data/Rakefile +0 -10
- data/appveyor.yml +0 -26
- data/benchmarks/memory.rb +0 -11
- data/bin/console +0 -6
- data/bin/setup +0 -6
- data/examples/bash.rb +0 -12
- data/examples/basic.rb +0 -9
- data/examples/cli +0 -4
- data/examples/env.rb +0 -9
- data/examples/logger.rb +0 -10
- data/examples/output.rb +0 -10
- data/examples/pty.rb +0 -7
- data/examples/redirect_stderr.rb +0 -10
- data/examples/redirect_stdin.rb +0 -15
- data/examples/redirect_stdout.rb +0 -10
- data/examples/stdin_input.rb +0 -10
- data/examples/threaded.rb +0 -12
- data/examples/timeout.rb +0 -7
- data/examples/wait.rb +0 -21
- data/tasks/console.rake +0 -11
- data/tasks/coverage.rake +0 -11
- data/tasks/spec.rake +0 -29
- data/tty-command.gemspec +0 -27
data/lib/tty-command.rb
CHANGED
data/lib/tty/command.rb
CHANGED
@@ -1,16 +1,16 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
|
5
|
-
require_relative
|
6
|
-
require_relative
|
7
|
-
require_relative
|
8
|
-
require_relative
|
9
|
-
require_relative
|
10
|
-
require_relative
|
11
|
-
require_relative
|
12
|
-
require_relative
|
13
|
-
require_relative
|
3
|
+
require "rbconfig"
|
4
|
+
|
5
|
+
require_relative "command/cmd"
|
6
|
+
require_relative "command/exit_error"
|
7
|
+
require_relative "command/dry_runner"
|
8
|
+
require_relative "command/process_runner"
|
9
|
+
require_relative "command/printers/null"
|
10
|
+
require_relative "command/printers/pretty"
|
11
|
+
require_relative "command/printers/progress"
|
12
|
+
require_relative "command/printers/quiet"
|
13
|
+
require_relative "command/version"
|
14
14
|
|
15
15
|
module TTY
|
16
16
|
class Command
|
@@ -19,9 +19,9 @@ module TTY
|
|
19
19
|
TimeoutExceeded = Class.new(StandardError)
|
20
20
|
|
21
21
|
# Path to the current Ruby
|
22
|
-
RUBY = ENV[
|
23
|
-
RbConfig::CONFIG[
|
24
|
-
RbConfig::CONFIG[
|
22
|
+
RUBY = ENV["RUBY"] || ::File.join(
|
23
|
+
RbConfig::CONFIG["bindir"],
|
24
|
+
RbConfig::CONFIG["ruby_install_name"] + RbConfig::CONFIG["EXEEXT"]
|
25
25
|
)
|
26
26
|
|
27
27
|
WIN_PLATFORMS = /cygwin|mswin|mingw|bccwin|wince|emx/.freeze
|
@@ -35,7 +35,7 @@ module TTY
|
|
35
35
|
end
|
36
36
|
|
37
37
|
def self.windows?
|
38
|
-
!!(RbConfig::CONFIG[
|
38
|
+
!!(RbConfig::CONFIG["host_os"] =~ WIN_PLATFORMS)
|
39
39
|
end
|
40
40
|
|
41
41
|
attr_reader :printer
|
@@ -128,7 +128,7 @@ module TTY
|
|
128
128
|
def wait(*args)
|
129
129
|
pattern = args.pop
|
130
130
|
unless pattern
|
131
|
-
raise ArgumentError,
|
131
|
+
raise ArgumentError, "Please provide condition to wait for"
|
132
132
|
end
|
133
133
|
|
134
134
|
run(*args) do |out, _|
|
@@ -204,7 +204,7 @@ module TTY
|
|
204
204
|
#
|
205
205
|
# @api private
|
206
206
|
def find_printer_class(name)
|
207
|
-
const_name = name.to_s.split(
|
207
|
+
const_name = name.to_s.split("_").map(&:capitalize).join.to_sym
|
208
208
|
if const_name.empty? || !TTY::Command::Printers.const_defined?(const_name)
|
209
209
|
raise ArgumentError, %(Unknown printer type "#{name}")
|
210
210
|
end
|
@@ -1,9 +1,8 @@
|
|
1
|
-
# encoding: utf-8
|
2
1
|
# frozen_string_literal: true
|
3
2
|
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
3
|
+
require "tempfile"
|
4
|
+
require "securerandom"
|
5
|
+
require "io/console"
|
7
6
|
|
8
7
|
module TTY
|
9
8
|
class Command
|
@@ -28,12 +27,12 @@ module TTY
|
|
28
27
|
verbose = cmd.options[:verbose]
|
29
28
|
|
30
29
|
pty = try_loading_pty(verbose) if pty
|
31
|
-
require(
|
30
|
+
require("pty") if pty # load within this scope
|
32
31
|
|
33
32
|
# Create pipes
|
34
|
-
in_rd, in_wr = pty ? PTY.open : IO.pipe(
|
35
|
-
out_rd, out_wr = pty ? PTY.open : IO.pipe(
|
36
|
-
err_rd, err_wr = pty ? PTY.open : IO.pipe(
|
33
|
+
in_rd, in_wr = pty ? PTY.open : IO.pipe("utf-8") # reading
|
34
|
+
out_rd, out_wr = pty ? PTY.open : IO.pipe("utf-8") # writing
|
35
|
+
err_rd, err_wr = pty ? PTY.open : IO.pipe("utf-8") # error
|
37
36
|
in_wr.sync = true
|
38
37
|
|
39
38
|
if binmode
|
@@ -133,7 +132,7 @@ module TTY
|
|
133
132
|
key = fd_to_process_key(spawn_key)
|
134
133
|
value = spawn_value
|
135
134
|
|
136
|
-
if key.to_s ==
|
135
|
+
if key.to_s == "in"
|
137
136
|
value = convert_to_fd(spawn_value)
|
138
137
|
end
|
139
138
|
|
@@ -196,7 +195,7 @@ module TTY
|
|
196
195
|
return object
|
197
196
|
end
|
198
197
|
|
199
|
-
tmp = ::Tempfile.new(::SecureRandom.uuid.split(
|
198
|
+
tmp = ::Tempfile.new(::SecureRandom.uuid.split("-")[0])
|
200
199
|
content = try_reading(object)
|
201
200
|
tmp.write(content)
|
202
201
|
tmp.rewind
|
data/lib/tty/command/cmd.rb
CHANGED
@@ -1,10 +1,13 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require "securerandom"
|
4
|
+
require "shellwords"
|
5
5
|
|
6
6
|
module TTY
|
7
7
|
class Command
|
8
|
+
# Encapsulates the executed command
|
9
|
+
#
|
10
|
+
# @api private
|
8
11
|
class Cmd
|
9
12
|
# A string command name, or shell program
|
10
13
|
# @api public
|
@@ -33,14 +36,15 @@ module TTY
|
|
33
36
|
if env_or_cmd.respond_to?(:to_hash)
|
34
37
|
@env = env_or_cmd
|
35
38
|
unless command = args.shift
|
36
|
-
raise ArgumentError,
|
39
|
+
raise ArgumentError, "Cmd requires command argument"
|
37
40
|
end
|
38
41
|
else
|
39
42
|
command = env_or_cmd
|
40
43
|
end
|
41
44
|
|
42
45
|
if args.empty? && cmd = command.to_s
|
43
|
-
raise ArgumentError,
|
46
|
+
raise ArgumentError, "No command provided" if cmd.empty?
|
47
|
+
|
44
48
|
@command = sanitize(cmd)
|
45
49
|
@argv = []
|
46
50
|
else
|
@@ -55,7 +59,7 @@ module TTY
|
|
55
59
|
@env ||= {}
|
56
60
|
@options = opts
|
57
61
|
|
58
|
-
@uuid = SecureRandom.uuid.split(
|
62
|
+
@uuid = SecureRandom.uuid.split("-")[0]
|
59
63
|
@only_output_on_error = opts.fetch(:only_output_on_error) { false }
|
60
64
|
freeze
|
61
65
|
end
|
@@ -63,8 +67,8 @@ module TTY
|
|
63
67
|
# Extend command options if keys don't already exist
|
64
68
|
#
|
65
69
|
# @api public
|
66
|
-
def update(
|
67
|
-
@options.update(options.
|
70
|
+
def update(options)
|
71
|
+
@options.update(options.merge(@options))
|
68
72
|
end
|
69
73
|
|
70
74
|
# The shell environment variables
|
@@ -79,32 +83,37 @@ module TTY
|
|
79
83
|
converted_key = key.is_a?(Symbol) ? key.to_s.upcase : key.to_s
|
80
84
|
escaped_val = val.to_s.gsub(/"/, '\"')
|
81
85
|
%(#{converted_key}="#{escaped_val}")
|
82
|
-
end.join(
|
86
|
+
end.join(" ")
|
83
87
|
end
|
84
88
|
|
85
89
|
def evars(value, &block)
|
86
90
|
return (value || block) unless environment.any?
|
87
|
-
|
91
|
+
|
92
|
+
"( export #{environment_string} ; #{value || block.call} )"
|
88
93
|
end
|
89
94
|
|
90
95
|
def umask(value)
|
91
96
|
return value unless options[:umask]
|
97
|
+
|
92
98
|
%(umask #{options[:umask]} && %s) % [value]
|
93
99
|
end
|
94
100
|
|
95
101
|
def chdir(value)
|
96
102
|
return value unless options[:chdir]
|
97
|
-
|
103
|
+
|
104
|
+
%(cd #{Shellwords.escape(options[:chdir])} && #{value})
|
98
105
|
end
|
99
106
|
|
100
107
|
def user(value)
|
101
108
|
return value unless options[:user]
|
102
|
-
|
109
|
+
|
110
|
+
vars = environment.any? ? "#{environment_string} " : ""
|
103
111
|
%(sudo -u #{options[:user]} #{vars}-- sh -c '%s') % [value]
|
104
112
|
end
|
105
113
|
|
106
114
|
def group(value)
|
107
115
|
return value unless options[:group]
|
116
|
+
|
108
117
|
%(sg #{options[:group]} -c \\\"%s\\\") % [value]
|
109
118
|
end
|
110
119
|
|
@@ -123,15 +132,15 @@ module TTY
|
|
123
132
|
|
124
133
|
# @api public
|
125
134
|
def to_s
|
126
|
-
[command.to_s, *Array(argv)].join(
|
135
|
+
[command.to_s, *Array(argv)].join(" ")
|
127
136
|
end
|
128
137
|
|
129
138
|
# @api public
|
130
139
|
def to_hash
|
131
140
|
{
|
132
141
|
command: command,
|
133
|
-
argv:
|
134
|
-
uuid:
|
142
|
+
argv: argv,
|
143
|
+
uuid: uuid
|
135
144
|
}
|
136
145
|
end
|
137
146
|
|
@@ -1,7 +1,6 @@
|
|
1
|
-
# encoding: utf-8
|
2
1
|
# frozen_string_literal: true
|
3
2
|
|
4
|
-
require_relative
|
3
|
+
require_relative "result"
|
5
4
|
|
6
5
|
module TTY
|
7
6
|
class Command
|
@@ -18,10 +17,10 @@ module TTY
|
|
18
17
|
# @api public
|
19
18
|
def run!(*)
|
20
19
|
cmd.to_command
|
21
|
-
message = "#{@printer.decorate(
|
20
|
+
message = "#{@printer.decorate("(dry run)", :blue)} " +
|
22
21
|
@printer.decorate(cmd.to_command, :yellow, :bold)
|
23
22
|
@printer.write(cmd, message, cmd.uuid)
|
24
|
-
Result.new(0,
|
23
|
+
Result.new(0, "", "")
|
25
24
|
end
|
26
25
|
end # DryRunner
|
27
26
|
end # Command
|
@@ -1,4 +1,3 @@
|
|
1
|
-
# encoding: utf-8
|
2
1
|
# frozen_string_literal: true
|
3
2
|
|
4
3
|
module TTY
|
@@ -25,7 +24,7 @@ module TTY
|
|
25
24
|
end
|
26
25
|
|
27
26
|
def extract_output(value)
|
28
|
-
(value ||
|
27
|
+
(value || "").strip.empty? ? "Nothing written" : value.strip
|
29
28
|
end
|
30
29
|
end # ExitError
|
31
30
|
end # Command
|
@@ -1,6 +1,4 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require 'pastel'
|
1
|
+
require "pastel"
|
4
2
|
|
5
3
|
module TTY
|
6
4
|
class Command
|
@@ -22,11 +20,11 @@ module TTY
|
|
22
20
|
def initialize(output, options = {})
|
23
21
|
@output = output
|
24
22
|
@options = options
|
25
|
-
@enabled = options.fetch(:color
|
26
|
-
@color = ::Pastel.new(
|
23
|
+
@enabled = options.fetch(:color, true)
|
24
|
+
@color = ::Pastel.new(enabled: @enabled)
|
27
25
|
|
28
|
-
@out_data =
|
29
|
-
@err_data =
|
26
|
+
@out_data = ""
|
27
|
+
@err_data = ""
|
30
28
|
end
|
31
29
|
|
32
30
|
def print_command_start(cmd, *args)
|
@@ -34,15 +32,15 @@ module TTY
|
|
34
32
|
end
|
35
33
|
|
36
34
|
def print_command_out_data(cmd, *args)
|
37
|
-
write(args.join(
|
35
|
+
write(args.join(" "))
|
38
36
|
end
|
39
37
|
|
40
38
|
def print_command_err_data(cmd, *args)
|
41
|
-
write(args.join(
|
39
|
+
write(args.join(" "))
|
42
40
|
end
|
43
41
|
|
44
42
|
def print_command_exit(cmd, *args)
|
45
|
-
write(args.join(
|
43
|
+
write(args.join(" "))
|
46
44
|
end
|
47
45
|
|
48
46
|
def write(cmd, message)
|
@@ -1,53 +1,54 @@
|
|
1
|
-
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
require 'pastel'
|
5
|
-
|
6
|
-
require_relative 'abstract'
|
1
|
+
require_relative "abstract"
|
7
2
|
|
8
3
|
module TTY
|
9
4
|
class Command
|
10
5
|
module Printers
|
11
6
|
class Pretty < Abstract
|
12
|
-
TIME_FORMAT = "%5.3f %s"
|
7
|
+
TIME_FORMAT = "%5.3f %s"
|
8
|
+
|
9
|
+
def initialize(*)
|
10
|
+
super
|
11
|
+
@uuid = options.fetch(:uuid, true)
|
12
|
+
end
|
13
13
|
|
14
14
|
def print_command_start(cmd, *args)
|
15
15
|
message = ["Running #{decorate(cmd.to_command, :yellow, :bold)}"]
|
16
|
-
message << args.map(&:chomp).join(
|
17
|
-
write(cmd, message.join
|
16
|
+
message << args.map(&:chomp).join(" ") unless args.empty?
|
17
|
+
write(cmd, message.join)
|
18
18
|
end
|
19
19
|
|
20
20
|
def print_command_out_data(cmd, *args)
|
21
|
-
message = args.map(&:chomp).join(
|
22
|
-
write(cmd, "\t#{message}",
|
21
|
+
message = args.map(&:chomp).join(" ")
|
22
|
+
write(cmd, "\t#{message}", out_data)
|
23
23
|
end
|
24
24
|
|
25
25
|
def print_command_err_data(cmd, *args)
|
26
|
-
message = args.map(&:chomp).join(
|
27
|
-
write(cmd, "\t" + decorate(message, :red),
|
26
|
+
message = args.map(&:chomp).join(" ")
|
27
|
+
write(cmd, "\t" + decorate(message, :red), err_data)
|
28
28
|
end
|
29
29
|
|
30
30
|
def print_command_exit(cmd, status, runtime, *args)
|
31
|
-
|
31
|
+
if cmd.only_output_on_error && !status.zero?
|
32
32
|
output << out_data
|
33
33
|
output << err_data
|
34
34
|
end
|
35
35
|
|
36
|
-
runtime = TIME_FORMAT % [runtime, pluralize(runtime,
|
36
|
+
runtime = TIME_FORMAT % [runtime, pluralize(runtime, "second")]
|
37
37
|
message = ["Finished in #{runtime}"]
|
38
38
|
message << " with exit status #{status}" if status
|
39
39
|
message << " (#{success_or_failure(status)})"
|
40
|
-
write(cmd, message.join
|
40
|
+
write(cmd, message.join)
|
41
41
|
end
|
42
42
|
|
43
43
|
# Write message out to output
|
44
44
|
#
|
45
45
|
# @api private
|
46
|
-
def write(cmd, message,
|
47
|
-
|
46
|
+
def write(cmd, message, data = nil)
|
47
|
+
cmd_set_uuid = cmd.options.fetch(:uuid, true)
|
48
|
+
uuid_needed = cmd.options[:uuid].nil? ? @uuid : cmd_set_uuid
|
48
49
|
out = []
|
49
50
|
if uuid_needed
|
50
|
-
out << "[#{decorate(uuid, :green)}] " unless uuid.nil?
|
51
|
+
out << "[#{decorate(cmd.uuid, :green)}] " unless cmd.uuid.nil?
|
51
52
|
end
|
52
53
|
out << "#{message}\n"
|
53
54
|
target = (cmd.only_output_on_error && !data.nil?) ? data : output
|
@@ -60,15 +61,15 @@ module TTY
|
|
60
61
|
#
|
61
62
|
# @api private
|
62
63
|
def pluralize(count, word)
|
63
|
-
"#{word}#{'s' unless count.
|
64
|
+
"#{word}#{'s' unless count.to_i == 1}"
|
64
65
|
end
|
65
66
|
|
66
67
|
# @api private
|
67
68
|
def success_or_failure(status)
|
68
69
|
if status == 0
|
69
|
-
decorate(
|
70
|
+
decorate("successful", :green, :bold)
|
70
71
|
else
|
71
|
-
decorate(
|
72
|
+
decorate("failed", :red, :bold)
|
72
73
|
end
|
73
74
|
end
|
74
75
|
end # Pretty
|
@@ -1,14 +1,9 @@
|
|
1
|
-
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
require 'pastel'
|
5
|
-
require_relative 'abstract'
|
1
|
+
require_relative "abstract"
|
6
2
|
|
7
3
|
module TTY
|
8
4
|
class Command
|
9
5
|
module Printers
|
10
6
|
class Progress < Abstract
|
11
|
-
|
12
7
|
def print_command_exit(cmd, status, runtime, *args)
|
13
8
|
output.print(success_or_failure(status))
|
14
9
|
end
|
@@ -21,9 +16,9 @@ module TTY
|
|
21
16
|
# @api private
|
22
17
|
def success_or_failure(status)
|
23
18
|
if status == 0
|
24
|
-
decorate(
|
19
|
+
decorate(".", :green)
|
25
20
|
else
|
26
|
-
decorate(
|
21
|
+
decorate("F", :red)
|
27
22
|
end
|
28
23
|
end
|
29
24
|
end # Progress
|
@@ -1,23 +1,19 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require_relative 'abstract'
|
1
|
+
require_relative "abstract"
|
4
2
|
|
5
3
|
module TTY
|
6
4
|
class Command
|
7
5
|
module Printers
|
8
6
|
class Quiet < Abstract
|
9
|
-
attr_reader :output, :options
|
10
|
-
|
11
7
|
def print_command_start(cmd)
|
12
8
|
# quiet
|
13
9
|
end
|
14
10
|
|
15
11
|
def print_command_out_data(cmd, *args)
|
16
|
-
write(cmd, args.join(
|
12
|
+
write(cmd, args.join(" "), out_data)
|
17
13
|
end
|
18
14
|
|
19
15
|
def print_command_err_data(cmd, *args)
|
20
|
-
write(cmd, args.join(
|
16
|
+
write(cmd, args.join(" "), err_data)
|
21
17
|
end
|
22
18
|
|
23
19
|
def print_command_exit(cmd, status, *args)
|