engine-hacks 0.2.0.pre1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 95e4571cc6ce855e88da5f20d9ffcbbb075eb338843240cbc0de0b853064bacf
4
+ data.tar.gz: d37295c1c30e192554bbec47cde9484ad9440475b46f5033d4355e778e7f406a
5
+ SHA512:
6
+ metadata.gz: 3441f2db1981c5ef615e57b9ca1e856b09fd6d126b979a507a235232f76aec9b195b055b79aae1a6758362ab67e5ad5bb72ba8a01268f2a4730fea6e6733090d
7
+ data.tar.gz: 415660b5d73eeadcee378092e9f8902bf6cfaa35d7b13c9da36e48aa858d18a67dfcca906ececf29a98e681282a91c6150d55ecd689cc5fd9905832c712d052a
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/Gemfile ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ # Specify your gem's dependencies in process-wrapper-mid.gemspec
6
+ gemspec
7
+
8
+ gem "rake", "~> 13.0"
9
+
10
+ gem "rspec", "~> 3.0"
11
+
12
+ gem "rake-compiler", "~> 1.2"
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # EngineHacks Library
2
+
3
+ Ruby Engine-specific extensions to enable SubSpawn.
4
+
5
+ ## Installation
6
+
7
+ For most users, install one the other SubSpawn gems directly instead.
8
+
9
+ Otherwise, install the gem and add to the application's Gemfile by executing:
10
+
11
+ $ bundle add engine-hacks
12
+
13
+ If bundler is not being used to manage dependencies, install the gem by executing:
14
+
15
+ $ gem install engine-hacks
16
+
17
+ ## Usage
18
+
19
+ For most users, use one of the other SubSpawn API's directly.
20
+
21
+ ```rb
22
+ require 'engine-hacks'
23
+ ```
24
+
25
+ An RBS file exists for this gem.
26
+
27
+ ## Development
28
+
29
+ See parent SubSpawn readme
data/Rakefile ADDED
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+
9
+ require 'rake/extensiontask'
10
+
11
+ Rake::ExtensionTask.new "engine_hacks" do |ext|
12
+ ext.lib_dir = "lib/engine-hacks"
13
+ end
14
+
15
+
16
+ task default: :build
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/engine-hacks/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "engine-hacks"
7
+ spec.version = EngineHacks::VERSION
8
+ spec.authors = ["Patrick Plenefisch"]
9
+ spec.email = ["simonpatp@gmail.com"]
10
+
11
+ spec.summary = "Engine-specific hacks to enable implement spawn in Ruby"
12
+ spec.description = "A SubSpawn subproject to provide c/java extensions to modify non-ruby-modifiable classes necessary to implementing SubSpawn, or any other spawn/popen API in pure Ruby"
13
+ final_github = "https://github.com/byteit101/subspawn"
14
+ spec.homepage = final_github
15
+ spec.required_ruby_version = ">= 2.6.0"
16
+
17
+ #spec.metadata["allowed_push_host"] = "TODO: Set to your gem server 'https://example.com'"
18
+
19
+ spec.metadata["homepage_uri"] = spec.homepage
20
+ spec.metadata["source_code_uri"] = final_github
21
+ spec.metadata["changelog_uri"] = final_github
22
+
23
+ # Specify which files should be added to the gem when it is released.
24
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
25
+ spec.files = Dir.chdir(__dir__) do
26
+ `git ls-files -z`.split("\x0").reject do |f|
27
+ (f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
28
+ end
29
+ end
30
+ spec.require_paths = ["lib"]
31
+
32
+ if RUBY_PLATFORM =~ /java/
33
+ spec.platform = "java"
34
+ else
35
+ spec.platform = Gem::Platform::RUBY
36
+ spec.extensions = ["ext/engine_hacks/extconf.rb"]
37
+ end
38
+
39
+ # For more information and examples about making a new gem, check out our
40
+ # guide at: https://bundler.io/guides/creating_gem.html
41
+
42
+ # You can use Ruby's license, or any of the JRuby tri-license options
43
+ spec.licenses = ["Ruby", "EPL-2.0", "LGPL-2.1-or-later"]
44
+ end
@@ -0,0 +1,64 @@
1
+ #include "ruby/ruby.h"
2
+ #include "ruby/io.h"
3
+ #include "ruby/intern.h"
4
+
5
+ // global to store the thread local name to read for $? and $CHILD_STATUS
6
+ static VALUE status_holder;
7
+
8
+
9
+ // $? accessor. returns `Thread.current[status_holder[0]]`
10
+ static VALUE
11
+ get_CHILD_STATUS(ID _x, VALUE *_y)
12
+ {
13
+ return rb_thread_local_aref(rb_thread_current(), SYM2ID(RARRAY_AREF(status_holder, 0)));
14
+ }
15
+
16
+ // overwrites old $? definition to our defintion, and save the new status thread local name
17
+ static VALUE
18
+ install_status(VALUE self, VALUE new_status)
19
+ {
20
+ rb_define_virtual_variable("$?", get_CHILD_STATUS, 0);
21
+ rb_define_virtual_variable("$CHILD_STATUS", get_CHILD_STATUS, 0);
22
+
23
+ // reset, and save the new state
24
+ rb_ary_clear(status_holder);
25
+ new_status = rb_to_symbol(new_status);
26
+ rb_ary_push(status_holder, new_status);
27
+
28
+ // return the name, converted
29
+ return new_status;
30
+ }
31
+
32
+ static VALUE
33
+ join_pipes(VALUE self, VALUE reader, VALUE writer)
34
+ {
35
+ rb_io_set_write_io(reader, writer);
36
+
37
+ // ensure flags are correct
38
+ RFILE(writer)->fptr->mode |= FMODE_SYNC|FMODE_DUPLEX;
39
+ RFILE(reader)->fptr->mode |= FMODE_SYNC|FMODE_DUPLEX;
40
+ RFILE(writer)->fptr->mode &= ~FMODE_READABLE;
41
+ RFILE(reader)->fptr->mode &= ~FMODE_WRITABLE;
42
+
43
+ // not functional, but what IO.popen does as API
44
+ rb_ivar_set(reader, rb_intern("@tied_io_for_writing"), writer);
45
+ return reader;
46
+
47
+ // TODO: we may need to worry that MRI io.c sets pipe_finalize?
48
+ }
49
+
50
+ void Init_engine_hacks(void)
51
+ {
52
+ VALUE EngineHacks = rb_define_module("EngineHacks");
53
+ VALUE EngineHacksMRI = rb_define_module_under(EngineHacks, "MRI");
54
+
55
+ // hold the status in an array, so we can mark the array, and avoid fiddling with making
56
+ // our own marking stuff for the GC. if we don't mark as gc, SEGV
57
+ status_holder = rb_ary_new();
58
+ rb_global_variable(&status_holder);
59
+
60
+ // Exposed methods. Unsafe, do not call these directly, use the cruby.rb wrapper functions only!
61
+ rb_define_singleton_method(EngineHacksMRI, "install_status!", install_status, 1);
62
+ rb_define_singleton_method(EngineHacksMRI, "join_io", join_pipes, 2);
63
+
64
+ }
@@ -0,0 +1,3 @@
1
+ require "mkmf"
2
+
3
+ create_makefile "engine_hacks/engine_hacks"
@@ -0,0 +1,27 @@
1
+ require 'engine_hacks/engine_hacks'
2
+ require 'English'
3
+
4
+ # TODO: this doesn't actually work
5
+ #alias $BUILTIN_CHILD_STATUS $?
6
+
7
+ module EngineHacks
8
+
9
+ def self.use_child_status symbol
10
+ @symbol = symbol.to_sym
11
+ MRI.install_status! symbol
12
+ end
13
+
14
+ def self.child_status= value
15
+ if defined? @symbol
16
+ Thread.current[@symbol] = value
17
+ else
18
+ nil # not installed yet
19
+ end
20
+ end
21
+
22
+ def self.duplex_io(read, write)
23
+ raise ArgumentError.new("Read argument must be IO") unless read.is_a? IO
24
+ raise ArgumentError.new("Write argument must be IO") unless write.is_a? IO
25
+ MRI.join_io(read, write)
26
+ end
27
+ end
@@ -0,0 +1,28 @@
1
+
2
+ module EngineHacks
3
+
4
+ def self.use_child_status symbol
5
+ # No-op on JRuby
6
+ nil
7
+ end
8
+
9
+ def self.child_status= status
10
+ require 'jruby'
11
+ JRuby.runtime.current_context.last_exit_status = status
12
+ end
13
+
14
+ def self.duplex_io(read, write)
15
+ raise ArgumentError.new("Read argument must be IO") unless read.is_a? IO
16
+ raise ArgumentError.new("Write argument must be IO") unless write.is_a? IO
17
+ require 'jruby'
18
+ readf = JRuby.ref(read).open_file
19
+ writef = JRuby.ref(read).open_file
20
+ raise ArgumentError.new("Read argument must be JRuby IO") if readf.nil?
21
+ raise ArgumentError.new("Write argument must be JRuby IO") if writef.nil?
22
+ readf.tied_io_for_writing = write
23
+ modes = writef.class
24
+ readf.mode = (readf.mode & ~modes::WRITABLE) | modes::SYNC | modes::DUPLEX
25
+ writef.mode = (writef.mode & ~modes::READABLE) | modes::SYNC | modes::DUPLEX
26
+ return read
27
+ end
28
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EngineHacks
4
+ VERSION = "0.2.0.pre1"
5
+ end
@@ -0,0 +1,8 @@
1
+ require 'engine-hacks/version'
2
+ if defined? JRUBY_VERSION # or: RUBY_PLATFORM =~ /java/
3
+ # JRuby
4
+ require 'engine-hacks/jruby'
5
+ else
6
+ # MRI or TruffleRuby
7
+ require 'engine-hacks/cruby'
8
+ end
@@ -0,0 +1,15 @@
1
+ module EngineHacks
2
+ # Makes $? use the thread-local variable named
3
+ # Returns nil if thread-local hack not necessary, the
4
+ # Symbol otherwise
5
+ def self.use_child_status: (String | Symbol) -> ?Symbol
6
+
7
+ # Sets $? to the given object. returns nil if use_child_status hasn't
8
+ # been called yet
9
+ def self.child_status=: (Object) -> ?Object
10
+
11
+ # Returns an IO that may be either of the input arguments or a new
12
+ # IO that is a duplex IO where .read calls read.read, and .write calls
13
+ # write.write, etc.
14
+ def self.duplex_io: (IO read, IO write) -> IO
15
+ end
metadata ADDED
@@ -0,0 +1,63 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: engine-hacks
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0.pre1
5
+ platform: ruby
6
+ authors:
7
+ - Patrick Plenefisch
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2024-05-01 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: A SubSpawn subproject to provide c/java extensions to modify non-ruby-modifiable
14
+ classes necessary to implementing SubSpawn, or any other spawn/popen API in pure
15
+ Ruby
16
+ email:
17
+ - simonpatp@gmail.com
18
+ executables: []
19
+ extensions:
20
+ - ext/engine_hacks/extconf.rb
21
+ extra_rdoc_files: []
22
+ files:
23
+ - ".rspec"
24
+ - Gemfile
25
+ - README.md
26
+ - Rakefile
27
+ - engine-hacks.gemspec
28
+ - ext/engine_hacks/engine_hacks.c
29
+ - ext/engine_hacks/extconf.rb
30
+ - lib/engine-hacks.rb
31
+ - lib/engine-hacks/cruby.rb
32
+ - lib/engine-hacks/jruby.rb
33
+ - lib/engine-hacks/version.rb
34
+ - sig/engine-hacks.rbs
35
+ homepage: https://github.com/byteit101/subspawn
36
+ licenses:
37
+ - Ruby
38
+ - EPL-2.0
39
+ - LGPL-2.1-or-later
40
+ metadata:
41
+ homepage_uri: https://github.com/byteit101/subspawn
42
+ source_code_uri: https://github.com/byteit101/subspawn
43
+ changelog_uri: https://github.com/byteit101/subspawn
44
+ post_install_message:
45
+ rdoc_options: []
46
+ require_paths:
47
+ - lib
48
+ required_ruby_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: 2.6.0
53
+ required_rubygems_version: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: '0'
58
+ requirements: []
59
+ rubygems_version: 3.5.3
60
+ signing_key:
61
+ specification_version: 4
62
+ summary: Engine-specific hacks to enable implement spawn in Ruby
63
+ test_files: []