shell 0.0.1 → 0.7
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 +7 -0
- data/.gitignore +8 -4
- data/.travis.yml +6 -0
- data/Gemfile +4 -2
- data/LICENSE.txt +22 -0
- data/README.md +90 -8
- data/Rakefile +7 -5
- data/bin/console +7 -0
- data/bin/setup +6 -0
- data/lib/shell.rb +462 -0
- data/lib/shell/builtin-command.rb +147 -0
- data/lib/shell/command-processor.rb +668 -0
- data/lib/shell/error.rb +26 -0
- data/lib/shell/filter.rb +138 -0
- data/lib/shell/process-controller.rb +309 -0
- data/lib/shell/system-command.rb +159 -0
- data/lib/shell/version.rb +17 -0
- data/shell.gemspec +21 -20
- metadata +46 -41
- data/lib/shell_utils.rb +0 -58
- data/lib/shell_utils/version.rb +0 -3
- data/test/shell_utils_test.rb +0 -25
- data/test/test_helper.rb +0 -4
@@ -0,0 +1,159 @@
|
|
1
|
+
# frozen_string_literal: false
|
2
|
+
#
|
3
|
+
# shell/system-command.rb -
|
4
|
+
# $Release Version: 0.7 $
|
5
|
+
# $Revision$
|
6
|
+
# by Keiju ISHITSUKA(keiju@ruby-lang.org)
|
7
|
+
#
|
8
|
+
# --
|
9
|
+
#
|
10
|
+
#
|
11
|
+
#
|
12
|
+
|
13
|
+
require_relative "filter"
|
14
|
+
|
15
|
+
class Shell
|
16
|
+
class SystemCommand < Filter
|
17
|
+
def initialize(sh, command, *opts)
|
18
|
+
if t = opts.find{|opt| !opt.kind_of?(String) && opt.class}
|
19
|
+
Shell.Fail TypeError, t.class, "String"
|
20
|
+
end
|
21
|
+
super(sh)
|
22
|
+
@command = command
|
23
|
+
@opts = opts
|
24
|
+
|
25
|
+
@input_queue = Thread::Queue.new
|
26
|
+
@pid = nil
|
27
|
+
|
28
|
+
sh.process_controller.add_schedule(self)
|
29
|
+
end
|
30
|
+
|
31
|
+
attr_reader :command
|
32
|
+
alias name command
|
33
|
+
|
34
|
+
def wait?
|
35
|
+
@shell.process_controller.waiting_job?(self)
|
36
|
+
end
|
37
|
+
|
38
|
+
def active?
|
39
|
+
@shell.process_controller.active_job?(self)
|
40
|
+
end
|
41
|
+
|
42
|
+
def input=(inp)
|
43
|
+
super
|
44
|
+
if active?
|
45
|
+
start_export
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def start
|
50
|
+
notify([@command, *@opts].join(" "))
|
51
|
+
|
52
|
+
@pid, @pipe_in, @pipe_out = @shell.process_controller.sfork(self) {
|
53
|
+
Dir.chdir @shell.pwd
|
54
|
+
$0 = @command
|
55
|
+
exec(@command, *@opts)
|
56
|
+
}
|
57
|
+
if @input
|
58
|
+
start_export
|
59
|
+
end
|
60
|
+
start_import
|
61
|
+
end
|
62
|
+
|
63
|
+
def flush
|
64
|
+
@pipe_out.flush if @pipe_out and !@pipe_out.closed?
|
65
|
+
end
|
66
|
+
|
67
|
+
def terminate
|
68
|
+
begin
|
69
|
+
@pipe_in.close
|
70
|
+
rescue IOError
|
71
|
+
end
|
72
|
+
begin
|
73
|
+
@pipe_out.close
|
74
|
+
rescue IOError
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def kill(sig)
|
79
|
+
if @pid
|
80
|
+
Process.kill(sig, @pid)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def start_import
|
85
|
+
notify "Job(%id) start imp-pipe.", @shell.debug?
|
86
|
+
_eop = true
|
87
|
+
Thread.start {
|
88
|
+
begin
|
89
|
+
while l = @pipe_in.gets
|
90
|
+
@input_queue.push l
|
91
|
+
end
|
92
|
+
_eop = false
|
93
|
+
rescue Errno::EPIPE
|
94
|
+
_eop = false
|
95
|
+
ensure
|
96
|
+
if !ProcessController::USING_AT_EXIT_WHEN_PROCESS_EXIT and _eop
|
97
|
+
notify("warn: Process finishing...",
|
98
|
+
"wait for Job[%id] to finish pipe importing.",
|
99
|
+
"You can use Shell#transact or Shell#check_point for more safe execution.")
|
100
|
+
redo
|
101
|
+
end
|
102
|
+
notify "job(%id}) close imp-pipe.", @shell.debug?
|
103
|
+
@input_queue.push :EOF
|
104
|
+
@pipe_in.close
|
105
|
+
end
|
106
|
+
}
|
107
|
+
end
|
108
|
+
|
109
|
+
def start_export
|
110
|
+
notify "job(%id) start exp-pipe.", @shell.debug?
|
111
|
+
_eop = true
|
112
|
+
Thread.start{
|
113
|
+
begin
|
114
|
+
@input.each do |l|
|
115
|
+
ProcessController::block_output_synchronize do
|
116
|
+
@pipe_out.print l
|
117
|
+
end
|
118
|
+
end
|
119
|
+
_eop = false
|
120
|
+
rescue Errno::EPIPE, Errno::EIO
|
121
|
+
_eop = false
|
122
|
+
ensure
|
123
|
+
if !ProcessController::USING_AT_EXIT_WHEN_PROCESS_EXIT and _eop
|
124
|
+
notify("shell: warn: Process finishing...",
|
125
|
+
"wait for Job(%id) to finish pipe exporting.",
|
126
|
+
"You can use Shell#transact or Shell#check_point for more safe execution.")
|
127
|
+
redo
|
128
|
+
end
|
129
|
+
notify "job(%id) close exp-pipe.", @shell.debug?
|
130
|
+
@pipe_out.close
|
131
|
+
end
|
132
|
+
}
|
133
|
+
end
|
134
|
+
|
135
|
+
alias super_each each
|
136
|
+
def each(rs = nil)
|
137
|
+
while (l = @input_queue.pop) != :EOF
|
138
|
+
yield l
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
# ex)
|
143
|
+
# if you wish to output:
|
144
|
+
# "shell: job(#{@command}:#{@pid}) close pipe-out."
|
145
|
+
# then
|
146
|
+
# mes: "job(%id) close pipe-out."
|
147
|
+
# yorn: Boolean(@shell.debug? or @shell.verbose?)
|
148
|
+
def notify(*opts)
|
149
|
+
@shell.notify(*opts) do |mes|
|
150
|
+
yield mes if iterator?
|
151
|
+
|
152
|
+
mes.gsub!("%id", "#{@command}:##{@pid}")
|
153
|
+
mes.gsub!("%name", "#{@command}")
|
154
|
+
mes.gsub!("%pid", "#{@pid}")
|
155
|
+
mes
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: false
|
2
|
+
#
|
3
|
+
# version.rb - shell version definition file
|
4
|
+
# $Release Version: 0.7$
|
5
|
+
# $Revision$
|
6
|
+
# by Keiju ISHITSUKA(keiju@ruby-lang.org)
|
7
|
+
#
|
8
|
+
# --
|
9
|
+
#
|
10
|
+
#
|
11
|
+
#
|
12
|
+
|
13
|
+
class Shell # :nodoc:
|
14
|
+
VERSION = "0.7"
|
15
|
+
@RELEASE_VERSION = VERSION
|
16
|
+
@LAST_UPDATE_DATE = "07/03/20"
|
17
|
+
end
|
data/shell.gemspec
CHANGED
@@ -1,25 +1,26 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
begin
|
2
|
+
require_relative "lib/shell/version"
|
3
|
+
rescue LoadError
|
4
|
+
# for Ruby core repository
|
5
|
+
require_relative "version"
|
6
|
+
end
|
4
7
|
|
5
|
-
Gem::Specification.new do |
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
s.homepage = ""
|
11
|
-
s.summary = %q{Some common shell utils}
|
12
|
-
s.description = %q{Some common shell utils.}
|
8
|
+
Gem::Specification.new do |spec|
|
9
|
+
spec.name = "shell"
|
10
|
+
spec.version = Shell::VERSION
|
11
|
+
spec.authors = ["Keiju ISHITSUKA"]
|
12
|
+
spec.email = ["keiju@ruby-lang.org"]
|
13
13
|
|
14
|
-
|
14
|
+
spec.summary = %q{An idiomatic Ruby interface for common UNIX shell commands.}
|
15
|
+
spec.description = %q{An idiomatic Ruby interface for common UNIX shell commands.}
|
16
|
+
spec.homepage = "https://github.com/ruby/shell"
|
17
|
+
spec.license = "BSD-2-Clause"
|
15
18
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
19
|
+
spec.files = [".gitignore", ".travis.yml", "Gemfile", "LICENSE.txt", "README.md", "Rakefile", "bin/console", "bin/setup", "lib/shell.rb", "lib/shell/builtin-command.rb", "lib/shell/command-processor.rb", "lib/shell/error.rb", "lib/shell/filter.rb", "lib/shell/process-controller.rb", "lib/shell/system-command.rb", "lib/shell/version.rb", "shell.gemspec"]
|
20
|
+
spec.bindir = "exe"
|
21
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
22
|
+
spec.require_paths = ["lib"]
|
20
23
|
|
21
|
-
|
22
|
-
|
23
|
-
s.add_development_dependency "rake"
|
24
|
-
s.add_development_dependency "minitest"
|
24
|
+
spec.add_development_dependency "bundler"
|
25
|
+
spec.add_development_dependency "rake"
|
25
26
|
end
|
metadata
CHANGED
@@ -1,84 +1,89 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: shell
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
5
|
-
prerelease:
|
4
|
+
version: '0.7'
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
|
-
-
|
7
|
+
- Keiju ISHITSUKA
|
9
8
|
autorequire:
|
10
|
-
bindir:
|
9
|
+
bindir: exe
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2018-12-04 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
|
-
name:
|
16
|
-
requirement:
|
17
|
-
none: false
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
18
16
|
requirements:
|
19
|
-
- -
|
17
|
+
- - ">="
|
20
18
|
- !ruby/object:Gem::Version
|
21
19
|
version: '0'
|
22
20
|
type: :development
|
23
21
|
prerelease: false
|
24
|
-
version_requirements:
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
25
27
|
- !ruby/object:Gem::Dependency
|
26
|
-
name:
|
27
|
-
requirement:
|
28
|
-
none: false
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
29
30
|
requirements:
|
30
|
-
- -
|
31
|
+
- - ">="
|
31
32
|
- !ruby/object:Gem::Version
|
32
33
|
version: '0'
|
33
34
|
type: :development
|
34
35
|
prerelease: false
|
35
|
-
version_requirements:
|
36
|
-
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
description: An idiomatic Ruby interface for common UNIX shell commands.
|
37
42
|
email:
|
38
|
-
-
|
43
|
+
- keiju@ruby-lang.org
|
39
44
|
executables: []
|
40
45
|
extensions: []
|
41
46
|
extra_rdoc_files: []
|
42
47
|
files:
|
43
|
-
- .gitignore
|
48
|
+
- ".gitignore"
|
49
|
+
- ".travis.yml"
|
44
50
|
- Gemfile
|
51
|
+
- LICENSE.txt
|
45
52
|
- README.md
|
46
53
|
- Rakefile
|
47
|
-
-
|
48
|
-
-
|
54
|
+
- bin/console
|
55
|
+
- bin/setup
|
56
|
+
- lib/shell.rb
|
57
|
+
- lib/shell/builtin-command.rb
|
58
|
+
- lib/shell/command-processor.rb
|
59
|
+
- lib/shell/error.rb
|
60
|
+
- lib/shell/filter.rb
|
61
|
+
- lib/shell/process-controller.rb
|
62
|
+
- lib/shell/system-command.rb
|
63
|
+
- lib/shell/version.rb
|
49
64
|
- shell.gemspec
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
65
|
+
homepage: https://github.com/ruby/shell
|
66
|
+
licenses:
|
67
|
+
- BSD-2-Clause
|
68
|
+
metadata: {}
|
54
69
|
post_install_message:
|
55
70
|
rdoc_options: []
|
56
71
|
require_paths:
|
57
72
|
- lib
|
58
73
|
required_ruby_version: !ruby/object:Gem::Requirement
|
59
|
-
none: false
|
60
74
|
requirements:
|
61
|
-
- -
|
75
|
+
- - ">="
|
62
76
|
- !ruby/object:Gem::Version
|
63
77
|
version: '0'
|
64
|
-
segments:
|
65
|
-
- 0
|
66
|
-
hash: -2267396776853077093
|
67
78
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
68
|
-
none: false
|
69
79
|
requirements:
|
70
|
-
- -
|
80
|
+
- - ">="
|
71
81
|
- !ruby/object:Gem::Version
|
72
82
|
version: '0'
|
73
|
-
segments:
|
74
|
-
- 0
|
75
|
-
hash: -2267396776853077093
|
76
83
|
requirements: []
|
77
|
-
rubyforge_project:
|
78
|
-
rubygems_version:
|
84
|
+
rubyforge_project:
|
85
|
+
rubygems_version: 2.7.6
|
79
86
|
signing_key:
|
80
|
-
specification_version:
|
81
|
-
summary:
|
82
|
-
test_files:
|
83
|
-
- test/shell_utils_test.rb
|
84
|
-
- test/test_helper.rb
|
87
|
+
specification_version: 4
|
88
|
+
summary: An idiomatic Ruby interface for common UNIX shell commands.
|
89
|
+
test_files: []
|
data/lib/shell_utils.rb
DELETED
@@ -1,58 +0,0 @@
|
|
1
|
-
require "shell_utils/version"
|
2
|
-
|
3
|
-
module ShellUtils
|
4
|
-
extend self
|
5
|
-
|
6
|
-
def sh(cmd, base = nil)
|
7
|
-
out, code = sh_with_code(cmd)
|
8
|
-
code == 0 ? out : raise(out.empty? ? "Running `#{cmd}' failed. Run this command directly for more detailed output." : out)
|
9
|
-
end
|
10
|
-
|
11
|
-
# Run in shell, return both status and output
|
12
|
-
# @see #sh
|
13
|
-
def sh_with_code(cmd, base = nil)
|
14
|
-
cmd << " 2>&1"
|
15
|
-
outbuf = ''
|
16
|
-
outbuf = `#{base && "cd '#{base}' && "}#{cmd}`
|
17
|
-
[outbuf, $?]
|
18
|
-
end
|
19
|
-
|
20
|
-
def escape(*command)
|
21
|
-
command.flatten.map {|word| escape_word(word) }.join(' ')
|
22
|
-
end
|
23
|
-
|
24
|
-
def escape_word(str)
|
25
|
-
if str.empty?
|
26
|
-
"''"
|
27
|
-
elsif %r{\A[0-9A-Za-z+,./:=@_-]+\z} =~ str
|
28
|
-
str
|
29
|
-
else
|
30
|
-
result = ''
|
31
|
-
str.scan(/('+)|[^']+/) {
|
32
|
-
if $1
|
33
|
-
result << %q{\'} * $1.length
|
34
|
-
else
|
35
|
-
result << "'#{$&}'"
|
36
|
-
end
|
37
|
-
}
|
38
|
-
result
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
def capture
|
43
|
-
old_out, old_err = STDOUT.dup, STDERR.dup
|
44
|
-
stdout_read, stdout_write = IO.pipe
|
45
|
-
stderr_read, stderr_write = IO.pipe
|
46
|
-
$stdout.reopen(stdout_write)
|
47
|
-
$stderr.reopen(stderr_write)
|
48
|
-
yield
|
49
|
-
stdout_write.close
|
50
|
-
stderr_write.close
|
51
|
-
out = stdout_read.rewind && stdout_read.read rescue nil
|
52
|
-
err = stderr_read.rewind && stderr_read.read rescue nil
|
53
|
-
[out, err]
|
54
|
-
ensure
|
55
|
-
$stdout.reopen(old_out)
|
56
|
-
$stderr.reopen(old_err)
|
57
|
-
end
|
58
|
-
end
|
data/lib/shell_utils/version.rb
DELETED
data/test/shell_utils_test.rb
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
require File.expand_path('../test_helper', __FILE__)
|
2
|
-
|
3
|
-
describe "ShellUtils" do
|
4
|
-
it "should sh" do
|
5
|
-
assert_equal Time.new.to_i.to_s, ShellUtils.sh("date +%s").strip
|
6
|
-
end
|
7
|
-
|
8
|
-
it "should sh and raise" do
|
9
|
-
assert_raises RuntimeError do
|
10
|
-
ShellUtils.sh("mymilkshakebringsvariousboystotheYARD")
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
it "should sh_with_code" do
|
15
|
-
out, status = ShellUtils.sh_with_code("date +%s")
|
16
|
-
assert_equal Time.new.to_i.to_s, out.strip
|
17
|
-
assert_equal 0, status.to_i
|
18
|
-
end
|
19
|
-
|
20
|
-
it "should sh_with_code and fail" do
|
21
|
-
out, status = ShellUtils.sh_with_code("mymilkshakebringsvariousboystotheYARD")
|
22
|
-
assert_equal "sh: mymilkshakebringsvariousboystotheYARD: command not found", out.strip
|
23
|
-
refute_equal 0, status.to_i
|
24
|
-
end
|
25
|
-
end
|
data/test/test_helper.rb
DELETED