shellany-0.0.1/0000755000175000017500000000000013203004376011401 5ustar daidaishellany-0.0.1/spec/0000755000175000017500000000000013203004376012333 5ustar daidaishellany-0.0.1/spec/spec_helper.rb0000644000175000017500000000102713203004376015151 0ustar daidaiRSpec.configure do |config| config.expect_with :rspec do |expectations| expectations.include_chain_clauses_in_custom_matcher_descriptions = true end config.mock_with :rspec do |mocks| mocks.verify_partial_doubles = true end config.filter_run :focus config.run_all_when_everything_filtered = true config.disable_monkey_patching! config.warnings = true config.default_formatter = 'doc' if config.files_to_run.one? # config.profile_examples = 10 config.order = :random Kernel.srand config.seed end shellany-0.0.1/spec/shellany_spec.rb0000644000175000017500000000016013203004376015506 0ustar daidaiRSpec.describe Shellany do it 'has a version number' do expect(Shellany::VERSION).not_to be nil end end shellany-0.0.1/spec/lib/0000755000175000017500000000000013203004376013101 5ustar daidaishellany-0.0.1/spec/lib/shellany/0000755000175000017500000000000013203004376014720 5ustar daidaishellany-0.0.1/spec/lib/shellany/sheller_spec.rb0000644000175000017500000000703113203004376017716 0ustar daidairequire "shellany/sheller" RSpec.describe Shellany::Sheller, :sheller_specs do before do allow(Kernel).to receive(:system) do |args| fail "Stub called with: #{args.inspect}" end end subject { described_class } context "without a command" do [:new, :run, :stdout, :stderr].each do |meth| describe ".#{meth}" do specify do expect { subject.send(meth) }. to raise_error ArgumentError, "no command given" end end end end context "with shell (string) cmd returning success" do let(:cmd) { "ls -l" } let(:output) { "foo.rb\n" } let(:errors) { "" } let(:result) do [instance_double(Process::Status, success?: true), output, errors] end context "when constructed with a cmd" do subject { described_class.new(cmd) } describe "#run" do it "runs the command given to constructor" do expect(described_class).to receive(:_system_with_capture). with(cmd).and_return(result) subject.run end end end end context "with array cmd returning success" do let(:cmd) { %w(ls -l) } let(:output) { "foo.rb\n" } let(:errors) { "" } let(:result) do [instance_double(Process::Status, success?: true), output, errors] end describe "when used as class" do describe ".run" do it "runs the given command" do expect(described_class).to receive(:_system_with_capture). with(*cmd) { result } subject.run(*cmd) end end describe ".new" do it "does not run anything" do expect(described_class).to_not receive(:_system_with_capture) subject end end describe ".stdout" do before do allow(described_class).to receive(:_system_with_capture). with(*cmd) { result } end it "runs command and returns output" do expect(subject.stdout(*cmd)).to eq "foo.rb\n" end end describe ".stderr" do before do allow(described_class).to receive(:_system_with_capture). with(*cmd) { result } end it "runs command and returns errors" do expect(subject.stderr(*cmd)).to eq "" end end end context "when constructed with a cmd" do subject { described_class.new(*cmd) } it "does not run anything" do expect(described_class).to_not receive(:_system_with_capture) subject end describe "#run" do it "runs the command given to constructor" do expect(described_class).to receive(:_system_with_capture). with(*cmd) { result } subject.run end end describe "#stdout" do before do allow(described_class).to receive(:_system_with_capture). with(*cmd) { result } end it "runs command and returns output" do expect(subject.stdout).to eq "foo.rb\n" end end describe "#stderr" do before do allow(described_class).to receive(:_system_with_capture). with(*cmd) { result } end it "runs command and returns output" do expect(subject.stderr).to eq "" end end describe "#ok?" do before do allow(described_class).to receive(:_system_with_capture). with(*cmd) { result } end it "runs command and returns output" do expect(subject).to be_ok end end end end end shellany-0.0.1/shellany.gemspec0000644000175000017500000000147713203004376014576 0ustar daidai# coding: utf-8 lib = File.expand_path('../lib', __FILE__) $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) require 'shellany/version' Gem::Specification.new do |spec| spec.name = "shellany" spec.version = Shellany::VERSION spec.authors = ["Cezary Baginski"] spec.email = ["cezary@chronomantic.net"] spec.summary = %q{Simple, somewhat portable command capturing} spec.description = %q{MRI+JRuby compatible command output capturing} spec.homepage = "" spec.license = "MIT" spec.files = `git ls-files -z`.split("\x0") spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) spec.require_paths = ["lib"] spec.add_development_dependency "bundler", "~> 1.7" end shellany-0.0.1/lib/0000755000175000017500000000000013203004376012147 5ustar daidaishellany-0.0.1/lib/shellany/0000755000175000017500000000000013203004376013766 5ustar daidaishellany-0.0.1/lib/shellany/version.rb0000644000175000017500000000005013203004376015773 0ustar daidaimodule Shellany VERSION = "0.0.1" end shellany-0.0.1/lib/shellany/sheller.rb0000644000175000017500000000720013203004376015750 0ustar daidairequire "open3" module Shellany # The Guard sheller abstract the actual subshell # calls and allow easier stubbing. # class Sheller attr_reader :status # Creates a new Guard::Sheller object. # # @param [String] args a command to run in a subshell # @param [Array] args an array of command parts to run in a subshell # @param [*String] args a list of command parts to run in a subshell # def initialize(*args) fail ArgumentError, "no command given" if args.empty? @command = args @ran = false end # Shortcut for new(command).run # def self.run(*args) new(*args).run end # Shortcut for new(command).run.stdout # def self.stdout(*args) new(*args).stdout end # Shortcut for new(command).run.stderr # def self.stderr(*args) new(*args).stderr end # Runs the command. # # @return [Boolean] whether or not the command succeeded. # def run unless ran? status, output, errors = self.class._system_with_capture(*@command) @ran = true @stdout = output @stderr = errors @status = status end ok? end # Returns true if the command has already been run, false otherwise. # # @return [Boolean] whether or not the command has already been run # def ran? @ran end # Returns true if the command succeeded, false otherwise. # # @return [Boolean] whether or not the command succeeded # def ok? run unless ran? @status && @status.success? end # Returns the command's output. # # @return [String] the command output # def stdout run unless ran? @stdout end # Returns the command's error output. # # @return [String] the command output # def stderr run unless ran? @stderr end # No output capturing # # NOTE: `$stdout.puts system('cls')` on Windows won't work like # it does for on systems with ansi terminals, so we need to be # able to call Kernel.system directly. def self.system(*args) _system_with_no_capture(*args) end def self._system_with_no_capture(*args) Kernel.system(*args) result = $? errors = (result == 0) || "Guard failed to run: #{args.inspect}" [result, nil, errors] end def self._system_with_capture(*args) # We use popen3, because it started working on recent versions # of JRuby, while JRuby doesn't handle options to Kernel.system args = _shellize_if_needed(args) stdout, stderr, status = nil Open3.popen3(*args) do |_stdin, _stdout, _stderr, _thr| stdout = _stdout.read stderr = _stderr.read status = _thr.value end [status, stdout, stderr] rescue Errno::ENOENT, IOError => e [nil, nil, "Guard::Sheller failed (#{e.inspect})"] end # Only needed on JRUBY, because MRI properly detects ';' and metachars def self._shellize_if_needed(args) return args unless RUBY_PLATFORM == "java" return args unless args.size == 1 return args unless /[;<>]/ =~ args.first # NOTE: Sheller was originally meant for Guard (which basically only uses # UNIX commands anyway) and JRuby doesn't support options to # Kernel.system (and doesn't automatically shell when there's a # metacharacter in the command). # # So ... I'm assuming /bin/sh exists - if not, PRs are welcome, # because I have no clue what to do if /bin/sh doesn't exist. # (use ENV["RUBYSHELL"] ? Detect cmd.exe ?) ["/bin/sh", "-c", args.first] end end end shellany-0.0.1/lib/shellany.rb0000644000175000017500000000011313203004376014306 0ustar daidairequire "shellany/version" module Shellany # Your code goes here... end shellany-0.0.1/Rakefile0000644000175000017500000000033713203004376013051 0ustar daidairequire "bundler/gem_tasks" require 'nenv' default_tasks = [] require 'rspec/core/rake_task' default_tasks << RSpec::Core::RakeTask.new(:spec) do |t| t.verbose = Nenv.ci? end task default: default_tasks.map(&:name) shellany-0.0.1/README.md0000644000175000017500000000334513203004376012665 0ustar daidai# Shellany Shellany captures command output. ## Features: - portability (should work on recent JRuby versions) - capturing stdout, stderr in a convenient way - returning the result in a convenient way - detecting if a shell is needed (though incomplete/primitive implementation) - prevents running the same command multiple times ## Installation Add this line to your application's Gemfile: ```ruby gem 'shellany' ``` And then execute: $ bundle Or install it yourself as: $ gem install shellany ## Usage Basic usage: ```ruby require 'shellany/sheller' Shellany::Sheller.stdout("echo abc") # => "abc" Shellany::Sheller.stderr("touch /foo") # => "touch: cannot touch ‘/aef’: Permission denied Shellany::Sheller.run("false") # => false Shellany::Sheller.system("clear") # => clears screen (no capture done) ``` Using Sheller object: ```ruby require 'shellany/sheller' sh = Shellany::Sheller.new('grep /etc/passed|tail -n 1') # does nothing sh.stdout # shows output (runs the command since it wasn't run) sh.stderr # shows stderr (does not run the command) sh.ok? # returns true if exit code was zero (does not run the command) ``` ## Project status Only developed enough for Guard to run, though pull requests are more than welcome. Especially for: - better API - better shell detection code - better support for various system() arguments - better support for redireciton handling - better support for shell detection (e.g. Windows) ## Contributing 1. Fork it ( https://github.com/[my-github-username]/shellany/fork ) 2. Create your feature branch (`git checkout -b my-new-feature`) 3. Commit your changes (`git commit -am 'Add some feature'`) 4. Push to the branch (`git push origin my-new-feature`) 5. Create a new Pull Request shellany-0.0.1/LICENSE.txt0000644000175000017500000000206013203004376013222 0ustar daidaiCopyright (c) 2014 Cezary Baginski MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. shellany-0.0.1/Gemfile0000644000175000017500000000033113203004376012671 0ustar daidaisource 'https://rubygems.org' # Specify your gem's dependencies in shellany.gemspec gemspec development_group: :gem_build_tools gem "rake", "~> 10.0" gem 'nenv', "~> 0.1" group :test do gem "rspec", "~> 3.1" end shellany-0.0.1/.travis.yml0000644000175000017500000000026213203004376013512 0ustar daidailanguage: ruby bundler_args: --without development rvm: - 1.9.3 - 2.0.0 - 2.1.5 - ruby-head - jruby - rbx-2 matrix: allow_failures: - rvm: rbx - rvm: jruby shellany-0.0.1/.rspec0000644000175000017500000000003613203004376012515 0ustar daidai--color --require spec_helper shellany-0.0.1/.gitignore0000644000175000017500000000016613203004376013374 0ustar daidai/.bundle/ /.yardoc /Gemfile.lock /_yardoc/ /coverage/ /doc/ /pkg/ /spec/reports/ /tmp/ *.bundle *.so *.o *.a mkmf.log